@orkestrel/mcp 0.0.4 → 0.0.6
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 +564 -0
- package/dist/src/browser/index.js +690 -0
- package/dist/src/browser/index.js.map +1 -0
- package/dist/src/core/index.cjs +277 -39
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +211 -17
- package/dist/src/core/index.d.ts +211 -17
- package/dist/src/core/index.js +273 -40
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +225 -139
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +138 -51
- package/dist/src/server/index.d.ts +138 -51
- package/dist/src/server/index.js +226 -142
- package/dist/src/server/index.js.map +1 -1
- package/package.json +38 -25
package/dist/src/core/index.js
CHANGED
|
@@ -5,15 +5,16 @@ import { Tool } from "@orkestrel/agent";
|
|
|
5
5
|
/** The MCP protocol revision this server implements (the default negotiated version). */
|
|
6
6
|
var MCP_PROTOCOL_VERSION = "2025-06-18";
|
|
7
7
|
/**
|
|
8
|
-
* The MCP protocol revisions this server can negotiate
|
|
9
|
-
* {@link MCP_PROTOCOL_VERSION} plus a prior rev a client may still request.
|
|
8
|
+
* The MCP protocol revisions this server can negotiate.
|
|
10
9
|
*
|
|
11
10
|
* @remarks
|
|
12
11
|
* `initialize` echoes the client's requested `protocolVersion` when it appears in
|
|
13
12
|
* this list, else falls back to {@link MCP_PROTOCOL_VERSION}. Frozen so the list is
|
|
14
|
-
* an immutable contract.
|
|
13
|
+
* an immutable contract. The package does not advertise `2025-03-26` because that
|
|
14
|
+
* revision mandates JSON-RPC batching, while this package accepts only individual
|
|
15
|
+
* JSON-RPC messages.
|
|
15
16
|
*/
|
|
16
|
-
var SUPPORTED_PROTOCOL_VERSIONS = Object.freeze(["2025-06-18"
|
|
17
|
+
var SUPPORTED_PROTOCOL_VERSIONS = Object.freeze(["2025-06-18"]);
|
|
17
18
|
/** JSON-RPC 2.0 reserved error: invalid JSON was received (the message did not parse). */
|
|
18
19
|
var JSONRPC_PARSE_ERROR = -32700;
|
|
19
20
|
/** JSON-RPC 2.0 reserved error: the payload was not a valid Request object. */
|
|
@@ -34,6 +35,61 @@ var DEFAULT_MCP_CLIENT_VERSION = "1.0.0";
|
|
|
34
35
|
*/
|
|
35
36
|
var DEFAULT_MCP_REQUEST_TIMEOUT = 3e4;
|
|
36
37
|
//#endregion
|
|
38
|
+
//#region src/core/errors.ts
|
|
39
|
+
/**
|
|
40
|
+
* A remote Model Context Protocol JSON-RPC error, preserving its machine-readable
|
|
41
|
+
* numeric code and optional structured context.
|
|
42
|
+
*
|
|
43
|
+
* @remarks
|
|
44
|
+
* {@link MCPClient} throws this error only for a remote JSON-RPC `error` response.
|
|
45
|
+
* Local lifecycle and transport conditions such as disconnects and request timeouts
|
|
46
|
+
* remain plain `Error`s. `context` carries the response's optional `error.data`
|
|
47
|
+
* unchanged and is `undefined` when the peer omitted it.
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* ```ts
|
|
51
|
+
* const error = new MCPError('Method not found', -32601, { method: 'missing' })
|
|
52
|
+
* error.code // -32601
|
|
53
|
+
* error.context // { method: 'missing' }
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
var MCPError = class extends Error {
|
|
57
|
+
name = "MCPError";
|
|
58
|
+
code;
|
|
59
|
+
context;
|
|
60
|
+
/**
|
|
61
|
+
* Create a remote MCP protocol error.
|
|
62
|
+
*
|
|
63
|
+
* @param message - The human-readable JSON-RPC error message
|
|
64
|
+
* @param code - The machine-readable numeric JSON-RPC error code
|
|
65
|
+
* @param context - The optional JSON-RPC `error.data` payload
|
|
66
|
+
*/
|
|
67
|
+
constructor(message, code, context) {
|
|
68
|
+
super(message);
|
|
69
|
+
this.code = code;
|
|
70
|
+
this.context = context;
|
|
71
|
+
}
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Determine whether an unknown value is an {@link MCPError}.
|
|
75
|
+
*
|
|
76
|
+
* @param value - The unknown value to inspect
|
|
77
|
+
* @returns `true` only when the value is an `MCPError`
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* isMCPError(new MCPError('Method not found', -32601)) // true
|
|
82
|
+
* isMCPError(new Error('Method not found')) // false
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
function isMCPError(value) {
|
|
86
|
+
try {
|
|
87
|
+
return value instanceof MCPError;
|
|
88
|
+
} catch {
|
|
89
|
+
return false;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
//#endregion
|
|
37
93
|
//#region src/core/validators.ts
|
|
38
94
|
/**
|
|
39
95
|
* Determine whether a value is a valid JSON-RPC REQUEST `id` — a string, a number,
|
|
@@ -279,6 +335,132 @@ function initializeResult(name, version, requested) {
|
|
|
279
335
|
}
|
|
280
336
|
};
|
|
281
337
|
}
|
|
338
|
+
/**
|
|
339
|
+
* Pipe an {@link MCPTransportInterface} into an {@link MCPServerInterface} — every
|
|
340
|
+
* inbound message runs through `server.handle`, and a defined reply is written back
|
|
341
|
+
* via `transport.send`.
|
|
342
|
+
*
|
|
343
|
+
* @remarks
|
|
344
|
+
* `server.handle` already turns a malformed message into a serialized `-32700` /
|
|
345
|
+
* `-32600` reply and a notification into `undefined` (no reply), so this binder adds
|
|
346
|
+
* no parsing of its own. A `transport.send` throw or rejection is caught and routed
|
|
347
|
+
* to `server.emitter`'s `error` event (never rethrown, never an unhandled rejection);
|
|
348
|
+
* a listener on that event that itself throws is swallowed (the end of the line —
|
|
349
|
+
* the caller's own bug, never this binder's). The returned unbind DETACHES this
|
|
350
|
+
* binder (further inbound messages and the transport's `closed` signal are ignored)
|
|
351
|
+
* WITHOUT closing the transport — closing is the caller's decision.
|
|
352
|
+
*
|
|
353
|
+
* `listen`/`closed` are REPLACE semantics (§ port contract): the returned unbind
|
|
354
|
+
* DETACHES by replacing this binder's own handlers with no-ops, so a subsequent
|
|
355
|
+
* `bindServer` call on the SAME transport is never double-dispatched by a stale
|
|
356
|
+
* subscription left behind — an unbind→rebind cycle yields exactly one reply per
|
|
357
|
+
* request.
|
|
358
|
+
*
|
|
359
|
+
* @param server - The transport-agnostic server to dispatch inbound messages over
|
|
360
|
+
* @param transport - The duplex channel to pipe the server over
|
|
361
|
+
* @returns Detach this binder from the transport (does not close it)
|
|
362
|
+
*
|
|
363
|
+
* @example
|
|
364
|
+
* ```ts
|
|
365
|
+
* const unbind = bindServer(server, transport)
|
|
366
|
+
* // ... later, detach without closing:
|
|
367
|
+
* unbind()
|
|
368
|
+
* ```
|
|
369
|
+
*/
|
|
370
|
+
function bindServer(server, transport) {
|
|
371
|
+
let active = true;
|
|
372
|
+
transport.listen(async (message) => {
|
|
373
|
+
if (!active) return;
|
|
374
|
+
try {
|
|
375
|
+
const response = await server.handle(message);
|
|
376
|
+
if (response !== void 0) await transport.send(response);
|
|
377
|
+
} catch (error) {
|
|
378
|
+
try {
|
|
379
|
+
server.emitter.emit("error", error);
|
|
380
|
+
} catch {}
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
transport.closed(() => {
|
|
384
|
+
active = false;
|
|
385
|
+
});
|
|
386
|
+
return () => {
|
|
387
|
+
active = false;
|
|
388
|
+
transport.listen(() => {});
|
|
389
|
+
transport.closed(() => {});
|
|
390
|
+
};
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* Pipe an {@link MCPTransportInterface} into an {@link MCPClientInterface} — every
|
|
394
|
+
* inbound message is decoded and delivered onto the client's OWN transport
|
|
395
|
+
* (`client.transport.emitter`'s `message` / `close` events), resolving/rejecting the
|
|
396
|
+
* client's correlated pending requests exactly as a direct reply would.
|
|
397
|
+
*
|
|
398
|
+
* @remarks
|
|
399
|
+
* The client's outbound writes flow through `client.transport.send` — its existing,
|
|
400
|
+
* unmodified request/response correlation — so `client` must have been constructed
|
|
401
|
+
* with a {@link import('./types.js').ClientTransportInterface} that itself carries
|
|
402
|
+
* the SAME `transport` (see {@link import('./factories.js').createDuplexClientTransport},
|
|
403
|
+
* the additive factory that adapts an {@link MCPTransportInterface} into that shape);
|
|
404
|
+
* this binder then completes the inbound half by decoding each message and pushing it
|
|
405
|
+
* onto `client.transport.emitter` (an {@link import('@orkestrel/emitter').EmitterInterface}
|
|
406
|
+
* exposes `emit`, so no client modification is needed). A malformed / non-JSON-RPC
|
|
407
|
+
* inbound message is DROPPED (§14, total — never throws); a delivery fault is routed to
|
|
408
|
+
* `client.transport.emitter`'s `error` event (never rethrown). The returned unbind
|
|
409
|
+
* DETACHES this binder (further inbound messages and the transport's `closed` signal are
|
|
410
|
+
* ignored) WITHOUT closing the transport.
|
|
411
|
+
*
|
|
412
|
+
* `listen`/`closed` are REPLACE semantics (§ port contract): the returned unbind
|
|
413
|
+
* DETACHES by replacing this binder's own handlers with no-ops, so a subsequent
|
|
414
|
+
* `bindClient` call on the SAME transport is never double-dispatched by a stale
|
|
415
|
+
* subscription left behind — an unbind→rebind cycle delivers exactly one `message`
|
|
416
|
+
* emit per inbound reply.
|
|
417
|
+
*
|
|
418
|
+
* @param client - The transport-agnostic client whose transport to deliver messages onto
|
|
419
|
+
* @param transport - The duplex channel to pipe the client over
|
|
420
|
+
* @returns Detach this binder from the transport (does not close it)
|
|
421
|
+
*
|
|
422
|
+
* @example
|
|
423
|
+
* ```ts
|
|
424
|
+
* const client = createMCPClient({ transport: createDuplexClientTransport(transport) })
|
|
425
|
+
* const unbind = bindClient(client, transport)
|
|
426
|
+
* await client.connect()
|
|
427
|
+
* // ... later, detach without closing:
|
|
428
|
+
* unbind()
|
|
429
|
+
* ```
|
|
430
|
+
*/
|
|
431
|
+
function bindClient(client, transport) {
|
|
432
|
+
let active = true;
|
|
433
|
+
transport.listen((message) => {
|
|
434
|
+
if (!active) return;
|
|
435
|
+
let parsed;
|
|
436
|
+
try {
|
|
437
|
+
parsed = JSON.parse(message);
|
|
438
|
+
} catch {
|
|
439
|
+
return;
|
|
440
|
+
}
|
|
441
|
+
const decoded = parseJSONRPCMessage(parsed);
|
|
442
|
+
if (decoded === void 0) return;
|
|
443
|
+
try {
|
|
444
|
+
client.transport.emitter.emit("message", decoded);
|
|
445
|
+
} catch (error) {
|
|
446
|
+
try {
|
|
447
|
+
client.transport.emitter.emit("error", error);
|
|
448
|
+
} catch {}
|
|
449
|
+
}
|
|
450
|
+
});
|
|
451
|
+
transport.closed(() => {
|
|
452
|
+
if (!active) return;
|
|
453
|
+
active = false;
|
|
454
|
+
try {
|
|
455
|
+
client.transport.emitter.emit("close");
|
|
456
|
+
} catch {}
|
|
457
|
+
});
|
|
458
|
+
return () => {
|
|
459
|
+
active = false;
|
|
460
|
+
transport.listen(() => {});
|
|
461
|
+
transport.closed(() => {});
|
|
462
|
+
};
|
|
463
|
+
}
|
|
282
464
|
//#endregion
|
|
283
465
|
//#region src/core/MCPServer.ts
|
|
284
466
|
/**
|
|
@@ -321,8 +503,8 @@ var MCPServer = class {
|
|
|
321
503
|
#tools;
|
|
322
504
|
constructor(options) {
|
|
323
505
|
this.#emitter = new Emitter({
|
|
324
|
-
on: options.on,
|
|
325
|
-
error: options.error
|
|
506
|
+
...options.on !== void 0 ? { on: options.on } : {},
|
|
507
|
+
...options.error !== void 0 ? { error: options.error } : {}
|
|
326
508
|
});
|
|
327
509
|
this.#name = options.name;
|
|
328
510
|
this.#version = options.version;
|
|
@@ -387,8 +569,9 @@ var MCPServer = class {
|
|
|
387
569
|
*
|
|
388
570
|
* @remarks
|
|
389
571
|
* - **The mirror of `MCPServer`.** The server DISPATCHES requests over a tool registry;
|
|
390
|
-
* this client ISSUES them over a transport. `connect` runs `initialize
|
|
391
|
-
* `notifications/initialized`; `tools()`
|
|
572
|
+
* this client ISSUES them over a transport. `connect` runs `initialize`, validates and
|
|
573
|
+
* exposes the negotiated `protocol`, then sends `notifications/initialized`; `tools()`
|
|
574
|
+
* lists the remote tools and wraps each as a
|
|
392
575
|
* local {@link ToolInterface} whose `execute` calls back through `call`; `call` runs a
|
|
393
576
|
* remote `tools/call` and returns the tool's value (a remote `isError: true` throws
|
|
394
577
|
* locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
|
|
@@ -425,10 +608,11 @@ var MCPClient = class {
|
|
|
425
608
|
#pending = /* @__PURE__ */ new Map();
|
|
426
609
|
#nextId = 0;
|
|
427
610
|
#connected = false;
|
|
611
|
+
#protocol = void 0;
|
|
428
612
|
constructor(options) {
|
|
429
613
|
this.#emitter = new Emitter({
|
|
430
|
-
on: options.on,
|
|
431
|
-
error: options.error
|
|
614
|
+
...options.on !== void 0 ? { on: options.on } : {},
|
|
615
|
+
...options.error !== void 0 ? { error: options.error } : {}
|
|
432
616
|
});
|
|
433
617
|
this.#transport = options.transport;
|
|
434
618
|
this.#name = options.name ?? "taverna";
|
|
@@ -442,6 +626,9 @@ var MCPClient = class {
|
|
|
442
626
|
get connected() {
|
|
443
627
|
return this.#connected;
|
|
444
628
|
}
|
|
629
|
+
get protocol() {
|
|
630
|
+
return this.#protocol;
|
|
631
|
+
}
|
|
445
632
|
get transport() {
|
|
446
633
|
return this.#transport;
|
|
447
634
|
}
|
|
@@ -451,7 +638,7 @@ var MCPClient = class {
|
|
|
451
638
|
async connect() {
|
|
452
639
|
if (this.#connected) return;
|
|
453
640
|
await this.#transport.start();
|
|
454
|
-
await this.#request("initialize", {
|
|
641
|
+
const result = await this.#request("initialize", {
|
|
455
642
|
protocolVersion: MCP_PROTOCOL_VERSION,
|
|
456
643
|
capabilities: {},
|
|
457
644
|
clientInfo: {
|
|
@@ -459,6 +646,13 @@ var MCPClient = class {
|
|
|
459
646
|
version: this.#version
|
|
460
647
|
}
|
|
461
648
|
});
|
|
649
|
+
const protocol = isRecord(result) ? result["protocolVersion"] : void 0;
|
|
650
|
+
if (!isString(protocol) || !SUPPORTED_PROTOCOL_VERSIONS.includes(protocol)) {
|
|
651
|
+
await this.#transport.close();
|
|
652
|
+
if (isString(protocol)) throw new Error(`MCP server negotiated unsupported protocol version '${protocol}'`);
|
|
653
|
+
throw new Error("MCP server returned a non-string protocol version");
|
|
654
|
+
}
|
|
655
|
+
this.#protocol = protocol;
|
|
462
656
|
this.#connected = true;
|
|
463
657
|
await this.#transport.send({
|
|
464
658
|
jsonrpc: "2.0",
|
|
@@ -469,8 +663,8 @@ var MCPClient = class {
|
|
|
469
663
|
async disconnect() {
|
|
470
664
|
if (!this.#connected) return;
|
|
471
665
|
this.#connected = false;
|
|
472
|
-
|
|
473
|
-
this.#pending.
|
|
666
|
+
this.#protocol = void 0;
|
|
667
|
+
for (const id of this.#pending.keys()) this.#settle(id, /* @__PURE__ */ new Error("MCP client disconnected"), true);
|
|
474
668
|
await this.#transport.close();
|
|
475
669
|
this.#emitter.emit("disconnect");
|
|
476
670
|
}
|
|
@@ -510,38 +704,24 @@ var MCPClient = class {
|
|
|
510
704
|
};
|
|
511
705
|
return new Promise((resolve, reject) => {
|
|
512
706
|
const deadline = AbortSignal.timeout(this.#timeout);
|
|
513
|
-
const
|
|
514
|
-
|
|
515
|
-
deadline.removeEventListener("abort", onDeadline);
|
|
516
|
-
};
|
|
517
|
-
const onDeadline = () => {
|
|
518
|
-
settle();
|
|
519
|
-
reject(/* @__PURE__ */ new Error(`MCP request '${method}' timed out after ${this.#timeout}ms`));
|
|
520
|
-
};
|
|
521
|
-
deadline.addEventListener("abort", onDeadline, { once: true });
|
|
707
|
+
const timeout = this.#timeoutRequest.bind(this, id, method);
|
|
708
|
+
deadline.addEventListener("abort", timeout, { once: true });
|
|
522
709
|
this.#pending.set(id, {
|
|
523
|
-
resolve
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
reject: (error) => {
|
|
528
|
-
settle();
|
|
529
|
-
reject(error);
|
|
530
|
-
}
|
|
710
|
+
resolve,
|
|
711
|
+
reject,
|
|
712
|
+
deadline,
|
|
713
|
+
timeout
|
|
531
714
|
});
|
|
532
715
|
this.#transport.send(request).catch((error) => {
|
|
533
|
-
|
|
534
|
-
if (pending === void 0) return;
|
|
535
|
-
pending.reject(error instanceof Error ? error : new Error(String(error)));
|
|
716
|
+
this.#settle(id, error instanceof Error ? error : new Error(String(error)), true);
|
|
536
717
|
});
|
|
537
718
|
});
|
|
538
719
|
}
|
|
539
720
|
#receive(message) {
|
|
540
721
|
if (isJSONRPCResponse(message) && isRequestId(message.id)) {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
else pending.resolve(message.result);
|
|
722
|
+
if (this.#pending.has(message.id)) {
|
|
723
|
+
if (message.error !== void 0) this.#settle(message.id, new MCPError(message.error.message, message.error.code, message.error.data), true);
|
|
724
|
+
else this.#settle(message.id, message.result, false);
|
|
545
725
|
return;
|
|
546
726
|
}
|
|
547
727
|
}
|
|
@@ -552,7 +732,7 @@ var MCPClient = class {
|
|
|
552
732
|
const description = descriptor["description"];
|
|
553
733
|
const options = {
|
|
554
734
|
name,
|
|
555
|
-
execute:
|
|
735
|
+
execute: this.call.bind(this, name)
|
|
556
736
|
};
|
|
557
737
|
if (isString(description)) options.description = description;
|
|
558
738
|
if (isRecord(inputSchema)) options.parameters = inputSchema;
|
|
@@ -564,6 +744,17 @@ var MCPClient = class {
|
|
|
564
744
|
for (const block of result["content"]) if (isRecord(block) && isString(block["text"])) parts.push(block["text"]);
|
|
565
745
|
return parts.join("\n");
|
|
566
746
|
}
|
|
747
|
+
#timeoutRequest(id, method) {
|
|
748
|
+
this.#settle(id, /* @__PURE__ */ new Error(`MCP request '${method}' timed out after ${this.#timeout}ms`), true);
|
|
749
|
+
}
|
|
750
|
+
#settle(id, value, failed) {
|
|
751
|
+
const pending = this.#pending.get(id);
|
|
752
|
+
if (pending === void 0) return;
|
|
753
|
+
this.#pending.delete(id);
|
|
754
|
+
pending.deadline.removeEventListener("abort", pending.timeout);
|
|
755
|
+
if (failed) pending.reject(value);
|
|
756
|
+
else pending.resolve(value);
|
|
757
|
+
}
|
|
567
758
|
};
|
|
568
759
|
//#endregion
|
|
569
760
|
//#region src/core/factories.ts
|
|
@@ -613,7 +804,8 @@ function createMCPServer(options) {
|
|
|
613
804
|
* @remarks
|
|
614
805
|
* The egress mirror of {@link createMCPServer}: where the server exposes a local tool
|
|
615
806
|
* registry over MCP, the client USES a remote server's tools. `connect()` handshakes,
|
|
616
|
-
* `tools()` lists + wraps the remote
|
|
807
|
+
* validates and exposes the negotiated protocol, `tools()` lists + wraps the remote
|
|
808
|
+
* tools (each `execute` calls back over the wire),
|
|
617
809
|
* and `call(name, args)` runs a remote `tools/call` (a remote tool failure throws
|
|
618
810
|
* locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
|
|
619
811
|
* isolates it). The transport is injected — a concrete one (the HTTP transport over
|
|
@@ -642,7 +834,48 @@ function createMCPServer(options) {
|
|
|
642
834
|
function createMCPClient(options) {
|
|
643
835
|
return new MCPClient(options);
|
|
644
836
|
}
|
|
837
|
+
/**
|
|
838
|
+
* Adapt an {@link MCPTransportInterface} (the environment-agnostic duplex message
|
|
839
|
+
* channel) into a {@link ClientTransportInterface} — the additive bridge that lets
|
|
840
|
+
* `createMCPClient` run over the new port without any change to `MCPClient`'s
|
|
841
|
+
* existing shape.
|
|
842
|
+
*
|
|
843
|
+
* @remarks
|
|
844
|
+
* Hand the RESULT to `createMCPClient({ transport })`, then pass the SAME
|
|
845
|
+
* `transport` to {@link import('./helpers.js').bindClient} to complete the inbound
|
|
846
|
+
* wiring: `send` serializes each outbound {@link JSONRPCMessage} and writes it via
|
|
847
|
+
* `transport.send`; `close` closes the underlying
|
|
848
|
+
* `transport`; `start` is a no-op (the duplex channel is already open by the time
|
|
849
|
+
* it is handed in — there is no separate connect step at this layer); `session` is
|
|
850
|
+
* always `undefined` (session correlation is a higher-level concern the duplex port
|
|
851
|
+
* does not carry). Inbound delivery (`emitter`'s `message` / `close` events) is
|
|
852
|
+
* `bindClient`'s job, not this factory's — the returned object exposes a `message`-
|
|
853
|
+
* capable emitter for `bindClient` to push onto.
|
|
854
|
+
*
|
|
855
|
+
* @param transport - The duplex channel to adapt
|
|
856
|
+
* @returns A {@link ClientTransportInterface} `createMCPClient` can drive
|
|
857
|
+
*
|
|
858
|
+
* @example
|
|
859
|
+
* ```ts
|
|
860
|
+
* const client = createMCPClient({ transport: createDuplexClientTransport(transport) })
|
|
861
|
+
* const unbind = bindClient(client, transport)
|
|
862
|
+
* await client.connect()
|
|
863
|
+
* ```
|
|
864
|
+
*/
|
|
865
|
+
function createDuplexClientTransport(transport) {
|
|
866
|
+
return {
|
|
867
|
+
emitter: new Emitter(),
|
|
868
|
+
session: void 0,
|
|
869
|
+
async start() {},
|
|
870
|
+
async send(message) {
|
|
871
|
+
await transport.send(JSON.stringify(message));
|
|
872
|
+
},
|
|
873
|
+
async close() {
|
|
874
|
+
await transport.close();
|
|
875
|
+
}
|
|
876
|
+
};
|
|
877
|
+
}
|
|
645
878
|
//#endregion
|
|
646
|
-
export { DEFAULT_MCP_CLIENT_NAME, DEFAULT_MCP_CLIENT_VERSION, DEFAULT_MCP_REQUEST_TIMEOUT, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_SERVER_ERROR, MCPClient, MCPServer, MCP_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, buildToolDescriptors, buildToolResult, createMCPClient, createMCPServer, initializeResult, isInitializeRequest, isJSONRPCMessage, isJSONRPCRequest, isJSONRPCResponse, isRequestId, jsonRPCError, jsonRPCResult, parseJSONRPCMessage };
|
|
879
|
+
export { DEFAULT_MCP_CLIENT_NAME, DEFAULT_MCP_CLIENT_VERSION, DEFAULT_MCP_REQUEST_TIMEOUT, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, JSONRPC_SERVER_ERROR, MCPClient, MCPError, MCPServer, MCP_PROTOCOL_VERSION, SUPPORTED_PROTOCOL_VERSIONS, bindClient, bindServer, buildToolDescriptors, buildToolResult, createDuplexClientTransport, createMCPClient, createMCPServer, initializeResult, isInitializeRequest, isJSONRPCMessage, isJSONRPCRequest, isJSONRPCResponse, isMCPError, isRequestId, jsonRPCError, jsonRPCResult, parseJSONRPCMessage };
|
|
647
880
|
|
|
648
881
|
//# sourceMappingURL=index.js.map
|