MCPのオプション引数を省略しただけで拒否される——Claude Code「nonoptional」エラーの正体
Claude CodeのMCP連携で、省略可能なはずのパラメータを外すだけでexpected nonoptional, received undefinedエラーになる回帰をGitHub Issueから整理。原因の見立て・回避策・自作サーバー側の対策までまとめた。
エンジニアのゆとです。
MCPサーバーのツールを呼んだら、渡してもいないパラメータについて「省略できないはずなのに省略されてる」という趣旨のエラーで弾かれる——そんな報告がここ数日、GitHub Issue側で立て続けに増えている。
Input validation error: Invalid arguments for tool ha_get_state: [
{"code":"invalid_type","expected":"nonoptional","path":["fields"],"message":"Invalid input: expected nonoptional, received undefined"},
{"code":"invalid_type","expected":"nonoptional","path":["attribute_keys"],"message":"Invalid input: expected nonoptional, received undefined"}
]
fieldsもattribute_keysも、MCPサーバー側のスキーマではちゃんと「省略可能・未指定ならデフォルト値を使う」と定義されている。なのにClaude Code側は「これは省略できない値だ(nonoptional)」と言って、渡していないことそのものをエラーにする。設定ミスでも、サーバー側のバグでもない。Claude Code側のツール呼び出しの検証ロジックで起きている回帰だ。
自分もMCPサーバーを何本か自作していて、この手の「クライアント側の検証層が変な挙動をする」系の不具合は一番厄介だと思っている。サーバー側のコードは何も変えていないのに、ある日突然呼べなくなる。しかも原因がクライアント側にあると、こっちでは直しようがない。今回は現時点(2026年9月17日)でまだ未修正のこの不具合を、GitHub Issueの一次情報ベースで整理しておく。
まず結論——省略可能パラメータを持つMCPツールが広く影響を受けている
先に状況を整理する。
- 症状: MCPツールの呼び出しで、JSON Schema上は省略可能(
requiredに含まれない、またはdefault付き)なパラメータを省略しただけでexpected: "nonoptional", received: "undefined"エラーになる - 発生箇所: 主にClaude Desktopアプリの「Code」タブ(内蔵のClaude Code)で再現報告が集中している
- 影響サーバー: 特定のMCPサーバー固有の問題ではない。Home Assistant連携の
ha-mcp、メモアプリ連携のjoplin-mcp、独自実装のaicontextmcpなど、実装もプロトコルSDKもバラバラな複数のMCPサーバーで同一のエラー文言が報告されている - バージョン境界: Windows環境での検証報告によると、Claude Code内蔵バージョン2.1.270までは正常、2.1.271から発生している
- 現在のステータス: 記事執筆時点(2026年9月17日)で、GitHub Issue #94718・#94608・#94890のいずれも未修正。Anthropic側からの公式な原因確定コメントもまだない
「特定のMCPサーバーの相性問題」に見えて、実際はクライアント側(Claude Code)のツール呼び出し検証層に起きている広範な回帰、というのがここまでの一次情報から読み取れる一番確からしい理解だ。
症状は2種類ある——「値を足せば直る」ケースと「詰む」ケース
このバグ、実は影響の深刻さが2段階に分かれている。
パターン1: 省略可能パラメータを明示的に渡せば回避できる
さきほどのha_get_stateのように、単純に「省略可能な値を省略したら拒否される」だけのケースは、その値を明示的に渡してやれば通る。fieldsやattribute_keysのようなリスト型なら空のリストを、文字列型なら空文字を渡すことでエラー自体は消える。
パターン2: 「AかBのどちらか一方だけ」を要求するツールで詰む
厄介なのはこちらだ。ha_call_serviceというツールは、通常のサービス呼び出し(domain/service/entity_id)か、WebSocketコマンド一発呼び出し(ws_command)のどちらか一方だけを受け付ける設計になっている。ツール自身のロジックはこう言う。
"These parameters apply only to service calls and must be omitted when
ws_command is set: entity_id, result_fields, result_attribute_keys."
ところがクライアント側の検証層は、ws_commandも含めて「全部のオプション引数を必ず渡せ」と要求してくる。
{"code":"invalid_type","expected":"nonoptional","path":["ws_command"],
"message":"Invalid input: expected nonoptional, received undefined"}
ws_commandを「省略する」という選択肢が検証層で潰されているので、通常のサービス呼び出しをしようとすると必ずこのエラーになる。かといってws_commandに何か値を入れると、今度はツール自身が「サービス呼び出しとws_commandは同時に使えない」と拒否してくる。空文字もnullも、JSON上のnullとして送る手段がない限り「値がある」扱いになってしまうので、この手のツールは今のところ呼び出す方法自体が存在しない。Issue報告者の言葉を借りるなら「クライアントは全項目の存在を要求し、サーバーはその一部の不在を要求する」という、ユーザー側では解決できない板挟み状態になる。
同じ形の詰みは、entity_idかunique_idのどちらか一方だけを要求するツールや、actionの値ごとに必須・禁止パラメータの組み合わせが変わるha_manage_hacsのようなツールでも報告されている。「AかBのどちらか一方だけ受け付ける」設計のMCPツールを使っている場合は、このパターンに当たっていないか疑ったほうがいい。
なぜ起きるのか——コミュニティが特定した2つの仮説
Anthropicからの公式な原因確定はまだ出ていないが、Issueのコメント欄でかなり具体的な技術的検証が進んでいる。大きく2つの見立てがある。
仮説A: クライアントとAgent SDKでZodのバージョンがズレている
Issue #94718のコメントで、Claude Desktop 2.110.0のバンドルを実際に読んだ検証者が原因を突き止めている。要点はこうだ。
- ローカルのstdio型MCPサーバーの場合、Claude Codeはツールを内蔵のAgent SDKの
tool()経由で再登録し直している - その過程で、ツールのJSON Schemaをアプリ本体側が持つZod 4.5.4でZodのスキーマ形に変換する。このとき
default付きのプロパティは.prefault(default)に、必須でないプロパティは.optional()に変換される - Zod 4.5系では、この
.optional()は内部的に_zod.optin === "defaulted"という状態を持つ - ところが実際の入力検証を行うのはAgent SDK側が内蔵する別バージョンのZod 4.4.3で、こちらの
handlePropertyResultはoptin === "optional"のときだけそのキーを省略可としてくれる。"defaulted"は対象外 - 結果、
defaultを持つプロパティは軒並み「省略不可(nonoptional)」判定になる
検証者が示した最小再現コードはこうだ。
// 内側のスキーマを[email protected]で、外側のz.objectを[email protected](zod/mini)で組み立てると…
z.object({ limit: z.number().prefault(null).optional() })
// -> {} を渡すと nonoptional エラーになる
// 両方とも4.5.4で揃えると正常にパースできる
アプリ本体とAgent SDKバンドルという、本来同期しているはずの2つのビルド成果物の間でライブラリのバージョンがズレた、という典型的な依存関係の管理ミスに見える。
仮説B: JSON Schemaの情報がクライアントに渡る過程で欠落している
一方でIssue #94890では、別の角度からの検証が報告されている。aicontextmcpという自作MCPサーバーに対して、サーバーへ直接stdioでtools/listを叩いた「生のスキーマ」と、Claude CodeのToolSearch経由で見えているスキーマを突き合わせたところ、後者ではtypeの型情報・additionalProperties: false・条件付き必須を定義するallOfブロックがまるごと消えていた。
生のスキーマにはあるが、Claude Code側に渡る時点で消えているもの:
- projectId / remote などのフィールドの "type": ["string", "null"]
- オブジェクト全体の "additionalProperties": false
- register=true のときだけrequestIdを必須にする allOf条件ブロック
この報告者は「typeが無い状態を見て、キーを必ず存在させろという判定に倒れているのでは」という見立てを立てているが、どのコンポーネントがこの欠落を起こしているかまでは特定できていない、と正直に書いている。
2つの仮説は微妙に違う角度からの指摘だが、「クライアント側でツールのスキーマを内部表現に変換する過程で、オプション性の情報が壊れる」という結論の方向性は共通している。どちらか一方が全体を説明しているのか、実は複数の要因が重なっているのかは、記事執筆時点ではまだ確定していない。
自分のセッションが影響を受けているか確認する
影響範囲の切り分けとして、まず自分の環境がどこに当てはまるか確認しておくといい。
claude --version
Windows環境での検証報告では、内蔵バージョン2.1.270までは同じMCPサーバー・同じツール呼び出しで問題なく通り、2.1.271になった瞬間に同じ呼び出しがnonoptionalエラーになる、という境界がセッションのトランスクリプトから確認されている。Claude Desktopアプリを使っている場合、claude --versionで出るのはPATH上のCLIバイナリのバージョンで、アプリが内部でバンドルしているClaude Codeビルドと必ずしも一致しない点には注意が要る。アプリの「バージョン情報」画面から確認するほうが確実だ。
再現報告の大半がClaude Desktopアプリの「Code」タブに集中している点も見ておく価値がある。Issue #94608の報告者は、同じマシン・同じ~/.claude.json・同じMCPサーバーに対して、Desktopアプリではnonoptionalエラーになる呼び出しが、ターミナルからclaude --resumeで同じセッションを開いた場合は問題なく通った、と書いている。この切り分けが常に有効だという保証はないが、Desktopアプリで詰まっているなら、一度ターミナル側のCLIで同じ操作を試してみる価値はある。
今できる回避策
修正を待つ間、現実的に取れる手はいくつかある。
1. 省略可能な値を明示的に渡す(パターン1のケース)
「AかBのどちらか一方だけ」という排他制約を持たないツールなら、省略せずに値を渡すことでエラー自体は回避できる。リスト型なら空リスト、文字列型なら空文字を渡してみる。ただしIssueのコメントでは、anyOf: [型, "null"]のように定義されたパラメータに対してJSONのnullを送ったつもりが、クライアント側でリテラル文字列"null"として送信されてしまい、結局サーバー側のバリデーションで別のエラーになるという報告もある。値を渡せば必ず解決する、とは言い切れない。
2. バージョンを2.1.270にピン留めする
境界がはっきりしている以上、2.1.270まで固定してしまうのが一番確実な回避策になる。ただし2.1.270にも別のバグが残っている可能性はあるので、あくまで「このバグを避けるための一時措置」として捉えたほうがいい。

3. Desktopアプリの「Code」タブではなく、ターミナルのCLIから同じ作業をする
前述のとおり、同一環境でもDesktopアプリのCodeタブとターミナルCLIとで挙動が違う、という報告が複数ある。恒久対策にはならないが、目の前の作業を今すぐ通したいだけなら試す価値はある。
4. デッドロック型のツール(パターン2)は、今のところ回避策なし
「AかBのどちらか一方だけ」を要求するツールについては、Issueを見る限り記事執筆時点で有効な回避策が見つかっていない。該当するツールを使う作業は、修正がリリースされるまで別の手段(サーバーのAPIを直接叩く、Web UIから操作する等)に一時退避させるほうが現実的だ。
自分でMCPサーバーを作っている人向け——サーバー側でできる緩和策
このブログはMCPサーバーを自作する読者も多いと思うので、サーバー実装者目線での話も書いておく。
Issue #94718のコメントには、サーバー側だけでできる緩和策も紹介されている。ツールのJSON Schemaで、トップレベルのプロパティにdefaultキーを持たせないようにする、というものだ。
ワークアラウンド: tools/listのレスポンスから、各ツールのinputSchema.properties
の各プロパティが持つ default キーを削除する小さなstdioラッパーを挟む。
これでクライアント側の変換結果はただの.optional()になり、検証を通過する。
サーバー自身のデフォルト値適用ロジックはそのまま生きる。
defaultを宣言しなければ.prefault()経由の変換が起きず、単純な.optional()として扱われるので今回の不具合を踏まない、という理屈だ。自作サーバーのスキーマ定義にdefaultを書いている場合、そのデフォルト適用をクライアントに申告する部分と、サーバー内部で実際にデフォルト値を当てるロジックを分離しておくと、こういうクライアント側の回帰に振り回されにくくなる。当面の設計判断として頭の片隅に置いておくといいと思う。
MCPサーバーの基本的な作り方・設定の全体像はこちらにまとめてある。

似た症状と混同しないために
MCP関連のエラーは「接続自体ができない」系と「接続はできているが呼び出しで弾かれる」系が混同されがちなので、整理しておく。
| 症状 | 該当する記事 |
|---|---|
/mcpやclaude mcp listでFailed to connectになる、ツールが0件になる | 接続トラブルの症状別対処表 |
ツール呼び出し自体がexpected nonoptional, received undefinedで拒否される(本記事) | — |
| MCPツールの説明文やドキュメント部分がキャッシュされず毎回課金対象になる | プロンプトキャッシュ無効化の記事 |
「接続はできているのに特定のツールだけ呼べない」場合は本記事の話、「そもそも接続ステータスが赤い」場合は別の話になる。

MCP関連の不具合は最近立て続けに報告が出ている。少し前にはプロンプトキャッシュが効かずコストが跳ねる不具合も扱ったので、MCP運用でコストや挙動の違和感を感じている人は合わせて見ておくと切り分けの参考になる。

FAQ
このエラーは自分のMCPサーバーの設定ミスですか?
違う可能性が高い。ha-mcp・joplin-mcp・独自実装サーバーなど、実装もプロトコルSDKも異なる複数のMCPサーバーで同じ文言のエラーが報告されている。サーバー側のtools/listが返すスキーマ自体は正しいのに、クライアント側の検証で弾かれているケースが大半なので、まずはclaude --versionで影響を受けるバージョンに当たっていないか確認するのが先になる。
Anthropicから修正の見通しは出ていますか?
記事執筆時点(2026年9月17日)では、CHANGELOG.mdにもIssueのコメント欄にも公式の修正コメントは出ていない。Issue自体は「has repro」ラベルが付いた状態で活発に追記が続いているので、動きがあれば比較的早くリリースノートに反映されると見ていいと思う。claude --versionで自分のバージョンを確認する習慣をつけつつ、Issueをウォッチしておくのが一番確実だ。
CLIなら絶対に安全ですか?
そこまでは言い切れない。報告の大半はDesktopアプリの「Code」タブに集中していて、同一環境でCLIなら通ったという報告もあるが、Windows環境の検証ではCLI相当の内蔵バージョンでも境界(2.1.270→2.1.271)が確認されている。「試す価値のある回避策」ではあるが、「保証された回避策」ではない、という前提で使ったほうがいい。
まとめ
Claude CodeのMCPツール呼び出しで、省略可能なはずのパラメータを省略しただけでexpected nonoptional, received undefinedエラーになる回帰が、記事執筆時点で複数のGitHub Issueにまたがって報告されている。原因はサーバー側ではなくクライアント側の検証層にあり、Zodのバージョン不一致・JSON Schemaの情報欠落という2つの技術的な仮説がコミュニティから出ているが、Anthropicによる公式な原因確定はまだない。
単純な省略拒否なら値を明示的に渡すことで回避できるが、「AかBのどちらか一方だけ」を要求するツールは現状回避策がなく、修正を待つしかない。当面はバージョンを2.1.270にピン留めするか、Desktopアプリではなくターミナル側のCLIで同じ作業を試すのが現実的な立ち回りになる。MCPサーバーを自作している側は、スキーマのdefault宣言とサーバー内部のデフォルト適用ロジックを分離しておくと、この手のクライアント側の回帰に巻き込まれにくくなる。
Claude Code本体は更新頻度が高いぶん、この手の回帰も次々出てくる。MCPを実務で使っている人ほど、アップデート直後は普段使っているツールが一通り呼べるか軽く確認する癖をつけておいたほうがいい。