@prefecthq/fastmcp-ts 1.5.1 → 1.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.d.ts CHANGED
@@ -1054,6 +1054,7 @@ declare class FastMCP {
1054
1054
  private _primaryServer;
1055
1055
  private _stdioServer;
1056
1056
  private _stdioState;
1057
+ private _stdioModern;
1057
1058
  private _stdioHandle;
1058
1059
  private _modernHandler;
1059
1060
  private _statelessLegacyHandler;
@@ -1067,32 +1068,28 @@ declare class FastMCP {
1067
1068
  /**
1068
1069
  * Create a new Server instance with all request handlers wired up.
1069
1070
  *
1070
- * `modern` forks the advertised `resources.subscribe` capability. The legacy
1071
- * `resources/subscribe`/`unsubscribe` RPCs are physically absent from the
1072
- * 2026-07-28 wire registry (a modern client uses `subscriptions/listen`
1073
- * instead), so a modern-only factory (the createMcpHandler path) must NOT
1074
- * advertise `subscribe` — the modern `server/discover` document is pinned to
1075
- * `resources: { listChanged: true }`. The primary in-process server and
1076
- * legacy HTTP sessions are always legacy, so they always advertise it.
1077
- * stdio forks it per-connection too: `run()`'s stdio branch reads the
1078
- * `ctx.era` the SDK's `McpServerFactory` hook hands it (serveStdio only
1079
- * calls the factory once the opening exchange has classified the era, so
1080
- * the modern-vs-legacy choice is already known at construction time) and
1081
- * passes it straight through as `opts.modern`.
1071
+ * `resources.subscribe` is advertised on both eras. On legacy it gates the
1072
+ * `resources/subscribe`/`unsubscribe` RPCs. On modern (2026-07-28) the same
1073
+ * capability gates the `subscriptions/listen` `resourceSubscriptions`
1074
+ * filter: the SDK's listen routers silently prune the filter from the
1075
+ * honored subset when the serving entry's capabilities omit `subscribe`,
1076
+ * so a modern server that supports per-resource updates MUST advertise it
1077
+ * (issue #88). The legacy RPCs are still physically absent from the modern
1078
+ * wire registry, so advertising the capability leaks no legacy-only
1079
+ * surface to a modern client.
1082
1080
  *
1083
- * The `completions` capability is NOT era-forked: `completion/complete` is in
1084
- * BOTH era wire registries (the legacy 2025-11-25 registry and the modern
1085
- * 2026-07-28 `dispatchRequestSchemas`), and `completions` is a valid key in
1086
- * both eras' ServerCapabilities schemas. So it is declared unconditionally —
1087
- * unlike `subscribe`, there is no legacy-only surface to hide from a modern
1088
- * client here, so nothing needs the era fork the way `subscribe` does. The
1089
- * SDK also requires this capability to be present to register the
1090
- * `completion/complete` handler (`assertRequestHandlerCapability`).
1081
+ * The `completions` capability follows the same shape: `completion/complete`
1082
+ * is in BOTH era wire registries (the legacy 2025-11-25 registry and the
1083
+ * modern 2026-07-28 `dispatchRequestSchemas`), and `completions` is a valid
1084
+ * key in both eras' ServerCapabilities schemas, so it is declared
1085
+ * unconditionally. The SDK also requires this capability to be present to
1086
+ * register the `completion/complete` handler
1087
+ * (`assertRequestHandlerCapability`).
1091
1088
  *
1092
- * `stateless` withdraws the same capability for a different reason. A
1093
- * stateless server has no session for a subscription to live in and no
1094
- * channel to deliver `notifications/resources/updated` on, so it must not
1095
- * claim the capability.
1089
+ * `stateless` withdraws the `resources.subscribe` capability. A stateless
1090
+ * server has no session for a subscription to live in and no channel to
1091
+ * deliver `notifications/resources/updated` on, so it must not claim the
1092
+ * capability.
1096
1093
  */
1097
1094
  private _makeServer;
1098
1095
  private _resolveToken;
@@ -1126,6 +1123,9 @@ declare class FastMCP {
1126
1123
  * per-stream filtering, delivering only to `subscriptions/listen` streams that
1127
1124
  * opted in to this URI. Optional chaining keeps it a no-op until the first
1128
1125
  * modern HTTP request has actually built the handler.
1126
+ * - A modern stdio connection is sent the notification unconditionally; the
1127
+ * SDK's stdio listen router intercepts it and fans out per honored
1128
+ * subscription (or drops it when no stream opted in to the URI).
1129
1129
  *
1130
1130
  * Unsubscribed sessions (and the modern streams that never opted in) receive
1131
1131
  * nothing, so calling this for a URI with no subscribers is safe and cheap.
package/dist/server.js CHANGED
@@ -1081,6 +1081,9 @@ var FastMCP = class {
1081
1081
  // Holds this connection's resource-subscription set; read by the resource-updated
1082
1082
  // fan-out. Null unless serving stdio.
1083
1083
  _stdioState = null;
1084
+ // Whether the current stdio connection negotiated the modern (2026-07-28) era.
1085
+ // Set by run()'s stdio factory; drives notifyResourceUpdated's stdio branch.
1086
+ _stdioModern = false;
1084
1087
  _stdioHandle = null;
1085
1088
  // Modern (2026-07-28) HTTP handler — one per FastMCP instance, lazily created.
1086
1089
  // Builds a fresh Server (via _makeServer) per request; see createMcpHandler.
@@ -1124,32 +1127,28 @@ var FastMCP = class {
1124
1127
  /**
1125
1128
  * Create a new Server instance with all request handlers wired up.
1126
1129
  *
1127
- * `modern` forks the advertised `resources.subscribe` capability. The legacy
1128
- * `resources/subscribe`/`unsubscribe` RPCs are physically absent from the
1129
- * 2026-07-28 wire registry (a modern client uses `subscriptions/listen`
1130
- * instead), so a modern-only factory (the createMcpHandler path) must NOT
1131
- * advertise `subscribe` — the modern `server/discover` document is pinned to
1132
- * `resources: { listChanged: true }`. The primary in-process server and
1133
- * legacy HTTP sessions are always legacy, so they always advertise it.
1134
- * stdio forks it per-connection too: `run()`'s stdio branch reads the
1135
- * `ctx.era` the SDK's `McpServerFactory` hook hands it (serveStdio only
1136
- * calls the factory once the opening exchange has classified the era, so
1137
- * the modern-vs-legacy choice is already known at construction time) and
1138
- * passes it straight through as `opts.modern`.
1130
+ * `resources.subscribe` is advertised on both eras. On legacy it gates the
1131
+ * `resources/subscribe`/`unsubscribe` RPCs. On modern (2026-07-28) the same
1132
+ * capability gates the `subscriptions/listen` `resourceSubscriptions`
1133
+ * filter: the SDK's listen routers silently prune the filter from the
1134
+ * honored subset when the serving entry's capabilities omit `subscribe`,
1135
+ * so a modern server that supports per-resource updates MUST advertise it
1136
+ * (issue #88). The legacy RPCs are still physically absent from the modern
1137
+ * wire registry, so advertising the capability leaks no legacy-only
1138
+ * surface to a modern client.
1139
1139
  *
1140
- * The `completions` capability is NOT era-forked: `completion/complete` is in
1141
- * BOTH era wire registries (the legacy 2025-11-25 registry and the modern
1142
- * 2026-07-28 `dispatchRequestSchemas`), and `completions` is a valid key in
1143
- * both eras' ServerCapabilities schemas. So it is declared unconditionally —
1144
- * unlike `subscribe`, there is no legacy-only surface to hide from a modern
1145
- * client here, so nothing needs the era fork the way `subscribe` does. The
1146
- * SDK also requires this capability to be present to register the
1147
- * `completion/complete` handler (`assertRequestHandlerCapability`).
1140
+ * The `completions` capability follows the same shape: `completion/complete`
1141
+ * is in BOTH era wire registries (the legacy 2025-11-25 registry and the
1142
+ * modern 2026-07-28 `dispatchRequestSchemas`), and `completions` is a valid
1143
+ * key in both eras' ServerCapabilities schemas, so it is declared
1144
+ * unconditionally. The SDK also requires this capability to be present to
1145
+ * register the `completion/complete` handler
1146
+ * (`assertRequestHandlerCapability`).
1148
1147
  *
1149
- * `stateless` withdraws the same capability for a different reason. A
1150
- * stateless server has no session for a subscription to live in and no
1151
- * channel to deliver `notifications/resources/updated` on, so it must not
1152
- * claim the capability.
1148
+ * `stateless` withdraws the `resources.subscribe` capability. A stateless
1149
+ * server has no session for a subscription to live in and no channel to
1150
+ * deliver `notifications/resources/updated` on, so it must not claim the
1151
+ * capability.
1153
1152
  */
1154
1153
  _makeServer(sessionState, opts) {
1155
1154
  const state = sessionState ?? this._primaryState;
@@ -1157,7 +1156,7 @@ var FastMCP = class {
1157
1156
  const server = new Server2(
1158
1157
  { name: this.name, version: this.version },
1159
1158
  {
1160
- capabilities: { tools: { listChanged: true }, resources: { listChanged: true, ...opts?.modern || opts?.stateless ? {} : { subscribe: true } }, prompts: { listChanged: true }, logging: {}, completions: {}, ...extensions ? { extensions } : {} },
1159
+ capabilities: { tools: { listChanged: true }, resources: { listChanged: true, ...opts?.stateless ? {} : { subscribe: true } }, prompts: { listChanged: true }, logging: {}, completions: {}, ...extensions ? { extensions } : {} },
1161
1160
  ...this._cacheHints ? { cacheHints: this._cacheHints } : {},
1162
1161
  ...this._requestStateCodec ? { requestState: { verify: this._requestStateCodec.verify.bind(this._requestStateCodec) } } : {},
1163
1162
  ...this._inputRequiredOptions ? { inputRequired: this._inputRequiredOptions } : {}
@@ -1749,6 +1748,9 @@ var FastMCP = class {
1749
1748
  * per-stream filtering, delivering only to `subscriptions/listen` streams that
1750
1749
  * opted in to this URI. Optional chaining keeps it a no-op until the first
1751
1750
  * modern HTTP request has actually built the handler.
1751
+ * - A modern stdio connection is sent the notification unconditionally; the
1752
+ * SDK's stdio listen router intercepts it and fans out per honored
1753
+ * subscription (or drops it when no stream opted in to the URI).
1752
1754
  *
1753
1755
  * Unsubscribed sessions (and the modern streams that never opted in) receive
1754
1756
  * nothing, so calling this for a URI with no subscribers is safe and cheap.
@@ -1760,7 +1762,11 @@ var FastMCP = class {
1760
1762
  });
1761
1763
  };
1762
1764
  pushIfSubscribed(this._primaryServer, this._primaryState);
1763
- if (this._stdioServer) pushIfSubscribed(this._stdioServer, this._stdioState);
1765
+ if (this._stdioServer) {
1766
+ if (this._stdioModern) this._stdioServer.sendResourceUpdated({ uri }).catch(() => {
1767
+ });
1768
+ else pushIfSubscribed(this._stdioServer, this._stdioState);
1769
+ }
1764
1770
  for (const { server, state } of this._sessions.values()) pushIfSubscribed(server, state);
1765
1771
  this._modernHandler?.notify.resourceUpdated(uri);
1766
1772
  }
@@ -2280,7 +2286,8 @@ var FastMCP = class {
2280
2286
  (ctx) => {
2281
2287
  const stdioState = /* @__PURE__ */ new Map();
2282
2288
  this._stdioState = stdioState;
2283
- this._stdioServer = this._makeServer(stdioState, { modern: ctx.era === "modern" });
2289
+ this._stdioModern = ctx.era === "modern";
2290
+ this._stdioServer = this._makeServer(stdioState);
2284
2291
  return this._stdioServer;
2285
2292
  },
2286
2293
  { transport: stdioTransport }
@@ -2317,7 +2324,7 @@ var FastMCP = class {
2317
2324
  * session state and server-initiated-request shim for run()'s default HTTP path. */
2318
2325
  _getModernHandler() {
2319
2326
  if (!this._modernHandler) {
2320
- this._modernHandler = createMcpHandler(() => this._makeServer(/* @__PURE__ */ new Map(), { modern: true }), {
2327
+ this._modernHandler = createMcpHandler(() => this._makeServer(/* @__PURE__ */ new Map()), {
2321
2328
  legacy: "reject",
2322
2329
  ...this._eventBus ? { bus: this._eventBus } : {}
2323
2330
  });
@@ -2585,6 +2592,7 @@ var FastMCP = class {
2585
2592
  this._stdioHandle = null;
2586
2593
  this._stdioServer = null;
2587
2594
  this._stdioState = null;
2595
+ this._stdioModern = false;
2588
2596
  }
2589
2597
  if (this._httpServer) {
2590
2598
  await new Promise((resolve, reject) => {