Skip to content

ctx mcp

ctx mcp is Contexo’s MCP server: with no subcommand it speaks JSON-RPC over stdio and hands the calling agent this project’s knowledge base. Its subcommands write that same server into each agent’s own config file.

You rarely type the bare command — the agent spawns it. You reach for the subcommands when an agent showed up after ctx init ran, when you want Codex wired (the one agent Contexo never wires silently, because its MCP config is global), or when the agent lists a contexo server with no tools and you need to know whether the problem is the wiring or the directory it was launched in. Two things trip people up. Agents read their MCP config at startup, so every wiring change needs an agent restart before it means anything. And the entry Contexo writes is literally {"command": "ctx", "args": ["mcp"]} — so ctx has to be on the PATH the agent sees, which on macOS GUI apps is often not the PATH your shell sees.

Terminal window
ctx mcp # run the server over stdio (agents invoke this)
ctx mcp install [--tool=…] # wire it into an agent's config
ctx mcp uninstall [--tool=…] # remove that wiring
ctx mcp status # what's wired for this project
ctx mcp guide # config recipes for every other harness

ctx mcp takes no flags.

Inherited from the root command:

FlagTypeDefaultDescription
--rootstringproject root directory (default: current directory)

--root is more load-bearing here than on other commands. The bare server resolves its project exactly once, at startup, from --root or the process’s working directory — and never re-checks. Agents launch ctx mcp with the project as the working directory, so you normally don’t need it; a harness that spawns MCP servers from a fixed directory does.

Bare ctx mcp opens the page store at <root>/.contexo, then reads newline-delimited JSON-RPC 2.0 from stdin and writes exactly one JSON response line to stdout per request (input lines up to 10 MB). It handles initialize, tools/list, tools/call, resources/list and resources/read; every other method returns -32601 method not found. It reports protocol version 2024-11-05 and serverInfo.name = "contexo", and it stores the clientInfo.name you send in initialize, which is how a pull gets attributed to the agent that made it.

All 10 tools and 5 resources are served from that one process — there is no daemon and no port. Most of the work is local disk; ctx_push, ctx_pull, ctx_history, ctx_diff and ctx_evolution call the Contexo server, and reads of ctx://wiki/{slug} fire a best-effort drift check against it (cached for 60s, silently skipped when offline).

If <root>/.contexo does not exist, the server does not fail. It runs dormant: initialize succeeds, tools/list and resources/list return empty arrays, and everything else answers -32601 method not available (no .contexo project in this directory).

That exists because of Codex. Codex’s MCP config is global, so a single ~/.codex/config.toml entry launches ctx mcp in every directory you open Codex in. A server that exited non-zero in unrelated repos would surface as a broken integration on every launch; a server with zero tools is honest and quiet. The practical consequence: if an agent shows contexo connected but with no tools, you are outside a Contexo project (or the agent’s working directory isn’t the project root). Run ctx init, then restart the agent.

Message Cause and fix
mcp: open store: … (did you run 'ctx init'?) .contexo exists but can’t be opened as a directory — usually a stray .contexo file, or a permissions problem. A merely missing .contexo goes dormant instead of erroring.
mcp install: not a Contexo project (run 'ctx init' first) ctx mcp install refuses to wire an agent to a project that doesn’t exist yet. uninstall, status and guide have no such check.
unknown --tool "x" (want claude, cursor, codex, or all) Typo in --tool. Accepted values are exactly claude, cursor, codex, all (and empty, which means all).

Writes the contexo MCP server into an agent’s config.

Terminal window
ctx mcp install # claude + cursor, plus codex if it's on PATH
ctx mcp install --tool=claude # ./.mcp.json
ctx mcp install --tool=cursor # ./.cursor/mcp.json
ctx mcp install --tool=codex -y # ~/.codex/config.toml, no prompt
FlagTypeDefaultDescription
--toolstringallagent to wire: claude|cursor|codex|all
--yes, -yboolfalseskip confirmation prompts (e.g. Codex's global config)

Each agent reads MCP servers from a different place, and only one of them is global:

Agent Config it reads Scope How Contexo writes it
Claude Code ./.mcp.json project merges the JSON itself
Cursor ./.cursor/mcp.json project merges the JSON itself
Codex ~/.codex/config.toml global shells out to codex mcp add contexo -- ctx mcp

Contexo never parses Codex’s TOML — that file’s format is Codex’s business, so wiring and unwiring both go through the codex CLI. That is also why Codex is the only agent this command probes for: wiring it means running codex mcp add, so the binary has to be on PATH. Claude and Cursor get no detection at all — each is just a project-local JSON file, harmless to write for an agent you don’t run.

--tool=all (the default) wires Claude and Cursor unconditionally and adds Codex only when that binary is present — an absent Codex is skipped silently. Ask for it explicitly and a missing binary is an error instead: mcp install codex: Codex CLI not found (`codex` not on PATH).

The JSON merge is idempotent and preserves every other key in the file — but it is not a “leave what’s there” merge: if the existing contexo entry differs in any way from {"command": "ctx", "args": ["mcp"]}, it is replaced. Custom tweaks (an absolute path to ctx, an env block) are silently reverted by the next ctx mcp install or ctx init. An entry that already matches is left untouched and reported as already wired.

ctx mcp install --help
Adds Contexo's MCP server so an agent's tools (ctx_push/pull/write_page,
history/diff, etc.) become available:

  claude  -> ./.mcp.json            (project-local)
  cursor  -> ./.cursor/mcp.json     (project-local)
  codex   -> ~/.codex/config.toml   (GLOBAL — prompts unless --yes)

--tool=all wires the project-local agents (claude, cursor) and also codex
when it is installed.

Usage:
  ctx mcp install [flags]

Flags:
  -h, --help          help for install
      --tool string   agent to wire: claude|cursor|codex|all (default "all")
  -y, --yes           skip confirmation prompts (e.g. Codex's global config)

Global Flags:
      --root string   project root directory (default: current directory)

Removes the contexo entry from an agent’s config.

Terminal window
ctx mcp uninstall # all three
ctx mcp uninstall --tool=cursor # just ./.cursor/mcp.json
FlagTypeDefaultDescription
--toolstringallagent to unwire: claude|cursor|codex|all

Unlike install, this does not require a Contexo project — you can unwire a directory whose .contexo/ is already gone. For Claude and Cursor it deletes just the contexo key; if that leaves mcpServers empty and mcpServers was the only top-level key, the file is deleted rather than left as an empty husk. Any other key in the file (another MCP server, an unrelated setting) keeps the file alive. For Codex it runs codex mcp remove contexo, but only after checking codex mcp get contexo — a Codex that isn’t installed, or isn’t wired, prints nothing to do. instead.

To undo the whole ctx init — MCP entries, capture hooks, the .gitignore line and the knowledge directory — use ctx detach instead of running these one at a time.

One table showing, per agent, whether the MCP server and the capture hook are wired for this project.

Terminal window
ctx mcp status

ctx mcp status takes no flags.

ctx mcp status
Agent integrations for this project:

  AGENT        MCP SERVER                CAPTURE (STOP HOOK)
  Claude Code  wired (.mcp.json)         installed
  Cursor       wired (.cursor/mcp.json)  installed
  Codex        not installed             not installed

Add another agent (Windsurf, OpenCode, Hermes, ...)? Run `ctx mcp guide`.

Every cell is computed live from a different source, which is worth knowing when a row looks wrong:

  • Claude Code / Cursor MCP — reads ./.mcp.json and ./.cursor/mcp.json and checks for an mcpServers.contexo key.
  • Codex MCPnot installed means the codex binary isn’t on PATH; otherwise it shells out to codex mcp get contexo and reports wired (~/.codex, global) or not wired (~/.codex, global).
  • Capture — reads three different files: .claude/settings.json, .codex/hooks.json, .cursor/hooks.json. See ctx hooks.

ctx mcp status reports what is on disk now, not what the running agent loaded. A row that says wired while the agent still shows no contexo server means the agent hasn’t been restarted since the wiring changed.

Prints config recipes for agents Contexo doesn’t wire directly.

Terminal window
ctx mcp guide

ctx mcp guide takes no flags.

ctx mcp guide
Add Contexo to another agent or harness
---------------------------------------
Contexo's MCP server is a standard stdio server:  command "ctx", args ["mcp"].
Add that to the agent's own MCP config — same server everywhere; only the
file and format differ:

  AGENT        CONFIG                               FORMAT / HOW
  Claude Code  ./.mcp.json                          JSON mcpServers   — ctx mcp install --tool=claude
  Cursor       ./.cursor/mcp.json                   JSON mcpServers   — ctx mcp install --tool=cursor
  Codex        ~/.codex/config.toml                 TOML [mcp_servers.contexo]   — ctx mcp install --tool=codex
  Windsurf     ~/.codeium/windsurf/mcp_config.json  JSON mcpServers
  OpenCode     ./opencode.json                      JSON  mcp: { contexo: { type: "local", command: ["ctx","mcp"] } }
  Hermes       config.yaml                          YAML  mcp_servers: { contexo: { command: ctx, args: [mcp] } }
  OpenClaw     (CLI-managed)                        run the `openclaw mcp` command

  JSON mcpServers entry:   "contexo": { "command": "ctx", "args": ["mcp"] }
  Any other MCP client: add the same server; see its docs for the exact path.

Capture (the Stop hook): Claude Code, Codex, and Cursor are supported —
  ctx hooks install --tool=claude|codex|cursor|all
Claude parses its transcript; Codex and Cursor pair their prompt + response
hooks inline. Other MCP-capable harnesses get the tools now; capture as they
expose a stop/turn-end hook.

This is static text — it needs no project and makes no network call, so it works anywhere. The same guide is printed at the end of ctx init; ctx mcp status only points at it. Every row is the same server (command: "ctx", args: ["mcp"]); only the file and the surrounding syntax change, which is why “add Contexo to my agent” is a config question and never a build question.

  • ctx init — creates .contexo/ and does this wiring for you
  • ctx hooks — the other half of agent integration: per-turn capture
  • ctx detach — remove every wire ctx init added
  • MCP reference — the tools this server exposes