MCP Server
The wwkg CLI ships an embedded Model Context Protocol server that
exposes every CLI subcommand as a tool an MCP-aware client can call directly.
Once configured, Claude Desktop, Claude Code, Cursor, and any other MCP host
can run SPARQL queries, manage workspaces, branch and merge, upload data, and
inspect node status by invoking the same subcommands you would type at the
shell, without you (or the LLM) having to assemble shell strings or parse
text output.
The tool catalog is auto-generated from the live CLI definition, so every new
wwkg command becomes an MCP tool with no separate maintenance — and read-only
tools are annotated separately from destructive ones, so MCP hosts can
auto-approve graph.query while still prompting you before workspace.delete
or graph.upload.
Quickstart
1. Verify your wwkg binary supports mcp
wwkg system mcp serve --helpIf you see a Serve the MCP protocol over stdio … summary, you’re good. If
not, upgrade:
wwkg system upgrade2. Register the server with your MCP client
The exact command depends on the client. Both Claude Desktop and Claude Code
use stdio transport, which is what wwkg system mcp serve
speaks.
Claude Code
claude mcp add wwkg wwkg system mcp serveThis writes a wwkg entry to your Claude Code MCP config. Verify it:
claude mcp listClaude Desktop / generic JSON config
Add an entry to your MCP client’s config file (e.g.
~/.config/claude-desktop/claude_desktop_config.json):
{
"mcpServers": {
"wwkg": {
"command": "wwkg",
"args": ["system", "mcp", "serve"]
}
}
}Codex CLI
The OpenAI Codex CLI reads MCP server config from
~/.codex/config.toml — there is no codex mcp add analogue, you edit the
file directly:
[mcp_servers.wwkg]
command = "wwkg"
args = ["system", "mcp", "serve"]Codex also accepts safety knobs the JSON-config clients don’t expose. The two most useful ones for a CLI with 124 tools that can mutate workspaces:
[mcp_servers.wwkg]
command = "wwkg"
args = ["system", "mcp", "serve"]
env = { WWKG_WORKSPACE = "urn:wwkg:workspace:…", WWKG_BRANCH = "main" }
# Hard-deny destructive tools regardless of approval prompts:
disabled_tools = [
"graph.upload",
"graph.update",
"workspace.delete",
"account.wallet.delete",
"node.host.uninstall",
]
# Or invert: only allow a curated read-only surface:
# enabled_tools = ["graph.query", "graph.explain", "workspace.info", "workspace.list"]
startup_timeout_sec = 30
tool_timeout_sec = 300enabled_tools / disabled_tools are evaluated by Codex before the tool
call ever reaches the server, so they’re a defense-in-depth layer on top of
the read-only / destructive annotations the server already emits.
3. Restart the MCP client
MCP servers are read at client startup, not at runtime. Exit Claude Desktop / Claude Code completely and relaunch — the WWKG tools appear in the client’s tool catalog on the next session.
4. Verify
In your fresh session, ask the assistant something WWKG-specific:
“What workspace am I in, and which branches does it have?”
The assistant should call mcp__wwkg__workspace_current and
mcp__wwkg__graph_branch_list (and ask you to approve any destructive
follow-ups). If it instead tries to spawn wwkg from a shell, the MCP server
isn’t registered — recheck step 2 and that you’ve restarted the client.
Tool naming
Tool names mirror the CLI’s subcommand path with the segments joined by dots,
prefixed by the MCP server name your client uses (mcp__wwkg__ for Claude
Code, wwkg. for Codex and plain MCP clients).
| CLI command | MCP tool |
|---|---|
wwkg system version | system.version |
wwkg graph query "ASK { ?s ?p ?o }" | graph.query |
wwkg graph branch list | graph.branch.list |
wwkg graph branch profile set main --enable … | graph.branch.profile.set |
wwkg workspace info | workspace.info |
wwkg account wallet create | account.wallet.create |
Subcommand arguments become MCP tool arguments under the same names. Global
flags (--workspace, --branch, --node, --port, --host, --ticket,
--json, --toml, --cbor, -C, --verbose, --debug, --trace,
--long) are accepted on every tool, so the LLM can override workspace or
branch selection per call without you having to leak that context into a
prompt.
Safety: read-only vs. destructive
Every tool ships with the standard MCP
ToolAnnotations: read-only tools (graph.query,
workspace.info, system.version, the entire *.show / *.list /
*.status / *.get family — 46 tools in total on the current build) carry
readOnlyHint: true, destructiveHint: false, so MCP hosts can auto-approve
them. Mutating tools (graph.upload, graph.update, workspace.delete,
account.wallet.create, anything that installs, deletes, rotates, or
transfers state — 78 tools in total) carry the reverse flags so the host
prompts you before each call.
This means: an LLM can freely read your graph without bothering you, but cannot upload, delete, or trust-host without your explicit OK each time.
Context (workspace, branch, node)
Three environment variables apply to every MCP tool call, same as they do to the shell CLI:
| Variable | Effect |
|---|---|
WWKG_WORKSPACE | Default workspace for any tool that doesn’t take workspace explicitly. |
WWKG_BRANCH | Default branch. |
WWKG_NODE | Default target node. |
Set these in your client’s MCP server env block to scope the LLM to a
specific workspace, or leave them empty and let the LLM pass workspace /
branch / node as tool arguments per call.
{
"mcpServers": {
"wwkg": {
"command": "wwkg",
"args": ["system", "mcp", "serve"],
"env": {
"WWKG_WORKSPACE": "urn:wwkg:workspace:…",
"WWKG_BRANCH": "main"
}
}
}
}Output format
Tools return whatever the CLI’s --json (or --toml / --cbor) output
would produce — structured, machine-parseable data. The LLM works on the same
typed envelope a script does, so it can answer questions like “how many
named graphs does this workspace have?” by parsing graph.query output
directly instead of scraping a human-formatted table.
If you want the human-formatted version instead (e.g. for an LLM that’s
better at reading tables than JSON), pass json: false on the tool call —
the MCP server respects the same output toggles the shell CLI does.
Common patterns
Run a query on a specific branch
graph.query
sparql: "SELECT (COUNT(*) AS ?n) WHERE { ?s ?p ?o }"
workspace: "research"
branch: "experiment-2026-q2"
json: true
Tail the live journal while the LLM watches a long upload
The LLM can call workspace.journal.show repeatedly (every few seconds) and
surface progress events as they arrive — useful for narrating long-running
operations.
Create a branch, run an update, inspect the result
The host will prompt for graph.branch.create and graph.update (both
destructive), then auto-approve graph.query to verify the change. The
entire workflow runs as a structured sequence the LLM can replay if it fails.
Limitations
- One server per process.
wwkg system mcp serveruns until the client closes the stdio stream. Multiple MCP clients can each launch their own instance. - Single-threaded. The MCP server uses a single-threaded async runtime because some CLI paths (notably bulk upload) hold non-thread-safe state across awaits. Long-running tool calls block subsequent calls on the same server until they complete.
- No streaming results yet. Tools return their result as one block when
the underlying CLI command finishes. For large
graph.queryresults this is fine; forgraph.uploadover multi-GB inputs you’ll want to call asynchronously (async: trueongraph.query) and pollworkspace.task.status.
Troubleshooting
The LLM doesn’t see any wwkg tools
You either haven’t registered the server (claude mcp list is empty for
wwkg) or you haven’t restarted the client since registering. MCP tool
catalogs load at client startup, not at runtime.
A tool returns unknown tool: …
The tool name doesn’t match the CLI subcommand path. Tool names use dots,
not spaces or slashes; wwkg graph branch list is graph.branch.list, not
graph branch list or graph/branch/list. Use tools/list from your MCP
client to see the canonical names.
A query times out
CLI queries are bounded by the host’s timeout_at — same as a shell
invocation. For long-running queries, submit asynchronously
(graph.query with async: true) and poll workspace.task.status /
workspace.task.result separately. The MCP host’s per-call timeout is a
separate (usually larger) ceiling on the JSON-RPC round-trip.
See also
- CLI reference — every subcommand the MCP server exposes is documented here.
- Querying — output formats and async submission.
- Workspaces — the workspace / branch / node context the MCP server relies on.