Skip to content

Mcp protocol#1715

Merged
aibrahim-oai merged 27 commits intomainfrom
mcp-protocol
Jul 30, 2025
Merged

Mcp protocol#1715
aibrahim-oai merged 27 commits intomainfrom
mcp-protocol

Conversation

@aibrahim-oai
Copy link
Copy Markdown
Collaborator

@aibrahim-oai aibrahim-oai commented Jul 28, 2025

  • Add typed MCP protocol surface in codex-rs/mcp-server/src/mcp_protocol.rs for requests, responses, and notifications
  • Requests: NewConversation, Connect, SendUserMessage, GetConversations
  • Message content parts: Text, Image (ImageUrl/FileId, optional ImageDetail), File (Url/Id/inline Data)
  • Responses: ToolCallResponseEnvelope with optional isError and structuredContent variants (NewConversation, Connect, SendUserMessageAccepted, GetConversations)
  • Notifications: InitialState, ConnectionRevoked, CodexEvent, Cancelled
  • Uniform _meta on notifications via NotificationMeta (conversationId, requestId)
  • Unit tests validate JSON wire shapes for key requests/responses/notifications

@aibrahim-oai aibrahim-oai added the code-review Issues relating to code reviews performed by codex label Jul 28, 2025
@github-actions github-actions Bot added codex-review-in-progress and removed code-review Issues relating to code reviews performed by codex labels Jul 28, 2025
@github-actions
Copy link
Copy Markdown
Contributor

Summary

Adds mcp_protocol.rs to codex-rs/mcp-server with the full set of request/response/notification structs (incl. serde tags & helpers) plus unit tests, and wires the new module into lib.rs.

Review

Nice, well-structured type definitions and exhaustive tests—build should stay green.

  • Naming / serde attributes follow the spec, tests cover key paths.
  • Consider re-exporting the main enums so callers don’t need the full path.
  • Minor: some TODO-style comments or inline docs would help future maintainers, but not blocking.

View workflow run

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
pub model: String,
pub cwd: String,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub approval_policy: Option<String>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is this a String instead of the enum value?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(default, skip_serializing_if = "Option::is_none")]
pub approval_policy: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<String>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Here too.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct SendUserMessageArgs {
pub conversation_id: Uuid,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I am still inclined to use a u32 instead of a Uuid for this.

FYI, in Rust, there is a thing called the "newtype" idiom: https://doc.rust-lang.org/rust-by-example/generics/new_types.html

In our case, I would be inclined to do:

struct ConversationId(u32)

so that we use the ConversationId throughout and if we want to change how we represent it, we can do it all in one place.

Rust is designed so that there is no extra allocation because this is a "struct:" it just uses the four bytes for the u32.

Copy link
Copy Markdown
Collaborator

@dylan-hurd-oai dylan-hurd-oai Jul 29, 2025

Choose a reason for hiding this comment

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

FWIW I do think UUID is the right call here, even if it's extra space. These will essentially serve as primary keys for sessions stored at clients, right? Feels like a good use of bytes to store and transport a very resilient id format.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConnectResult {}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you define the result closer to the request? The request is ConnectArgs in this case, right?

I am probably in the minority, but I would favor using Uuid in the request and then "exchanging" it for u32 in the response.

Copy link
Copy Markdown
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 get this part:
I am probably in the minority, but I would favor using Uuid in the request and then "exchanging" it for u32 in the response.

How are we exchanging them from the request to response and why?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not sure I follow. Can you explain?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
pub enum ToolCallResponseData {
NewConversation(NewConversationResult),
Connect(ConnectResult),
SendUserMessage(SendUserMessageAccepted),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can/should we use a consistent suffix for all these names? The others are all Result?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Rust was saying remove any suffix because it's part of an enum.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
// Notifications
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ConversationNotificationParams {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think we want one enum for all notifications, not just conversation notifications?

On the client side, I think we want to be able to dispatch based on the type field.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

What other types did I miss? most of it is included in CodexEvent

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}),
reason: "New connect() took over".into(),
};
let got = match serde_json::to_value(&params) {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Note "observed" is generally the preferred term compared to "got."

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

let got = match serde_json::to_value(&params) {
Ok(v) => v,
Err(e) => panic!("failed to serialize InitialStateNotificationParams: {e}"),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If you use expect() you can still specify the message but avoid the extra lines from the match.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Comment on lines +12 to +14
NewConversation(NewConversationArgs),
Connect(ConnectArgs),
SendUserMessage(SendUserMessageArgs),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I still want to tighten up these names.

  1. The fact that the resource in new is Conversation and follow-up is UserMessage feels makes them feel unrelated but they're very related
  2. Connect is not descriptive enough

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

how about now?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
pub conversation_id: Uuid,
pub content: Vec<InputMessageContentPart>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message_id: Option<String>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This is going to need ~all of the fields from NewConversation (model, cwd, etc). They can be optional and inherit the parent message but they need to be there

Data {
#[serde(default, skip_serializing_if = "Option::is_none")]
filename: Option<String>,
file_data: String,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this base64? Can you document that? Does this only support PDF? Admittedly, the API is confusing. It keeps referencing PDFs but I'd be shocked if it didn't support other file types.
https://platform.openai.com/docs/guides/pdf-files?api-mode=responses#base64-encoded-files

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

It's base64. I am not sure if it only supports PDF or what else.

file_url: String,
},
Id {
file_id: String,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Comment on lines +135 to +136
pub history_log_id: u64,
pub history_entry_count: usize,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What would a caller do with the history log id and entry count?

What is the entry count for?

Is there a reason log id would be different than conversation id?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

They are currently part of sessionConfigured I can remove them if they aren't useful.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

If we can't think of a good use case for it, let's keep it as an implementation detail for now. If we need to add it later, we can

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did you want to remove these?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

yes

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConnectResult {}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Not sure I follow. Can you explain?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(rename_all = "camelCase")]
pub struct NotificationMeta {
#[serde(skip_serializing_if = "Option::is_none")]
pub conversation_id: Option<Uuid>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Since we have RequestId as a type, let's define ConversationId (tbd on uuid vs u32 depending on your conversation with Michael)

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ConversationNotificationParams {
InitialState(InitialStateNotificationParams),
ConnectionRevoked(ConnectionRevokedNotificationParams),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What is the difference between ConnectionRevoked and Cancelled? I think you can combine them.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

ConnectionRevoked tells a client “the stream for this conversation was taken over by a newer connect(); stop listening to this one.” cancelled should be sent on a cancellation notification.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think it's okay to send Cancellation for both. Maybe you can add reason to cancellation or something but from the calling side, I think it's okay for them to be the same. @bolinfest wdyt?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wdyt about this?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I used poor wording. cancellation here is the cancellation that a client sends to the server. there is no response for a cancellation notification.
ConnectionRevoked will be from the server to the client (opposite direction). I don't think the server can send a cancel notification to the client. I renamed it to CancellNotificationParams

@aibrahim-oai aibrahim-oai requested review from bolinfest and gpeal July 29, 2025 00:37
pub limit: Option<u32>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub cursor: Option<String>,
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

simple, i like it

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(rename = "isError", default, skip_serializing_if = "Option::is_none")]
pub is_error: Option<bool>,
#[serde(
rename = "structuredContent",
Copy link
Copy Markdown
Collaborator

@dylan-hurd-oai dylan-hurd-oai Jul 29, 2025

Choose a reason for hiding this comment

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

non-blocking: why not use rename_all="camelCase" on the struct?

pub struct InitialStateNotificationParams {
#[serde(rename = "_meta", skip_serializing_if = "Option::is_none")]
pub meta: Option<NotificationMeta>,
pub initial_state: InitialStatePayload,
Copy link
Copy Markdown
Collaborator

@dylan-hurd-oai dylan-hurd-oai Jul 29, 2025

Choose a reason for hiding this comment

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

Why have a nested struct here?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I wanted to define the initial_state on its own.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs
Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Comment on lines +29 to +31
pub approval_policy: Option<codex_core::protocol::AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<codex_core::config_types::SandboxMode>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
pub approval_policy: Option<codex_core::protocol::AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<codex_core::config_types::SandboxMode>,
pub approval_policy: Option<AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<SandboxMode>,

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Comment on lines +49 to +51
pub approval_policy: Option<codex_core::protocol::AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<codex_core::config_types::SandboxMode>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
pub approval_policy: Option<codex_core::protocol::AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<codex_core::config_types::SandboxMode>,
pub approval_policy: Option<AskForApproval>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub sandbox: Option<SandboxMode>,

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum InputMessageContentPart {
// following OpenAI's Responses API: https://platform.openai.com/docs/api-reference/responses
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this comment associated with Text or InputMessageContentPart? If the former, it should be /// and above the derive. 2 / is a regular comment 3, is documentation and will show up in the IDE documentation popup

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "snake_case")]
pub enum InputMessageContentPart {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wdyt about this name?

Suggested change
pub enum InputMessageContentPart {
pub enum MessageInputItem {

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(untagged)]
pub enum FileSource {
// following OpenAI's Responses API: https://platform.openai.com/docs/guides/pdf-files?api-mode=responses#uploading-files
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same comment as above regarding doc comment + position

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Id {
file_id: String,
},
Data {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think this is a bit clearer. Wdyt?

Suggested change
Data {
Base64 {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

feels better but a bit misleading because the struct has filename as well. Changed it anyways.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
Comment on lines +135 to +136
pub history_log_id: u64,
pub history_entry_count: usize,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Did you want to remove these?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ConversationNotificationParams {
InitialState(InitialStateNotificationParams),
// sent when a second client connects to the same conversation
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
// sent when a second client connects to the same conversation
// Sent when a second client connects to the same conversation.

nit (for this and for others): For documentation comments, let's use sentence case.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think you forgot to address this one

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

oh yeah

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ConversationNotificationParams {
InitialState(InitialStateNotificationParams),
ConnectionRevoked(ConnectionRevokedNotificationParams),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Wdyt about this?

Copy link
Copy Markdown
Collaborator

@dylan-hurd-oai dylan-hurd-oai left a comment

Choose a reason for hiding this comment

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

I like what we're standardizing on! My primary remaining concern is just mixing snake_case and camelCase.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
pub reason: Option<String>,
}

/// Strongly-typed notification envelope (no unwraps/expect, no serde_json::Value payloads).
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

🙌

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct CancellNotificationParams {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

typo

Suggested change
pub struct CancellNotificationParams {
pub struct CancelNotificationParams {

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs
Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "name", content = "arguments", rename_all = "snake_case")]
Copy link
Copy Markdown
Collaborator

@dylan-hurd-oai dylan-hurd-oai Jul 29, 2025

Choose a reason for hiding this comment

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

We seem to use a mix of snake_case and camelCase in this protocol. I'd strongly suggest we standardize on either snake_case or camelCase. I have a light preference for camelCase to match MCP patterns, but it's much more important to use one consistent casing. Using snake_case everywhere would be strictly better than an approach of "camelCase when we can"

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

// Requests
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCallRequestEnvelope {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

What does Envelope mean here? Why is it not ToolCallRequest?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs
Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
pub conversation_id: ConversationId,
pub content: Vec<MessageInputItem>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub message_id: Option<String>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should this be parent_message_id and document that, by default, it will continue from the last message but this can be specified to edit a or resume from an earlier message.

Could you define a MessageId struct like you did for ConversationId?

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum MessageInputItem {
/// Following OpenAI's Responses API: https://platform.openai.com/docs/api-reference/responses
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This should be above the #derive because this is a doc for MessageInputItem not Text. Same below

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
// Responses
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ToolCallResponseEnvelope {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same question re: Envelope

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ConversationSendMessageAccepted {
pub accepted: bool,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
pub accepted: bool,
pub success: bool,

nit: I think success is a bit more conventional here

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum ToolCallResponseContent {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this used?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

it's remaining from previous edits. nice catch.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
#[serde(tag = "type", content = "data", rename_all = "snake_case")]
pub enum ConversationNotificationParams {
InitialState(InitialStateNotificationParams),
// sent when a second client connects to the same conversation
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I think you forgot to address this one

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone)]
pub enum NotificationEnvelope {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same question re: Envelope

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
CodexEvent(CodexEventNotificationParams),
}

impl From<ConversationNotificationParams> for NotificationEnvelope {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why is ConversationNotificationParams prefixed with Conversation but NotificationEnvelope isn't?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

added prefix.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

use mcp_types::RequestId;

pub type ConversationId = Uuid;
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Can you make a struct for ConversationId, too?

Michael may have a preference here. I think we want struct so that it's actually type safe but we certainly want them to be consistent

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs
Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
ConversationsList(ConversationsListArgs),
}

/// Wrap this request in a JSON-RPC request.
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Is this the doc for into_request? You have it as the doc for the whole struct impl

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
// Sent when a second client connects to the same conversation.
ConnectionRevoked(ConnectionRevokedNotificationParams),
CodexEvent(CodexEventNotificationParams),
Cancelled(CancelNotificationParams),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Let's split Cancel into a separate enum so we have separate types for server -> client and vice versa

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InitialStatePayload {
#[serde(default, skip_serializing_if = "Vec::is_empty")]
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Suggested change
#[serde(default, skip_serializing_if = "Vec::is_empty")]
#[serde(default)]

Let's not skip this if it's empty so clients can always work with an array

pub struct CancelNotificationParams {
pub request_id: RequestId,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub reason: Option<String>,
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Give reason an enum so it's clear what the String options are

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

discussed in person. We don't need an enum because the client sends it.

Comment thread codex-rs/mcp-server/src/mcp_protocol.rs Outdated
}

#[derive(Debug, Clone)]
pub enum ConversationNotification {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Why do this and ConversationNotificationParams need to exist? It looks like they're roughly the same

@aibrahim-oai aibrahim-oai requested a review from gpeal July 30, 2025 00:15
Copy link
Copy Markdown
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.

🚢🚢🚢🚢🚢🚢🚢🚢🚢

@aibrahim-oai aibrahim-oai merged commit 3823b32 into main Jul 30, 2025
11 checks passed
@aibrahim-oai aibrahim-oai deleted the mcp-protocol branch July 30, 2025 03:14
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 30, 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.

4 participants