Skip to content

Fix: Support additionalProperties as both boolean and schema object#73

Merged
leehack merged 2 commits intoleehack:mainfrom
benkaiser:main
Feb 27, 2026
Merged

Fix: Support additionalProperties as both boolean and schema object#73
leehack merged 2 commits intoleehack:mainfrom
benkaiser:main

Conversation

@benkaiser
Copy link
Contributor

@benkaiser benkaiser commented Feb 23, 2026

Problem

JsonObject.fromJson() hard-casts additionalProperties as bool?:

additionalProperties: json['additionalProperties'] as bool?,

In https://json-schema.org/understanding-json-schema/reference/object#additionalproperties, additionalProperties can be either a boolean (true/false) or a schema object constraining the shape of extra properties. When an MCP server returns a tool schema where additionalProperties is an object (e.g., {}), the parser throws:

type '_Map<String, dynamic>' is not a subtype of type 'bool?' in type cast

This crashes tools/list parsing entirely, preventing the client from connecting to the server.

Reproduction

Any MCP server whose tools use Zod's z.record() will trigger this. For example, the
https://github.com/modelcontextprotocol/ext-apps/tree/main/examples/debug-server from the official ext-apps repo defines:

z.object({
  config: z.record(z.string(), z.unknown()),
  // ...
})

Which produces the JSON Schema:

{
  "type": "object",
  "properties": {
    "config": {
      "type": "object",
      "additionalProperties": {}
    }
  }
}

The additionalProperties: {} is a valid schema object (accepts any value), but mcp_dart crashes trying to cast it as
bool?.

Fix

  • Changed JsonObject.additionalProperties from bool? to Object?, which can hold either a bool or a JsonSchema
  • fromJson() now checks the runtime type: bool values are stored directly, Map values are parsed as JsonSchema.fromJson()
  • toJson() serializes JsonSchema values back via .toJson(), booleans are written directly
  • JsonSchemaValidator now validates extra properties against the schema when additionalProperties is a JsonSchema
    (previously it had a TODO comment acknowledging this was missing)

Notes

This PR was AI-assisted (Claude). I did review the code myself and also validated it worked end-to-end on the stated debug server from the official examples.

JSON Schema allows additionalProperties to be either a boolean or a
schema object constraining extra properties. The parser was hardcoded
to cast it as bool?, crashing when MCP servers return tool schemas
with additionalProperties as an object (e.g. from z.record()).
@codecov
Copy link

codecov bot commented Feb 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 78.49%. Comparing base (8a4bfb3) to head (8882640).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main      #73      +/-   ##
==========================================
+ Coverage   78.45%   78.49%   +0.04%     
==========================================
  Files          40       40              
  Lines        5371     5381      +10     
==========================================
+ Hits         4214     4224      +10     
  Misses       1157     1157              
Flag Coverage Δ
unittests 78.49% <100.00%> (+0.04%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Parse additionalProperties when decoded as Map<dynamic, dynamic> so schema objects like {} are not dropped. Add regression tests and document the 2.0.0 breaking JSON Schema API update in the changelog.
@leehack
Copy link
Owner

leehack commented Feb 27, 2026

Thanks for the contribution @benkaiser

@leehack leehack merged commit e5e4945 into leehack:main Feb 27, 2026
1 check passed
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.

2 participants