Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/nornir

.nornir/mcp-from-claude-code.md

Wire nornir's MCP into Claude Code (idiot-proof)

nornir-mcp is an MCP server over stdio that exposes nornir's whole surface (56 tools — see mcp-tools.md) to any MCP client. Two ways to run it:

Copy-paste the path that matches your setup.


1. Install (on the machine running Claude Code)

cargo install nornir       # ships nornir-mcp by default (≥ 0.4.21), + nornir, nornir-server, nornir-ui

nornir-mcp lands in ~/.cargo/bin — make sure that's on PATH:

which nornir-mcp        # → /home/you/.cargo/bin/nornir-mcp

On < 0.4.21 the MCP binary was gated behind a feature, so cargo install nornir shipped it only with --features mcp (or cli); without it claude mcp add … -- nornir-mcp referenced a missing binary and the client just said "Failed to connect." Upgrade (cargo install nornir --force) so a plain install includes it.

Debugging a "Failed to connect"

Claude Code's stdio transport hides the real error — it only shows ✘ Failed to connect. Run the binary directly to see why:

NORNIR_SERVER=http://oden:7878 NORNIR_SERVER_TOKEN=<token> nornir-mcp   # prints the real startup error to stderr
nornir-mcp --help                                                       # works without any config

Note: NORNIR_SERVER is a gRPC endpoint — don't curl it (you'll get a confusing HTTP/0.9 / reset that looks like the server is down; it isn't).


2a. Register it — REMOTE (relay to a nornir-server)

One MCP serves EVERY workspace. Just two env vars — point it at the server. Do not pin a workspace: workspaces_list shows all workspaces with their repos, and workspace_use <name> switches focus at runtime.

claude mcp add (CLI):

claude mcp add nornir \
  --env NORNIR_SERVER=http://oden:7878 \
  --env NORNIR_SERVER_TOKEN=<the shared token> \
  -- nornir-mcp

…or .mcp.json in the project root:

{
  "mcpServers": {
    "nornir": {
      "command": "nornir-mcp",
      "env": {
        "NORNIR_SERVER": "http://oden:7878",
        "NORNIR_SERVER_TOKEN": "<the shared token>"
      }
    }
  }
}

Working across all workspaces (the agent flow)

  1. workspaces_list → every workspace with its repos — the full workspace×repo surface in one call (e.g. knut: [knut, knut-pipelines, …], znippy: [znippy, zoomies, …]). No switching needed just to see it.
  2. workspace_use <name> → focus a workspace; subsequent repos_list / repo_overview / deps_of / search / … target it. No restart.
  3. Repeat 2 to hop workspaces — one MCP covers knut, korp, znippy, skade, holger, njord, … without relaunching.

2b. Register it — EMBEDDED (local warehouse, no server)

No NORNIR_SERVER. Point it at a local nornir.toml so it can find the workspace + warehouse:

{
  "mcpServers": {
    "nornir": {
      "command": "nornir-mcp",
      "env": {
        "NORNIR_CONFIG": "/abs/path/to/workspace_X/release/nornir.toml"
      }
    }
  }
}

3. Verify it works (do this once)

After registering, restart Claude Code so it picks up the MCP, then:

claude mcp list             # nornir should appear, "connected"

Inside Claude Code, the tools show up as mcp__nornir__*. Sanity-check with two calls:

  1. List the surface — ask: "call the nornir MCP tool repos_list". You should get back a JSON array of repo names (proves the server/warehouse is reachable and scoped to your workspace).
  2. Call one real tool — ask: "use nornir repo_overview for holger" (or any repo from step 1). A non-empty JSON orientation block = working.

If repos_list is empty or errors:


4. Example tool calls

Just ask Claude Code in plain language; it picks the mcp__nornir__* tool:

Highlights of the 56 tools: repo_overview/deps_of/build_order (dependency Mímir), knowledge_{symbol_lookup,defined_in,callers,callees,call_path} (the syn graph), dwarf_* (binary symbols), search (BM25), release_gate_*, bench_history, docs_*, and the funnel_* planning DAG. Full table: mcp-tools.md.


Why this helps a small / on-prem model

In relay mode the server does the heavy lifting once (clone → syn scan → index → embed → Iceberg) on the host. A weak local model then asks precise questions over MCP and gets back exact symbols / call paths / ranked snippets — so it needs far less context window and zero local indexing/embedding compute. All reads hit the server's live warehouse, fed by the monitor poll loop (see running-as-a-server.md).


Verified 2026-06-09: a Claude Code-style client drove nornir-mcp → http://oden:7878, scoped to the njord workspace, and got real data back (knowledge_symbol_lookup, search). The full 56-tool surface is exercised on every build by cargo test --features mcp --test mcp_matrix (see mcp-tool-testing.md).