mirror of
https://github.com/openai/codex.git
synced 2026-11-08 20:40:33 +00:00
Preserve complete MCP namespace descriptions (#36882)
## What changed - Keep complete MCP namespace descriptions in tool-search source metadata. - Raise the namespace tool-spec description limit from 1,000 bytes to 512 KiB, truncating at a UTF-8 character boundary only when the new limit is exceeded. ## Testing - Cover descriptions beyond the former limit and multibyte truncation at 512 KiB. - Update SSE and stdio MCP tests to verify that complete server instructions are preserved without hiding tools. GitOrigin-RevId: 000bfcafb3df348065ae451685bfbf978a0e3248
This commit is contained in:
@@ -31,7 +31,7 @@ use serde_json::Value;
|
||||
|
||||
const LEGACY_MCP_TOOL_NAME_PREFIX: &str = "mcp__";
|
||||
const MCP_TOOL_NAME_DELIMITER: &str = "__";
|
||||
const MAX_MCP_NAMESPACE_DESCRIPTION_BYTES: usize = 1_000;
|
||||
const MAX_MCP_NAMESPACE_DESCRIPTION_BYTES: usize = 512 * 1024;
|
||||
|
||||
pub struct McpHandler {
|
||||
tool_info: ToolInfo,
|
||||
@@ -106,7 +106,6 @@ impl ToolExecutor<ToolInvocation> for McpHandler {
|
||||
.as_deref()
|
||||
.map(str::trim)
|
||||
.filter(|description| !description.is_empty())
|
||||
.map(bounded_mcp_namespace_description)
|
||||
.map(str::to_string),
|
||||
});
|
||||
|
||||
@@ -258,15 +257,12 @@ fn create_tool_spec(tool_info: &ToolInfo) -> Result<ToolSpec, serde_json::Error>
|
||||
|
||||
Ok(ToolSpec::Namespace(ResponsesApiNamespace {
|
||||
name: tool_info.callable_namespace.clone(),
|
||||
description: bounded_mcp_namespace_description(&description).to_string(),
|
||||
description: take_bytes_at_char_boundary(&description, MAX_MCP_NAMESPACE_DESCRIPTION_BYTES)
|
||||
.to_string(),
|
||||
tools: vec![ResponsesApiNamespaceTool::Function(tool)],
|
||||
}))
|
||||
}
|
||||
|
||||
fn bounded_mcp_namespace_description(description: &str) -> &str {
|
||||
take_bytes_at_char_boundary(description, MAX_MCP_NAMESPACE_DESCRIPTION_BYTES)
|
||||
}
|
||||
|
||||
fn mcp_hook_tool_input(raw_arguments: &str) -> Value {
|
||||
if raw_arguments.trim().is_empty() {
|
||||
return Value::Object(Map::new());
|
||||
|
||||
@@ -43,9 +43,8 @@ fn search_info_uses_connector_name_for_output_namespace_description() {
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_namespace_descriptions_are_bounded_without_mutating_metadata() {
|
||||
let expected_description = "é".repeat(499);
|
||||
let full_description = format!("{expected_description}🦀keep the complete app metadata");
|
||||
fn mcp_namespace_descriptions_preserve_complete_metadata() {
|
||||
let full_description = format!("{}🦀keep the complete app metadata", "é".repeat(499));
|
||||
let mut info = tool_info();
|
||||
info.namespace_description = Some(full_description.clone());
|
||||
let handler = McpHandler::new(info).expect("MCP tool spec should build");
|
||||
@@ -55,17 +54,39 @@ fn mcp_namespace_descriptions_are_bounded_without_mutating_metadata() {
|
||||
search_info.source_info,
|
||||
Some(ToolSearchSourceInfo {
|
||||
name: "Calendar".to_string(),
|
||||
description: Some(expected_description.clone()),
|
||||
description: Some(full_description.clone()),
|
||||
})
|
||||
);
|
||||
let LoadableToolSpec::Namespace(namespace) = search_info.entry.output else {
|
||||
panic!("expected namespace search output");
|
||||
};
|
||||
assert_eq!(namespace.description, full_description);
|
||||
assert_eq!(
|
||||
handler.tool_info.namespace_description,
|
||||
Some(full_description)
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn mcp_namespace_descriptions_are_bounded_at_512_kib() {
|
||||
let expected_description = "é".repeat(MAX_MCP_NAMESPACE_DESCRIPTION_BYTES / 2 - 1);
|
||||
let full_description = format!("{expected_description}🦀overflow");
|
||||
let mut info = tool_info();
|
||||
info.namespace_description = Some(full_description.clone());
|
||||
let handler = McpHandler::new(info).expect("MCP tool spec should build");
|
||||
let search_info = handler.search_info().expect("MCP search info");
|
||||
|
||||
assert_eq!(
|
||||
search_info.source_info,
|
||||
Some(ToolSearchSourceInfo {
|
||||
name: "Calendar".to_string(),
|
||||
description: Some(full_description),
|
||||
})
|
||||
);
|
||||
let LoadableToolSpec::Namespace(namespace) = search_info.entry.output else {
|
||||
panic!("expected namespace search output");
|
||||
};
|
||||
assert_eq!(namespace.description, expected_description);
|
||||
assert_eq!(
|
||||
handler.tool_info.namespace_description,
|
||||
Some(full_description)
|
||||
);
|
||||
}
|
||||
|
||||
fn tool_info() -> ToolInfo {
|
||||
|
||||
Reference in New Issue
Block a user