Skip to content

Conversation

bolinfest
Copy link
Collaborator

@bolinfest bolinfest commented Sep 29, 2025

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.

Copy link
Contributor

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Comment on lines 752 to +779
session_configured,
..
}) => {
let event = Event {
id: "".to_string(),
msg: EventMsg::SessionConfigured(session_configured.clone()),
};
self.outgoing.send_event_as_notification(&event, None).await;
self.outgoing
.send_server_notification(ServerNotification::SessionConfigured(
SessionConfiguredNotification {
session_id: session_configured.session_id,
model: session_configured.model.clone(),
reasoning_effort: session_configured.reasoning_effort,
history_log_id: session_configured.history_log_id,
history_entry_count: session_configured.history_entry_count,
initial_messages: session_configured.initial_messages.clone(),
rollout_path: session_configured.rollout_path.clone(),
},
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Resumed conversations no longer emit codex/event/session_configured

The new resume_conversation path now sends a ServerNotification::SessionConfigured JSON‑RPC notification (method: "sessionConfigured") instead of reusing send_event_as_notification to emit the standard codex/event/session_configured event. There is no code anywhere in the repo that listens for sessionConfigured (searching for SessionConfiguredNotification or the method name returns nothing outside this file), while numerous consumers handle session initialization via EventMsg::SessionConfigured routed through the generic codex/event handler. This means a client resuming a conversation will no longer receive the expected session_configured event and will miss metadata like history log IDs, breaking any UI logic that depends on that event. Consider continuing to publish the event via the existing codex/event path (possibly in addition to the new notification) or updating clients to handle the new method.

Useful? React with 👍 / 👎.

@bolinfest bolinfest force-pushed the pr4471 branch 7 times, most recently from 9a7aeeb to 32e0d6e Compare September 30, 2025 05:05
Copy link
Collaborator

@gpeal gpeal left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall, LGTM. Left a few comments and decently skimmed the whole thing. I'm okay if you want to land this and then iterate.

Since we already have codex mcp, should this be codex mcp start-server?

Ok(())
}

/// Send a `newConversation` JSON-RPC request.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These comments seem a bit redundant

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair point, though this is from the original version:

/// Send a `newConversation` JSON-RPC request.

use std::process::Command as StdCommand;
use tokio::process::Command;

pub struct McpProcess {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure you want to call this McpProcess?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't, but from the PR body:

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.

}

async fn send_jsonrpc_message(&mut self, message: JSONRPCMessage) -> anyhow::Result<()> {
eprintln!("writing message to stdin: {message:?}");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to leave this in?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these are in the existing codex-rs/mcp-server/tests/common/mcp_process.rs that this is taken from. Note this is a test utility, so it's not that bad that they're here.

If we want to remove them, we should probably do it from both the app-server and mcp-server versions.

@bolinfest
Copy link
Collaborator Author

I don't think we should have codex mcp start-server because I think managing your MCPs when using Codex CLI and running Codex as an MCP server are sufficiently different things so they shouldn't share the codex mcp subcommand.

@bolinfest bolinfest enabled auto-merge (squash) September 30, 2025 07:00
@bolinfest bolinfest merged commit d9dbf48 into main Sep 30, 2025
40 checks passed
@bolinfest bolinfest deleted the pr4471 branch September 30, 2025 07:06
@github-actions github-actions bot locked and limited conversation to collaborators Sep 30, 2025
@dylan-hurd-oai
Copy link
Collaborator

I don't think we should have codex mcp start-server because I think managing your MCPs when using Codex CLI and running Codex as an MCP server are sufficiently different things so they shouldn't share the codex mcp subcommand.

Agree!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants