@orkestrel/mcp 0.0.30 → 0.0.31

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.
@@ -275,9 +275,12 @@ var DEFAULT_MCP_SUBSCRIPTION_CAPACITY = 64;
275
275
  * optional structured context.
276
276
  *
277
277
  * @remarks
278
- * {@link MCPClient} throws this error for a remote JSON-RPC `error` response and for a
279
- * locally detected protocol incompatibility. Local lifecycle and transport conditions such
280
- * as disconnects and request timeouts remain plain `Error`s. For a remote response, `context`
278
+ * {@link MCPClient} throws this error for a remote JSON-RPC `error` response, for a locally
279
+ * detected protocol incompatibility, and for a session-bound request refused because the
280
+ * client holds no connection — that one carries `-32600`, so a caller separates "reconnect"
281
+ * from "retry" without reading a message. Local lifecycle and transport conditions that
282
+ * settle a request already in flight, such as a disconnect and a request timeout, remain
283
+ * plain `Error`s. For a remote response, `context`
281
284
  * carries the optional `error.data` unchanged and is `undefined` when the peer omitted it.
282
285
  * This includes the modern reserved paths: `-32020` carries no context, `-32021` may carry
283
286
  * `requiredCapabilities`, and `-32022` carries the peer's `supported` revisions and
@@ -1128,19 +1131,17 @@ function buildCallOutcome(name, result) {
1128
1131
  * Builds the canonical Tool call for one validated MCP `tools/call` request.
1129
1132
  *
1130
1133
  * @param request - The original MCP request
1131
- * @param caller - Optional consumer-asserted caller context
1132
1134
  * @param args - Optional once-validated modern arguments; omission retains legacy normalization
1133
1135
  * @returns The canonical call, or `undefined` when the name is invalid
1134
1136
  */
1135
- function buildToolCall(request, caller, args) {
1137
+ function buildToolCall(request, args) {
1136
1138
  const name = request.params?.["name"];
1137
1139
  if (typeof name !== "string") return void 0;
1138
1140
  const rawArguments = request.params?.["arguments"];
1139
1141
  return {
1140
1142
  id: String(request.id),
1141
1143
  name,
1142
- arguments: args ?? ((0, _orkestrel_contract.isRecord)(rawArguments) ? rawArguments : {}),
1143
- ...caller === void 0 ? {} : { caller }
1144
+ arguments: args ?? ((0, _orkestrel_contract.isRecord)(rawArguments) ? rawArguments : {})
1144
1145
  };
1145
1146
  }
1146
1147
  /**
@@ -1231,7 +1232,8 @@ function buildMethodOptions(options, lifetime) {
1231
1232
  *
1232
1233
  * @remarks
1233
1234
  * Each {@link import('@orkestrel/tool').ToolDefinition} carries through its
1234
- * `name` and (when present) `description`; its open JSON-Schema `parameters`
1235
+ * `name`, optional `title` and `description`, and mapped annotation hints;
1236
+ * its open JSON-Schema `parameters`
1235
1237
  * becomes `inputSchema`, defaulting to an empty object schema (`{ type: 'object' }`)
1236
1238
  * when a tool declares none (MCP requires an `inputSchema`).
1237
1239
  *
@@ -1240,14 +1242,50 @@ function buildMethodOptions(options, lifetime) {
1240
1242
  */
1241
1243
  function buildToolDescriptors(manager) {
1242
1244
  return manager.definitions().map((definition) => {
1243
- const descriptor = {
1245
+ const annotations = definition.annotations === void 0 ? {} : toolAnnotationsToMCP(definition.annotations);
1246
+ return {
1244
1247
  name: definition.name,
1245
- inputSchema: definition.parameters ?? { type: "object" }
1248
+ inputSchema: definition.parameters ?? { type: "object" },
1249
+ ...definition.title === void 0 ? {} : { title: definition.title },
1250
+ ...definition.description === void 0 ? {} : { description: definition.description },
1251
+ ...Object.keys(annotations).length === 0 ? {} : { annotations }
1246
1252
  };
1247
- if (definition.description !== void 0) descriptor.description = definition.description;
1248
- return descriptor;
1249
1253
  });
1250
1254
  }
1255
+ /**
1256
+ * Projects domain tool annotations onto MCP wire hints without inventing defaults.
1257
+ *
1258
+ * @param annotations - The authored domain annotations
1259
+ * @returns The mapped hints; `untrusted` has no MCP counterpart
1260
+ *
1261
+ * @example
1262
+ * ```ts
1263
+ * toolAnnotationsToMCP({ pure: true, consequential: false }) // { readOnlyHint: true, destructiveHint: false }
1264
+ * ```
1265
+ */
1266
+ function toolAnnotationsToMCP(annotations) {
1267
+ return {
1268
+ ...annotations.pure === void 0 ? {} : { readOnlyHint: annotations.pure },
1269
+ ...annotations.consequential === void 0 ? {} : { destructiveHint: annotations.consequential }
1270
+ };
1271
+ }
1272
+ /**
1273
+ * Projects MCP wire hints onto domain tool annotations without inventing defaults.
1274
+ *
1275
+ * @param annotations - The validated MCP wire annotations
1276
+ * @returns The mapped annotations; unmapped wire hints are omitted
1277
+ *
1278
+ * @example
1279
+ * ```ts
1280
+ * mcpAnnotationsToTool({ readOnlyHint: false, destructiveHint: true }) // { pure: false, consequential: true }
1281
+ * ```
1282
+ */
1283
+ function mcpAnnotationsToTool(annotations) {
1284
+ return {
1285
+ ...annotations.readOnlyHint === void 0 ? {} : { pure: annotations.readOnlyHint },
1286
+ ...annotations.destructiveHint === void 0 ? {} : { consequential: annotations.destructiveHint }
1287
+ };
1288
+ }
1251
1289
  function buildModernResult(result, identity, ttl, scope) {
1252
1290
  const currentMetadata = (0, _orkestrel_contract.isRecord)(result) ? result["_meta"] : void 0;
1253
1291
  if (!(0, _orkestrel_contract.isJSONValue)(identity)) throw new TypeError("MCP identity must be exact JSON");
@@ -1452,10 +1490,11 @@ function buildSubscriptionResult(id, identity) {
1452
1490
  * @remarks
1453
1491
  * `capabilities.resources` and `capabilities.prompts` appear only for servers with their
1454
1492
  * respective managers and derive notification flags from the configured subscription filter.
1455
- * `capabilities.completions` is independent and appears only with a completion provider.
1456
- * `capabilities.extensions` appears only for a server that configured the extension it
1457
- * would name. An advertisement is a promise a client is entitled to act on, so a server
1458
- * with no `task` policy omits the member entirely rather than advertising an empty
1493
+ * `tools.listChanged` is always advertised because the server produces the family from its
1494
+ * own registry. `capabilities.completions` is independent and appears only with a completion
1495
+ * provider. `capabilities.extensions` appears only for a server that configured the
1496
+ * extension it would name. An advertisement is a promise a client is entitled to act on, so
1497
+ * a server with no `task` policy omits the member entirely rather than advertising an empty
1459
1498
  * record — and its discovery answer stays byte-for-byte what it was before the extension
1460
1499
  * existed.
1461
1500
  *
@@ -1466,7 +1505,7 @@ function buildDiscoverResult(options) {
1466
1505
  return buildModernResult({
1467
1506
  supportedVersions: SUPPORTED_MODERN_PROTOCOL_VERSIONS,
1468
1507
  capabilities: {
1469
- tools: {},
1508
+ tools: { listChanged: true },
1470
1509
  ...options.resources === void 0 ? {} : { resources: {
1471
1510
  ...options.subscription?.notifications.resourceSubscriptions === void 0 ? {} : { subscribe: true },
1472
1511
  ...options.subscription?.notifications.resourcesListChanged === true ? { listChanged: true } : {}
@@ -2665,6 +2704,28 @@ function isMCPResource(value) {
2665
2704
  }
2666
2705
  }
2667
2706
  /**
2707
+ * Checks whether a value carries valid consumed MCP 2026-07-28 tool annotation hints.
2708
+ *
2709
+ * @remarks
2710
+ * Validates only `readOnlyHint` and `destructiveHint`; other wire fields are not consumed, so
2711
+ * the open `objectOf` combinator carries them through unread. Every declared member is
2712
+ * optional, a hostile read answers `false` rather than throwing, and an array is refused.
2713
+ *
2714
+ * @param value - The unknown wire annotations
2715
+ * @returns True if consumed annotation fields are optional booleans; false otherwise
2716
+ *
2717
+ * @example
2718
+ * ```ts
2719
+ * isMCPToolAnnotations({ readOnlyHint: false }) // true
2720
+ * ```
2721
+ */
2722
+ function isMCPToolAnnotations(value) {
2723
+ return (0, _orkestrel_contract.objectOf)({
2724
+ readOnlyHint: _orkestrel_contract.isBoolean,
2725
+ destructiveHint: _orkestrel_contract.isBoolean
2726
+ }, true)(value);
2727
+ }
2728
+ /**
2668
2729
  * Determines whether a value is one resource-template descriptor.
2669
2730
  *
2670
2731
  * @remarks
@@ -3273,6 +3334,22 @@ function isMCPSubscriptionFilter(value) {
3273
3334
  return (0, _orkestrel_contract.isUndefined)(tasks) || (0, _orkestrel_contract.arrayOf)(_orkestrel_contract.isString)(tasks);
3274
3335
  }
3275
3336
  /**
3337
+ * Checks whether a subscription filter leaves the built-in tools family to the server.
3338
+ *
3339
+ * @param value - The unknown value to inspect
3340
+ * @returns True if the filter is valid and does not claim tools changes; false otherwise
3341
+ *
3342
+ * @example
3343
+ * ```ts
3344
+ * isMCPConsumerFilter({ promptsListChanged: true }) // true
3345
+ * isMCPConsumerFilter({ toolsListChanged: true }) // false
3346
+ * ```
3347
+ */
3348
+ function isMCPConsumerFilter(value) {
3349
+ const owned = (0, _orkestrel_contract.attempt)(() => (0, _orkestrel_contract.cloneJSONRecord)(value));
3350
+ return owned.success && isMCPSubscriptionFilter(owned.value) && owned.value["toolsListChanged"] !== true;
3351
+ }
3352
+ /**
3276
3353
  * Determines whether a value is a graceful `subscriptions/listen` result.
3277
3354
  *
3278
3355
  * @param value - The unknown value to inspect
@@ -5015,6 +5092,7 @@ var MCPServer = class {
5015
5092
  #limits;
5016
5093
  #subscriptions = 0;
5017
5094
  constructor(options) {
5095
+ if (options.subscription !== void 0 && !isMCPConsumerFilter(options.subscription.notifications)) throw new MCPError("The consumer filter must be a valid filter that omits tools changes, because the server produces that family from its registry", JSONRPC_INVALID_PARAMS);
5018
5096
  this.#emitter = new _orkestrel_emitter.Emitter({
5019
5097
  ...options.on !== void 0 ? { on: options.on } : {},
5020
5098
  ...options.error !== void 0 ? { error: options.error } : {}
@@ -5287,14 +5365,14 @@ var MCPServer = class {
5287
5365
  const args = (0, _orkestrel_contract.isRecord)(rawArguments) ? rawArguments : EMPTY_MCP_ARGUMENTS;
5288
5366
  const input = await this.#input(request, args, options);
5289
5367
  if (input !== void 0) return input;
5290
- const call = buildToolCall(request, options.caller, args);
5368
+ const call = buildToolCall(request, args);
5291
5369
  if (call === void 0) return buildJSONRPCError(id, JSONRPC_INVALID_PARAMS, "Invalid params: a string `name` is required");
5292
5370
  const deferred = await this.#defer(request, call, options);
5293
5371
  if (deferred !== void 0) return deferred;
5294
5372
  const token = params?.["_meta"];
5295
5373
  const progressToken = (0, _orkestrel_contract.isRecord)(token) ? token["progressToken"] : void 0;
5296
5374
  if (this.#options.execution !== void 0 && ((0, _orkestrel_contract.isString)(progressToken) || typeof progressToken === "number" && Number.isInteger(progressToken))) return this.#progress(request, call, progressToken, options);
5297
- const result = await this.#execute(request, call, options.signal);
5375
+ const result = await this.#execute(request, call, options);
5298
5376
  return "jsonrpc" in result ? result : buildJSONRPCResult(id, result);
5299
5377
  }
5300
5378
  async #defer(request, call, options) {
@@ -5338,7 +5416,7 @@ var MCPServer = class {
5338
5416
  keys: this.#limits.keys,
5339
5417
  depth: this.#limits.depth
5340
5418
  }, signal);
5341
- const execution = this.#execute(request, call, signal, reporter);
5419
+ const execution = this.#execute(request, call, options, reporter);
5342
5420
  try {
5343
5421
  while (true) {
5344
5422
  const outcome = await Promise.race([reporter.take(), execution]);
@@ -5356,14 +5434,19 @@ var MCPServer = class {
5356
5434
  reporter.stop();
5357
5435
  }
5358
5436
  }
5359
- async #execute(request, call, signal, progress) {
5437
+ async #execute(request, call, options, progress) {
5438
+ const { signal, caller } = options;
5360
5439
  let result;
5361
5440
  try {
5362
- result = this.#options.execution === void 0 ? await this.#options.tools.execute(call) : await this.#options.execution({
5441
+ result = this.#options.execution === void 0 ? await this.#options.tools.execute(call, {
5442
+ signal,
5443
+ ...caller === void 0 ? {} : { caller }
5444
+ }) : await this.#options.execution({
5363
5445
  request,
5364
5446
  call,
5365
5447
  tools: this.#options.tools,
5366
5448
  signal,
5449
+ ...caller === void 0 ? {} : { caller },
5367
5450
  ...progress === void 0 ? {} : { progress }
5368
5451
  });
5369
5452
  } catch (error) {
@@ -5551,7 +5634,10 @@ var MCPServer = class {
5551
5634
  const task = this.#options.task;
5552
5635
  const configured = this.#options.subscription;
5553
5636
  const tasks = task !== void 0 && configured !== void 0;
5554
- let notifications = buildSubscriptionFilter(requested, configured?.notifications ?? {}, tasks);
5637
+ let notifications = buildSubscriptionFilter(requested, {
5638
+ ...configured?.notifications,
5639
+ toolsListChanged: true
5640
+ }, tasks);
5555
5641
  const requestedTaskIds = notifications.taskIds;
5556
5642
  if (requestedTaskIds !== void 0) {
5557
5643
  const resolved = [];
@@ -5564,19 +5650,22 @@ var MCPServer = class {
5564
5650
  taskIds: resolved
5565
5651
  } : rest;
5566
5652
  }
5653
+ const state = {
5654
+ frame: void 0,
5655
+ failure: void 0,
5656
+ iterator: void 0
5657
+ };
5658
+ const source = new ReadableStream({
5659
+ start: this.#startSubscription.bind(this, notifications, options, configured, state),
5660
+ pull: this.#pullSubscription.bind(this, notifications, options, state)
5661
+ });
5567
5662
  yield buildSubscriptionAcknowledgement(notifications, id);
5568
- if (configured !== void 0) {
5569
- const iterator = (await configured.producer(notifications, options))[Symbol.asyncIterator]();
5570
- options.signal.addEventListener("abort", () => void iterator.return?.(void 0)?.catch(() => void 0), { once: true });
5571
- for (let next = await iterator.next(); next.done !== true; next = await iterator.next()) {
5572
- const owned = parseJSONRPCMessage(next.value, {
5573
- bytes: this.#limits.message,
5574
- depth: this.#limits.depth
5575
- });
5576
- if (owned === void 0 || !isJSONRPCNotification(owned)) continue;
5577
- if (matchesSubscriptionNotification(owned, notifications)) yield stampSubscriptionNotification(owned, id);
5578
- }
5663
+ for await (const notification of source) {
5664
+ if (notification === void 0) continue;
5665
+ if (notification === state.frame) state.frame = void 0;
5666
+ yield stampSubscriptionNotification(notification, id);
5579
5667
  }
5668
+ if (state.failure !== void 0) throw state.failure.error;
5580
5669
  return buildSubscriptionResult(id, this.#options.identity);
5581
5670
  } catch (error) {
5582
5671
  if (options.signal.aborted) throw error;
@@ -5585,6 +5674,72 @@ var MCPServer = class {
5585
5674
  slot.abort();
5586
5675
  }
5587
5676
  }
5677
+ async #startSubscription(notifications, options, configured, state, controller) {
5678
+ const emitter = this.#options.tools.emitter;
5679
+ const changed = this.#change.bind(this, controller, options.signal, state);
5680
+ if (options.signal.aborted) {
5681
+ controller.error(options.signal.reason);
5682
+ return;
5683
+ }
5684
+ if (notifications.toolsListChanged === true && !emitter.destroyed) {
5685
+ emitter.on("add", changed);
5686
+ emitter.on("remove", changed);
5687
+ emitter.on("clear", changed);
5688
+ }
5689
+ options.signal.addEventListener("abort", () => {
5690
+ emitter.off("add", changed);
5691
+ emitter.off("remove", changed);
5692
+ emitter.off("clear", changed);
5693
+ const iterator = state.iterator;
5694
+ state.iterator = void 0;
5695
+ if (iterator !== void 0) this.#releaseProducer(iterator, options.signal.reason);
5696
+ controller.error(options.signal.reason);
5697
+ }, { once: true });
5698
+ try {
5699
+ if (configured === void 0) return;
5700
+ const iterator = (await configured.producer(notifications, options))[Symbol.asyncIterator]();
5701
+ if (options.signal.aborted) this.#releaseProducer(iterator, options.signal.reason);
5702
+ else state.iterator = iterator;
5703
+ } catch (error) {
5704
+ this.#failSubscription(state, options.signal, controller, error);
5705
+ }
5706
+ }
5707
+ #change(controller, signal, state) {
5708
+ if (signal.aborted || state.failure !== void 0 || state.frame !== void 0) return;
5709
+ const notification = {
5710
+ jsonrpc: "2.0",
5711
+ method: "notifications/tools/list_changed"
5712
+ };
5713
+ state.frame = notification;
5714
+ controller.enqueue(notification);
5715
+ }
5716
+ async #pullSubscription(notifications, options, state, controller) {
5717
+ try {
5718
+ if (options.signal.aborted) return;
5719
+ const next = await state.iterator?.next();
5720
+ if (options.signal.aborted) return;
5721
+ if (next === void 0 || next.done === true) {
5722
+ state.iterator = void 0;
5723
+ if (notifications.toolsListChanged !== true) controller.close();
5724
+ return;
5725
+ }
5726
+ const owned = parseJSONRPCMessage(next.value, {
5727
+ bytes: this.#limits.message,
5728
+ depth: this.#limits.depth
5729
+ });
5730
+ controller.enqueue(owned !== void 0 && isJSONRPCNotification(owned) && owned.method !== "notifications/tools/list_changed" && matchesSubscriptionNotification(owned, notifications) ? owned : void 0);
5731
+ } catch (error) {
5732
+ this.#failSubscription(state, options.signal, controller, error);
5733
+ }
5734
+ }
5735
+ #failSubscription(state, signal, controller, error) {
5736
+ if (signal.aborted) return;
5737
+ state.failure = { error };
5738
+ controller.close();
5739
+ }
5740
+ #releaseProducer(iterator, reason) {
5741
+ iterator.return?.(reason)?.catch(() => void 0);
5742
+ }
5588
5743
  #readTaskId(request) {
5589
5744
  const id = request.id;
5590
5745
  const context = parseRequestContext(request, {
@@ -5952,9 +6107,11 @@ var MCPClient = class {
5952
6107
  async *#openSubscription(notifications, signal, capacity) {
5953
6108
  signal.throwIfAborted();
5954
6109
  if (!(0, _orkestrel_contract.isInteger)(capacity) || capacity < 1) throw new MCPError("MCP subscription capacity must be a positive integer", JSONRPC_INVALID_PARAMS);
6110
+ const method = "subscriptions/listen";
6111
+ const opening = this.#refuse(method);
6112
+ if (opening !== void 0) throw opening;
5955
6113
  this.#nextId += 1;
5956
6114
  const id = this.#nextId;
5957
- const method = "subscriptions/listen";
5958
6115
  const modern = this.#version;
5959
6116
  const request = {
5960
6117
  jsonrpc: "2.0",
@@ -6002,7 +6159,16 @@ var MCPClient = class {
6002
6159
  this.#cancelSubscription(id, /* @__PURE__ */ new Error("MCP subscription closed by its consumer"));
6003
6160
  }
6004
6161
  }
6162
+ #refuse(method) {
6163
+ if (method === "server/discover") return void 0;
6164
+ if (this.#connected) return void 0;
6165
+ const inflight = this.#connecting;
6166
+ if (inflight !== void 0 && inflight.generation === this.#generation) return void 0;
6167
+ return new MCPError(`MCP client is not connected, so '${method}' was not issued`, JSONRPC_INVALID_REQUEST);
6168
+ }
6005
6169
  #request(method, params, deadline, version, options) {
6170
+ const refusal = this.#refuse(method);
6171
+ if (refusal !== void 0) return Promise.reject(refusal);
6006
6172
  this.#nextId += 1;
6007
6173
  const id = this.#nextId;
6008
6174
  const timeout = deadline;
@@ -6144,16 +6310,20 @@ var MCPClient = class {
6144
6310
  #tool(name, descriptor) {
6145
6311
  const inputSchema = descriptor["inputSchema"];
6146
6312
  const description = descriptor["description"];
6147
- const options = {
6313
+ const title = descriptor["title"];
6314
+ const annotations = descriptor["annotations"];
6315
+ const projected = isMCPToolAnnotations(annotations) ? mcpAnnotationsToTool(annotations) : {};
6316
+ return new _orkestrel_tool.Tool({
6148
6317
  name,
6318
+ ...(0, _orkestrel_contract.isString)(title) ? { title } : {},
6319
+ ...(0, _orkestrel_contract.isString)(description) ? { description } : {},
6320
+ ...(0, _orkestrel_contract.isRecord)(inputSchema) ? { parameters: inputSchema } : {},
6321
+ ...Object.keys(projected).length === 0 ? {} : { annotations: projected },
6149
6322
  execute: this.#execute.bind(this, name)
6150
- };
6151
- if ((0, _orkestrel_contract.isString)(description)) options.description = description;
6152
- if ((0, _orkestrel_contract.isRecord)(inputSchema)) options.parameters = inputSchema;
6153
- return new _orkestrel_tool.Tool(options);
6323
+ });
6154
6324
  }
6155
- async #execute(name, args) {
6156
- const outcome = await this.call(name, args);
6325
+ async #execute(name, args, context) {
6326
+ const outcome = await this.call(name, args, { signal: context.signal });
6157
6327
  if (outcome.resultType !== "complete") throw new Error(`MCP tool '${name}' answered '${outcome.resultType}' and has no inline value`);
6158
6328
  return outcome.value;
6159
6329
  }
@@ -6809,6 +6979,7 @@ exports.isMCPCompletion = isMCPCompletion;
6809
6979
  exports.isMCPCompletionParams = isMCPCompletionParams;
6810
6980
  exports.isMCPCompletionReference = isMCPCompletionReference;
6811
6981
  exports.isMCPCompletionResult = isMCPCompletionResult;
6982
+ exports.isMCPConsumerFilter = isMCPConsumerFilter;
6812
6983
  exports.isMCPContent = isMCPContent;
6813
6984
  exports.isMCPElicitFieldSchema = isMCPElicitFieldSchema;
6814
6985
  exports.isMCPElicitForm = isMCPElicitForm;
@@ -6859,6 +7030,7 @@ exports.isMCPTaskNotification = isMCPTaskNotification;
6859
7030
  exports.isMCPTaskResult = isMCPTaskResult;
6860
7031
  exports.isMCPTaskStatus = isMCPTaskStatus;
6861
7032
  exports.isMCPTextResource = isMCPTextResource;
7033
+ exports.isMCPToolAnnotations = isMCPToolAnnotations;
6862
7034
  exports.isMCPVersion = isMCPVersion;
6863
7035
  exports.isModernRequest = isModernRequest;
6864
7036
  exports.isRFC3339Date = isRFC3339Date;
@@ -6868,6 +7040,7 @@ exports.legacyInvocationToModern = legacyInvocationToModern;
6868
7040
  exports.legacyResultToModern = legacyResultToModern;
6869
7041
  exports.matchesResultType = matchesResultType;
6870
7042
  exports.matchesSubscriptionNotification = matchesSubscriptionNotification;
7043
+ exports.mcpAnnotationsToTool = mcpAnnotationsToTool;
6871
7044
  exports.modernInvocationToLegacy = modernInvocationToLegacy;
6872
7045
  exports.modernResultToLegacy = modernResultToLegacy;
6873
7046
  exports.parseJSONRPCMessage = parseJSONRPCMessage;
@@ -6883,5 +7056,6 @@ exports.snapshotToolResult = snapshotToolResult;
6883
7056
  exports.stampSubscriptionNotification = stampSubscriptionNotification;
6884
7057
  exports.supportsFormElicitation = supportsFormElicitation;
6885
7058
  exports.supportsTask = supportsTask;
7059
+ exports.toolAnnotationsToMCP = toolAnnotationsToMCP;
6886
7060
 
6887
7061
  //# sourceMappingURL=index.cjs.map