> ## Documentation Index
> Fetch the complete documentation index at: https://www.plungeai.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MCP servers

> An MCP server is an external process (or HTTP endpoint) that contributes tools, resources and prompts to a run. oceancode reads the same server-config files the other tools use, so a server you configured for Claude Code, Cursor or OpenCode is picked up as-is.


An **MCP server** is an external process (or HTTP endpoint) that contributes tools, resources and
prompts to a run. `oceancode` reads the same server-config files the other tools use, so a server
you configured for Claude Code, Cursor or OpenCode is picked up as-is.

## Where servers are configured

Servers are read from several files at once and merged by precedence:

| File | Ecosystem | Shape |
|---|---|---|
| `.mcp.json` | Claude Code (project) | `mcpServers { … }` |
| `~/.claude.json` | Claude Code (user) | `mcpServers { … }` |
| `.cursor/mcp.json` | Cursor (project) | `mcpServers { … }` |
| `opencode.json` (`mcp {}`) | OpenCode | `mcp { … }`, local and remote |
| `<plugin>/.mcp.json` | an installed plugin | `mcpServers { … }` |
| `oceancode.json` (`mcp {}`) | OceanCode | `mcp { … }` — declared servers win over discovered ones of the same name |

**Precedence, highest first: local > project > user > plugin.** A server defined closer to you
overrides a same-named server from a wider scope. Every server from every file is folded into
the one manager at boot, so `/mcp`, `GET /mcp` and `oceancode mcp list` all show the same set —
but a name declared at two tiers runs **once**: the copy that lost its name (qualified
`<tier>:<name>`, say `user:cloudflare-dev` for a `~/.claude.json` copy of the project's
`.mcp.json` server) is folded **held disabled** — listed, never spawned, its tools never offered a
second time under a `user_cloudflare-dev_*` prefix — and `mcp list` reads `shadowed` on it. Only
when the winning copy cannot run (held untrusted or disabled) does the next copy run in its place.
Before 2026-10-13 both copies were started.

## Held until trusted

A server that arrived with a checkout (the project's `.mcp.json`) or with a plugin can run code
on your machine, so it is **listed but held** — status `untrusted` — until you trust it. Nothing is
dialed or spawned for a held server. Three ways to release one, all persisted in
`~/.oceancode/trust.json` under the project's absolute path:

```bash
oceancode trust repo on            # trust the repo tier: its .mcp.json servers and its hooks
oceancode trust mcp <name> on      # trust one server (beats the repo flag); `off` holds it again; `clear` removes the override
oceancode trust show               # repo=<bool>, one `mcp <name>=<bool>` per override, one `disabled <name>` per held-disabled server, then TRUST_OK
```

(the pager's `/mcps` lists a held server as `blocked by policy` but has no trust action). Trust pins what was approved: the first time a trusted
repo or plugin server is seen (or when you trust it), its command (stdio) or URL is recorded as a
hash in `trust.json` (`mcp_hashes`). If the checkout or plugin later changes that command or URL,
the server is held `untrusted` again until you re-approve it with `oceancode trust mcp <name> on`;
`/mcps` shows the reason on its row (`blocked by policy — its command changed since it was approved; …`). Environment and headers are not pinned. Once it runs, each of its calls still passes
the `mcp` permission rules and asks by default
([12 · Permissions](/oceancode/permissions-and-sandbox#mcp-calls--the-mcp-key)).

A server Claude Code has switched off for this
project (`disabledMcpServers` / `disabledMcpjsonServers` in `~/.claude.json`, seeded by
`oceancode plugin import --from claude-code`) is held **disabled** at every tier and reports
`disabled`. User-tier servers (`~/.claude.json`) are trusted by default.

Enabled and trusted are independent: `oceancode mcp disable <name>` (or the pager's `/mcps` tab) switches a
server off — disconnecting it and recording the hold in `trust.json` — without changing its trust,
and `enable` switches it back on; a server that is enabled but still untrusted stays held and
reports `untrusted`, and `connect` refuses to dial it until it is trusted. The engine reads a
`trust.json` change made from the CLI at its next boot; the pager and the HTTP routes apply it
live.

`oceancode mcp enable|disable` is the MCP arm of the one enable interface skills, plugins and MCP
servers share (`skill enable|disable`, `plugin enable|disable`, and `enable-all`/`disable-all` on
each) — see [Enabling and disabling skills](/oceancode/capabilities#enabling-and-disabling-skills). MCP
keeps its own `disabled_mcp` hold model rather than the skills' four-tier fold; the verbs are the
same shape so there is one thing to learn. An explicit enable is remembered per project as
`enabled_mcp` in `~/.oceancode/trust.json` and beats a config entry's `enabled: false`, so a server
your project config ships off can be switched on from the picker or the CLI and stays on.

Any `${VAR}` or `${VAR:-default}` in a server's command, args, env or headers is expanded from
your environment when the server starts; an unresolved `${VAR}` is left literal rather than
blanked, so a misconfigured variable is visible instead of silently empty.

Like hooks, MCP servers execute on your behalf, so they run only from a **trusted** source (see
[09 · Capabilities and plugins](/oceancode/capabilities#enable-is-not-trust)).

## Resources, prompts and elicitation

An MCP server offers more than tools:

- **Resources** — the server's `resources/list` and `resources/read` are surfaced so a server can
  hand documents into a run.
- **Prompts** — each server prompt appears as a slash command named `/mcp__<server>__<prompt>`.
- **Elicitation** — a server that asks the user a question mid-call is routed to the same
  `question` seam the rest of the app uses, so the prompt shows up in your UI and the answer goes
  back to the server.

## Meta-dispatch for large tool sets

When many servers are connected, the flat tool catalog gets unwieldy for the model — and some
providers reject a `tools` array longer than 128. Past 128 connected MCP tools the engine always
replaces the flat catalog with two meta-tools — `search_tool` (find a tool by keyword) and
`use_tool` (invoke one by id). Setting `OC_MCP_META_TOOLS=1` does the same from 64 tools up.
See [02 · Configuration](/oceancode/configuration).

## Managing servers — `oceancode mcp`

```bash
# A stdio server (a local command):
oceancode mcp add <name> --command <cmd> [--arg <a>]... [--env K=V]...

# A remote server (an HTTP endpoint):
oceancode mcp add <name> --url <url> [--header K=V]...

oceancode mcp list             # name  stdio|remote  tier  trusted|untrusted  enabled|disabled|shadowed  source
oceancode mcp enable <name>    # / disable <name>  — switch any server off or on (config-declared or discovered; held disabled in ~/.oceancode/trust.json, honoured at boot)
oceancode mcp remove <name>
oceancode mcp login <name>     # / logout <name>  — OAuth for a server that needs it
oceancode mcp doctor           # probe every server and report reachable / failed (a shadowed copy is not dialed; it reads shadowed)
```

`list` walks every config file above for the current directory (`--dir <d>`, `--home <h>` to
point elsewhere) and shows, per server, its tier, whether it may run and whether it is enabled.

`add` writes a Claude-Code-shaped `.mcp.json`, so the server is immediately visible to any tool
that reads that file. Pass exactly one of `--command` (stdio) or `--url` (remote). `--root <dir>`
and `--home <dir>` override where the config and home are read.

`doctor` gives each server a short connect budget and reports it `reachable` or `failed` quickly,
so one unreachable server does not hang the check.

In Ocean pager, `/mcps` opens the MCP tab of the capabilities picker (add, enable/disable and
trust go through the engine); see [19 · Ocean pager](/oceancode/pager#what-is-wired-to-the-ocean-engine).
A server whose handshake is still in flight reads **`connecting`** (the status list is
`connected` / `connecting` / `needs-auth` / `failed` / `disabled` / `untrusted`); a status read
gives the startup pass at most two seconds and then answers with the live rows (the handshake
itself may take up to 30 s, the `timeout` default). Disconnecting, disabling or untrusting a
server is bounded to about two seconds even when the server process left a child holding its
output pipe open.

A prompt's first model request waits up to `OC_MCP_WAIT_SECONDS` (default 5; `0` never waits;
sub-agents never wait) for the servers configured at boot to finish connecting, so their tools are
already in that request. The tool list is then fixed for the rest of the prompt: a server that
connects, or lists new tools (`tools/list_changed`), while a prompt runs reaches the model on the
next prompt, because a changed tool list at the front of the request would make the provider
re-write its whole prompt cache. Toggling a server, connecting or disconnecting it by hand, trust or
any capability still applies on the very next step.

Over HTTP a client reads `GET /mcp` (each entry carries `trusted`, `enabled`, `provenance` and
`kind` beside `status`), `GET /mcp/{name}/tools`, `GET /mcp/{name}/prompts`,
`GET /mcp/{name}/resources`, and posts `POST /mcp/{name}/trust {"on"}`,
`POST /mcp/{name}/enable {"on"}`, `POST /mcp/{name}/connect|disconnect`, `POST /mcp/{name}/auth`
and `DELETE /mcp/{name}/auth`.

## See also

- [09 · Capabilities and plugins](/oceancode/capabilities) — discovery, tiers, and the trust gate.
- [10 · Hooks](/oceancode/hooks) — the other capability that runs your code.
- [02 · Configuration](/oceancode/configuration) — `OC_MCP_META_TOOLS` and the `mcp` config key.
- [07 · Headless and server](/oceancode/headless-and-server#managing-capabilities-from-the-cli) — `oceancode trust` and `oceancode mcp list`.
