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

Invalid input schema for {origin}

Error message

Invalid input schema for {origin}

What it means

Each MCP tool definition must carry an inputSchema that is a dict whose 'type' is 'object' (absent 'type' defaults to 'object'). A schema that is not a dict, or typed as 'array'/'string'/etc., is rejected with ValueError because the host republishes it as the tool's input_schema for the model and only object schemas are valid for tool arguments.

Source

Thrown at s15_integrated_harness/code.py:2563

    for server_name, mcp_client in mcp_clients.items():
        safe_server = normalize_mcp_name(server_name)
        for tool_def in mcp_client.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=mcp_client, 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


# -- Lead Worktree Tools --

View on GitHub (pinned to 985456f4ad)

Solutions

  1. Make inputSchema an object schema: {"type": "object", "properties": {...}, "required": [...]}
  2. If a tool takes no arguments, use {"type": "object", "properties": {}} or omit inputSchema entirely (it defaults)
  3. Add a fixture/test that registers every production tool_def so schema errors surface in CI

Example fix

# before
{"name": "deploy", "inputSchema": {"type": "array", "items": {"type": "string"}}}

# after
{"name": "deploy", "inputSchema": {"type": "object", "properties": {"target": {"type": "string"}}, "required": ["target"]}}
Defensive patterns

Strategy: validation

Validate before calling

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

for tool in client.tools:
    assert is_object_schema(tool.get("inputSchema", {})), f"bad schema on {tool.get('name')}"

Type guard

def has_valid_input_schema(tool_def: dict) -> bool:
    schema = tool_def.get("inputSchema", {})
    return isinstance(schema, dict) and schema.get("type", "object") == "object"

Try / catch

try:
    harness = build_harness(mcp_clients)
except ValueError as exc:
    if "Invalid input schema" in str(exc):
        # origin in message identifies server/tool; fix its inputSchema to an object schema
        raise SystemExit(str(exc)) from exc
    raise

Prevention

When it happens

Trigger: Registering a tool_def with "inputSchema": {"type": "array", ...}, with "inputSchema": [] or a string, or omitting a malformed schema key ('inputSchema': None). Tools registered without register() and appended directly to client.tools bypass the earlier name checks but still hit this one at wiring time.

Common situations: Hand-writing tool definitions instead of using a schema helper. Copying an output schema into the inputSchema field. MCP servers from other ecosystems that describe args as a JSON array of parameters instead of a JSON-schema object.

Related errors


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