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
Copy file name to clipboardExpand all lines: .changeset/client-response-cache-substrate.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,4 +4,4 @@
4
4
5
5
`Client.listTools()` / `listPrompts()` / `listResources()` / `listResourceTemplates()` now **auto-aggregate every page** when called without a `cursor` and return the complete result with `nextCursor: undefined` (matching the C#, Java, and mcp.d SDKs). Pass an explicit `{ cursor }` string to fetch a single page; the per-page path is unchanged. Existing manual pagination loops keep working — the first iteration returns everything and the loop exits — but can be deleted. The aggregated result is written to the new pluggable `ResponseCacheStore` (default: a fresh per-instance `InMemoryResponseCacheStore`); a `ClientResponseCache` collaborator owns the eviction-generation guard and the derived `tools/list` index that `callTool`'s output validation and SEP-2243 `Mcp-Param-*` mirroring read. New exports: `ResponseCacheStore`, `CacheKey`, `CacheEntry`, `CacheScope`, `MaybePromise`, `InMemoryResponseCacheStore`; new `ClientOptions.responseCacheStore` / `ClientOptions.listMaxPages` (caps the auto-aggregate walk at 64 pages by default; throws `SdkError` with `SdkErrorCode.ListPaginationExceeded` on overrun so a partial aggregate is never cached). The store interface is async-ready (`MaybePromise<…>`); the in-memory default stays synchronous. Entries are automatically scoped by the connected server's identity and (when set) the consumer-supplied `cachePartition`, so a shared store does not collide across servers or principals; evictions are likewise scoped to the connected server's partitions.
6
6
7
-
**Behavior change (every era):** output-schema validator compilation is now lazy — validators are compiled on the first `callTool()` against the cached `tools/list` entry, not eagerly inside `listTools()` — and non-throwing: an uncompilable `outputSchema`is `console.warn`-ed and validation is skipped for that tool only (previously `listTools()`threw). A pluggable `jsonSchemaValidator` provider therefore observes compilation at `callTool` time, not `listTools` time. The legacy-era `listTools()` path is unchanged at the wire level but is observably different at the validator-lifecycle level.
7
+
**Behavior change (every era):** output-schema validator compilation is now lazy — validators are compiled on the first `callTool()` against the cached `tools/list` entry, not eagerly inside `listTools()`. `listTools()` no longer throws on an uncompilable `outputSchema`(every tool stays listed; the compile failure is captured per-tool); calling `callTool()` on the affected tool throws `ProtocolError(InvalidParams, "Tool 'X' has an invalid outputSchema: …")`with `data.reason` set to the structured kind, before the request is sent — output-schema validation is never silently skipped. A pluggable `jsonSchemaValidator` provider therefore observes compilation at `callTool` time, not `listTools` time. The legacy-era `listTools()` path is unchanged at the wire level but is observably different at the validator-lifecycle level.
Copy file name to clipboardExpand all lines: docs/migration-SKILL.md
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -574,7 +574,7 @@ side: auto-fulfilment is on by default (`ClientOptions.inputRequired`, `maxRound
574
574
575
575
`Client.listTools()` / `listPrompts()` / `listResources()` / `listResourceTemplates()` / `readResource()` now honour the server-stamped SEP-2549 `ttlMs`/`cacheScope`: a still-fresh cached entry is returned without a round trip. Opt-in by server hint — a server that sends `ttlMs: 0` (the SDK's default stamp) sees no behaviour change. Per-call override: pass `{ cacheMode: 'refresh' }` (always fetch and re-store) or `{ cacheMode: 'bypass' }` (fetch without touching the cache). Server `ttlMs` is clamped at 24 h (`MAX_CACHE_TTL_MS`). Entries are automatically scoped by connected-server identity; new `ClientOptions.cachePartition` (per-principal slot for `'private'`-scoped entries on a shared `responseCacheStore`; default `''`) and `ClientOptions.defaultCacheTtlMs` (TTL when the result lacks one, e.g. legacy-era responses; default `0`). `ResponseCacheStore` gained `delete(key)` (driven by `notifications/resources/updated`); `InMemoryResponseCacheStore` is now bounded (`{ maxEntries }`, default 512).
576
576
577
-
Output-schema validator compilation is now lazy (first `callTool()` against the cached `tools/list` entry) and non-throwing (an uncompilable `outputSchema`is `console.warn`-ed and validation is skipped for that tool only); `listTools()`no longer throws on an uncompilable `outputSchema`. Applies on every era — the legacy-era `listTools()` path is unchanged at the wire level only.
577
+
Output-schema validator compilation is now lazy (first `callTool()` against the cached `tools/list` entry); `listTools()` no longer throws on an uncompilable `outputSchema`— every tool stays listed and the compile failure is captured per-tool. Calling `callTool()`on the affected tool throws `ProtocolError(InvalidParams)` with `data.reason` set to the structured kind, before the request is sent (validation is never silently skipped). Applies on every era — the legacy-era `listTools()` path is unchanged at the wire level only.
578
578
579
579
No code changes required; wire-behavior note: on a 2026-07-28 Streamable HTTP connection, aborting an in-flight client request (caller `signal` / timeout) closes that request's SSE response stream as the spec cancellation signal — `notifications/cancelled` is no longer POSTed
580
580
there. 2025-era connections and stdio at any era still send `notifications/cancelled`. Custom `Transport` implementations that open one underlying request per outbound message and honor `TransportSendOptions.requestSignal` may declare `readonly hasPerRequestStream = true` to opt
@@ -670,6 +670,7 @@ JSON Schema 2020-12 posture (SEP-1613 / SEP-2106): the default validator support
| relying on default `Ajv` being draft-07 |`const ajv = new Ajv({ strict: false, validateFormats: true, validateSchema: false, allErrors: true }); addFormats(ajv); new AjvJsonSchemaValidator(ajv)` (import `Ajv`, `addFormats` from `…/validators/ajv`) |
673
+
| draft-07 idioms via `fromJsonSchema(schema)`|`fromJsonSchema(schema, new AjvJsonSchemaValidator(ajv))` — the `McpServer`/`Client``jsonSchemaValidator` option does **not** reach `fromJsonSchema`-authored schemas |
673
674
|`outputSchema` or `inputSchema` with absolute-URI `$ref`| inline under `$defs` and reference with `#/$defs/Name`|
Copy file name to clipboardExpand all lines: docs/migration.md
+5-4Lines changed: 5 additions & 4 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -594,9 +594,10 @@ New `ClientOptions`:
594
594
595
595
The `ResponseCacheStore` interface gained `delete(key)` (the per-URI invalidation `notifications/resources/updated` drives) — custom stores written against the alpha substrate need to add it. The default `InMemoryResponseCacheStore` is now bounded (default 512 entries, oldest-first eviction; configurable via `{ maxEntries }`).
596
596
597
-
**Output-schema validator lifecycle (every era):** validator compilation is now lazy — validators are compiled on the first `callTool()` against the cached `tools/list` entry, not eagerly inside `listTools()` — and non-throwing: an uncompilable `outputSchema` is `console.warn`-ed
598
-
and validation is skipped for that tool only. In v1, `listTools()` threw on an uncompilable `outputSchema`; now it succeeds, and a pluggable `jsonSchemaValidator` provider observes compilation at `callTool` time, not `listTools` time. The legacy-era `listTools()` path is
599
-
unchanged at the wire level but is observably different at the validator-lifecycle level.
597
+
**Output-schema validator lifecycle (every era):** validator compilation is now lazy — validators are compiled on the first `callTool()` against the cached `tools/list` entry, not eagerly inside `listTools()`. In v1, `listTools()` threw on an uncompilable `outputSchema`; now
598
+
`listTools()` succeeds (every tool stays listed) and the compile failure is captured per-tool. Calling `callTool()` on the affected tool then throws `ProtocolError(InvalidParams, "Tool 'X' has an invalid outputSchema: …")` with `data.reason` set to the structured kind, **before
599
+
the request is sent** — output-schema validation is never silently skipped. A pluggable `jsonSchemaValidator` provider observes compilation at `callTool` time, not `listTools` time. The legacy-era `listTools()` path is unchanged at the wire level but is observably different at
600
+
the validator-lifecycle level.
600
601
601
602
### `InMemoryTransport` moved
602
603
@@ -1454,7 +1455,7 @@ The default validator supports **JSON Schema 2020-12 only** (the spec's only MUS
1454
1455
1455
1456
-**You declared 2020-12 keywords (`$defs`, `prefixItems`, `unevaluatedProperties`, `dependentRequired`) in a server schema and they were silently ignored.** They are now enforced. If a previously "passing" tool input or output starts failing validation, the schema was always
1456
1457
wrong on the wire — fix the schema or the data.
1457
-
-**You authored draft-07 idioms via `fromJsonSchema()`** (e.g. tuple `items: [...]` instead of `prefixItems`, draft-07 `definitions`). Port to 2020-12 spelling, or pass a draft-07 Ajv instance per the opt-back below.
1458
+
-**You authored draft-07 idioms via `fromJsonSchema()`** (e.g. tuple `items: [...]` instead of `prefixItems`, draft-07 `definitions`). Port to 2020-12 spelling, or pass a draft-07 Ajv instance **as the second argument** — `fromJsonSchema(schema, new AjvJsonSchemaValidator(ajv))` — built per the opt-back recipe below. The `McpServer`/`Client``jsonSchemaValidator` option does **not** reach `fromJsonSchema()`-authored schemas (`fromJsonSchema()` compiles eagerly with the package-level default unless a validator is passed directly).
1458
1459
-**You imported `Ajv` from the SDK's validator subpath and relied on the re-export being the draft-07 class.** It still is — `Ajv` remains the draft-07 class (re-exported for the opt-back), but it is **no longer** what the SDK uses by default.
1459
1460
1460
1461
To validate other dialects, pass a pre-configured Ajv instance:
0 commit comments