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
- Make inputSchema an object schema: {"type": "object", "properties": {...}, "required": [...]}
- If a tool takes no arguments, use {"type": "object", "properties": {}} or omit inputSchema entirely (it defaults)
- 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
- Default every inputSchema to {"type": "object", "properties": {}}
- Generate schemas with a helper that always emits object schemas
- Never copy an array-style parameter list into inputSchema
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
- Every MCP tool needs a non-empty name
- Duplicate MCP tool name on server {self.name!r}
- Missing MCP handlers: {', '.join(missing)}
- MCP tool name is longer than 64 characters: {prefixed}
- Invalid input schema for {origin}
AI-assisted analysis of shareAI-lab/learn-claude-code@985456f4ad (2026-08-14).
Data as JSON: /api/errors/48e283ce844d7d45.
Report an issue: GitHub.