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

Invalid input schema for {origin}

Error message

Invalid input schema for {origin}

What it means

Raised while registering tools from an MCP server: each tool's advertised inputSchema must be a JSON object schema (a dict whose 'type' is 'object', explicitly or by default). The harness enforces this because it forwards the schema verbatim to the model as the tool's input contract, and a non-object or non-dict schema would produce an invalid tool definition. The offending server/tool is named in {origin} as 'MCP tool <server>/<rawname>'.

Source

Thrown at s14_mcp_plugin/code.py:340

    }

    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)
            )
            policies[prefixed] = MCP_HOST_POLICY.get(
                (server_name, raw_name), "confirm"
            )

    mcp_tool_policies = policies
    return tools, handlers

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Fix the offending MCP server so each tool definition includes inputSchema as a dict with "type": "object" (or omit 'type' so the default 'object' applies).
  2. If you cannot change the server, wrap its tool_defs and inject {"type": "object"} as a default inputSchema before registration.
  3. Inspect the server's tools/list response (e.g. via MCPClient.call_tool or a raw client) to identify exactly which tool advertises the bad schema named in {origin}.

Example fix

// before
tool_defs = [{"name": "echo", "description": "echo text"}]
server.register(tool_defs, handlers)  // raises: Invalid input schema for MCP tool ...

// after
tool_defs = [{
    "name": "echo",
    "description": "echo text",
    "inputSchema": {"type": "object", "properties": {"text": {"type": "string"}}},
}]
server.register(tool_defs, handlers)
Defensive patterns

Strategy: validation

Validate before calling

def valid_tool_defs(tool_defs):
    for t in tool_defs:
        s = t.get("inputSchema")
        if not isinstance(s, dict) or s.get("type", "object") != "object":
            return False
    return True

if not valid_tool_defs(tool_defs):
    tool_defs = [{**t, "inputSchema": t.get("inputSchema") if isinstance(t.get("inputSchema"), dict) and t["inputSchema"].get("type", "object") == "object" else {"type": "object"}} for t in tool_defs]

Type guard

def is_object_schema(schema) -> bool:
    return isinstance(schema, dict) and schema.get("type", "object") == "object"

Try / catch

try:
    register_mcp_tools(server, tool_defs)
except ValueError as e:
    if "Invalid input schema" in str(e):
        log.warning("skipping %s: bad inputSchema", e)
    else:
        raise

Prevention

When it happens

Trigger: Calling the MCP plugin's registration loop (build of mcp__<server>__<tool> handlers) where a tool_def's 'inputSchema' key is missing, is a list/string/None, or has "type": "array" / "string" / non-'object'. Typical of hand-rolled MCP servers or test doubles that omit inputSchema or emit JSON-Schema draft-style arrays.

Common situations: A custom in-process MCP server registered with tool dicts lacking 'inputSchema'; a server copied from docs that uses 'parameters' instead of 'inputSchema'; a proxy that stringifies the schema; upstream server version change renaming the field.

Related errors


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