You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Tools' inputSchema/outputSchema now conform to full JSON Schema 2020-12 and
structuredContent may be any JSON value (#2192).
- outputSchema accepts any 2020-12 schema (arrays/primitives/objects/compositions);
inputSchema keeps `type: "object"` but allows all 2020-12 keywords. Updated the
generated spec types, the zod schemas, and standardSchemaToJsonSchema (output path
no longer forces `type: "object"`).
- structuredContent widens from `{ [key: string]: unknown }` to `unknown`
(source-breaking for typed consumers).
- Stronger typing: new CallToolResultWithStructuredContent<T>; client.callTool<T>()
generic (cast-free via overload); registerTool type-checks a handler's
structuredContent against its outputSchema's inferred output.
- Fix falsy-structuredContent bug (=== undefined) in server + client.
- Server auto-emits a serialized TextContent fallback for non-object
structuredContent (pre-SEP client interop).
- Security: validators reject non-same-document $ref/$dynamicRef (SSRF) and
schemas exceeding depth/subschema bounds (composition DoS) via schemaBounds.
Adds unit + integration tests, migration docs (migration.md + migration-SKILL.md),
and a changeset.
Implement SEP-2106: tool `inputSchema`/`outputSchema` conform to JSON Schema 2020-12, and `structuredContent` may be any JSON value.
8
+
9
+
-`inputSchema` still requires `type: "object"` at the root but now accepts any JSON Schema 2020-12 keyword (`oneOf`/`anyOf`/`allOf`/`not`, `if`/`then`/`else`, `$ref`/`$defs`/`$anchor`, …).
10
+
-`outputSchema` may now be **any** valid JSON Schema 2020-12 — objects, arrays, primitives, or compositions — instead of being restricted to `type: "object"`.
11
+
-`CallToolResult.structuredContent` widens from `{ [key: string]: unknown }` to `unknown`. **This is a source-breaking type change** for typed consumers: property access now requires a narrowing guard or a type argument.
12
+
-`client.callTool<T>()` is now generic so callers get a precisely typed `structuredContent` (defaults to `JSONValue`). New `CallToolResultWithStructuredContent<T>` type.
13
+
-`McpServer.registerTool` type-checks a handler's returned `structuredContent` against the tool's `outputSchema` inferred output.
14
+
- Servers returning array or primitive `structuredContent` automatically also emit a serialized `TextContent` block, so pre-SEP clients can fall back to the text content.
15
+
- Built-in validators refuse to dereference non-same-document `$ref`/`$dynamicRef` (SSRF guard) and reject schemas exceeding depth / subschema-count bounds (composition-DoS guard).
Copy file name to clipboardExpand all lines: docs/migration-SKILL.md
+32-2Lines changed: 32 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -537,7 +537,36 @@ Validator behavior:
537
537
`@modelcontextprotocol/{client,server}/validators/cf-worker` for `CfWorkerJsonSchemaValidator`. Importing from a subpath means the corresponding peer dep must be in your `package.json`.
538
538
- To replace validation entirely, pass `jsonSchemaValidator: myCustomValidator` with your own implementation of the `jsonSchemaValidator` interface.
- A server returning array/primitive `structuredContent` automatically also emits a serialized `TextContent` block (old-client interop). No action required.
567
+
- Built-in validators reject non-same-document `$ref`/`$dynamicRef` (SSRF) and over-budget schemas (composition DoS). Use a custom `jsonSchemaValidator` to change this.
2. Replace all imports from `@modelcontextprotocol/sdk/...` using the import mapping tables (sections 3-4), including `StreamableHTTPServerTransport` → `NodeStreamableHTTPServerTransport`
@@ -549,4 +578,5 @@ Validator behavior:
549
578
8. If using server SSE transport, migrate to Streamable HTTP
550
579
9. If using server auth from the SDK: RS helpers (`requireBearerAuth`, `mcpAuthMetadataRouter`, `OAuthTokenVerifier`) → `@modelcontextprotocol/express`; AS helpers → `@modelcontextprotocol/server-legacy/auth` (deprecated); migrate AS to external IdP/OAuth library
551
580
10. If relying on `listTools()`/`listPrompts()`/etc. throwing on missing capabilities, set `enforceStrictCapabilities: true`
552
-
11. Verify: build with `tsc` / run tests
581
+
11. If you read properties off `result.structuredContent`, add a type argument to `callTool<T>()` or a narrowing guard — it is now typed `unknown` (section 15)
Copy file name to clipboardExpand all lines: docs/migration.md
+31Lines changed: 31 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -977,6 +977,37 @@ subpath in some files and rely on the default in others.
977
977
978
978
To replace validation wholesale rather than customizing the built-in classes, implement the `jsonSchemaValidator` interface and pass your own implementation through the option above.
979
979
980
+
### Tool schemas conform to JSON Schema 2020-12; `structuredContent` may be any JSON value (SEP-2106)
981
+
982
+
Per [SEP-2106](https://github.com/modelcontextprotocol/modelcontextprotocol/blob/main/seps/2106-json-schema-2020-12.md), tool schemas are no longer restricted to the `type`/`properties`/`required` subset, and a tool's structured output may be any JSON value:
983
+
984
+
-**`inputSchema`** still requires `type: "object"` at the root (tool arguments are always objects), but may now use any JSON Schema 2020-12 keyword alongside it — composition (`oneOf`/`anyOf`/`allOf`/`not`), conditional (`if`/`then`/`else`), references (`$ref`/`$defs`/`$anchor`), etc.
985
+
-**`outputSchema`** may now be **any** valid JSON Schema 2020-12 — objects, arrays, primitives, or compositions. It is no longer restricted to `type: "object"`.
986
+
-**`structuredContent`** may now be any JSON value (object, array, string, number, boolean, or null), not just an object.
987
+
988
+
**Source-breaking type change.**`CallToolResult.structuredContent` widened from `{ [key: string]: unknown }` to `unknown`. Property access without a narrowing guard no longer type-checks (the previous type was inaccurate whenever a tool returned a non-object):
989
+
990
+
```typescript
991
+
// Before (v1): compiled, but was a lie for non-object output
const temp =result.structuredContent?.temperature; // typed as number
1003
+
```
1004
+
1005
+
**Stronger server-side typing.** When a tool declares an `outputSchema`, `registerTool` now type-checks the handler's returned `structuredContent` against the schema's inferred output type at compile time — a mismatch is a type error rather than a runtime-only failure.
1006
+
1007
+
**Old-client interoperability.** A server that returns array or primitive `structuredContent` will automatically also emit a `TextContent` block containing the serialized JSON, so pre-SEP clients that only understand object-typed `structuredContent` can fall back to the text content. Object `structuredContent` (and results that already include a text block) are left unchanged.
1008
+
1009
+
**Security.** The built-in validators never dereference non-same-document `$ref`/`$dynamicRef` (anything not beginning with `#`) — such schemas are rejected rather than fetched, preventing SSRF. Schemas exceeding a generous depth / subschema-count bound are also rejected to prevent composition-based validation DoS. Supply your own `jsonSchemaValidator` implementation if you need different behavior.
1010
+
980
1011
## Unchanged APIs
981
1012
982
1013
The following APIs are unchanged between v1 and v2 (only the import paths changed):
0 commit comments