From c3951a448c022add2e159929ce60d1c9b5641c2c Mon Sep 17 00:00:00 2001 From: kevin9327 Date: Fri, 4 Sep 2026 20:12:02 +0900 Subject: [PATCH] fix(tools): report the ListMcpResources cap in resources, not bytes `gate_mcp_resources` caps the list at `MCP_RESOURCE_LIMIT` (200 resources), then describes that truncation with `truncation_notice`, which is written for byte budgets and was handed `MCP_TEXT_LIMIT`. A server returning 250 resources produced: [truncated: ListMcpResources result exceeded 32768 bytes; showing 200 of 250 bytes] Neither figure describes what happened: 32768 is a text budget this path never applies, and the counts are resources rather than bytes. The notice goes into a sentinel resource's description, so it is what the model reads to learn why the list is short -- and it invites the conclusion that the list was cut for size and would fit under a smaller byte budget. State the cap that was actually applied, in its own unit, matching the wording the sibling item-count truncation in `gate_mcp` already uses. Co-Authored-By: Claude Opus 5 --- .../src/cursor/tools/tool_call_result/gate.rs | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/server/src/cursor/tools/tool_call_result/gate.rs b/server/src/cursor/tools/tool_call_result/gate.rs index 3c72a4b..b12283a 100644 --- a/server/src/cursor/tools/tool_call_result/gate.rs +++ b/server/src/cursor/tools/tool_call_result/gate.rs @@ -517,11 +517,9 @@ fn gate_mcp_resources(tool: &mut pb::ListMcpResourcesToolCall) { .push(pb::list_mcp_resources_exec_result::McpResource { uri: "truncated:list-mcp-resources".into(), name: Some("truncated".into()), - description: Some(truncation_notice( - "ListMcpResources", - MCP_TEXT_LIMIT, - success.resources.len(), - original, + description: Some(format!( + "[truncated: ListMcpResources result exceeded {MCP_RESOURCE_LIMIT} resources; showing {} of {original} resources]", + success.resources.len() )), ..Default::default() }); @@ -861,4 +859,39 @@ mod tests { let mut content = String::new(); tool_completion("Grep", &mut tool, &mut content); } + + #[test] + fn list_mcp_resources_reports_the_cap_it_actually_applied() { + let resources = (0..MCP_RESOURCE_LIMIT + 50) + .map(|index| pb::list_mcp_resources_exec_result::McpResource { + uri: format!("mcp://resource/{index}"), + ..Default::default() + }) + .collect(); + let mut tool = pb::ListMcpResourcesToolCall { + args: None, + result: Some(pb::ListMcpResourcesExecResult { + result: Some(pb::list_mcp_resources_exec_result::Result::Success( + pb::ListMcpResourcesSuccess { resources }, + )), + }), + }; + + gate_mcp_resources(&mut tool); + + let pb::list_mcp_resources_exec_result::Result::Success(success) = + tool.result.unwrap().result.unwrap() + else { + panic!("expected a successful result"); + }; + let notice = success.resources.last().unwrap(); + assert_eq!(notice.uri, "truncated:list-mcp-resources"); + assert_eq!( + notice.description.as_deref(), + Some( + "[truncated: ListMcpResources result exceeded 200 resources; \ + showing 200 of 250 resources]" + ) + ); + } }