# `@origintrail-official/dkg-mcp`

[Model Context Protocol](https://modelcontextprotocol.io) server that exposes your local DKG V10 daemon to **Cursor**, **Claude Code**, **Claude Desktop**, **Windsurf**, **VSCode + GitHub Copilot Chat**, **Cline**, and any other MCP-aware coding assistant. It is the canonical V10 surface for "DKG as agent memory."

The package ships transitively as part of `@origintrail-official/dkg`. You don't run the bin directly — the umbrella CLI's `dkg mcp serve` invokes it on the client's behalf.

## Install

Two commands, same shape as `dkg openclaw setup`:

```bash
npm install -g @origintrail-official/dkg     # umbrella CLI bundles this MCP server
dkg mcp setup                                # one-shot: init + start + fund + register + verify
```

`dkg mcp setup` runs a bundled, idempotent flow. In order, it:

1. Initializes `~/.dkg/config.json` if absent (skipped silently when present)
2. Starts the DKG daemon as a background process (skipped if already running)
3. Funds the node's generated admin and operational wallets via the testnet faucet (skip with `--no-fund`)
4. Detects each MCP-aware client by its config file and writes the canonical entry. **You confirm per detected client interactively** (`Register DKG MCP with <client>? [Y/n]`) unless `--yes` is passed; non-TTY invocations (CI, piped stdin) auto-confirm so scripts don't hang. The detection set is seven clients: **Cursor** (`~/.cursor/mcp.json`), **Claude Code** (`~/.claude.json`), **Claude Desktop** (per-platform — `~/Library/Application Support/Claude/claude_desktop_config.json` on macOS, `%APPDATA%\Claude\claude_desktop_config.json` on Windows, `$XDG_CONFIG_HOME/Claude/claude_desktop_config.json` (or `~/.config/Claude/...` when XDG_CONFIG_HOME is unset) on Linux), **Windsurf** (`~/.codeium/windsurf/mcp_config.json`), **VSCode + GitHub Copilot Chat** (per-platform Code user-settings dir + `mcp.json` — note this client uses the `servers.dkg` shape, not `mcpServers.dkg`), **Cline** (deep-nested under VSCode's per-extension globalStorage at `Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`), and **Codex CLI** (`~/.codex/config.toml` — TOML format, table key `mcp_servers.dkg`). The clients receive the same canonical entry, serialized into each client's native format
5. Verifies the daemon is healthy

Every step short-circuits when its work is already done, so re-running on a set-up box is safe. Step-skip flags: `--no-start`, `--no-fund`, `--no-verify`, `--dry-run` (preview only), `--force` (refresh every detected client config regardless of state), `--yes` (auto-confirm per-client registrations; default false — TTY mode prompts interactively, non-TTY auto-confirms; pass `--yes` in scripts for the safer scripted-environment posture). First-init overrides: `--port <n>`, `--name <s>`, `--network <name>` (`mainnet-gnosis` default \| `mainnet-base` \| `testnet`; persisted as `config.networkConfig`; applies to a FRESH node only — an existing node keeps its current network, switch with `dkg init --network`). The bundled flow re-uses the same primitives `dkg openclaw setup` does, so the two verbs stay byte-aligned on network defaults, daemon-readiness probes, faucet retry/back-off, and manual-curl fallback.

The canonical entry written into each client's config (paths shown POSIX-style; Windows users see equivalent Windows-absolute paths):

```json
{
  "mcpServers": {
    "dkg": {
      "command": "/usr/local/bin/node",
      "args": [
        "/usr/local/lib/node_modules/@origintrail-official/dkg/dist/cli.js",
        "mcp",
        "serve"
      ],
      "env": {
        "DKG_HOME": "/Users/you/.dkg"
      }
    }
  }
}
```

The `command` is the absolute path to the Node binary running this CLI (`process.execPath` at setup time); the first arg is the absolute path to the installed CLI's `cli.js` (resolved from `process.argv[1]` via `realpathSync`, which canonicalises symlinks across `npm relink` / version-manager rotations). GUI MCP clients (Claude Desktop, Windsurf, VSCode + Copilot) often don't inherit the shell PATH that includes `node` or the `dkg` shim, so writing the resolved absolute paths makes the registration robust against that gap. The `env.DKG_HOME` field propagates the resolved bootstrap home so spawned MCP servers (which don't inherit shell env in GUI clients) read the same `config.yaml` / `auth.token` that setup just bootstrapped — important under `DKG_HOME=/custom` or `--monorepo` where the home is `~/.dkg-dev`. `dkg mcp setup` resolves and writes all three automatically — you only need this manual shape when configuring by hand. For VSCode + Copilot Chat, swap the outer `mcpServers` key for `servers` while keeping the same inner block.

No tokens or URLs in the JSON — those live in `~/.dkg/config.yaml` and the daemon-written `~/.dkg/auth.token`. If no client is detected, run `dkg mcp setup --print-only` to emit the JSON for manual paste.

After `dkg mcp setup` runs, restart your client so it discovers the MCP. Verify by asking the agent: *"What tools does dkg expose?"* The `tools/list` response must include `dkg_knowledge_asset_create`, `dkg_knowledge_asset_write`, and `dkg_memory_search`.

### Manual config (alternative)

For environments where `dkg mcp setup` can't run (CI, locked-down configs, custom paths), drop the same block in by hand:

- **Cursor** — `~/.cursor/mcp.json` (or workspace `.cursor/mcp.json`); `mcpServers.dkg`
- **Claude Code** — `~/.claude.json`, or run `claude mcp add dkg dkg mcp serve`; `mcpServers.dkg`
- **Claude Desktop** — per-platform path (see step 4 above); `mcpServers.dkg`
- **Windsurf (Codeium)** — `~/.codeium/windsurf/mcp_config.json`; `mcpServers.dkg`
- **VSCode + GitHub Copilot Chat** — per-platform Code user-settings dir + `mcp.json`; **`servers.dkg`** (Copilot Chat uses `servers`, not `mcpServers` — copy the inner block, not the outer wrapper)
- **Cline** — `Code/User/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json` under your VSCode user dir; `mcpServers.dkg`
- **Codex CLI** — `~/.codex/config.toml`; `mcp_servers.dkg` (TOML table key — Codex CLI uses `mcp_servers`, not `mcpServers`)
- **Any other MCP client** — run `dkg mcp setup --print-only` to emit the canonical JSON block, then translate into the client's native format and paste it under whichever key the client expects

### Contributor (monorepo dev) workflow

To register the local monorepo CLI dist with your MCP clients (so the registered server runs your in-progress changes), use **either** of these two entry-points. Auto-detect keys off the *running CLI's* on-disk location, **not** your shell `cwd` — so just `cd`-ing into the checkout and calling the global `dkg` is NOT enough.

**Option A (preferred): invoke the repo-built CLI directly.** Auto-detect sees the running CLI lives inside the monorepo and switches to monorepo mode automatically:

```bash
pnpm --filter @origintrail-official/dkg build         # rebuild the CLI dist
node packages/cli/dist/cli.js mcp setup               # invoke the local build directly
```

**Option B: pass `--monorepo` with the global bin.** When you have `npm i -g @origintrail-official/dkg` already and want to override auto-detect from the global install, pass `--monorepo` from inside the checkout. The flag's contract is "use the monorepo from this `cwd`", so the global `dkg` invocation resolves the local checkout via cwd:

```bash
pnpm --filter @origintrail-official/dkg build         # rebuild the CLI dist
dkg mcp setup --monorepo                              # global `dkg` + explicit monorepo override
```

Either way, the resolved registration looks like this — the shape stays uniform across modes; only `args[0]` differs:

```json
{
  "mcpServers": {
    "dkg": {
      "command": "/usr/local/bin/node",
      "args": ["/absolute/path/to/dkg/packages/cli/dist/cli.js", "mcp", "serve"]
    }
  }
}
```

**What does NOT work**: `cd dkg && dkg mcp setup` (without `--monorepo`). With a globally-installed `dkg`, the running CLI lives at the npm global path — auto-detect sees that location is outside any monorepo and stays in installed mode, registering the global build. Your local edits won't be picked up. Either invoke the local dist directly (Option A) or pass `--monorepo` (Option B).

**Always rebuild before re-running setup** — skip the rebuild and the registered entry points at a stale `dist/cli.js`, so your edits won't show up.

**Mode overrides** (mutually exclusive — pass at most one):

- `--installed` forces installed-mode setup. **Bootstrap home**: `~/.dkg`. **Registered binary**: the running CLI (whichever invoked the command — typically the global `dkg`). Use this from a monorepo cwd when you want the global install registered instead of the local dist. Only the bootstrap home changes — the registered binary is always the CLI you ran.
- `--monorepo` forces monorepo-mode setup. **Bootstrap home**: `~/.dkg-dev`. **Registered binary**: the local `<repo>/packages/cli/dist/cli.js` script (located via cwd-first walk; falls back to the running CLI dir). Errors if no DKG monorepo root is detected. Unlike `--installed`, this switches **both** the bootstrap home **and** the registered binary — so re-running setup in a fresh checkout with `--monorepo` swaps the persisted MCP entry to the local build.

The `[setup] Registering CLI: …` log line emitted at registration time prints the exact `command` and `args` that will be persisted into client configs, so you can verify the resolved binary path before any write happens.

**Moved checkout caveat.** The written `args` carry an absolute path. If you rename or move your checkout, every registered client still points at the old path. Re-run `dkg mcp setup --force` from the new location to refresh every detected client's entry.

### Configuration sources

The MCP server resolves config from two places, in priority order:

1. **`.dkg/config.yaml`** — walked upwards from the working directory (the spec-canonical workspace config; see `dkgv10-spec / 22_AGENT_ONBOARDING §2.1`)
2. **environment variables** — `DKG_API`, `DKG_TOKEN`, `DKG_PROJECT`, `DKG_AGENT_URI`

Env values win over the file; tool-call arguments (`projectId`, `view`, …) win over both.

#### Minimal `.dkg/config.yaml`

Copy `packages/mcp-dkg/config.yaml.example` into `<workspace>/.dkg/config.yaml` and edit:

```yaml
contextGraph: my-research

node:
  api: http://localhost:9200
  tokenFile: ~/.dkg/auth.token

agent:
  uri: urn:dkg:agent:cursor-branarakic

capture:
  subGraph: chat
  assertion: chat-log
  privacy: team
autoShare: true
```

`.dkg/` is gitignored repo-wide so this file stays local to each operator. The `tokenFile` path is resolved relative to the YAML; default of `~/.dkg/auth.token` matches what `dkg start` writes on first boot.

## Tool surface (29 tools)

All tools are available the moment `dkg mcp setup` registers the MCP with your client. They group into seven categories tracking how a session typically uses memory: check health, discover the graph, set it up, drive the knowledge-asset lifecycle (create → write → finalize → share → publish), recall from it, query it, and message other agents.

### Health / identity

| Tool | What it does |
|---|---|
| `dkg_status` | Show DKG node status: peer ID, connected peers, multiaddrs, wallet addresses. First call most agents make to verify the daemon is running. |
| `dkg_peer_info` | Look up a peer by peer ID: connection state, transports, and diagnostic blocks (connections, peer store, outbox). |
| `dkg_wallet_balances` | TRAC and ETH balances per operational wallet, plus chain id and RPC URL. Use before publishing to verify funds. |

### Discovery (graph navigation)

| Tool | What it does |
|---|---|
| `dkg_list_context_graphs` | List all context graphs (called "projects" in the DKG node UI) this node knows about. Returns id, display name, role (curator / participant), and layer. The first call most agents make when joining a workspace. |
| `dkg_sub_graph_list` | List the sub-graphs inside a context graph (e.g. `code`, `github`, `decisions`, `tasks`, `meta`, `chat`) with entity counts. Use to figure out what kind of knowledge a CG exposes before querying. |
| `dkg_get_entity` | All triples where the given URI is the subject, plus a 1-hop inbound-edges neighbourhood. Equivalent to the entity detail page in the Node UI. Use to understand a specific decision, task, file, or PR end-to-end. |
| `dkg_get_entity_sources` | An entity's facts, each tagged with the Knowledge Asset (author + KA number) that asserted it, so you can cite/verify provenance. Reads one tier — verifiable-memory by default (published/on-chain), or shared-working-memory (pre-publish draft). Facts in non-per-KA graphs are disclosed by count. |
| `dkg_list_activity` | Recent activity across all sub-graphs, newest first. Mirrors the "Recent activity" feed on the project overview page: decisions, tasks, PRs, chat turns. Use to catch up at the start of a session. |
| `dkg_get_agent` | Look up an agent by URI (or display name) and return its profile card: framework, operator, wallet address, joined-at, reputation, plus everything that agent has authored in the project. |

### Setup (graph CRUD)

| Tool | What it does |
|---|---|
| `dkg_context_graph_create` | Create a context graph (called "projects" in the DKG node UI). The `id` slug is auto-derived from `name` when omitted. Idempotent — pre-existing CGs are returned unchanged. |
| `dkg_subscribe` | Subscribe to a context graph so its data syncs locally from peers. Defaults to also syncing Shared Working Memory; pass `includeSharedMemory: false` to skip SWM. |
| `dkg_sub_graph_create` | Create a named sub-graph inside a context graph (e.g. `code`, `tasks`, `meta`). Idempotent — pre-existing sub-graphs are silently reused. |

### Write (the canonical knowledge-asset lifecycle)

The lifecycle tool family that lets agents stage memory, seal it, share it, publish it on chain, and recover from mistakes — the canonical V10 pattern, mirrored byte-for-byte across the OpenClaw adapter and the umbrella CLI. The 5-stage sequence is **create → write → finalize → share → publish**.

| Tool | Step | What it does |
|---|---|---|
| `dkg_knowledge_asset_create` | 1 | Create an empty Working Memory assertion graph (knowledge asset). Idempotent — duplicate names land as `alreadyExists: true`. Name validation matches the daemon's `validateAssertionName`: any IRI-safe name up to 256 chars (no `/`, no whitespace, no `` <>"{}|^`\ `` characters), and not a reserved B3 KA id — NOT restricted to a lowercase-hyphen slug. |
| `dkg_knowledge_asset_write` | 2 | Append RDF quads into an existing WM assertion. Set-merge — duplicates collapse. To replace, call `dkg_knowledge_asset_discard` first or mint a unique name. |
| `dkg_knowledge_asset_finalize` | 3 | **Seal** the WM draft (the "git commit"): compute the merkleRoot over the whole assertion, build + sign an EIP-712 AuthorAttestation, stamp the seal. Returns `merkleRoot`, `authorAddress`, `schemeVersion`, `chainId`, `kav10Address`, `eip712Digest`. Seals the entire draft — no subset parameter. |
| `dkg_knowledge_asset_share` | 4 | Share a WM assertion (or specific root entities) from private WM to Shared Working Memory so teammates see it (formerly "promote"). Omit `entities` for a full share, which auto-seals best-effort; a subset share is SWM-only and not publishable to VM as a subset. |
| `dkg_knowledge_asset_publish` | 5 | **Mint / update on chain** (the sealed assertion → Verifiable Memory). Takes no selector (the seal commits the whole assertion). Returns the **UAL** + `kaId` + `txHash` — see "The canonical round-trip" below. |
| `dkg_knowledge_asset_pull_from` | edit-loop | Seed a fresh WM draft from the current SWM or VM state (the "git checkout"). Body `{ layer: "swm" \| "vm", onConflict?: "reject" \| "replace" }`; `409 WM_DRAFT_CONFLICT` on a dirty draft unless `replace`. |
| `dkg_knowledge_asset_discard` | rollback | Discard a WM assertion without sharing it. Idempotent — no-op on a missing assertion. Use before re-writing an assertion whose name you want to keep stable. |
| `dkg_knowledge_asset_query` | introspect | Return every quad in a WM assertion. The canonical introspection step for the create + write + share round-trip. |
| `dkg_knowledge_asset_import_file` | bulk | Import a local document (markdown, PDF, DOCX, HTML, txt, csv) into a WM assertion via the daemon's extraction pipeline. Useful for seeding a context graph from existing documents in one step. |
| `dkg_knowledge_asset_history` | audit | An assertion's lifecycle descriptor: author, extraction status, share state, timestamps. Returns 404 if no record exists. |
| `dkg_knowledge_asset_import_artifact_resolve` | import | Re-check the metadata of a completed imported attachment. |
| `dkg_knowledge_asset_import_artifact_read_markdown` | import | Safely read the content-addressed Markdown blob for a completed imported attachment. |
| `dkg_knowledge_asset_semantic_enrichment_write` | import | Append model-derived semantic triples + provenance to an imported assertion. |

### Publish (SWM → on-chain)

The canonical per-KA sealed publish is `dkg_knowledge_asset_publish` (step 5 of the lifecycle above — returns the **UAL**): it publishes a single named, sealed assertion from SWM to Verifiable Memory. It ships ungated — no `agent.canPublishToVm` flag — to mirror the OpenClaw adapter exactly.

> The legacy CG-wide SWM-bridge publish tools were removed in #1087. Author content as a named knowledge asset and publish it through the lifecycle above.

### Search & query

| Tool | What it does |
|---|---|
| `dkg_memory_search` | Trust-weighted free-text recall across WM/SWM/VM in the agent-context graph (and an optional project graph). Higher-trust layers (VM > SWM > WM) collapse lower-trust hits for the same entity URI. Each hit surfaces `contextGraphId`, `layer`, and `trustWeight`. Use this for "ask my memory anything" recall. |
| `dkg_query` | Execute SPARQL SELECT / ASK / CONSTRUCT against a context graph. Known prefixes are auto-prepended. Scope with `view`: `"working-memory"` (default), `"shared-working-memory"`, or `"verifiable-memory"`. Set `includeSharedMemory: true` alongside `view: "working-memory"` to query WM ∪ SWM in one call. |

### Messaging (agent-to-agent)

| Tool | What it does |
|---|---|
| `dkg_send_message` | Send a direct message to another agent over P2P (best-effort; fails gracefully when the peer is offline). |
| `dkg_check_inbox` | Read inbound direct messages addressed to this node's agents. |

## The canonical round-trip

Lifted from the repo-root README's [DKG V10 as agent memory quickstart](../../README.md#round-trip-write-then-recall), reproduced here for completeness:

1. `dkg_knowledge_asset_create` with a slug name (idempotent — re-runs return `alreadyExists: true`).
2. `dkg_knowledge_asset_write` with one or more quads (additive set-merge).
3. `dkg_memory_search` with a keyword from the write — the just-written triple comes back from the WM layer with `trustWeight` set.
4. *(optional)* `dkg_knowledge_asset_finalize` to **seal** the draft (the EIP-712 "git commit" — note: this is the rc.17 *seal* verb, distinct from the on-chain mint in step 6).
5. *(optional)* `dkg_knowledge_asset_share` to advance the lifecycle to SWM and gossip to peers (a full share auto-seals best-effort, so step 4 can be skipped for the common case).
6. *(optional)* `dkg_knowledge_asset_publish` to **mint on chain** (costs TRAC + gas, clears SWM). The response carries the asset's **UAL** (`did:dkg:<chainId>/<addr>/<number>`) plus `kaId` and `txHash` — store the UAL to reference the asset later.

For ad-hoc filtering or non-text-search queries, `dkg_query` is the lower-level SPARQL surface. To put fresh quads on chain, author them as a named knowledge asset and publish through the lifecycle (`create → write → finalize → share → publish`).

## View semantics

The `view` argument (on `dkg_query`) and the `layer` argument (on `dkg_get_entity`, `dkg_list_activity`) scope reads to one of the three DKG memory tiers:

- `working-memory` — private to this node's agents (default for most reads)
- `shared-working-memory` — gossiped to every participant on the CG; trust-weighted above WM in `dkg_memory_search`
- `verifiable-memory` — on-chain anchored; responses include UAL + publisher info; highest trust weight

A separate `includeSharedMemory: boolean` axis (on `dkg_query` and `dkg_subscribe`) layers SWM on top of the requested view; `view: "working-memory"` + `includeSharedMemory: true` matches what the Node UI's default reader shows.

## Capture hook

The package ships a tool-agnostic hook script at `hooks/capture-chat.mjs` that turns every conversation turn into `chat:Turn` triples on the project's `chat` sub-graph and auto-promotes them to SWM so teammates see them immediately. The same script works for Cursor and Claude Code — only the event wiring differs.

### Cursor — `.cursor/hooks.json`

```json
{
  "version": 1,
  "hooks": {
    "beforeSubmitPrompt": [{ "command": "DKG_WORKSPACE=/path/to/repo node /path/to/packages/mcp-dkg/hooks/capture-chat.mjs beforeSubmitPrompt", "failClosed": false }],
    "afterAgentResponse": [{ "command": "DKG_WORKSPACE=/path/to/repo node /path/to/packages/mcp-dkg/hooks/capture-chat.mjs afterAgentResponse", "failClosed": false }]
  }
}
```

`DKG_WORKSPACE` tells the hook where to walk upward from when looking for `.dkg/config.yaml` — useful when Cursor's cwd differs from the repo root (e.g. multi-folder workspaces). `failClosed: false` is deliberate — the hook exists to enrich the DKG, never to block the user's conversation. Errors log to `/tmp/dkg-capture.log` (override via `DKG_CAPTURE_LOG`) and the hook still exits `0`.

### Claude Code — `~/.claude/settings.json`

Merge the following `hooks` block into your existing `~/.claude/settings.json`. The script accepts the native Claude Code event names (`UserPromptSubmit`, `Stop`) as aliases for `beforeSubmitPrompt` / `afterAgentResponse`:

```json
{
  "hooks": {
    "UserPromptSubmit": [
      { "hooks": [{ "type": "command", "command": "DKG_WORKSPACE=/path/to/repo DKG_CAPTURE_TOOL=claude-code DKG_AGENT_URI=urn:dkg:agent:claude-code-<op> node /path/to/packages/mcp-dkg/hooks/capture-chat.mjs UserPromptSubmit" }] }
    ],
    "Stop": [
      { "hooks": [{ "type": "command", "command": "DKG_WORKSPACE=/path/to/repo DKG_CAPTURE_TOOL=claude-code DKG_AGENT_URI=urn:dkg:agent:claude-code-<op> node /path/to/packages/mcp-dkg/hooks/capture-chat.mjs Stop" }] }
    ]
  }
}
```

`DKG_CAPTURE_TOOL=claude-code` ensures turns carry `chat:speakerTool "claude-code"` in the graph so the UI chips them correctly. `DKG_AGENT_URI` lets you attribute Claude Code sessions to a distinct agent entity from your Cursor sessions — recommended (the "one human, two tools" shape in spec §4 of `22_AGENT_ONBOARDING`).

Per-turn state is kept in `~/.cache/dkg-mcp/sessions/*.json`; safe to delete at any time.

## Troubleshooting

- **`dkg mcp setup` says "no MCP-aware clients detected"** → install one of Cursor, Claude Code, Claude Desktop, Windsurf, VSCode + GitHub Copilot Chat, Cline, or Codex CLI. For any other MCP client, run `dkg mcp setup --print-only` and paste the JSON manually (translating into the client's native format if it isn't JSON).
- **`dkg mcp` says command not found** → the umbrella CLI isn't on PATH. Verify with `which dkg`. Note: `npm i -g @origintrail-official/dkg` does NOT propagate transitive bins to global PATH, so the `dkg-mcp` bin is only reachable through `dkg mcp serve` or via a direct `npx -p @origintrail-official/dkg-mcp dkg-mcp`.
- **MCP not visible in client** → restart the client. On Cursor, verify `~/.cursor/mcp.json` is syntactically valid JSON. On Claude Code, run `claude mcp list`.
- **"No project specified"** → set `contextGraph: <id>` in `.dkg/config.yaml`, or pass `projectId` on each tool call, or export `DKG_PROJECT`.
- **HTTP 401 from MCP tools** → token mismatch. `dkg auth show` returns the expected value; confirm it matches `~/.dkg/auth.token`. On CI / containers / proxied environments where `dkg init` can't run, the env-var fallbacks are `DKG_API` (daemon URL, default `http://localhost:9200`), `DKG_TOKEN` (bearer), `DKG_PROJECT` (default context graph), `DKG_AGENT_URI` (operator agent URI). A stale exported `DKG_PROJECT` from a prior session can silently mis-route writes — unset it if you switch projects.
- **HTTP 404 on `/api/context-graph/list`** → you're on an older daemon; the client automatically falls back to the legacy endpoint.
- **`tools/list` is missing tools after `dkg mcp setup`** → the client's MCP config still points at a prior install. Re-run `dkg mcp setup --force` to refresh stale entries.
- **Daemon unreachable** → `dkg status`; if it errors, `dkg logs` and `cat ~/.dkg/daemon.log`. Stale pid → `cat ~/.dkg/daemon.pid` and kill it, then `dkg start` again.
- **Port 9200 already in use** → another node is running. `dkg stop` once, or override via `dkg init` and pick a different API port.
- **WSL2: daemon dies when the terminal closes** → wrap in `tmux` or install as a systemd user service. See the [WSL2 section in JOIN_TESTNET.md](../../docs/archive/internal/setup/JOIN_TESTNET.md) for the systemd unit file.
- **WSL2: Windows-side MCP clients (Claude Desktop, Cursor, VSCode + Copilot, Cline, Windsurf)** → run `dkg mcp setup` from **PowerShell**, not from inside WSL. Setup invoked from WSL detects the Windows-side configs and writes entries into them, but the registered `command` is the Linux-side `node` binary path; Win32 clients can't spawn Linux executables, so the entries fail at MCP startup. For **Linux-side** clients (Linux Cursor, Linux Claude Code), run setup from inside WSL as normal. End-to-end Windows-side support from a WSL invocation is tracked separately (will use a `wsl.exe`-wrapper command form once shipped).

## Package layout

| File | Purpose |
|---|---|
| `src/index.ts` | Stdio MCP server entrypoint. Boots `McpServer` and registers the 29 tools. |
| `src/tools.ts` | Read tools (`dkg_list_context_graphs`, `dkg_sub_graph_list`, `dkg_query`, `dkg_get_entity`, `dkg_get_entity_sources`, `dkg_list_activity`, `dkg_get_agent`). |
| `src/tools/assertions.ts` | Knowledge-asset lifecycle (`dkg_knowledge_asset_*` × 13: create/write/finalize/share/publish/pull_from/discard/query/history/import_file + import_artifact_resolve/read_markdown + semantic_enrichment_write). |
| `src/tools/health.ts` | `dkg_status`, `dkg_peer_info`, `dkg_wallet_balances`. |
| `src/tools/memory-search.ts` | `dkg_memory_search` with WM/SWM/VM fan-out and trust-weighted ranking. |
| `src/tools/setup.ts` | `dkg_context_graph_create`, `dkg_subscribe`, `dkg_sub_graph_create`. |
| `src/tools/chat.ts` | `dkg_send_message`, `dkg_check_inbox`. |
| `src/client.ts` | `DkgClient` HTTP wrapper. Re-exported as `@origintrail-official/dkg-mcp/client`. |
| `src/manifest/{publish,fetch,install}.ts` | Project manifest publish/install pipeline. Re-exported as `@origintrail-official/dkg-mcp/manifest/*` and consumed by the umbrella CLI's daemon routes. |
| `hooks/capture-chat.mjs` | Cursor/Claude Code chat-turn capture hook (above). |
| `schema/dev-context-graph.ttl` | The canonical dev-coordination ontology (devgraph namespace). |

## Historical recovery

Ten V9-era and coding-project tools were dropped from the V10 surface during consolidation. The annotated git tag `pre-v10-tool-drop` preserves them — recover any individual handler with `git show pre-v10-tool-drop:packages/mcp-dkg/src/tools/<file>`. Design rationale and reintroduction-pointers for each drop are in [`agent-docs/dkg-v10-mcp-consolidation/v9-design-archive.md`](../../agent-docs/dkg-v10-mcp-consolidation/v9-design-archive.md).
