v1.1.17
Fixed
-
Every tool was rejected by the client, because the advertised schemas declared JSON Schema draft-07. MCP has standardized on 2020-12, and hosts now refuse anything else —
Tool '<name>' has an invalid outputSchema: JSON Schema declares an unsupported dialect ("$schema": "http://json-schema.org/draft-07/schema#"). The default validator supports JSON Schema 2020-12 only.The server starts and connects normally, so the failure presents as all 26 tools silently unavailable rather than as a crash. The dialect comes from the MCP SDK, not from this repo:server/mcp.jscalls its Zod converter with notarget,mapMiniTarget(undefined)resolves todraft-7, and everyinputSchemaandoutputSchemais stamped draft-07 on the way out. Upgrading Zod does not fix it — both the v3 (zod-to-json-schema) and v4 (zod/v4-minitoJSONSchema) branches fall back to draft-07 without a target, verified empirically against SDK 1.30.0 + Zod 4.4.3 — so no dependency bump could have cleared this. The outgoingtools/listpayload is now normalized at the transport boundary, the only public seam that does not reach into SDK internals: the 2020-12 dialect is re-stamped at each schema root, nested$schemadeclarations are stripped (illegal on a subschema), and the keywords that changed between the drafts are rewritten —definitions→$defswith its#/definitions/…$refs repointed, tuple-formitems→prefixItems,additionalItems→items,dependenciessplit intodependentRequired/dependentSchemas, and booleanexclusiveMinimum/exclusiveMaximumcollapsed onto the numeric bound. Today's emitted schemas use none of those constructs, so the rewrite is a no-op on current output — it exists so a Zod construct added later cannot quietly reintroduce a draft-07-only keyword alongside a 2020-12 declaration, which would be worse than the bug it replaces. No tool, Zod schema, or handler changed; all 26 tools still register, and each now advertiseshttps://json-schema.org/draft/2020-12/schemaon both its input and output schema. Reported against the sibling server as sweetrb/apple-mail-mcp#147; all four Apple MCP servers were affected identically and are fixed in lockstep. -
The dialect converter is now POSITION-AWARE, so it cannot corrupt a tool parameter that happens to be named after a schema keyword. The first cut of the converter recursed uniformly and then switched on every key it met — but the keys of a
propertiesmap are caller-chosen tool parameter names, not schema keywords. A tool declaring a parameter nameddefinitionswould have had it renamed to$defson the wire; one named$schemawould have been silently deleted whilerequiredwent on naming it, producing a schema no input can satisfy;dependencieswould have been restructured intodependentRequired/dependentSchemasandadditionalItemsdropped outright. The same class applied to instance data:enum,const,defaultandexampleshold a caller's literal values, and recursing into them rewrote those literals as if they were schema keywords — adefaultof{ "definitions": 1 }came back as{ "$defs": 1 }. The walk now distinguishes the three positions: a name → schema map (properties,patternProperties,$defs,dependentSchemas) has only its values converted and its keys copied verbatim; data keywords (enum,const,default,examples,required,dependentRequired) pass through untouched; everything else is a schema and recurses as before. Verified latent, not live: no server in the fleet hits a corrupting name today — apple-notes-mcp'sget-checklist-statehas an output property nameditems, which happens to land in a safe branch — so this is fixed before the release rather than after. The advertisedtools/listpayload for all 26 tools is byte-identical across the fix (SHA-2568eb7f7b7…45ac3f10before and after), which is exactly the expected result for a latent defect.
Added
- The
outputSchemacontract test now asserts the advertised dialect. The existing checks boot the real built server over stdio and inspect what it advertises — every tool has anoutputSchema, none requires a field, none setsadditionalProperties: false— but none of them looked at$schema, so a dialect that made the client discard every tool passed CI cleanly. The suite now fails any advertised schema that does not declare 2020-12, that mentionsdraft-07anywhere, that uses a draft-07-only keyword (definitions,dependencies,additionalItems), or that declares$schemaon more than one node. Unit tests for the converter itself cover each keyword rewrite and the transport wrapper.