@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.
- package/dist/src/browser/index.d.ts +786 -0
- package/dist/src/browser/index.js +636 -4
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +216 -42
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +144 -32
- package/dist/src/core/index.d.ts +144 -32
- package/dist/src/core/index.js +214 -44
- package/dist/src/core/index.js.map +1 -1
- package/package.json +6 -6
package/dist/src/core/index.cjs
CHANGED
|
@@ -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
|
|
279
|
-
*
|
|
280
|
-
*
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
* `
|
|
1456
|
-
* `capabilities.
|
|
1457
|
-
*
|
|
1458
|
-
*
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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
|
|
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,
|
|
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
|
-
|
|
5569
|
-
|
|
5570
|
-
|
|
5571
|
-
|
|
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
|
|
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
|