Repository navigation
Description
Problem (one or two sentences)
When mcp--<server>--<tool> is longer than 64 characters, buildMcpToolName cuts it with a plain slice(0, 64). The model can call the complete, uncut name instead: Zoo Code still resolves and runs it, then stores that >64-char name in the API history, and every later request in the task gets rejected by the provider.
Context (who is affected and when)
Anyone with MCP tools whose mcp--<server>--<tool> name goes over 64 characters, on a provider that validates tool names found in the history: Bedrock Converse (also when reached through a LiteLLM / OpenAI-compatible proxy) and Azure OpenAI both reject them. Once it happens the task is stuck as is, since every retry replays the same history (see the workaround below).
Reproduction steps
- Add an MCP server named e.g.
company-gateway-tools(21 chars) that exposes a tool namedconfluence-confluence_get_space_page_tree(41 chars). The full namemcp--company-gateway-tools--confluence-confluence_get_space_page_treeis 69 chars, so the tool is declared asmcp--company-gateway-tools--confluence-confluence_get_space_page. - Use the LiteLLM provider, pointed at a LiteLLM proxy serving Claude Haiku 5.5 from Bedrock, and run a task that ends up using that tool.
- The model calls the tool, the call succeeds.
- The next request fails with the error below, and so does every retry.
Expected result
The tool name written to the API history is the one declared to the model, so it stays within the provider's limit and the task keeps working.
Actual result
400 ... Value at 'messages.190.member.content.1.member.toolUse.name' failed to satisfy constraint: Member must have length less than or equal to 64 on every request after the call.
Variations tried (optional)
Bedrock reports a single validation error, on the history entry only: the tool definitions sent in the same request pass, which they always do since buildMcpToolName caps them at 64. So the >64-char name can only come from the model's own tool call, which is kept verbatim (name: toolCall.name in NativeToolCallParser.parseDynamicMcpTool, then name: mcpBlock.name in Task.ts), while parseMcpToolName happily resolves the uncut name to the right server and tool.
Same request shape sent straight to a LiteLLM proxy on /v1/chat/completions, with a 71-char tool name present only in the history:
- Bedrock Converse (Claude Haiku 5.5): 400
toolUse.name ... Member must have length less than or equal to 64 - Azure OpenAI (gpt-5-mini): 400
Invalid 'messages[1].tool_calls[0].function.name': string too long. Expected a string with maximum length 64 - Anthropic Messages API (
/v1/messages): 200
Workaround: rename the MCP server so every mcp--<server>--<tool> fits in 64 characters. Renaming alone does not unblock a task that already has the long name in its history: condense the context (tool blocks are turned into text for the summary and the history restarts from it) or start a new task.
Code (at 8018cba):
- cut:
Zoo-Code/src/utils/mcp-name.ts
Lines 127 to 136 in 8018cba
export function buildMcpToolName(serverName: string, toolName: string): string { const sanitizedServer = sanitizeMcpName(serverName) const sanitizedTool = sanitizeMcpName(toolName) // Build the full name: mcp--{server}--{tool} const fullName = `${MCP_TOOL_PREFIX}${MCP_TOOL_SEPARATOR}${sanitizedServer}${MCP_TOOL_SEPARATOR}${sanitizedTool}` // Truncate if necessary (max 64 chars for Gemini) if (fullName.length > 64) { return fullName.slice(0, 64) - model-returned name kept:
name: toolCall.name, - written to history:
Zoo-Code/src/core/task/Task.ts
Line 4835 in 8018cba
name: mcpBlock.name, // Original dynamic name
Possible fix, two parts: write the history entry under the declared name (e.g. rebuild it with buildMcpToolName(serverName, toolName) from what parseMcpToolName returned) so a long name can never reach the history, and replace the plain cut with a hash suffix so the declared name no longer looks like a word cut in half that the model wants to complete. The hash suffix was tried in Roo Code: RooCodeInc/Roo-Code#10770 (from RooCodeInc/Roo-Code#10766), closed without merge when the fuzzy-matching rewrite landed, and that rewrite kept the cut.
App Version
v3.88.0
API Provider (optional)
LiteLLM
Model Used (optional)
Claude Haiku 5.5 (Amazon Bedrock, through a LiteLLM proxy)
Relevant logs or errors (optional)
LiteLLM streaming error: 400 litellm.BadRequestError: BedrockException - {"message":"1 validation error detected: Value at 'messages.190.member.content.1.member.toolUse.name' failed to satisfy constraint: Member must have length less than or equal to 64"}
Activity
PierrunoYT commentedon Oct 20, 2026
Working on this!
fix(mcp): keep over-long MCP tool names out of API history