Skip to content

Conversation

bolinfest
Copy link
Collaborator

@bolinfest bolinfest commented Aug 13, 2025

This introduces a new set of request types that our codex mcp supports. Note that these do not conform to MCP tool calls so that instead of having to send something like this:

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": 42,
  "params": {
    "name": "newConversation",
    "arguments": {
      "model": "gpt-5",
      "approvalPolicy": "on-request"
    }
  }
}

we can send something like this:

{
  "jsonrpc": "2.0",
  "method": "newConversation",
  "id": 42,
  "params": {
    "model": "gpt-5",
    "approvalPolicy": "on-request"
  }
}

Admittedly, this new format is not a valid MCP tool call, but we are OK with that right now. (That is, not everything we might want to request of codex mcp is something that is appropriate for an autonomous agent to do.)

To start, this introduces four request types:

  • newConversation
  • sendUserMessage
  • addConversationListener
  • removeConversationListener

The new mcp-server/tests/codex_message_processor_flow.rs shows how these can be used.

The types are defined on the CodexRequest enum, so we introduce a new CodexMessageProcessor that is responsible for dealing with requests from this enum. The top-level MessageProcessor has been updated so that when process_request() is called, it first checks whether the request conforms to CodexRequest and dispatches it to CodexMessageProcessor if so.

Note that I also decided to use camelCase for the on-the-wire format, as that seems to be the convention for MCP.

For the moment, the new protocol is defined in wire_format.rs within the mcp-server crate, but in a subsequent PR, I will probably move it to its own crate to ensure the protocol has minimal dependencies and that we can codegen a schema from it.


Stack created with Sapling. Best reviewed with ReviewStack.

@bolinfest bolinfest changed the base branch from main to pr2263 August 13, 2025 20:04
bolinfest added a commit that referenced this pull request Aug 13, 2025
…rsations (#2240)

This PR does two things because after I got deep into the first one I
started pulling on the thread to the second:

- Makes `ConversationManager` the place where all in-memory
conversations are created and stored. Previously, `MessageProcessor` in
the `codex-mcp-server` crate was doing this via its `session_map`, but
this is something that should be done in `codex-core`.
- It unwinds the `ctrl_c: tokio::sync::Notify` that was threaded
throughout our code. I think this made sense at one time, but now that
we handle Ctrl-C within the TUI and have a proper `Op::Interrupt` event,
I don't think this was quite right, so I removed it. For `codex exec`
and `codex proto`, we now use `tokio::signal::ctrl_c()` directly, but we
no longer make `Notify` a field of `Codex` or `CodexConversation`.

Changes of note:

- Adds the files `conversation_manager.rs` and `codex_conversation.rs`
to `codex-core`.
- `Codex` and `CodexSpawnOk` are no longer exported from `codex-core`:
other crates must use `CodexConversation` instead (which is created via
`ConversationManager`).
- `core/src/codex_wrapper.rs` has been deleted in favor of
`ConversationManager`.
- `ConversationManager::new_conversation()` returns `NewConversation`,
which is in line with the `new_conversation` tool we want to add to the
MCP server. Note `NewConversation` includes `SessionConfiguredEvent`, so
we eliminate checks in cases like `codex-rs/core/tests/client.rs` to
verify `SessionConfiguredEvent` is the first event because that is now
internal to `ConversationManager`.
- Quite a bit of code was deleted from
`codex-rs/mcp-server/src/message_processor.rs` since it no longer has to
manage multiple conversations itself: it goes through
`ConversationManager` instead.
- `core/tests/live_agent.rs` has been deleted because I had to update a
bunch of tests and all the tests in here were ignored, and I don't think
anyone ever ran them, so this was just technical debt, at this point.
- Removed `notify_on_sigint()` from `util.rs` (and in a follow-up, I
hope to refactor the blandly-named `util.rs` into more descriptive
files).
- In general, I started replacing local variables named `codex` as
`conversation`, where appropriate, though admittedly I didn't do it
through all the integration tests because that would have added a lot of
noise to this PR.




---
[//]: # (BEGIN SAPLING FOOTER)
Stack created with [Sapling](https://sapling-scm.com). Best reviewed
with [ReviewStack](https://reviewstack.dev/openai/codex/pull/2240).
* #2264
* #2263
* __->__ #2240
Base automatically changed from pr2263 to main August 13, 2025 21:29
@bolinfest bolinfest force-pushed the pr2264 branch 3 times, most recently from c50e892 to 1b07bd7 Compare August 13, 2025 23:02
@bolinfest bolinfest marked this pull request as ready for review August 13, 2025 23:13
};

let subscription_id = Uuid::new_v4();
let (sender, mut receiver) = oneshot::channel();
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
let (sender, mut receiver) = oneshot::channel();
let (cancel_tx, mut cancel_rx) = oneshot::channel();

@bolinfest bolinfest merged commit e7bad65 into main Aug 14, 2025
26 checks passed
@bolinfest bolinfest deleted the pr2264 branch August 14, 2025 00:36
@github-actions github-actions bot locked and limited conversation to collaborators Aug 14, 2025
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.

2 participants