Repository navigation
fix(mcp): keep padded optional arguments from filtering MCP reads - #1578
TheGreatAxios merged 2 commits into
Conversation
Self-Review (
|
|
Triage: Pass No changes needed from you. A maintainer will review this pull request. |
There was a problem hiding this comment.
Review · Approve
When a model fills an optional argument with null on a read-only tool, that null is removed before the call. A padded null no longer filters the results. On Linear, that is the difference between listing every issue in a release and getting none, because assignee: null means "unassigned." Write tools still receive null, so clearing a field still works. GPT models are told they may send null for "not set," and only on fields where that null will be removed again.
bun test src/mcp/placeholder-args.test.ts src/mcp/plugin.test.ts src/agent/tool-schema-normalize.test.ts src/session/assemble-runtime.test.ts src/mcp/tool-permissions.test.ts — 117 pass, 0 fail.
Two cases where the read-only check still keeps or drops the wrong null:
-
A list or get tool sometimes arrives marked "not destructive" or "can reach the network," but without an explicit read-only mark (
src/mcp/tool-permissions.ts:61). We then treat it as a write and keep null. On Linear,assignee: nullmeans "unassigned," so a request for every issue comes back empty. If the tool is also marked read-only, null is dropped and this does not happen. -
Some tool names only look read-only (
src/mcp/tool-permissions.ts:64).search_replace,get_or_create_issue, and similar names are treated as reads, so a null that was meant to clear a field is deleted and the field stays as it was.update_issuekeeps null unless the server marks that tool read-only, in which case a clear is deleted too.
Summary
readOnlyHint, or alist_/get_-style name) no longer receive JSONnullon optional arguments: the handler drops it, so a paddedassignee: nulldoes not filter Linearlist_issuesdown to unassigned issues. Write tools keepnull, which they use to clear a field.nullin the wire schema, so the model writesnullfor "not set" instead of a real value such aspriority: 0. A property gainsnullonly where the handler drops it again, and only when the widened property still validatesnullunder JSON Schema.Verification
bun run check(lint, typecheck, dead exports, build, test suite) passes: 9524 pass, 0 fail.codex/plus/gpt-5.6-terra, asking for every issue in releasev0345-ef53e73667fareturns all 6 issues from onelist_issuescall in 5 of 5 runs;origin/mainreturns 0 in 5 of 5. Per-configuration counts are on CL-11352."null"returns the same unassigned issues as JSONnull(raw MCP call), so "unassigned" stays reachable on read tools.Fixes CL-11352