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 itThen 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:
- 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.
-
Claude apps. Adds a
natmcpentry 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.
- the Claude desktop app (chat):
-
R profile (optional). Adds
natmcp::natmcp_session(quiet = TRUE)to your~/.Rprofileso 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):
-
Claude desktop app (chat): open Settings → Developer → Edit Config and add a
natmcpentry undermcpServers, alongside any servers already there:{ "mcpServers": { "natmcp": { "command": "/path/to/Rscript", "args": ["-e", "natmcp::natmcp_mcp_server()"] } } }After restarting, Settings → Developer should show
natmcpas running; if it shows an error, click it for the log. The usual culprits are a wrongRscriptpath or natmcp not being installed in the library thatRscriptuses. -
Claude Code: if you have the
claudecommand-line tool,and check with
claude mcp list. Otherwise add the same entry undermcpServersin~/.claude.json. Other MCP clients: use the same
commandandargsin 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 fornatmcp_run_runless 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 resultTools
| 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, thenv_datasetsfacts table). It writesindex.rds+ a reproduciblemanifest.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 natversethen 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:
-
natmcp isn’t running in Claude. Rerun
natmcp::natmcp_setup()and fully quit and reopen Claude. Settings → Developer (desktop chat) orclaude mcp list(Claude Code) should listnatmcp. -
The session isn’t registered. Run
natmcp::natmcp_session()in it (or add it to your.Rprofilewithnatmcp_setup(rprofile = TRUE)). - 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).
-
Claude says it can’t run code. Run
natmcp::natmcp_session(run_r = TRUE)in that session (and installevaluateif 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