From fcc4ca552f7753c537fe4b8af4276caf8edff762 Mon Sep 17 00:00:00 2001 From: jif Date: Wed, 5 Aug 2026 09:33:38 +0000 Subject: [PATCH] Preserve longer MCP source descriptions in tool search (#37066) ## Why The 4 KiB aggregate limit can truncate source metadata before it reaches the model through the tool search description. ## What changed Raise the aggregate source-description limit to 512 KiB while retaining the existing character-boundary-safe truncation and bounded output. ## Testing Expand unit and RMCP round-trip coverage to verify that substantially longer Unicode descriptions remain complete within the new limit. GitOrigin-RevId: 002760cdd2e8741e531b45f75f8624ef84334d24 --- codex-rs/core/src/tools/handlers/tool_search_spec.rs | 6 ++++-- codex-rs/core/tests/suite/rmcp_client.rs | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/codex-rs/core/src/tools/handlers/tool_search_spec.rs b/codex-rs/core/src/tools/handlers/tool_search_spec.rs index cdcf9ff823..c607ae0762 100644 --- a/codex-rs/core/src/tools/handlers/tool_search_spec.rs +++ b/codex-rs/core/src/tools/handlers/tool_search_spec.rs @@ -5,7 +5,7 @@ use codex_tools::ToolSpec; use codex_utils_string::take_bytes_at_char_boundary; use std::collections::BTreeMap; -const MAX_TOOL_SEARCH_SOURCE_DESCRIPTION_BYTES: usize = 4 * 1024; +const MAX_TOOL_SEARCH_SOURCE_DESCRIPTION_BYTES: usize = 512 * 1024; #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub(crate) enum ToolSearchSourceListing { @@ -176,10 +176,11 @@ mod tests { #[test] fn create_tool_search_tool_bounds_aggregate_source_descriptions() { + let long_description = "🦀".repeat(20_000); let sources = (0..8) .map(|index| ToolSearchSourceInfo { name: format!("source-{index:02}"), - description: Some("🦀".repeat(300)), + description: Some(long_description.clone()), }) .collect::>(); let ToolSpec::ToolSearch { description, .. } = create_tool_search_tool( @@ -198,6 +199,7 @@ mod tests { .expect("tool search should retain its discovery instructions"); assert!(source_descriptions.len() <= MAX_TOOL_SEARCH_SOURCE_DESCRIPTION_BYTES); assert!(source_descriptions.starts_with("- source-00: 🦀")); + assert!(source_descriptions.contains(&long_description)); let advertised_names = source_descriptions .lines() .map(|line| { diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 4c6d2032d4..6bb23a3221 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -620,7 +620,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { .await; let expected_env_value = "propagated-env"; - let expected_description = format!("{}🦀keep the complete MCP metadata", "é".repeat(499)); + let expected_description = format!("{}🦀keep the complete MCP metadata", "é".repeat(11_000)); let instructions = expected_description.clone(); let rmcp_test_server_bin = remote_aware_stdio_server_bin()?; @@ -713,7 +713,7 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { .and_then(|tool| tool.get("description").and_then(Value::as_str)) .expect("the model should receive a tool search description"); assert!( - search_description.len() < 5 * 1024, + search_description.len() < 513 * 1024, "the complete tool search description must remain bounded" ); assert!(search_description.contains(&format!("- rmcp: {expected_description}")));