Skip to content

fix: omit SerializedMember 'name' when null to honor output schema#87

Merged
IvanMurzak merged 2 commits into
mainfrom
worktree-86-serializedmember-name-null
Jun 2, 2026
Merged

fix: omit SerializedMember 'name' when null to honor output schema#87
IvanMurzak merged 2 commits into
mainfrom
worktree-86-serializedmember-name-null

Conversation

@IvanMurzak

Copy link
Copy Markdown
Owner

Summary

  • SerializedMemberConverter.Write now omits the name property when it is null instead of writing "name": null, which violated the converter's own output JSON Schema (which types name as a non-nullable string and does not list it in required). Strict MCP clients (e.g. Copilot) were rejecting SerializedMember-returning tool results with -32602.
  • The schema is unchanged (NOT widened to ["string","null"]PostprocessFields strips "null" from type unions). An absent non-required key is schema-valid; a present key is always a string.
  • Adds regression tests: null-name omission, non-null string emission, the schema contract (name typed string, not required), and round-trip stability.

Test plan

  • Suite 1 — ReflectorNet xUnit: 1465 passed / 0 failed on net8.0 + net9.0.
  • Suite 2 — MCP-Plugin-dotnet consumer (against locally-packed ReflectorNet): McpPlugin.Tests 268 + McpPlugin.Server.Tests 409 passed / 0 failed, both TFMs.
  • Suite 3 — Unity-MCP-Plugin EditMode: 961 passed / 0 failed.

Closes #86

SerializedMemberConverter.Write always wrote the "name" property, emitting
JSON null for value-only / root / unnamed members. The converter's own schema
types "name" as a non-nullable "string" and does not list it in "required", so
"name": null violated the advertised output schema and strict MCP clients
(e.g. Copilot) rejected the tool result with -32602.

Write "name" only when non-null. An absent non-required key is schema-valid;
a present key is always a string. The schema is left unchanged (NOT widened to
["string","null"] — PostprocessFields strips "null" from type unions).

Adds regression tests covering null-name omission, non-null string emission,
the schema contract (name typed string, not required), and round-trip stability.

verified-downstream: McpPlugin.Tests, McpPlugin.Server.Tests, Unity-EditMode

Closes #86
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Test Results

    2 files  ± 0      2 suites  ±0   8m 4s ⏱️ -49s
1 466 tests + 5  1 466 ✅ + 5  0 💤 ±0  0 ❌ ±0 
2 932 runs  +10  2 932 ✅ +10  0 💤 ±0  0 ❌ ±0 

Results for commit b3cfb4f. ± Comparison against base commit 90dcb1c.

♻️ This comment has been updated with latest results.

The existing facts cover null-name omission only at the flat/root level.
Add a regression test for the recursive case from issue #86: a SerializedMember
tree whose fields/props children have a null name. Because children are
serialized through the same converter, the omit-when-null behavior must hold at
every depth — real tool outputs (assets-get-data, gameobject-component-get) return
nested trees whose value-only leaves legitimately have null names.

Asserts each nested child object omits the "name" key while the parent's name and
every typeName are preserved.

Closes #86
@IvanMurzak IvanMurzak merged commit 77ccfc0 into main Jun 2, 2026
2 checks passed
@IvanMurzak IvanMurzak deleted the worktree-86-serializedmember-name-null branch June 2, 2026 20:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SerializedMember serialization emits name:null, violating the tool output schema (omit name when null)

1 participant