[BUG] Desktop app rejects MCP calls that omit optional parameters (expected, nonoptional, rerecived undefined)

Status Fixed / completed
Reported on v2.1.273
Maintainer reply None cached
Activity 3 comments · opened Sep 15, 2026 · closed Sep 16, 2026

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

  1. 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.

  1. 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={...})

  1. 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.

  1. 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"

  1. 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.

  1. 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_transform
  • ha_get_entity ‚Äî entity_id / unique_id ("Provide exactly one of entity_id or unique_id, not both.")
  • ha_config_get_dashboard ‚Äî mode, typed Literal['search'] | None; None cannot be expressed, so only mode="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

View original on GitHub ↗

3 Comments

tozwierz · 28 days ago

Same issue here with ha-mcp 8.4.3, Claude Desktop 2.110.0 on macOS. Additional data point that narrows the regression:

  • Bundled Claude Code 2.1.270: works (including write tools with mutually exclusive optional params)
  • 2.1.271: broken — from the first MCP call after the session switched versions

Timeline from ~/Library/Logs/Claude/main.log:

  • 2026-09-15 22:25 — app initialized 2.1.271; the running session stayed on fallback 2.1.270, all MCP calls fine
  • 2026-09-16 08:04 — first session spawned on 2.1.271 → expected nonoptional
  • 2026-09-16 08:40 — existing session switched 2.1.270 → 2.1.271 → error from the next call
  • App restart doesn't help

Pattern: only properties declared as {"default": null} without type are 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.

alexnbg88 · 28 days ago

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:

  • {"type": "boolean", "default": false} on a local stdio server from claude_desktop_config.json (schema draft-07)
  • {"type": "number", "default": 5} on a Desktop extension (schema draft-07)

Accepted in the same session, with a defaulted parameter omitted:

  • {"type": "number", "default": 2500} on a remote HTTP server added with claude mcp add (schema draft 2020-12)
  • {"type": "integer", "default": 25} on a claude.ai connector (no $schema)

Workaround until fixed: pass every parameter that has a default explicitly.

HolgerSeithHmh · 28 days ago

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, mcp 1.30.0), started via uvx 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": null and absent from required is reported as expected nonoptional, received undefined, e.g. jira_get_issue called with only issue_key lists expand, properties, update_history, use_display_names.

One more shape of the deadlock: jira_add_comment has "public": {"type": "boolean", "default": null}. Omitting it is rejected client-side, passing null fails with expected boolean, received null, and passing false is 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.