Skip to content

Connect your agent

There is exactly one server to connect: ctx mcp, a plain MCP server over stdio. Every agent gets the same ten tools and five resources. The only thing that differs between agents is which file holds the server entry, and its shape: for Codex the file is global rather than per-project, and VS Code uses its own format.

what ctx writes into .mcp.json / .cursor/mcp.json
{
"mcpServers": {
"contexo": { "command": "ctx", "args": ["mcp"] }
}
}

The server resolves the project from its working directory, which is why a global registration still gives per-project knowledge: run the agent in ~/work/acme-api and it reads ~/work/acme-api/.contexo/. VS Code does not promise that working directory, so its entry passes the project explicitly with --root (below).

Agent MCP config Scope Wired by
Claude Code ./.mcp.json project ctx init — always
Cursor ./.cursor/mcp.json project ctx init — when Cursor is detected
VS Code (agent mode, GitHub Copilot) ./.vscode/mcp.json project ctx init — when VS Code is detected
Codex ~/.codex/config.toml global never automatic — ctx mcp install --tool=codex
Anything else its own file varies you, once — see other clients

Detection is deliberately asymmetric. Cursor counts as installed if ~/.cursor exists or cursor is on your PATH, and VS Code if ~/.vscode exists or code is on your PATH, because wiring either only writes a harmless project-local file. (TERM_PROGRAM is ignored: Cursor’s terminal reports vscode too.) Codex counts only if the codex binary is on your PATH — a bare ~/.codex directory is not enough, since other tools create that directory too, and a false positive there would mean touching a global config.

ctx init
── SETUP
  Wired Claude Code (.mcp.json) — restart your agent to load the contexo server
  Cursor detected — wired .cursor/mcp.json
  VS Code detected — wired .vscode/mcp.json
  .vscode/ is usually committed: teammates need ctx on PATH
  Created .gitignore with .contexo/
  Installed Contexo capture Stop-hook in .claude/settings.json
  Restart Claude Code (or open a new session) so the hook is picked up.
  Installed Cursor capture hooks (.cursor/hooks.json: beforeSubmitPrompt + afterAgentResponse)

✔ Initialized .contexo in ~/projects/acme-api

── AGENT INTEGRATIONS

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

── 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
  VS Code      ./.vscode/mcp.json                   JSON servers   — ctx mcp install --tool=vscode
  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"] }
  VS Code servers entry:   "contexo": { "type": "stdio", "command": "ctx", "args": ["mcp", "--root", "${workspaceFolder}"] }
  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.
try  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.

In one run: the .contexo/ tree, Claude Code’s MCP entry, Cursor’s and VS Code’s MCP entries (both detected here), capture hooks for Claude Code and Cursor, and the .gitignore line. VS Code has no capture hook, hence the - in its row. Codex, when present, gets a one-line nudge rather than a config write. .vscode/ is usually committed, so ctx init reminds you that teammates who open the project need ctx on their PATH.

Each piece has an opt-out:

FlagTypeDefaultDescription
--no-cursorboolfalseskip auto-wiring Cursor (.cursor/mcp.json) even when Cursor is detected
--no-gitignoreboolfalseskip adding .contexo/ to .gitignore
--no-hooksboolfalseskip registering the Claude Code Stop hook for per-turn capture
--no-mcpboolfalseskip wiring the MCP server into agent configs (.mcp.json, .cursor/mcp.json, .vscode/mcp.json)
--no-vscodeboolfalseskip auto-wiring VS Code (.vscode/mcp.json) even when VS Code is detected

ctx init merges rather than replaces — it preserves every other key in .mcp.json and every other server under mcpServers, and re-running when the entry is already there prints “already has the contexo entry” and changes nothing.

Terminal window
ctx mcp install --tool=claude # ./.mcp.json
ctx mcp install --tool=cursor # ./.cursor/mcp.json
ctx mcp install --tool=vscode # ./.vscode/mcp.json
ctx mcp install --tool=codex # ~/.codex/config.toml — global
ctx mcp install # = --tool=all

--tool=all wires the project-local agents (Claude Code, Cursor), adds VS Code when it is detected, and Codex only when the CLI is actually installed. All of these require an initialized project: outside one, ctx mcp install errors with “not a Contexo project (run ‘ctx init’ first)”.

VS Code’s agent mode reads workspace MCP servers from ./.vscode/mcp.json, in a format of its own: the top-level key is servers (not mcpServers) and each entry has a type. ctx init (when VS Code is detected) and ctx mcp install --tool=vscode add this entry and keep every other server and key in the file:

.vscode/mcp.json
{
"servers": {
"contexo": {
"type": "stdio",
"command": "ctx",
"args": ["mcp", "--root", "${workspaceFolder}"]
}
}
}

VS Code replaces ${workspaceFolder} with the folder you opened, so the server always serves that project’s .contexo/. To skip this wiring, run ctx init --no-vscode (--no-mcp skips every MCP entry).

VS Code allows comments and trailing commas in that file. ctx never rewrites a .vscode/mcp.json that is not strict JSON, so it cannot drop your comments: it leaves the file alone, warns, and prints the entry above for you to add by hand.

This wires the agent’s MCP tools. The separate Contexo extension adds the knowledge base to VS Code’s Source Control view.

Codex owns its TOML, so Contexo never edits ~/.codex/config.toml directly — it shells out to codex mcp add contexo -- ctx mcp (and codex mcp remove / codex mcp get for uninstall and status). Because the result is global, the command asks “Wire Contexo into Codex’s GLOBAL config (~/.codex/config.toml)?” and does nothing unless you answer yes.

Pass --yes to skip the prompt in a script. After it lands, every Codex session on your machine launches ctx mcp — and each one operates on whatever project it was started in. Started somewhere with no .contexo/, ctx mcp serves a dormant server that advertises zero tools and zero resources rather than failing, so the global entry costs nothing in unrelated repos.

Add the same stdio server to whatever config your client uses:

Windsurf — ~/.codeium/windsurf/mcp_config.json
{ "mcpServers": { "contexo": { "command": "ctx", "args": ["mcp"] } } }
OpenCode — ./opencode.json
{ "mcp": { "contexo": { "type": "local", "command": ["ctx", "mcp"] } } }
Codex — ~/.codex/config.toml (written for you by codex mcp add)
[mcp_servers.contexo]
command = "ctx"
args = ["mcp"]

ctx mcp guide prints this list from the binary you actually have installed, including a few more harnesses — worth running instead of trusting a docs page that could age.

Wiring MCP gives the agent the tools. Capture hooks are what give ctx_push something to distil: they append each turn to a local buffer under .contexo/raw/sessions/_pending/. No LLM call, no upload.

Agent Hook file Events Command
Claude Code .claude/settings.json Stop ctx capture turn
Codex .codex/hooks.json UserPromptSubmit + Stop ctx capture turn --agent codex
Cursor .cursor/hooks.json beforeSubmitPrompt + afterAgentResponse ctx capture turn --agent cursor

All three files are project-local, so ctx init installs Claude’s hook always and the other two whenever those agents are detected. Claude’s hook reads the session transcript; Codex and Cursor need two hooks each because they pair the prompt they saw on the way in with the response text on the way out, which avoids parsing a transcript at all.

Manage them separately from MCP wiring:

Terminal window
ctx hooks install --tool=claude|codex|cursor|all
ctx hooks uninstall --tool=…
ctx hooks status
ctx hooks status
── CAPTURE HOOKS

     AGENT   CAPTURE HOOK   CONFIG
  ●  claude  installed      .claude/settings.json
  ○  codex   not installed  .codex/hooks.json
  ●  cursor  installed      .cursor/hooks.json

Contexo tags its Claude hook entry with an internal marker, so install is idempotent and uninstall removes only Contexo’s hook and leaves yours alone. The hook command exits 0 when the project isn’t a Contexo project, and setting CONTEXO_CAPTURE_DISABLE=1 turns capture off without unwiring anything.

ctx mcp status
── AGENT INTEGRATIONS

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

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

That’s the local view. For the end-to-end check, restart your agent and ask it to call ctx_status — if it answers with your repo, page count and last-pull sha, the server is loaded and talking to the right project.

Terminal window
ctx mcp uninstall --tool=claude|cursor|vscode|codex|all
ctx hooks uninstall --tool=claude|codex|cursor|all

ctx mcp uninstall removes only the contexo entry. If that empties mcpServers (or servers in .vscode/mcp.json) and it was the file’s only key, the file is deleted instead of left behind as a husk; any other server or key you had is preserved, and the .vscode/ folder itself is never removed. To undo everything ctx init did in one step — MCP entries, hooks, the .gitignore line — use ctx detach, which lists what it will do and waits for a yes. It deletes .contexo/ too unless you pass --keep-knowledge.