@orkestrel/mcp 0.0.5 → 0.0.7

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.
@@ -144,10 +144,10 @@ export declare type ClientTransportEventMap = {
144
144
  *
145
145
  * @remarks
146
146
  * The mirror of the server's "a transport pumps strings through `handle`": here the
147
- * {@link MCPClientInterface} hands the transport a {@link JSONRPCMessage} (or a batch)
148
- * via `send`, and the transport delivers each decoded reply back through the
147
+ * {@link MCPClientInterface} hands the transport one {@link JSONRPCMessage} via
148
+ * `send`, and the transport delivers each decoded reply back through the
149
149
  * `message` event the client subscribed to. The minimal carrier surface (§21): a
150
- * `start` (open the connection / arm any reader), `send` (write a message or batch),
150
+ * `start` (open the connection / arm any reader), `send` (write one message),
151
151
  * and `close` (tear down). `session` exposes a server-assigned session id once a
152
152
  * stateful transport has one (`undefined` for the stateless v1) — reserved for the
153
153
  * later sessions tier. Concrete transports (the HTTP transport over `fetch`, a future
@@ -165,7 +165,7 @@ export declare interface ClientTransportInterface {
165
165
  */
166
166
  start(): Promise<void>;
167
167
  /**
168
- * Send one JSON-RPC message (or a batch) to the remote server.
168
+ * Send one JSON-RPC message to the remote server.
169
169
  *
170
170
  * @remarks
171
171
  * Each decoded reply is surfaced on the `emitter`'s `message` event — `send`
@@ -173,10 +173,10 @@ export declare interface ClientTransportInterface {
173
173
  * transport, its synchronous reply emitted), not when a logical response arrives;
174
174
  * the {@link MCPClientInterface} awaits the response through its `id` correlation.
175
175
  *
176
- * @param message - One message, or a batch of them, to write to the wire
177
- * @returns Resolves once the message(s) have been sent
176
+ * @param message - The message to write to the wire
177
+ * @returns Resolves once the message has been sent
178
178
  */
179
- send(message: JSONRPCMessage | readonly JSONRPCMessage[]): Promise<void>;
179
+ send(message: JSONRPCMessage): Promise<void>;
180
180
  /**
181
181
  * Close the transport — end the connection and release resources.
182
182
  *
@@ -194,8 +194,8 @@ export declare interface ClientTransportInterface {
194
194
  * @remarks
195
195
  * Hand the RESULT to `createMCPClient({ transport })`, then pass the SAME
196
196
  * `transport` to {@link import('./helpers.js').bindClient} to complete the inbound
197
- * wiring: `send` serializes each outbound {@link JSONRPCMessage} (or batch, one per
198
- * message) and writes it via `transport.send`; `close` closes the underlying
197
+ * wiring: `send` serializes each outbound {@link JSONRPCMessage} and writes it via
198
+ * `transport.send`; `close` closes the underlying
199
199
  * `transport`; `start` is a no-op (the duplex channel is already open by the time
200
200
  * it is handed in — there is no separate connect step at this layer); `session` is
201
201
  * always `undefined` (session correlation is a higher-level concern the duplex port
@@ -224,7 +224,8 @@ export declare function createDuplexClientTransport(transport: MCPTransportInter
224
224
  * @remarks
225
225
  * The egress mirror of {@link createMCPServer}: where the server exposes a local tool
226
226
  * registry over MCP, the client USES a remote server's tools. `connect()` handshakes,
227
- * `tools()` lists + wraps the remote tools (each `execute` calls back over the wire),
227
+ * validates and exposes the negotiated protocol, `tools()` lists + wraps the remote
228
+ * tools (each `execute` calls back over the wire),
228
229
  * and `call(name, args)` runs a remote `tools/call` (a remote tool failure throws
229
230
  * locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
230
231
  * isolates it). The transport is injected — a concrete one (the HTTP transport over
@@ -379,6 +380,20 @@ export declare function isJSONRPCRequest(value: unknown): value is JSONRPCReques
379
380
  */
380
381
  export declare function isJSONRPCResponse(value: unknown): value is JSONRPCResponse;
381
382
 
383
+ /**
384
+ * Determine whether an unknown value is an {@link MCPError}.
385
+ *
386
+ * @param value - The unknown value to inspect
387
+ * @returns `true` only when the value is an `MCPError`
388
+ *
389
+ * @example
390
+ * ```ts
391
+ * isMCPError(new MCPError('Method not found', -32601)) // true
392
+ * isMCPError(new Error('Method not found')) // false
393
+ * ```
394
+ */
395
+ export declare function isMCPError(value: unknown): value is MCPError;
396
+
382
397
  /**
383
398
  * Determine whether a value is a valid JSON-RPC REQUEST `id` — a string, a number,
384
399
  * or absent.
@@ -502,8 +517,9 @@ export declare const MCP_PROTOCOL_VERSION = "2025-06-18";
502
517
  *
503
518
  * @remarks
504
519
  * - **The mirror of `MCPServer`.** The server DISPATCHES requests over a tool registry;
505
- * this client ISSUES them over a transport. `connect` runs `initialize` then sends
506
- * `notifications/initialized`; `tools()` lists the remote tools and wraps each as a
520
+ * this client ISSUES them over a transport. `connect` runs `initialize`, validates and
521
+ * exposes the negotiated `protocol`, then sends `notifications/initialized`; `tools()`
522
+ * lists the remote tools and wraps each as a
507
523
  * local {@link ToolInterface} whose `execute` calls back through `call`; `call` runs a
508
524
  * remote `tools/call` and returns the tool's value (a remote `isError: true` throws
509
525
  * locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
@@ -536,6 +552,7 @@ export declare class MCPClient implements MCPClientInterface {
536
552
  constructor(options: MCPClientOptions);
537
553
  get emitter(): EmitterInterface<MCPClientEventMap>;
538
554
  get connected(): boolean;
555
+ get protocol(): string | undefined;
539
556
  get transport(): ClientTransportInterface;
540
557
  on<K extends keyof MCPClientEventMap>(event: K, handler: (...args: MCPClientEventMap[K]) => void): void;
541
558
  connect(): Promise<void>;
@@ -580,7 +597,8 @@ export declare type MCPClientEventMap = {
580
597
  * @remarks
581
598
  * - **The mirror of {@link MCPServerInterface}.** Where the server DISPATCHES requests
582
599
  * over a tool registry, the client ISSUES them over a transport: `connect` runs the
583
- * `initialize` handshake (then sends `notifications/initialized`); `tools()` lists
600
+ * `initialize` handshake, validates and exposes the negotiated `protocol` (then sends
601
+ * `notifications/initialized`); `tools()` lists
584
602
  * the remote tools and wraps each as a local {@link ToolInterface} whose `execute`
585
603
  * calls back through `call`; `call(name, args)` runs a remote `tools/call` and
586
604
  * returns the tool's value (a remote tool FAILURE — `isError: true` — throws locally,
@@ -604,6 +622,11 @@ export declare interface MCPClientInterface {
604
622
  readonly emitter: EmitterInterface<MCPClientEventMap>;
605
623
  /** Whether the `initialize` handshake has completed and the client is connected. */
606
624
  readonly connected: boolean;
625
+ /**
626
+ * The MCP protocol revision negotiated by {@link connect}, or `undefined` before
627
+ * connecting and after {@link disconnect}.
628
+ */
629
+ readonly protocol: string | undefined;
607
630
  /** The injected transport the client drives the remote server over. */
608
631
  readonly transport: ClientTransportInterface;
609
632
  /**
@@ -616,11 +639,14 @@ export declare interface MCPClientInterface {
616
639
  on<K extends keyof MCPClientEventMap>(event: K, handler: (...args: MCPClientEventMap[K]) => void): void;
617
640
  /**
618
641
  * Connect to the remote server — open the transport and run the `initialize`
619
- * handshake (then send `notifications/initialized`).
642
+ * handshake, validate its negotiated protocol, then send
643
+ * `notifications/initialized`.
620
644
  *
621
645
  * @remarks
622
646
  * Idempotent — a second `connect` while already connected is a no-op. On success
623
- * the `connect` event fires.
647
+ * {@link protocol} contains a supported revision and the `connect` event fires. A
648
+ * non-string or unsupported revision closes the transport and rejects without
649
+ * connecting or sending the initialized notification.
624
650
  *
625
651
  * @returns Resolves once the handshake completes and the client is connected
626
652
  */
@@ -631,7 +657,7 @@ export declare interface MCPClientInterface {
631
657
  *
632
658
  * @remarks
633
659
  * Idempotent — a second `disconnect` while already disconnected is a no-op. The
634
- * `disconnect` event fires.
660
+ * `disconnect` event fires and {@link protocol} becomes `undefined`.
635
661
  *
636
662
  * @returns Resolves once the transport is closed
637
663
  */
@@ -703,6 +729,37 @@ export declare interface MCPContent {
703
729
  readonly text: string;
704
730
  }
705
731
 
732
+ /**
733
+ * A remote Model Context Protocol JSON-RPC error, preserving its machine-readable
734
+ * numeric code and optional structured context.
735
+ *
736
+ * @remarks
737
+ * {@link MCPClient} throws this error only for a remote JSON-RPC `error` response.
738
+ * Local lifecycle and transport conditions such as disconnects and request timeouts
739
+ * remain plain `Error`s. `context` carries the response's optional `error.data`
740
+ * unchanged and is `undefined` when the peer omitted it.
741
+ *
742
+ * @example
743
+ * ```ts
744
+ * const error = new MCPError('Method not found', -32601, { method: 'missing' })
745
+ * error.code // -32601
746
+ * error.context // { method: 'missing' }
747
+ * ```
748
+ */
749
+ export declare class MCPError extends Error {
750
+ readonly name = "MCPError";
751
+ readonly code: number;
752
+ readonly context: unknown;
753
+ /**
754
+ * Create a remote MCP protocol error.
755
+ *
756
+ * @param message - The human-readable JSON-RPC error message
757
+ * @param code - The machine-readable numeric JSON-RPC error code
758
+ * @param context - The optional JSON-RPC `error.data` payload
759
+ */
760
+ constructor(message: string, code: number, context?: unknown);
761
+ }
762
+
706
763
  /**
707
764
  * A transport-agnostic Model Context Protocol server — dispatches JSON-RPC 2.0
708
765
  * requests over a live {@link ToolManagerInterface}, with NO transport coupling.
@@ -928,13 +985,14 @@ export declare interface MCPTransportInterface {
928
985
  export declare function parseJSONRPCMessage(value: unknown): JSONRPCMessage | undefined;
929
986
 
930
987
  /**
931
- * The MCP protocol revisions this server can negotiate — the current
932
- * {@link MCP_PROTOCOL_VERSION} plus a prior rev a client may still request.
988
+ * The MCP protocol revisions this server can negotiate.
933
989
  *
934
990
  * @remarks
935
991
  * `initialize` echoes the client's requested `protocolVersion` when it appears in
936
992
  * this list, else falls back to {@link MCP_PROTOCOL_VERSION}. Frozen so the list is
937
- * an immutable contract.
993
+ * an immutable contract. The package does not advertise `2025-03-26` because that
994
+ * revision mandates JSON-RPC batching, while this package accepts only individual
995
+ * JSON-RPC messages.
938
996
  */
939
997
  export declare const SUPPORTED_PROTOCOL_VERSIONS: readonly string[];
940
998
 
@@ -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 — the current
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", "2025-03-26"]);
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,
@@ -313,18 +369,16 @@ function initializeResult(name, version, requested) {
313
369
  */
314
370
  function bindServer(server, transport) {
315
371
  let active = true;
316
- transport.listen((message) => {
372
+ transport.listen(async (message) => {
317
373
  if (!active) return;
318
- (async () => {
374
+ try {
375
+ const response = await server.handle(message);
376
+ if (response !== void 0) await transport.send(response);
377
+ } catch (error) {
319
378
  try {
320
- const response = await server.handle(message);
321
- if (response !== void 0) await transport.send(response);
322
- } catch (error) {
323
- try {
324
- server.emitter.emit("error", error);
325
- } catch {}
326
- }
327
- })();
379
+ server.emitter.emit("error", error);
380
+ } catch {}
381
+ }
328
382
  });
329
383
  transport.closed(() => {
330
384
  active = false;
@@ -449,8 +503,8 @@ var MCPServer = class {
449
503
  #tools;
450
504
  constructor(options) {
451
505
  this.#emitter = new Emitter({
452
- on: options.on,
453
- error: options.error
506
+ ...options.on !== void 0 ? { on: options.on } : {},
507
+ ...options.error !== void 0 ? { error: options.error } : {}
454
508
  });
455
509
  this.#name = options.name;
456
510
  this.#version = options.version;
@@ -515,8 +569,9 @@ var MCPServer = class {
515
569
  *
516
570
  * @remarks
517
571
  * - **The mirror of `MCPServer`.** The server DISPATCHES requests over a tool registry;
518
- * this client ISSUES them over a transport. `connect` runs `initialize` then sends
519
- * `notifications/initialized`; `tools()` lists the remote tools and wraps each as a
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
520
575
  * local {@link ToolInterface} whose `execute` calls back through `call`; `call` runs a
521
576
  * remote `tools/call` and returns the tool's value (a remote `isError: true` throws
522
577
  * locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
@@ -553,10 +608,11 @@ var MCPClient = class {
553
608
  #pending = /* @__PURE__ */ new Map();
554
609
  #nextId = 0;
555
610
  #connected = false;
611
+ #protocol = void 0;
556
612
  constructor(options) {
557
613
  this.#emitter = new Emitter({
558
- on: options.on,
559
- error: options.error
614
+ ...options.on !== void 0 ? { on: options.on } : {},
615
+ ...options.error !== void 0 ? { error: options.error } : {}
560
616
  });
561
617
  this.#transport = options.transport;
562
618
  this.#name = options.name ?? "taverna";
@@ -570,6 +626,9 @@ var MCPClient = class {
570
626
  get connected() {
571
627
  return this.#connected;
572
628
  }
629
+ get protocol() {
630
+ return this.#protocol;
631
+ }
573
632
  get transport() {
574
633
  return this.#transport;
575
634
  }
@@ -579,7 +638,7 @@ var MCPClient = class {
579
638
  async connect() {
580
639
  if (this.#connected) return;
581
640
  await this.#transport.start();
582
- await this.#request("initialize", {
641
+ const result = await this.#request("initialize", {
583
642
  protocolVersion: MCP_PROTOCOL_VERSION,
584
643
  capabilities: {},
585
644
  clientInfo: {
@@ -587,6 +646,13 @@ var MCPClient = class {
587
646
  version: this.#version
588
647
  }
589
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;
590
656
  this.#connected = true;
591
657
  await this.#transport.send({
592
658
  jsonrpc: "2.0",
@@ -597,8 +663,8 @@ var MCPClient = class {
597
663
  async disconnect() {
598
664
  if (!this.#connected) return;
599
665
  this.#connected = false;
600
- for (const pending of this.#pending.values()) pending.reject(/* @__PURE__ */ new Error("MCP client disconnected"));
601
- this.#pending.clear();
666
+ this.#protocol = void 0;
667
+ for (const id of this.#pending.keys()) this.#settle(id, /* @__PURE__ */ new Error("MCP client disconnected"), true);
602
668
  await this.#transport.close();
603
669
  this.#emitter.emit("disconnect");
604
670
  }
@@ -638,38 +704,24 @@ var MCPClient = class {
638
704
  };
639
705
  return new Promise((resolve, reject) => {
640
706
  const deadline = AbortSignal.timeout(this.#timeout);
641
- const settle = () => {
642
- this.#pending.delete(id);
643
- deadline.removeEventListener("abort", onDeadline);
644
- };
645
- const onDeadline = () => {
646
- settle();
647
- reject(/* @__PURE__ */ new Error(`MCP request '${method}' timed out after ${this.#timeout}ms`));
648
- };
649
- deadline.addEventListener("abort", onDeadline, { once: true });
707
+ const timeout = this.#timeoutRequest.bind(this, id, method);
708
+ deadline.addEventListener("abort", timeout, { once: true });
650
709
  this.#pending.set(id, {
651
- resolve: (value) => {
652
- settle();
653
- resolve(value);
654
- },
655
- reject: (error) => {
656
- settle();
657
- reject(error);
658
- }
710
+ resolve,
711
+ reject,
712
+ deadline,
713
+ timeout
659
714
  });
660
715
  this.#transport.send(request).catch((error) => {
661
- const pending = this.#pending.get(id);
662
- if (pending === void 0) return;
663
- pending.reject(error instanceof Error ? error : new Error(String(error)));
716
+ this.#settle(id, error instanceof Error ? error : new Error(String(error)), true);
664
717
  });
665
718
  });
666
719
  }
667
720
  #receive(message) {
668
721
  if (isJSONRPCResponse(message) && isRequestId(message.id)) {
669
- const pending = this.#pending.get(message.id);
670
- if (pending !== void 0) {
671
- if (message.error !== void 0) pending.reject(/* @__PURE__ */ new Error(`MCP error ${message.error.code}: ${message.error.message}`));
672
- 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);
673
725
  return;
674
726
  }
675
727
  }
@@ -680,7 +732,7 @@ var MCPClient = class {
680
732
  const description = descriptor["description"];
681
733
  const options = {
682
734
  name,
683
- execute: (args) => this.call(name, args)
735
+ execute: this.call.bind(this, name)
684
736
  };
685
737
  if (isString(description)) options.description = description;
686
738
  if (isRecord(inputSchema)) options.parameters = inputSchema;
@@ -692,6 +744,17 @@ var MCPClient = class {
692
744
  for (const block of result["content"]) if (isRecord(block) && isString(block["text"])) parts.push(block["text"]);
693
745
  return parts.join("\n");
694
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
+ }
695
758
  };
696
759
  //#endregion
697
760
  //#region src/core/factories.ts
@@ -741,7 +804,8 @@ function createMCPServer(options) {
741
804
  * @remarks
742
805
  * The egress mirror of {@link createMCPServer}: where the server exposes a local tool
743
806
  * registry over MCP, the client USES a remote server's tools. `connect()` handshakes,
744
- * `tools()` lists + wraps the remote tools (each `execute` calls back over the wire),
807
+ * validates and exposes the negotiated protocol, `tools()` lists + wraps the remote
808
+ * tools (each `execute` calls back over the wire),
745
809
  * and `call(name, args)` runs a remote `tools/call` (a remote tool failure throws
746
810
  * locally, so an agent's {@link import('@orkestrel/agent').ToolManagerInterface}
747
811
  * isolates it). The transport is injected — a concrete one (the HTTP transport over
@@ -779,8 +843,8 @@ function createMCPClient(options) {
779
843
  * @remarks
780
844
  * Hand the RESULT to `createMCPClient({ transport })`, then pass the SAME
781
845
  * `transport` to {@link import('./helpers.js').bindClient} to complete the inbound
782
- * wiring: `send` serializes each outbound {@link JSONRPCMessage} (or batch, one per
783
- * message) and writes it via `transport.send`; `close` closes the underlying
846
+ * wiring: `send` serializes each outbound {@link JSONRPCMessage} and writes it via
847
+ * `transport.send`; `close` closes the underlying
784
848
  * `transport`; `start` is a no-op (the duplex channel is already open by the time
785
849
  * it is handed in — there is no separate connect step at this layer); `session` is
786
850
  * always `undefined` (session correlation is a higher-level concern the duplex port
@@ -804,8 +868,7 @@ function createDuplexClientTransport(transport) {
804
868
  session: void 0,
805
869
  async start() {},
806
870
  async send(message) {
807
- const messages = Array.isArray(message) ? message : [message];
808
- for (const one of messages) await transport.send(JSON.stringify(one));
871
+ await transport.send(JSON.stringify(message));
809
872
  },
810
873
  async close() {
811
874
  await transport.close();
@@ -813,6 +876,6 @@ function createDuplexClientTransport(transport) {
813
876
  };
814
877
  }
815
878
  //#endregion
816
- 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, bindClient, bindServer, buildToolDescriptors, buildToolResult, createDuplexClientTransport, 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 };
817
880
 
818
881
  //# sourceMappingURL=index.js.map