# Tool MCP Servers

Codex MMO distinguishes two unrelated uses of MCP:

- **Agent MCP** is the internal `mmo_mesh` server that launches and supervises profile
  participants.
- **Tool MCP** connects Codex agents to third-party tools and context, such as a web-research
  service or a reverse-engineering application.

`mmo_mesh` is runtime-owned and reserved. Tool MCP definitions use operator-owned registry files;
profile packs contain grants only. This keeps installed profile packs static and prevents one from
introducing a local executable or remote endpoint.

Codex MMO compiles tool definitions to Codex's documented `[mcp_servers.NAME]` configuration.
Codex 0.149 supports local STDIO processes and Streamable HTTP endpoints, environment-backed
authentication, tool allow/deny lists, startup/tool timeouts, and server/tool approval policy. See
the official [Codex MCP documentation](https://developers.openai.com/codex/mcp) and
[configuration reference](https://developers.openai.com/codex/config-reference).

## Operator registry

Place registry fragments under:

```text
~/.config/codex-mmo/tool-mcp.d/*.toml
```

Fragments load in lexical filename order. When multiple fragments define the same server ID, the
later definition replaces the complete earlier entry. Fields are not recursively retained across a
transport change.

This example is illustrative; use the command, URL, and exact tool names documented by the MCP
server you install:

```toml
schema_version = 8

[tool_mcp_servers.firecrawl]
transport = "streamable_http"
url = "https://mcp.example.invalid/"
bearer_token_env_var = "FIRECRAWL_API_KEY"
enabled_tools = ["search", "scrape"]
default_tools_approval_mode = "writes"
startup_timeout_sec = 15
tool_timeout_sec = 120

[tool_mcp_servers.firecrawl.tools.scrape]
approval_mode = "prompt"

[tool_mcp_servers.ida_pro]
transport = "stdio"
command = "ida-pro-mcp"
args = []
env_vars = ["IDA_MCP_TOKEN"]
enabled_tools = ["list_functions", "decompile"]
default_tools_approval_mode = "writes"
```

Every definition requires:

- A stable lowercase server ID other than `mmo_mesh`.
- `transport = "stdio"` plus `command`, or `transport = "streamable_http"` plus `url`.
- A non-empty `enabled_tools` array. This is the operator's maximum exposure, including for future
  profile grants.
- An explicit `default_tools_approval_mode`: `auto`, `prompt`, `writes`, or `approve`.

The STDIO `command` may be a bare executable resolved through `PATH` or an
absolute/tilde-expanded path. STDIO definitions may also use `args`, absolute/tilde-expanded `cwd`,
non-secret literal `env`, and environment-forwarded `env_vars`. HTTP definitions may use
`bearer_token_env_var`, non-secret `http_headers`, and environment-backed `env_http_headers`. Both transports accept
`startup_timeout_sec`, `tool_timeout_sec`, `supports_parallel_tool_calls`, and per-tool approval
overrides under `tools`.

The private app-server lifecycle wait is automatically at least 30 seconds longer than the
largest enabled `startup_timeout_sec` for that role, and never less than twenty minutes. A valid long
MCP startup therefore is not cut off by an unrelated fixed thread-start timeout. The separate
`tool_timeout_sec` continues to bound each Tool MCP call; it is not a model-turn deadline.
The generated `mmo_mesh` timeout is independently derived from the largest app-server lifecycle
reachable through that caller's exact spawn/control grants, plus protocol overhead.

Schema version 8 rejects OAuth fields, plaintext bearer tokens, recognizable credential-bearing
literal environment/header fields, transport-incompatible fields, and unknown fields. OAuth is not
copied from the base Codex home because `.credentials.json` can contain credentials for unrelated
MCP servers.

## Credentials

Put values in the existing operator credential file or the launch environment:

```bash
${EDITOR:-vi} ~/.config/codex-mmo/credentials.env
```

```dotenv
FIRECRAWL_API_KEY=replace-me
IDA_MCP_TOKEN=replace-me
```

Snapshots and generated TOML contain only environment variable names. At session launch, the
runtime forwards only names referenced by a server selected for that Codex process. Missing values
are reported by `tool-mcp validate` and `profile doctor`; a profile's `required` policy determines
whether Codex treats server startup failure as fatal.

## Profile grants

Grant servers independently to each role:

```toml
[agents.researcher.tool_mcp_servers.firecrawl]
required = true
enabled_tools = ["search"]

[agents.reverse_engineer.tool_mcp_servers.ida_pro]
required = true
```

`required` defaults to `true`. Omitting `enabled_tools` grants the complete operator allowlist;
otherwise it must be a non-empty subset. A profile cannot change the command, URL, credentials,
headers, timeouts, parallel-call declaration, or approval policy. Omitting a server grant disables
that server for the role.

The compiler stores normalized definitions and grants in the immutable snapshot. Changing a
registry definition therefore changes future snapshot identity without changing a running session.

## Native-role behavior

Native roles share their parent's Codex process, and Codex recursively merges custom-agent config
layers. The generated root config consequently contains the union of servers used by the root and
reachable native roles. Each role layer explicitly enables its grants and disables every other
server. The operator `enabled_tools` list remains constant, while role-specific narrowing is emitted
as `disabled_tools`; this lets a child clear a narrower inherited deny-list without exceeding the
operator maximum.

Tool visibility remains role-scoped, but process environment variables do not. If a native role
uses an environment-authenticated MCP, its parent and sibling native agents share the containing
process environment. Use a separately launched Agent-MCP participant when strict credential
isolation is required.

## Security boundary

Codex shell settings do not constrain an external MCP server:

- `permissions = "read-only"` controls the Codex filesystem sandbox, not whether an MCP tool can
  mutate an IDA database, browser, SaaS account, or other external state.
- `network_access = false` controls sandboxed shell networking, not an HTTP MCP connection or a
  local MCP process's own networking.
- MCP server instructions and tool results are external content and may carry prompt injection.

Use narrow operator allowlists, conservative approval modes, per-tool `prompt` overrides for
mutating operations, role-specific grants, and independent verification of consequential results.

## Inspection and diagnostics

These commands validate configuration without launching an MCP server:

```bash
codex-mmo tool-mcp list
codex-mmo tool-mcp show firecrawl
codex-mmo tool-mcp validate
codex-mmo tool-mcp validate firecrawl
codex-mmo profile show PROFILE --resolved
codex-mmo profile doctor PROFILE
```

Readiness checks report command resolution, working-directory availability, and whether referenced
environment variables are present. They never print credential values. Actual protocol/tool
behavior remains a live acceptance concern; exercise it through a profile smoke task after reviewing
the server and its tool schema.
