2025-10-06 08:43:50 -07:00
# Codex MCP Server Interface [experimental]
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
This document describes Codex's experimental MCP server interface: a JSON-RPC API that runs over the Model Context Protocol (MCP) transport to control a local Codex engine.
2025-09-14 21:30:56 -07:00
- Status: experimental and subject to change without notice
fix: separate `codex mcp` into `codex mcp-server` and `codex app-server` (#4471)
This is a very large PR with some non-backwards-compatible changes.
Historically, `codex mcp` (or `codex mcp serve`) started a JSON-RPC-ish
server that had two overlapping responsibilities:
- Running an MCP server, providing some basic tool calls.
- Running the app server used to power experiences such as the VS Code
extension.
This PR aims to separate these into distinct concepts:
- `codex mcp-server` for the MCP server
- `codex app-server` for the "application server"
Note `codex mcp` still exists because it already has its own subcommands
for MCP management (`list`, `add`, etc.)
The MCP logic continues to live in `codex-rs/mcp-server` whereas the
refactored app server logic is in the new `codex-rs/app-server` folder.
Note that most of the existing integration tests in
`codex-rs/mcp-server/tests/suite` were actually for the app server, so
all the tests have been moved with the exception of
`codex-rs/mcp-server/tests/suite/mod.rs`.
Because this is already a large diff, I tried not to change more than I
had to, so `codex-rs/app-server/tests/common/mcp_process.rs` still uses
the name `McpProcess` for now, but I will do some mechanical renamings
to things like `AppServer` in subsequent PRs.
While `mcp-server` and `app-server` share some overlapping functionality
(like reading streams of JSONL and dispatching based on message types)
and some differences (completely different message types), I ended up
doing a bit of copypasta between the two crates, as both have somewhat
similar `message_processor.rs` and `outgoing_message.rs` files for now,
though I expect them to diverge more in the near future.
One material change is that of the initialize handshake for `codex
app-server`, as we no longer use the MCP types for that handshake.
Instead, we update `codex-rs/protocol/src/mcp_protocol.rs` to add an
`Initialize` variant to `ClientRequest`, which takes the `ClientInfo`
object we need to update the `USER_AGENT_SUFFIX` in
`codex-rs/app-server/src/message_processor.rs`.
One other material change is in
`codex-rs/app-server/src/codex_message_processor.rs` where I eliminated
a use of the `send_event_as_notification()` method I am generally trying
to deprecate (because it blindly maps an `EventMsg` into a
`JSONNotification`) in favor of `send_server_notification()`, which
takes a `ServerNotification`, as that is intended to be a custom enum of
all notification types supported by the app server. So to make this
update, I had to introduce a new variant of `ServerNotification`,
`SessionConfigured`, which is a non-backwards compatible change with the
old `codex mcp`, and clients will have to be updated after the next
release that contains this PR. Note that
`codex-rs/app-server/tests/suite/list_resume.rs` also had to be update
to reflect this change.
I introduced `codex-rs/utils/json-to-toml/src/lib.rs` as a small utility
crate to avoid some of the copying between `mcp-server` and
`app-server`.
2025-09-30 00:06:18 -07:00
- Server binary: `codex mcp-server` (or `codex-mcp-server` )
2026-03-03 13:18:25 -08:00
- Transport: standard MCP over stdio (JSON-RPC 2.0, line-delimited)
2025-09-14 21:30:56 -07:00
## Overview
2026-03-03 13:18:25 -08:00
Codex exposes MCP-compatible methods to manage threads, turns, accounts, config, and approvals. The types live in `app-server-protocol/src/protocol/{common,v1,v2}.rs` and are consumed by the app server implementation in `app-server/` .
2025-09-14 21:30:56 -07:00
At a glance:
2026-03-03 13:18:25 -08:00
- Primary v2 RPCs
- `thread/start` , `thread/resume` , `thread/fork` , `thread/read` , `thread/list`
- `turn/start` , `turn/steer` , `turn/interrupt`
2025-11-07 08:17:19 -08:00
- `account/read` , `account/login/start` , `account/login/cancel` , `account/logout` , `account/rateLimits/read`
2026-03-03 13:18:25 -08:00
- `config/read` , `config/value/write` , `config/batchWrite`
- `model/list` , `app/list` , `collaborationMode/list`
- Remaining v1 compatibility RPCs
- `getConversationSummary`
- `getAuthStatus`
- `gitDiffToRemote`
- `fuzzyFileSearch` , `fuzzyFileSearch/sessionStart` , `fuzzyFileSearch/sessionUpdate` , `fuzzyFileSearch/sessionStop`
- Notifications
- v2 typed notifications such as `thread/started` , `turn/completed` , `account/login/completed`
- `codex/event/*` stream notifications for live agent events
- `fuzzyFileSearch/sessionUpdated` , `fuzzyFileSearch/sessionCompleted`
- Approvals (server -> client requests)
2025-09-14 21:30:56 -07:00
- `applyPatchApproval` , `execCommandApproval`
2026-03-03 13:18:25 -08:00
See code for full type definitions and exact shapes: `app-server-protocol/src/protocol/{common,v1,v2}.rs` .
2025-09-14 21:30:56 -07:00
## Starting the server
Run Codex as an MCP server and connect an MCP client:
```bash
fix: separate `codex mcp` into `codex mcp-server` and `codex app-server` (#4471)
This is a very large PR with some non-backwards-compatible changes.
Historically, `codex mcp` (or `codex mcp serve`) started a JSON-RPC-ish
server that had two overlapping responsibilities:
- Running an MCP server, providing some basic tool calls.
- Running the app server used to power experiences such as the VS Code
extension.
This PR aims to separate these into distinct concepts:
- `codex mcp-server` for the MCP server
- `codex app-server` for the "application server"
Note `codex mcp` still exists because it already has its own subcommands
for MCP management (`list`, `add`, etc.)
The MCP logic continues to live in `codex-rs/mcp-server` whereas the
refactored app server logic is in the new `codex-rs/app-server` folder.
Note that most of the existing integration tests in
`codex-rs/mcp-server/tests/suite` were actually for the app server, so
all the tests have been moved with the exception of
`codex-rs/mcp-server/tests/suite/mod.rs`.
Because this is already a large diff, I tried not to change more than I
had to, so `codex-rs/app-server/tests/common/mcp_process.rs` still uses
the name `McpProcess` for now, but I will do some mechanical renamings
to things like `AppServer` in subsequent PRs.
While `mcp-server` and `app-server` share some overlapping functionality
(like reading streams of JSONL and dispatching based on message types)
and some differences (completely different message types), I ended up
doing a bit of copypasta between the two crates, as both have somewhat
similar `message_processor.rs` and `outgoing_message.rs` files for now,
though I expect them to diverge more in the near future.
One material change is that of the initialize handshake for `codex
app-server`, as we no longer use the MCP types for that handshake.
Instead, we update `codex-rs/protocol/src/mcp_protocol.rs` to add an
`Initialize` variant to `ClientRequest`, which takes the `ClientInfo`
object we need to update the `USER_AGENT_SUFFIX` in
`codex-rs/app-server/src/message_processor.rs`.
One other material change is in
`codex-rs/app-server/src/codex_message_processor.rs` where I eliminated
a use of the `send_event_as_notification()` method I am generally trying
to deprecate (because it blindly maps an `EventMsg` into a
`JSONNotification`) in favor of `send_server_notification()`, which
takes a `ServerNotification`, as that is intended to be a custom enum of
all notification types supported by the app server. So to make this
update, I had to introduce a new variant of `ServerNotification`,
`SessionConfigured`, which is a non-backwards compatible change with the
old `codex mcp`, and clients will have to be updated after the next
release that contains this PR. Note that
`codex-rs/app-server/tests/suite/list_resume.rs` also had to be update
to reflect this change.
I introduced `codex-rs/utils/json-to-toml/src/lib.rs` as a small utility
crate to avoid some of the copying between `mcp-server` and
`app-server`.
2025-09-30 00:06:18 -07:00
codex mcp-server | your_mcp_client
2025-09-14 21:30:56 -07:00
```
For a simple inspection UI, you can also try:
```bash
fix: separate `codex mcp` into `codex mcp-server` and `codex app-server` (#4471)
This is a very large PR with some non-backwards-compatible changes.
Historically, `codex mcp` (or `codex mcp serve`) started a JSON-RPC-ish
server that had two overlapping responsibilities:
- Running an MCP server, providing some basic tool calls.
- Running the app server used to power experiences such as the VS Code
extension.
This PR aims to separate these into distinct concepts:
- `codex mcp-server` for the MCP server
- `codex app-server` for the "application server"
Note `codex mcp` still exists because it already has its own subcommands
for MCP management (`list`, `add`, etc.)
The MCP logic continues to live in `codex-rs/mcp-server` whereas the
refactored app server logic is in the new `codex-rs/app-server` folder.
Note that most of the existing integration tests in
`codex-rs/mcp-server/tests/suite` were actually for the app server, so
all the tests have been moved with the exception of
`codex-rs/mcp-server/tests/suite/mod.rs`.
Because this is already a large diff, I tried not to change more than I
had to, so `codex-rs/app-server/tests/common/mcp_process.rs` still uses
the name `McpProcess` for now, but I will do some mechanical renamings
to things like `AppServer` in subsequent PRs.
While `mcp-server` and `app-server` share some overlapping functionality
(like reading streams of JSONL and dispatching based on message types)
and some differences (completely different message types), I ended up
doing a bit of copypasta between the two crates, as both have somewhat
similar `message_processor.rs` and `outgoing_message.rs` files for now,
though I expect them to diverge more in the near future.
One material change is that of the initialize handshake for `codex
app-server`, as we no longer use the MCP types for that handshake.
Instead, we update `codex-rs/protocol/src/mcp_protocol.rs` to add an
`Initialize` variant to `ClientRequest`, which takes the `ClientInfo`
object we need to update the `USER_AGENT_SUFFIX` in
`codex-rs/app-server/src/message_processor.rs`.
One other material change is in
`codex-rs/app-server/src/codex_message_processor.rs` where I eliminated
a use of the `send_event_as_notification()` method I am generally trying
to deprecate (because it blindly maps an `EventMsg` into a
`JSONNotification`) in favor of `send_server_notification()`, which
takes a `ServerNotification`, as that is intended to be a custom enum of
all notification types supported by the app server. So to make this
update, I had to introduce a new variant of `ServerNotification`,
`SessionConfigured`, which is a non-backwards compatible change with the
old `codex mcp`, and clients will have to be updated after the next
release that contains this PR. Note that
`codex-rs/app-server/tests/suite/list_resume.rs` also had to be update
to reflect this change.
I introduced `codex-rs/utils/json-to-toml/src/lib.rs` as a small utility
crate to avoid some of the copying between `mcp-server` and
`app-server`.
2025-09-30 00:06:18 -07:00
npx @modelcontextprotocol/inspector codex mcp-server
2025-09-14 21:30:56 -07:00
```
fix: separate `codex mcp` into `codex mcp-server` and `codex app-server` (#4471)
This is a very large PR with some non-backwards-compatible changes.
Historically, `codex mcp` (or `codex mcp serve`) started a JSON-RPC-ish
server that had two overlapping responsibilities:
- Running an MCP server, providing some basic tool calls.
- Running the app server used to power experiences such as the VS Code
extension.
This PR aims to separate these into distinct concepts:
- `codex mcp-server` for the MCP server
- `codex app-server` for the "application server"
Note `codex mcp` still exists because it already has its own subcommands
for MCP management (`list`, `add`, etc.)
The MCP logic continues to live in `codex-rs/mcp-server` whereas the
refactored app server logic is in the new `codex-rs/app-server` folder.
Note that most of the existing integration tests in
`codex-rs/mcp-server/tests/suite` were actually for the app server, so
all the tests have been moved with the exception of
`codex-rs/mcp-server/tests/suite/mod.rs`.
Because this is already a large diff, I tried not to change more than I
had to, so `codex-rs/app-server/tests/common/mcp_process.rs` still uses
the name `McpProcess` for now, but I will do some mechanical renamings
to things like `AppServer` in subsequent PRs.
While `mcp-server` and `app-server` share some overlapping functionality
(like reading streams of JSONL and dispatching based on message types)
and some differences (completely different message types), I ended up
doing a bit of copypasta between the two crates, as both have somewhat
similar `message_processor.rs` and `outgoing_message.rs` files for now,
though I expect them to diverge more in the near future.
One material change is that of the initialize handshake for `codex
app-server`, as we no longer use the MCP types for that handshake.
Instead, we update `codex-rs/protocol/src/mcp_protocol.rs` to add an
`Initialize` variant to `ClientRequest`, which takes the `ClientInfo`
object we need to update the `USER_AGENT_SUFFIX` in
`codex-rs/app-server/src/message_processor.rs`.
One other material change is in
`codex-rs/app-server/src/codex_message_processor.rs` where I eliminated
a use of the `send_event_as_notification()` method I am generally trying
to deprecate (because it blindly maps an `EventMsg` into a
`JSONNotification`) in favor of `send_server_notification()`, which
takes a `ServerNotification`, as that is intended to be a custom enum of
all notification types supported by the app server. So to make this
update, I had to introduce a new variant of `ServerNotification`,
`SessionConfigured`, which is a non-backwards compatible change with the
old `codex mcp`, and clients will have to be updated after the next
release that contains this PR. Note that
`codex-rs/app-server/tests/suite/list_resume.rs` also had to be update
to reflect this change.
I introduced `codex-rs/utils/json-to-toml/src/lib.rs` as a small utility
crate to avoid some of the copying between `mcp-server` and
`app-server`.
2025-09-30 00:06:18 -07:00
Use the separate `codex mcp` subcommand to manage configured MCP server launchers in `config.toml` .
2026-03-03 13:18:25 -08:00
## Threads and turns
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
Use the v2 thread and turn APIs for all new integrations. `thread/start` creates a thread, `turn/start` submits user input, `turn/interrupt` stops an in-flight turn, and `thread/list` / `thread/read` expose persisted history.
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
`getConversationSummary` remains as a compatibility helper for clients that still need a summary lookup by `conversationId` or `rolloutPath` .
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
For complete request and response shapes, see the app-server README and the protocol definitions in `app-server-protocol/src/protocol/v2.rs` .
2026-01-26 11:24:36 -08:00
2025-10-21 11:15:17 -07:00
## Models
Fetch the catalog of models available in the current Codex build with `model/list` . The request accepts optional pagination inputs:
2026-03-03 13:18:25 -08:00
- `limit` - number of models to return (defaults to a server-selected value)
- `cursor` - opaque string from the previous response's `nextCursor`
2025-10-21 11:15:17 -07:00
Each response yields:
2026-03-03 13:18:25 -08:00
- `data` - ordered list of models. A model includes:
2025-10-21 11:15:17 -07:00
- `id` , `model` , `displayName` , `description`
2026-03-03 13:18:25 -08:00
- `supportedReasoningEfforts` - array of objects with:
- `reasoningEffort` - one of `none|minimal|low|medium|high|xhigh`
- `description` - human-friendly label for the effort
- `defaultReasoningEffort` - suggested effort for the UI
- `inputModalities` - accepted input types for the model
- `supportsPersonality` - whether the model supports personality-specific instructions
- `isDefault` - whether the model is recommended for most users
- `upgrade` - optional recommended upgrade model id
- `upgradeInfo` - optional upgrade metadata object with:
- `model` - recommended upgrade model id
- `upgradeCopy` - optional display copy for the upgrade recommendation
- `modelLink` - optional link for the upgrade recommendation
- `migrationMarkdown` - optional markdown shown when presenting the upgrade
- `nextCursor` - pass into the next request to continue paging (optional)
2025-10-21 11:15:17 -07:00
2026-01-17 12:32:50 -08:00
## Collaboration modes (experimental)
Fetch the built-in collaboration mode presets with `collaborationMode/list` . This endpoint does not accept pagination and returns the full list in one response:
2026-03-03 13:18:25 -08:00
- `data` - ordered list of collaboration mode masks (partial settings to apply on top of the base mode)
2026-01-24 23:35:31 -08:00
- For tri-state fields like `reasoning_effort` and `developer_instructions` , omit the field to keep the current value, set it to `null` to clear it, or set a concrete value to update it.
2026-01-17 12:32:50 -08:00
2026-02-07 12:59:41 -08:00
When sending `turn/start` with `collaborationMode` , `settings.developer_instructions: null` means "use built-in instructions for the selected mode".
2025-09-14 21:30:56 -07:00
## Event stream
While a conversation runs, the server sends notifications:
2026-03-03 13:18:25 -08:00
- `codex/event` with the serialized Codex event payload. The shape matches `core/src/protocol.rs` 's `Event` and `EventMsg` types. Some notifications include a `_meta.requestId` to correlate with the originating request.
- `fuzzyFileSearch/sessionUpdated` and `fuzzyFileSearch/sessionCompleted` for the legacy fuzzy search flow.
2025-09-14 21:30:56 -07:00
Clients should render events and, when present, surface approval requests (see next section).
2026-01-15 18:33:11 -08:00
## Tool responses
2026-03-03 13:18:25 -08:00
The `codex` and `codex-reply` tools return standard MCP `CallToolResult` payloads. For compatibility with MCP clients that prefer `structuredContent` , Codex mirrors the content blocks inside `structuredContent` alongside the `threadId` .
2026-01-15 18:33:11 -08:00
Example:
```json
{
"content": [{ "type": "text", "text": "Hello from Codex" }],
"structuredContent": {
"threadId": "019bbed6-1e9e-7f31-984c-a05b65045719",
"content": "Hello from Codex"
}
}
```
2026-03-03 13:18:25 -08:00
## Approvals (server -> client)
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
When Codex needs approval to apply changes or run commands, the server issues JSON-RPC requests to the client:
2025-09-14 21:30:56 -07:00
- `applyPatchApproval { conversationId, callId, fileChanges, reason?, grantRoot? }`
2026-02-17 17:55:57 -08:00
- `execCommandApproval { conversationId, callId, approvalId?, command, cwd, reason? }`
2025-09-14 21:30:56 -07:00
The client must reply with `{ decision: "allow" | "deny" }` for each request.
## Auth helpers
2026-03-03 13:18:25 -08:00
For the complete request/response shapes and flow examples, see the [Auth endpoints (v2) section in the app-server README ](../app-server/README.md#auth-endpoints-v2 ).
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
## Legacy compatibility methods
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
The server still accepts a narrow v1 compatibility surface for existing app clients:
2025-09-14 21:30:56 -07:00
2026-03-03 13:18:25 -08:00
- `getConversationSummary`
- `getAuthStatus`
- `gitDiffToRemote`
- `fuzzyFileSearch` , `fuzzyFileSearch/sessionStart` , `fuzzyFileSearch/sessionUpdate` , `fuzzyFileSearch/sessionStop`
2025-09-14 21:30:56 -07:00
## Compatibility and stability
2026-03-03 13:18:25 -08:00
This interface is experimental. Method names, fields, and event shapes may evolve. For the authoritative schema, consult `app-server-protocol/src/protocol/{common,v1,v2}.rs` and the corresponding server wiring in `app-server/` .