`_build_input_schema` misclassifies properties-less JSON Schemas as param mappings, breaking no-arg tools
メンテナーはふだん 2 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
src/claude_agent_sdk/init.py の _build_input_schema(439~453行目付近)から始めてください。ここでは、生の dict は 'type' と 'properties' の両方を持つ場合にのみそのまま渡されます。既存のパススルーテスト test_json_schema_constraints_are_enforced(tests/test_sdk_mcp_integration.py)を読み、create_sdk_mcp_server 経由で {"type": "object"} を使って再現してください。このスキーマがそのまま返され、{} での呼び出しでハンドラーが実行され、型の値を持つパラメータを使った dict 形式のパラメータマッピングが引き続き正しく構築され、既存のテストがすべて通れば完了です。
索引モデルが issue の本文から書いたものです。
説明
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-sdk0.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;
jsonschema4.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+propertiesraw 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.
- 主要言語
- Python
- スター
- 8.5k
- フォーク
- 1.4k
- 平均マージ
- 3日 10時間
- マージ済み PR(30日)
- 13
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
anthropics/claude-agent-sdk-python のほかの issue
-
`parse_message` raises raw `TypeError` instead of `MessageParseError` on non-dict nested payloadsオープンbug good first issue
難易度 2/5 半日 初心者へのやさしさ 76/100
anthropics/claude-agent-sdk-python#1508 ·
メンテナーはふだん 2 日以内に返信
-
bug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
anthropics/claude-agent-sdk-python#1507 ·
メンテナーはふだん 2 日以内に返信
-
`fork_session` hangs forever on a cyclic `parentUuid` chain (no cycle guard in `_build_fork_lines`)オープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
anthropics/claude-agent-sdk-python#1506 ·
メンテナーはふだん 2 日以内に返信
-
ClaudeSDKClient.connect() with an async iterable closes stdin, so follow-up query() fails対応中かも @m4xkushnir が 19 日前に担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
anthropics/claude-agent-sdk-python#1443 ·
メンテナーはふだん 2 日以内に返信
-
fork_session drops transcript entries containing U+2028/U+2029/U+0085 (str.splitlines), breaking the parentUuid chain対応中かも @mangeshraut712 が 19 日前に担当しました。 オープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
anthropics/claude-agent-sdk-python#1441 ·
メンテナーはふだん 2 日以内に返信
anthropics/claude-agent-sdk-python の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
dbt-labs/spark-utils#51 ·
-
bug pydanty:is-working
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
pydantic/pydantic-ai#13444 ·
メンテナーはふだん 1 日以内に返信
-
good first issue help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
good first issue help wanted
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
-
changelog investigate
難易度 1/5 1時間未満 初心者へのやさしさ 68/100
ramnes/notion-sdk-py#502 ·