`_build_input_schema` misclassifies properties-less JSON Schemas as param mappings, breaking no-arg tools

Aperta Adatta ai principianti
#1,509 0 commenti 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 2 giorni

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
2/5
Tempo stimato
1-3 ore
Idoneità per principianti
74/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Attiva
Stack tecnologico
python
Ambito
api

Direzione di ricerca

Inizia da _build_input_schema in src/claude_agent_sdk/init.py (intorno alle righe 439-453), dove un dict grezzo viene passato così com'è solo se contiene sia 'type' sia 'properties'. Leggi il test di passthrough esistente, test_json_schema_constraints_are_enforced in tests/test_sdk_mcp_integration.py, e riproduci il problema con {"type": "object"} tramite create_sdk_mcp_server. Il lavoro è completo quando quello schema viene restituito invariato, una chiamata con {} esegue l'handler, le mappature di parametri in stile dict con parametri di tipo valore vengono ancora costruite correttamente e i test esistenti passano.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug

Summary

_build_input_schema recognizes a raw JSON Schema dict only when it has both 'type' and 'properties' keys. Any valid JSON Schema without 'properties' — e.g. {"type": "object"}, {"type": "object", "additionalProperties": false}, {"anyOf": [...]} — is silently reinterpreted as a dict-style param mapping: its schema keywords become required string-typed parameters, and every call with the intended arguments fails validation with a misleading error.

This is a correctness bug, not a security vulnerability: the schema dict comes from the developer's own tool definition.

Version

  • Repo: anthropics/claude-agent-sdk-python
  • Package: claude-agent-sdk 0.2.181
  • Commit: 22b8eb9c19adfa78759b79e22bd664a57843bb06 (main, 2026-11-12)

Location

src/claude_agent_sdk/__init__.py:439-453 (_build_input_schema):

if isinstance(tool_def.input_schema, dict):
    if (
        "type" in tool_def.input_schema
        and "properties" in tool_def.input_schema
        and isinstance(tool_def.input_schema["type"], str)
    ):
        return tool_def.input_schema
    properties = {
        param_name: _python_type_to_json_schema(param_type)
        for param_name, param_type in tool_def.input_schema.items()
    }
    return {
        "type": "object",
        "properties": properties,
        "required": list(properties.keys()),
    }

For {"type": "object"}, _python_type_to_json_schema("object") falls through every branch (:381-413) to the default {"type": "string"} at :415, yielding properties: {"type": {"type": "string"}} with required: ["type"].

The tool() docstring promises input_schema may be "A JSON Schema dictionary for full validation" (:294-298) with no properties requirement, and test_json_schema_constraints_are_enforced (tests/test_sdk_mcp_integration.py:999-1017) establishes raw-schema passthrough as intended behavior for the type+properties shape. No test or doc states properties-less schemas are unsupported. ({} remains a working no-arg form — docstring :334 — which does not disprove misclassification of the canonical {"type": "object"} schema.)

The trigger chain: create_sdk_mcp_server builds the bogus schema (:606), run_tool validates with jsonschema.validate (:630) and returns an "Input validation error" (:631-632).

Minimal repro

import asyncio
from claude_agent_sdk import tool, create_sdk_mcp_server

@tool("t", "intended no-arg tool", {"type": "object"})
async def t(args):
    return "t-ran"

server = create_sdk_mcp_server("srv", tools=[t])
# tools/list advertises the schema, and tools/call "t" with {} fails:
#   Input validation error: 'type' is a required property

Schema-level demonstration of the misclassification:

# _build_input_schema({"type": "object"}) produces:
{"type": "object", "properties": {"type": {"type": "string"}}, "required": ["type"]}
# jsonschema.validate({}, <that schema>) raises:
#   ValidationError: 'type' is a required property

The same misclassification applies to {"type": "object", "additionalProperties": false} (keywords become required params type and additionalProperties) and {"anyOf": [...]} (anyOf becomes a required string parameter).

Observed: the advertised wire schema is the bogus rebuilt schema, and a live call with {} through the real run_tool closure and the real jsonschema package is rejected with 'type' is a required property.

Expected: {"type": "object"} passes through verbatim as the tool's input schema, and a call with {} runs the handler.

Impact

Developers who declare tools with the canonical no-argument JSON Schema {"type": "object"} (or any properties-less schema) get a tool that rejects every intended call with a misleading error demanding a bogus parameter — while the schema the tool advertises on the wire is wrong. The failure is silent at definition time and only surfaces at call time. Local functional impact only.

Suggested fix

Broaden the raw-schema recognition in _build_input_schema to accept dicts carrying JSON Schema keywords — e.g. 'type' with a string value, or 'anyOf' / 'allOf' / 'oneOf' / '$ref' / 'additionalProperties' — even without 'properties', returning them verbatim instead of rebuilding them as param mappings. (Note the known ambiguity: a dict-style param literally named "type" with a string value would need care; the dict-style form with type-valued params should keep building as a param mapping.)

Environment

  • Python 3.12.3, Linux; jsonschema 4.10.3 (real package; the SDK declares >=4.20.0, but the required-property rejection exercised here is stable across these versions, and the misclassification is visible in the produced schema dict independently of the validator)
  • Verified against the pinned commit above. Baseline: a type+properties raw schema passes through verbatim; dict-style {"name": str} builds a correct param schema and the live call succeeds; {} builds an empty-properties schema and the live no-arg call succeeds. The live call was exercised on the MCP 1.x server path; the defect is in _build_input_schema, which both majors consume, and the bogus schema is demonstrated directly from that function as well as via the wire listing.
Lingua principale
Python
Stelle
8.5k
Fork
1.4k
Merge medio
3g 10h
PR unite (30g)
13

Preparare l'ambiente

Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di anthropics/claude-agent-sdk-python

Tutte le issue di anthropics/claude-agent-sdk-python

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.