Skip to content
flyconnectomePublic

About

MCP server giving coding agents authoritative, current, token-efficient access to natverse ground truth

Resources

Stars

1 star

Watchers

0 watching

Forks

Repository files navigation

natmcp

natverse Lifecycle: experimental

An MCP server that gives coding agents authoritative, current, token-efficient access to natverse ground truth — so they generate, extend, optimise and repurpose natverse analysis code without working from stale or fuzzy memory of the ecosystem.

natmcp is a knowledge server, not a code generator or executor: the agent already writes and edits code well; natmcp supplies the natverse specifics it gets wrong (signatures, return shapes, idioms, dataset conventions, current vs deprecated APIs). It complements coda — coda is entry-level exploration with its own notebook code-gen; natmcp serves coders building robust, extensible, publication-grade code.

Experimental. The API and index format may change without notice, and natmcp is not yet on CRAN. Install from GitHub.

Quick start

Three steps, all in R:

# 1. Install (with the natverse installer)
if (!requireNamespace("natmanager")) install.packages("natmanager")
natmanager::install(pkgs = "flyconnectome/natmcp")

# 2. Set up: fetch the natverse index and register natmcp with Claude
natmcp::natmcp_setup()
#    ...then fully quit and reopen Claude

# 3. In the R session you want Claude to work with
natmcp::natmcp_session()               # Claude can use this session
natmcp::natmcp_session(run_r = TRUE)   # ...and can also run R code in it

Then ask Claude to "connect to my R session". Step 3 is optional: without it Claude still gets natverse answers from natmcp, it just can't see or use your session.

The sections below explain each step in more detail.

Setup in detail

What natmcp_setup() does

You don't start the natmcp server yourself: Claude launches it in the background (as Rscript -e "natmcp::natmcp_mcp_server()") whenever it needs it. natmcp_setup() registers that command once, asking before each step:

  1. Index. Downloads the published natverse index (or builds one from your installed packages). If you skip this, the server downloads it the first time Claude uses a natmcp tool.

  2. Claude apps. Adds a natmcp entry to the configuration of

    • the Claude desktop app (chat): claude_desktop_config.json, and
    • Claude Code (terminal, IDEs and the desktop app's Code tab): ~/.claude.json.

    These are separate configurations, so both are set up by default. Nothing else in either file is touched, and a backup is saved next to each before it changes.

  3. R profile (optional). Adds natmcp::natmcp_session(quiet = TRUE) to your ~/.Rprofile so every interactive R session is available to Claude.

After it finishes, quit Claude completely (Cmd-Q / File → Exit, not just closing the window) and reopen it. To check it worked, ask Claude "Using natmcp, what's the signature of nat::nlapply?"

Run natmcp::natmcp_setup(ask = FALSE) to accept the defaults without questions; see ?natmcp_setup for the options. The index is rebuilt weekly from the current natverse, and the server checks for a newer one about once a week; run natmcp::fetch_index() to pick one up straight away.

Setting up by hand

If you'd rather edit the configuration yourself, first find the full path to your Rscript (apps started from the Dock/Start menu don't see your shell PATH, so a bare Rscript often fails):

file.path(R.home("bin"), "Rscript")
#> e.g. "/Library/Frameworks/R.framework/Resources/bin/Rscript"
  • Claude desktop app (chat): open Settings → Developer → Edit Config and add a natmcp entry under mcpServers, alongside any servers already there:

    {
      "mcpServers": {
        "natmcp": {
          "command": "/path/to/Rscript",
          "args": ["-e", "natmcp::natmcp_mcp_server()"]
        }
      }
    }

    After restarting, Settings → Developer should show natmcp as running; if it shows an error, click it for the log. The usual culprits are a wrong Rscript path or natmcp not being installed in the library that Rscript uses.

  • Claude Code: if you have the claude command-line tool,

    claude mcp add -s user natmcp -- /path/to/Rscript -e "natmcp::natmcp_mcp_server()"

    and check with claude mcp list. Otherwise add the same entry under mcpServers in ~/.claude.json.

  • Other MCP clients: use the same command and args in whatever configuration the client uses for a local ("stdio") server.

Working in your R session

Connecting Claude to a session

By default the natmcp server runs in its own background R process. Running

natmcp::natmcp_session()

makes the R session you're working in (RStudio, Positron, a terminal) available to Claude as well. It returns immediately and leaves the console free; the session just listens in the background. Then ask Claude to "connect to my R session": Claude uses the list_r_sessions and select_r_session tools to pick it, and from then on its tool calls run in that session until you restart Claude or it connects to another. If you have several sessions registered, tell Claude which one you mean (they are listed by working directory).

Letting Claude run code

natmcp::natmcp_session(run_r = TRUE)

additionally lets Claude run R code in this session: it sees the printed output, plots, messages, warnings and errors, and the objects it creates appear in your workspace. You can then ask e.g. "read the FAFB DA1 PNs into da1 and plot them". Revoke it with natmcp_session(run_r = FALSE).

The server always offers Claude a natmcp_run_r tool, but it only works in a session where you ran natmcp_session(run_r = TRUE); anywhere else it refuses. It needs the evaluate package and is built on btw's btw_tool_run_r().

Security. With run_r = TRUE, Claude can execute arbitrary R code in your session with your permissions: read and write files, delete objects, and use any credentials the session has. Your Claude app asks you to approve each tool call unless you've told it to always allow that tool; keep approval on for natmcp_run_r unless you're comfortable with what it may run.

Trying the tools by hand

The tools are plain ellmer::tool() objects, so you can call one directly from R without any MCP client:

sig <- natmcp::natmcp_tools("signature")[[1]]  # pick one tool by group
sig(symbol = "nat::read.neurons")              # returns the tool's result

Tools

Tool Job
guide orientation: package roles, altitude map, dataset roster
find task → candidate functions + a canonical snippet
signature ground-truth formals, defaults, return value, lifecycle
snippet canonical usage from tested examples/vignettes
dataset id conventions, coordinate space, auth, quirks
lint are these real, current natverse calls?
run_r run R code in a connected session that allows it
sitrep diagnose setup and session-connection problems

How it works

Two decoupled artefacts:

  • The index (data). build_index() introspects installed natverse packages (namespaces, formals(), Rd) into signature records, harvests their examples and vignettes into tagged snippets, and folds in a small curated corpus (a package/altitude guide, the nv_datasets facts table). It writes index.rds + a reproducible manifest.json (git SHA + package version of everything it touched). Sourcing is org-driven (natverse + flyconnectome).
  • The server (code). natmcp_mcp_server() serves the tools over MCP (stdio) by reading a built index. Serving needs no natverse toolchain, so the same server runs as a local per-user process or a hosted endpoint. The index is built in CI and published; the server fetches it on first use (fetch_index()).

Building your own index (developers)

The published index is built in CI from the current natverse. If you want the tools to reflect the packages you have installed (e.g. development versions), build a local index and point the server at it:

natmcp::build_index(out_dir = "~/natmcp-index")  # introspects installed natverse

then use natmcp::natmcp_mcp_server(index = '~/natmcp-index') as the -e expression in your Claude config. (With no out_dir, the index goes to inst/index in the working directory, which the server only finds when it is launched from that directory — e.g. Claude Code in the natmcp checkout.)

Built on

natmcp stands on the Posit R MCP stack rather than reinventing it:

  • mcptools — MCP transport.
  • ellmer — tools are ellmer::tool() objects, so they work both over MCP and when R is the client.
  • btw — surfaces generic package documentation; natmcp delegates generic docs to btw and adds the curated natverse layer on top. The two compose in one server: c(btw::btw_tools(), natmcp::natmcp_tools()).

It introspects the natverse packages themselves (e.g. nat, coconatfly, neuprintr, fafbseg, nat.templatebrains, nat.flybrains), plus a curated interop surface of adjacent foundations (rgl, Rvcg, Morpho, igraph).

FAQ

Can I see the code Claude runs in my R session?

Not as it runs. natmcp_run_r evaluates code in the background, so nothing is echoed to your console and it doesn't appear in your R history. Claude's app shows each call (and asks you to approve it unless you've allowed the tool permanently), and objects it creates appear in your workspace. If you want a record you can read, rerun and share, ask Claude to work in a notebook instead, e.g. "put each step in analysis.Rmd as a chunk, then run it". You then have the code alongside its results, and can run chunks yourself.

Claude can't connect to my R session

Run this in the R session Claude should use, and paste the output into Claude:

natmcp::natmcp_sitrep()

It shows natmcp's Claude configuration, the index, whether the session is registered and allows running code, and which R sessions are visible. Claude can run the same report from the server (the natmcp_sitrep tool) and compare the two. The usual fixes:

  1. natmcp isn't running in Claude. Rerun natmcp::natmcp_setup() and fully quit and reopen Claude. Settings → Developer (desktop chat) or claude mcp list (Claude Code) should list natmcp.
  2. The session isn't registered. Run natmcp::natmcp_session() in it (or add it to your .Rprofile with natmcp_setup(rprofile = TRUE)).
  3. Claude picked the wrong session, or lost it after a restart. Ask it to "list my R sessions" and name the one you mean (they are listed by working directory).
  4. Claude says it can't run code. Run natmcp::natmcp_session(run_r = TRUE) in that session (and install evaluate if asked).

Sessions list is empty (macOS). R sessions and the server meet in a socket directory that mcptools derives from TMPDIR, and apps launched from the Dock (like Claude) can see a different TMPDIR from your terminal or RStudio. natmcp pins both sides to your per-user temp directory, but can only do so if mcptools isn't already loaded; natmcp_session() warns if that happened and natmcp_sitrep() flags a MISMATCH. Restart R and call natmcp_session() first, or pin the directory yourself at the top of your ~/.Rprofile with the path the warning suggests:

Sys.setenv(MCPTOOLS_SOCKET_DIR = "/var/folders/ab/c123.../T/mcptools")

Reference

Bates, Manton, et al. (2020). The natverse, a versatile toolbox for combining and analysing neuroanatomical data. eLife 9:e53350. https://doi.org/10.7554/eLife.53350

About

MCP server giving coding agents authoritative, current, token-efficient access to natverse ground truth

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages