MCP server: route structured tool-call requests and expose mcp_protocol [Stack 2/3] (#1751)
- Expose mcp_protocol from mcp-server for reuse in tests and callers. - In MessageProcessor, detect structured ToolCallRequestParams in tools/call and forward to a new handler. - Add handle_new_tool_calls scaffold (returns error for now). - Test helper: add send_send_user_message_tool_call to McpProcess to send ConversationSendMessage requests; This is the second PR in a stack. Stack: Final: #1686 Intermediate: #1751 First: #1750
This commit is contained in:
2
codex-rs/Cargo.lock
generated
2
codex-rs/Cargo.lock
generated
@@ -2643,6 +2643,7 @@ version = "0.0.0"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
|
"codex-core",
|
||||||
"codex-mcp-server",
|
"codex-mcp-server",
|
||||||
"mcp-types",
|
"mcp-types",
|
||||||
"pretty_assertions",
|
"pretty_assertions",
|
||||||
@@ -2650,6 +2651,7 @@ dependencies = [
|
|||||||
"shlex",
|
"shlex",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"uuid",
|
||||||
"wiremock",
|
"wiremock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ mod codex_tool_config;
|
|||||||
mod codex_tool_runner;
|
mod codex_tool_runner;
|
||||||
mod exec_approval;
|
mod exec_approval;
|
||||||
mod json_to_toml;
|
mod json_to_toml;
|
||||||
mod mcp_protocol;
|
pub mod mcp_protocol;
|
||||||
mod message_processor;
|
mod message_processor;
|
||||||
mod outgoing_message;
|
mod outgoing_message;
|
||||||
mod patch_approval;
|
mod patch_approval;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ use crate::codex_tool_config::CodexToolCallParam;
|
|||||||
use crate::codex_tool_config::CodexToolCallReplyParam;
|
use crate::codex_tool_config::CodexToolCallReplyParam;
|
||||||
use crate::codex_tool_config::create_tool_for_codex_tool_call_param;
|
use crate::codex_tool_config::create_tool_for_codex_tool_call_param;
|
||||||
use crate::codex_tool_config::create_tool_for_codex_tool_call_reply_param;
|
use crate::codex_tool_config::create_tool_for_codex_tool_call_reply_param;
|
||||||
|
use crate::mcp_protocol::ToolCallRequestParams;
|
||||||
use crate::outgoing_message::OutgoingMessageSender;
|
use crate::outgoing_message::OutgoingMessageSender;
|
||||||
|
|
||||||
use codex_core::Codex;
|
use codex_core::Codex;
|
||||||
@@ -300,6 +301,14 @@ impl MessageProcessor {
|
|||||||
params: <mcp_types::CallToolRequest as mcp_types::ModelContextProtocolRequest>::Params,
|
params: <mcp_types::CallToolRequest as mcp_types::ModelContextProtocolRequest>::Params,
|
||||||
) {
|
) {
|
||||||
tracing::info!("tools/call -> params: {:?}", params);
|
tracing::info!("tools/call -> params: {:?}", params);
|
||||||
|
// Serialize params into JSON and try to parse as new type
|
||||||
|
if let Ok(new_params) =
|
||||||
|
serde_json::to_value(¶ms).and_then(serde_json::from_value::<ToolCallRequestParams>)
|
||||||
|
{
|
||||||
|
// New tool call matched → forward
|
||||||
|
self.handle_new_tool_calls(id, new_params).await;
|
||||||
|
return;
|
||||||
|
}
|
||||||
let CallToolRequestParams { name, arguments } = params;
|
let CallToolRequestParams { name, arguments } = params;
|
||||||
|
|
||||||
match name.as_str() {
|
match name.as_str() {
|
||||||
@@ -323,6 +332,20 @@ impl MessageProcessor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
async fn handle_new_tool_calls(&self, request_id: RequestId, _params: ToolCallRequestParams) {
|
||||||
|
// TODO: implement the new tool calls
|
||||||
|
let result = CallToolResult {
|
||||||
|
content: vec![ContentBlock::TextContent(TextContent {
|
||||||
|
r#type: "text".to_string(),
|
||||||
|
text: "Unknown tool".to_string(),
|
||||||
|
annotations: None,
|
||||||
|
})],
|
||||||
|
is_error: Some(true),
|
||||||
|
structured_content: None,
|
||||||
|
};
|
||||||
|
self.send_response::<mcp_types::CallToolRequest>(request_id, result)
|
||||||
|
.await;
|
||||||
|
}
|
||||||
|
|
||||||
async fn handle_tool_call_codex(&self, id: RequestId, arguments: Option<serde_json::Value>) {
|
async fn handle_tool_call_codex(&self, id: RequestId, arguments: Option<serde_json::Value>) {
|
||||||
let (initial_prompt, config): (String, CodexConfig) = match arguments {
|
let (initial_prompt, config): (String, CodexConfig) = match arguments {
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ path = "lib.rs"
|
|||||||
anyhow = "1"
|
anyhow = "1"
|
||||||
assert_cmd = "2"
|
assert_cmd = "2"
|
||||||
codex-mcp-server = { path = "../.." }
|
codex-mcp-server = { path = "../.." }
|
||||||
|
codex-core = { path = "../../../core" }
|
||||||
mcp-types = { path = "../../../mcp-types" }
|
mcp-types = { path = "../../../mcp-types" }
|
||||||
pretty_assertions = "1.4.1"
|
pretty_assertions = "1.4.1"
|
||||||
serde_json = "1"
|
serde_json = "1"
|
||||||
@@ -22,3 +23,4 @@ tokio = { version = "1", features = [
|
|||||||
"rt-multi-thread",
|
"rt-multi-thread",
|
||||||
] }
|
] }
|
||||||
wiremock = "0.6"
|
wiremock = "0.6"
|
||||||
|
uuid = { version = "1", features = ["serde", "v4"] }
|
||||||
@@ -11,8 +11,13 @@ use tokio::process::ChildStdout;
|
|||||||
|
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use assert_cmd::prelude::*;
|
use assert_cmd::prelude::*;
|
||||||
|
use codex_core::protocol::InputItem;
|
||||||
use codex_mcp_server::CodexToolCallParam;
|
use codex_mcp_server::CodexToolCallParam;
|
||||||
use codex_mcp_server::CodexToolCallReplyParam;
|
use codex_mcp_server::CodexToolCallReplyParam;
|
||||||
|
use codex_mcp_server::mcp_protocol::ConversationId;
|
||||||
|
use codex_mcp_server::mcp_protocol::ConversationSendMessageArgs;
|
||||||
|
use codex_mcp_server::mcp_protocol::ToolCallRequestParams;
|
||||||
|
|
||||||
use mcp_types::CallToolRequestParams;
|
use mcp_types::CallToolRequestParams;
|
||||||
use mcp_types::ClientCapabilities;
|
use mcp_types::ClientCapabilities;
|
||||||
use mcp_types::Implementation;
|
use mcp_types::Implementation;
|
||||||
@@ -29,6 +34,7 @@ use pretty_assertions::assert_eq;
|
|||||||
use serde_json::json;
|
use serde_json::json;
|
||||||
use std::process::Command as StdCommand;
|
use std::process::Command as StdCommand;
|
||||||
use tokio::process::Command;
|
use tokio::process::Command;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub struct McpProcess {
|
pub struct McpProcess {
|
||||||
next_request_id: AtomicI64,
|
next_request_id: AtomicI64,
|
||||||
@@ -174,6 +180,26 @@ impl McpProcess {
|
|||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn send_user_message_tool_call(
|
||||||
|
&mut self,
|
||||||
|
message: &str,
|
||||||
|
session_id: &str,
|
||||||
|
) -> anyhow::Result<i64> {
|
||||||
|
let params = ToolCallRequestParams::ConversationSendMessage(ConversationSendMessageArgs {
|
||||||
|
conversation_id: ConversationId(Uuid::parse_str(session_id)?),
|
||||||
|
content: vec![InputItem::Text {
|
||||||
|
text: message.to_string(),
|
||||||
|
}],
|
||||||
|
parent_message_id: None,
|
||||||
|
conversation_overrides: None,
|
||||||
|
});
|
||||||
|
self.send_request(
|
||||||
|
mcp_types::CallToolRequest::METHOD,
|
||||||
|
Some(serde_json::to_value(params)?),
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
async fn send_request(
|
async fn send_request(
|
||||||
&mut self,
|
&mut self,
|
||||||
method: &str,
|
method: &str,
|
||||||
|
|||||||
Reference in New Issue
Block a user