shareAI-lab/learn-claude-code · error · ValueError

MCP tool name is longer than 64 characters: {prefixed}

Error message

MCP tool name is longer than 64 characters: {prefixed}

What it means

When building the unified tool catalog, each MCP tool becomes 'mcp__<server>__<tool>' (both parts normalized). The model's tool-name limit is 64 characters, so a prefixed name longer than that raises ValueError at catalog-build time — better than shipping a tool the model can never call.

Source

Thrown at s14_mcp_plugin/code.py:331

def assemble_tool_pool() -> tuple[list[dict], dict[str, callable]]:
    """Combine built-in tools with every connected server tool."""
    global mcp_tool_policies
    tools = list(BUILTIN_TOOLS)
    handlers = dict(BUILTIN_HANDLERS)
    policies: dict[str, str] = {}
    origins = {
        tool["name"]: f"built-in tool {tool['name']!r}"
        for tool in tools
    }

    for server_name, server in mcp_clients.items():
        safe_server = normalize_mcp_name(server_name)
        for tool_def in server.tools:
            raw_name = tool_def["name"]
            safe_tool = normalize_mcp_name(raw_name)
            prefixed = f"mcp__{safe_server}__{safe_tool}"
            if len(prefixed) > 64:
                raise ValueError(f"MCP tool name is longer than 64 characters: {prefixed}")
            origin = f"MCP tool {server_name!r}/{raw_name!r}"
            if prefixed in origins:
                raise ValueError(
                    "MCP tool name collision after normalization: "
                    f"{prefixed!r} maps both {origins[prefixed]} and {origin}"
                )
            schema = tool_def.get("inputSchema", {})
            if not isinstance(schema, dict) or schema.get("type", "object") != "object":
                raise ValueError(f"Invalid input schema for {origin}")
            origins[prefixed] = origin
            tools.append({
                "name": prefixed,
                "description": tool_def.get("description", ""),
                "input_schema": schema,
            })
            handlers[prefixed] = (
                lambda *, client=server, tool=raw_name, **kwargs:
                client.call_tool(tool, kwargs)

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Shorten the server name in its MCPClient('name') constructor (biggest lever, it appears once per tool).
  2. Rename the offending tool(s) to concise verbs.
  3. Budget: total = 6 + len(server) + 2 + len(tool); keep server+tool under ~56 chars.

Example fix

// before
server = MCPClient('internal-documentation-platform')
// tool 'search_across_all_versions' -> prefixed 60+? over 64 -> ValueError

// after
server = MCPClient('docops')  // 'mcp__docops__search_across_all_versions' fits
Defensive patterns

Strategy: validation

Validate before calling

def prefixed_name_len(server: str, tool: str) -> int:
    return len(f'mcp__{server}__{tool}')

def fits_model_limit(server: str, tool: str) -> bool:
    return prefixed_name_len(server, tool) <= 64

Prevention

When it happens

Trigger: A server named 'internal-documentation-platform' with a tool named 'search_across_all_versions' produces a >64-char prefixed name; long hyphenated server names from config; verbose auto-generated tool names.

Common situations: Real-world MCP server names (often domain-like) combined with descriptive tool verbs; mirrors of external APIs with long method names.

Related errors


AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14). Data as JSON: /api/errors/37e8cac0ecfe8b2c. Report an issue: GitHub.