mirror of
https://github.com/openai/codex.git
synced 2026-05-02 04:11:39 +03:00
Add output schema to MCP tools and expose MCP tool results in code mode (#14236)
Summary - drop `McpToolOutput` in favor of `CallToolResult`, moving its helpers to keep MCP tooling focused on the final result shape - wire the new schema definitions through code mode, context, handlers, and spec modules so MCP tools serialize the exact output shape expected by the model - extend code mode tests to cover multiple MCP call scenarios and ensure the serialized data matches the new schema - refresh JS runner helpers and protocol models alongside the schema changes Testing - Not run (not requested)
This commit is contained in:
@@ -7,10 +7,10 @@ use crate::truncate::TruncationPolicy;
|
||||
use crate::truncate::formatted_truncate_text;
|
||||
use crate::turn_diff_tracker::TurnDiffTracker;
|
||||
use crate::unified_exec::resolve_max_tokens;
|
||||
use codex_protocol::mcp::CallToolResult;
|
||||
use codex_protocol::models::FunctionCallOutputBody;
|
||||
use codex_protocol::models::FunctionCallOutputContentItem;
|
||||
use codex_protocol::models::FunctionCallOutputPayload;
|
||||
use codex_protocol::models::McpToolOutput;
|
||||
use codex_protocol::models::ResponseInputItem;
|
||||
use codex_protocol::models::ShellToolCallParams;
|
||||
use codex_protocol::models::function_call_output_content_items_to_text;
|
||||
@@ -82,7 +82,7 @@ pub trait ToolOutput: Send {
|
||||
}
|
||||
}
|
||||
|
||||
impl ToolOutput for McpToolOutput {
|
||||
impl ToolOutput for CallToolResult {
|
||||
fn log_preview(&self) -> String {
|
||||
let output = self.as_function_call_output_payload();
|
||||
let preview = output.body.to_text().unwrap_or_else(|| output.to_string());
|
||||
@@ -90,7 +90,7 @@ impl ToolOutput for McpToolOutput {
|
||||
}
|
||||
|
||||
fn success_for_logging(&self) -> bool {
|
||||
self.success
|
||||
self.success()
|
||||
}
|
||||
|
||||
fn to_response_item(&self, call_id: &str, _payload: &ToolPayload) -> ResponseInputItem {
|
||||
@@ -99,6 +99,12 @@ impl ToolOutput for McpToolOutput {
|
||||
output: self.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn code_mode_result(&self, _payload: &ToolPayload) -> JsonValue {
|
||||
serde_json::to_value(self).unwrap_or_else(|err| {
|
||||
JsonValue::String(format!("failed to serialize mcp result: {err}"))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct FunctionToolOutput {
|
||||
@@ -272,12 +278,11 @@ fn response_input_to_code_mode_result(response: ResponseInputItem) -> JsonValue
|
||||
}
|
||||
},
|
||||
ResponseInputItem::McpToolCallOutput { output, .. } => {
|
||||
match output.as_function_call_output_payload().body {
|
||||
FunctionCallOutputBody::Text(text) => JsonValue::String(text),
|
||||
FunctionCallOutputBody::ContentItems(items) => {
|
||||
content_items_to_code_mode_result(&items)
|
||||
}
|
||||
}
|
||||
output.code_mode_result(&ToolPayload::Mcp {
|
||||
server: String::new(),
|
||||
tool: String::new(),
|
||||
raw_arguments: String::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -413,6 +418,48 @@ mod tests {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_code_mode_result_serializes_full_call_tool_result() {
|
||||
let output = CallToolResult {
|
||||
content: vec![serde_json::json!({
|
||||
"type": "text",
|
||||
"text": "ignored",
|
||||
})],
|
||||
structured_content: Some(serde_json::json!({
|
||||
"threadId": "thread_123",
|
||||
"content": "done",
|
||||
})),
|
||||
is_error: Some(false),
|
||||
meta: Some(serde_json::json!({
|
||||
"source": "mcp",
|
||||
})),
|
||||
};
|
||||
|
||||
let result = output.code_mode_result(&ToolPayload::Mcp {
|
||||
server: "server".to_string(),
|
||||
tool: "tool".to_string(),
|
||||
raw_arguments: "{}".to_string(),
|
||||
});
|
||||
|
||||
assert_eq!(
|
||||
result,
|
||||
serde_json::json!({
|
||||
"content": [{
|
||||
"type": "text",
|
||||
"text": "ignored",
|
||||
}],
|
||||
"structuredContent": {
|
||||
"threadId": "thread_123",
|
||||
"content": "done",
|
||||
},
|
||||
"isError": false,
|
||||
"_meta": {
|
||||
"source": "mcp",
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_tool_calls_can_derive_text_from_content_items() {
|
||||
let payload = ToolPayload::Custom {
|
||||
|
||||
Reference in New Issue
Block a user