[BUG] Desktop app rejects MCP calls that omit optional parameters (expected, nonoptional, rerecived undefined)
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
Desktop app rejects MCP calls that omit optional parameters (expected nonoptional, received undefined)
Tool params declared "default": null in the server's JSON Schema are being treated as required by the desktop app's client-side validation. Supplying them to satisfy the validator then trips server-side mutually-exclusive-parameter checks, making those tools uncallable — no value ("", {}, null) represents "absent".
Repro: call ha_config_set_dashboard (ha-mcp) with only url_path and config. Client rejects with expected nonoptional for 8 params. Supply them → server returns "Cannot use both config and python_transform simultaneously."
Not reproducible in the Claude Code CLI — same MCP server, same machine, same ~/.claude.json. Desktop-client-only.
nonoptional suggests a Zod v4 schema-conversion regression where default: null is mapped to a required field
What Should Happen?
It should work. It works on the same machine from claude code terminal. It has explained to me the above report and this is a frustrating bug that makes using claude code and desktop are not able to do the same changes
Error Messages/Logs
Steps to Reproduce
- Connect an MCP server whose tools declare optional parameters — i.e. properties
present in the schema with "default": null and not listed under required.
Reproduced with ha-mcp (Home Assistant), but the shape is generic.
- In the Claude Code desktop app, have Claude call such a tool while omitting
one or more of those optional parameters. Example — ha_config_set_dashboard
with only url_path and config:
ha_config_set_dashboard(url_path="presence-radar", config={...})
- The call is rejected by client-side validation before it reaches the server.
Every optional parameter is reported as missing:
{"code": "invalid_type",
"expected": "nonoptional",
"path": ["python_transform"],
"message": "Invalid input: expected nonoptional, received undefined"}
…repeated for config_hash, title, icon, require_admin, show_in_sidebar,
return_screenshot and view_path — 8 optional params in total.
- Retry, now supplying a value for every parameter the validator demanded.
The call reaches the server and is rejected there, because two *mutually
exclusive* optional parameters are now both present:
"Cannot use both config and python_transform simultaneously"
- Try to express "absent" for the conflicting parameter. Every option fails:
python_transform="" -> server sees a string, not None -> same error
python_transform=null -> arrives as the string "null" -> same error
config={} -> passes typing, still not None -> same error
config="" -> "expected a JSON object"
There is no value that means "omitted", so the tool is uncallable.
- Run the identical task in the Claude Code CLI — same machine, same
~/.claude.json, same MCP server:
cd <project> && claude --resume
It succeeds immediately. Desktop-client only.
Expected
Properties with "default": null that are absent from required are optional.
Omitting them should send them not at all, and the server should apply its default.
Actual
The desktop client treats them as required. Supplying them to satisfy the
validator then trips server-side mutual-exclusion checks (is not None), making
the tool impossible to call.
Also affected (same server)
ha_config_set_dashboard—config/python_transformha_get_entity—entity_id/unique_id("Provide exactly one of entity_id or unique_id, not both.")ha_config_get_dashboard—mode, typedLiteral['search'] | None; None cannot be expressed, so onlymode="search"is reachable
Read-only tools without a mutually-exclusive pair still work, which is what makes
this look like an HA or permissions problem at first.
Note
"expected": "nonoptional" is Zod v4 wording, suggesting the JSON Schema ‚Üí
Zod conversion maps default: null to a required field rather than an optional
one defaulting to null.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.273 (Claude Code)
Platform
Anthropic API
Operating System
macOS
Terminal/Shell
Terminal.app (macOS)
Additional Information
Claude Desktop version: Claude 2.110.0 (dfb2ba) 2026-09-15T05:50:55.000Z
3 Comments
Same issue here with ha-mcp 8.4.3, Claude Desktop 2.110.0 on macOS. Additional data point that narrows the regression:
Timeline from
~/Library/Logs/Claude/main.log:expected nonoptionalPattern: only properties declared as
{"default": null}withouttypeare affected; typed params with defaults (e.g.{"type": "boolean", "default": false}) pass. Rejected calls never reach the MCP server (no entry in its log), so validation is client-side.The 2.1.271 release notes mention changes to tool search / deferred MCP tools; all affected tools in my sessions were deferred and loaded via tool search — may or may not be related.
Adding data from a second macOS machine (Claude Desktop 2.110.0), same regression.
Bundled Claude Code 2.1.270: tool calls that omit parameters with a default worked (last seen 2026-09-15). 2.1.271 (installed 2026-09-16): the same calls are rejected with "expected nonoptional, received undefined". Rejected calls never reach the server (no entry in its log).
Correction to the comment above: typed parameters with a default are affected too, not only {"default": null} without a type. Rejected in the same Code session on 2.1.271:
Accepted in the same session, with a defaulted parameter omitted:
claude mcp add(schema draft 2020-12)Workaround until fixed: pass every parameter that has a default explicitly.
Same regression on Windows 11 (Claude Desktop, Code tab, Claude Code 2.1.234), so it is not macOS-specific, and with a different server:
mcp-atlassian 0.23.1(FastMCP 3.4.7,mcp1.30.0), started viauvx mcp-atlassian. Server packages were unchanged; the same calls worked in the same session a few hours before the desktop app update on 2026-09-16.Every parameter declared
"default": nulland absent fromrequiredis reported asexpected nonoptional, received undefined, e.g.jira_get_issuecalled with onlyissue_keylistsexpand,properties,update_history,use_display_names.One more shape of the deadlock:
jira_add_commenthas"public": {"type": "boolean", "default": null}. Omitting it is rejected client-side, passingnullfails withexpected boolean, received null, and passingfalseis a real value that routes the comment through the Service Desk API. So there is no way to call the tool with the "absent" semantics. Workaround for us: bypass MCP and call the Jira REST API directly.