@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.
@@ -85,8 +85,10 @@ export declare function bridgeMessageTransport(transport: ClientTransportInterfa
85
85
  * and the reply is surfaced on the transport's `message` event for the client's id
86
86
  * correlation. Add `options.headers` (e.g. an `Authorization` bearer) to reach a guarded
87
87
  * server. `start` / `close` hold no connection; against a STATEFUL server it captures the
88
- * `mcp-session-id` from `initialize` and echoes it on later requests, so the same
89
- * `MCPClient` passes session validation (a stateless server sends none).
88
+ * `mcp-session-id` from `initialize` and echoes it on later requests. It also captures
89
+ * the initialize result's `protocolVersion` and sends `mcp-protocol-version` on every
90
+ * subsequent request, so the same `MCPClient` passes the session and 2025-06-18
91
+ * protocol gates without caller wiring.
90
92
  *
91
93
  * @param options - `url` (the remote endpoint; REQUIRED), optional `headers` merged onto
92
94
  * every request, optional `fetch` (default `globalThis.fetch`), and optional `timeout`
@@ -107,6 +109,34 @@ export declare function bridgeMessageTransport(transport: ClientTransportInterfa
107
109
  */
108
110
  export declare function createHTTPClientTransport(options: HTTPClientTransportOptions): ClientTransportInterface;
109
111
 
112
+ /**
113
+ * Create the Streamable-HTTP POST handler used by `createMCPRoutes`.
114
+ *
115
+ * @remarks
116
+ * A present `mcp-protocol-version` header must name a supported revision; an
117
+ * unsupported value returns an HTTP `400` JSON-RPC invalid-request error without
118
+ * dispatching. An absent header is accepted for the initialize/bootstrap request.
119
+ *
120
+ * @param mcp - The transport-agnostic MCP server to dispatch through
121
+ * @param streaming - Whether an event-stream response may be negotiated
122
+ * @returns A request handler for the stateless MCP POST route
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * import { createMCPServer } from '@orkestrel/mcp'
127
+ * import { createMCPPostHandler } from '@orkestrel/mcp/server'
128
+ * import { createToolManager } from '@orkestrel/agent'
129
+ *
130
+ * const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
131
+ * const handler = createMCPPostHandler(mcp, true)
132
+ * await handler(new Request('http://localhost/mcp', {
133
+ * method: 'POST',
134
+ * body: '{"jsonrpc":"2.0","method":"ping","id":1}',
135
+ * }))
136
+ * ```
137
+ */
138
+ export declare function createMCPPostHandler(mcp: MCPServerInterface, streaming: boolean): (request: Request) => Promise<Response>;
139
+
110
140
  /**
111
141
  * Create the MCP Streamable-HTTP transport routes — mounts a transport-agnostic
112
142
  * {@link MCPServerInterface} (the `@src/core` dispatch core) on the fetch-standard router
@@ -122,6 +152,9 @@ export declare function createHTTPClientTransport(options: HTTPClientTransportOp
122
152
  * - A **transport** failure — a malformed JSON body, or a parsed value that is not a
123
153
  * JSON-RPC REQUEST — is an HTTP `400` carrying a JSON-RPC error BODY (`-32700` Parse
124
154
  * error / `-32600` Invalid Request, id `null`).
155
+ * - A present `mcp-protocol-version` header is validated before dispatch: a supported
156
+ * value proceeds, while an unsupported value returns HTTP `400` with a JSON-RPC
157
+ * `-32600` body. An absent value proceeds for initialize/bootstrap compatibility.
125
158
  * - A **dispatch** result — a success OR an IN-BAND JSON-RPC error from `mcp.dispatch`
126
159
  * (e.g. `-32601` method-not-found) — is an HTTP `200` carrying the JSON-RPC response
127
160
  * envelope (the error is in-band per JSON-RPC, NOT an HTTP error).
@@ -468,7 +501,7 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
468
501
  *
469
502
  * @remarks
470
503
  * - **Request/response over `fetch`.** `send(message)` POSTs the JSON-serialized
471
- * message (or batch) to `options.url` with `content-type: application/json` and an
504
+ * message to `options.url` with `content-type: application/json` and an
472
505
  * `Accept` of BOTH `application/json` and `text/event-stream` (so the server may
473
506
  * answer with either framing) — plus any `options.headers` (e.g. an `Authorization`
474
507
  * bearer). It then decodes the reply and emits each decoded {@link JSONRPCMessage} on
@@ -480,13 +513,18 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
480
513
  * readEventStream}) — the inverse of the server's `openStream` seam, so the wire
481
514
  * round-trips. A `202`
482
515
  * Accepted (a notification) carries no body and emits nothing.
483
- * - **Session echo.** `start()` / `close()` are no-ops (a request/response transport
484
- * holds no long-lived connection). The `mcp-session-id` response header, when a
485
- * STATEFUL server sends one (on `initialize`), is captured into `session` and then
486
- * ECHOED as the `mcp-session-id` request header on every SUBSEQUENT request — so an
487
- * `MCPClient` passes a stateful server's session validation. Before initialize returns
488
- * an id, `session` is `undefined` and no header is sent (safe against a stateless
489
- * server, which neither sends nor expects one).
516
+ * - **Session and protocol echo.** `start()` is a no-op (a
517
+ * request/response transport opens no long-lived connection). The
518
+ * `mcp-session-id` response header, when a STATEFUL server sends one (on
519
+ * `initialize`), is captured into `session` and then ECHOED as the
520
+ * `mcp-session-id` request header on every SUBSEQUENT request so an
521
+ * `MCPClient` passes a stateful server's session validation. The
522
+ * initialize result's `protocolVersion` is likewise captured, but only
523
+ * when it is a SUPPORTED value, and echoed as `mcp-protocol-version` on
524
+ * every subsequent request, as required by the 2025-06-18 Streamable-HTTP
525
+ * transport. Before initialize returns, neither captured header is sent.
526
+ * `close()` clears the captured protocol so a reconnect's `initialize`
527
+ * POST is headerless; the captured `session` persists across `close()`.
490
528
  * - **Total at the boundary (§14).** Every reply is narrowed (`parseJSONRPCMessage`,
491
529
  * the SSE decoder) — a non-message reply is dropped, never asserted; a `fetch` /
492
530
  * decode failure surfaces on the `error` event rather than escaping `send`.
@@ -506,7 +544,7 @@ export declare class HTTPClientTransport implements ClientTransportInterface_2 {
506
544
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
507
545
  get session(): string | undefined;
508
546
  start(): Promise<void>;
509
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
547
+ send(message: JSONRPCMessage_2): Promise<void>;
510
548
  close(): Promise<void>;
511
549
  }
512
550
 
@@ -574,10 +612,13 @@ export declare interface LineExtraction {
574
612
  }
575
613
 
576
614
  /**
577
- * The Streamable-HTTP transport header that carries the negotiated MCP protocol version
578
- * on a subsequent request. The version is negotiated in the `initialize` JSON-RPC result
579
- * body; a stateful transport MAY additionally read this header to pin the per-request
580
- * protocol version (optional — the result body remains the source of truth).
615
+ * The Streamable-HTTP transport header carrying the negotiated MCP protocol version
616
+ * on every post-initialize client request.
617
+ *
618
+ * @remarks
619
+ * Required by MCP 2025-06-18 after initialization. Both HTTP client transports
620
+ * capture the initialize result's `protocolVersion` and send it on subsequent
621
+ * requests; `createMCPRoutes` rejects a present unsupported value before dispatch.
581
622
  */
582
623
  export declare const MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version";
583
624
 
@@ -675,12 +716,12 @@ export declare class MCPSession implements MCPSessionInterface {
675
716
  *
676
717
  * @remarks
677
718
  * - `session` — the live {@link MCPSession} entity the store keys by session id.
678
- * - `touched` — the epoch-ms instant of the last access; mutated (not replaced) on every
719
+ * - `touched` — the epoch-ms instant of the last access; the entry is replaced on every
679
720
  * resolved request so the middleware's lazy sweep can evict an idle entry past `ttl`.
680
721
  */
681
722
  export declare interface MCPSessionEntry {
682
723
  readonly session: MCPSession;
683
- touched: number;
724
+ readonly touched: number;
684
725
  }
685
726
 
686
727
  /**
@@ -755,7 +796,7 @@ export declare interface MCPSessionOptions {
755
796
  * before calling `next`).
756
797
  */
757
798
  export declare interface MCPSessionState {
758
- session?: MCPSessionInterface;
799
+ readonly session?: MCPSessionInterface;
759
800
  }
760
801
 
761
802
  /**
@@ -846,8 +887,8 @@ export declare function rejectUnknownSession(): Response;
846
887
  * {@link dispatchLines} helper — a well-formed {@link JSONRPCMessage} emits
847
888
  * `message`, a malformed line emits `error` (§14, never throws). The child's
848
889
  * `close` bridges to this transport's `close`.
849
- * - **Outbound (`send`).** `send(message | messages)` writes ONE newline-terminated
850
- * `JSON.stringify`d line per message to the child's `stdin`.
890
+ * - **Outbound (`send`).** `send(message)` writes one newline-terminated
891
+ * `JSON.stringify`d line to the child's `stdin`.
851
892
  * - **`close()`** kills the child process and fires `close` (idempotent).
852
893
  * - **Observable (§13).** Owns the `emitter` ({@link ClientTransportEventMap}); the
853
894
  * emitter isolates a listener throw; `error` is a DOMAIN event (a transport-level
@@ -866,7 +907,7 @@ export declare class StdioClientTransport implements ClientTransportInterface_2
866
907
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
867
908
  get session(): string | undefined;
868
909
  start(): Promise<void>;
869
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
910
+ send(message: JSONRPCMessage_2): Promise<void>;
870
911
  close(): Promise<void>;
871
912
  }
872
913
 
@@ -923,8 +964,8 @@ export declare interface StdioServerOptions {
923
964
  * well-formed {@link JSONRPCMessage} re-emits on `message`, a malformed line
924
965
  * emits `error` (§14, never throws). `input`'s `close` bridges to this
925
966
  * transport's `close`.
926
- * - **Outbound (`send`).** `send(message | messages)` writes ONE newline-terminated
927
- * `JSON.stringify`d line per message to `output`.
967
+ * - **Outbound (`send`).** `send(message)` writes one newline-terminated
968
+ * `JSON.stringify`d line to `output`.
928
969
  * - **`close()`** fires this transport's `close` (idempotent) — the injected streams
929
970
  * are owned by the caller (typically `process.stdin`/`process.stdout`, which must
930
971
  * never be closed out from under the process) and are not torn down here.
@@ -938,7 +979,7 @@ export declare class StdioServerTransport implements ClientTransportInterface_2
938
979
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
939
980
  get session(): string | undefined;
940
981
  start(): Promise<void>;
941
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
982
+ send(message: JSONRPCMessage_2): Promise<void>;
942
983
  close(): Promise<void>;
943
984
  }
944
985
 
@@ -979,7 +1020,7 @@ export declare function upgradeRequestPath(request: IncomingMessage): string;
979
1020
  * event (the reply the {@link import('@src/core').MCPClientInterface} correlates by `id`); a
980
1021
  * non-JSON / non-message frame surfaces on `error` and is dropped (§14). The socket's `close`
981
1022
  * / `error` bridge to this transport's events.
982
- * - **Outbound (`send`).** `send(message | messages)` writes ONE masked text frame per message.
1023
+ * - **Outbound (`send`).** `send(message)` writes one masked text frame.
983
1024
  * - **`close()`** closes the underlying socket and fires `close` (idempotent).
984
1025
  * - **URL scheme.** `options.url` accepts a `ws://` / `wss://` URL or an `http://` / `https://`
985
1026
  * one; a `ws(s)` scheme is converted to `http(s)` for the underlying upgrade request (`wss`
@@ -1001,7 +1042,7 @@ export declare class WebSocketClientTransport implements ClientTransportInterfac
1001
1042
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
1002
1043
  get session(): string | undefined;
1003
1044
  start(): Promise<void>;
1004
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
1045
+ send(message: JSONRPCMessage_2): Promise<void>;
1005
1046
  close(): Promise<void>;
1006
1047
  }
1007
1048
 
@@ -1067,8 +1108,8 @@ export declare interface WebSocketServerOptions {
1067
1108
  * parsed envelope the {@link import('@src/core').MCPServerInterface} pump dispatches), while
1068
1109
  * a non-JSON or non-message frame is surfaced on `error` and DROPPED, never thrown (§14). It
1069
1110
  * also bridges the socket's `close` → this transport's `close`, and the socket's `error`.
1070
- * - **Outbound (`send`).** `send(message | messages)` writes ONE text frame per message
1071
- * (`nodeWs.send(JSON.stringify(...))`); the underlying wrapper no-ops a write on a
1111
+ * - **Outbound (`send`).** `send(message)` writes one text frame
1112
+ * (`nodeWs.send(JSON.stringify(message))`); the underlying wrapper no-ops a write on a
1072
1113
  * non-open socket, so a closed connection drops silently rather than throwing.
1073
1114
  * - **`close()`** closes the underlying socket (the RFC 6455 close handshake) and fires the
1074
1115
  * transport's `close` event (idempotent — a second `close`, or a socket-driven close, emits
@@ -1083,7 +1124,7 @@ export declare class WebSocketServerTransport implements ClientTransportInterfac
1083
1124
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
1084
1125
  get session(): string | undefined;
1085
1126
  start(): Promise<void>;
1086
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
1127
+ send(message: JSONRPCMessage_2): Promise<void>;
1087
1128
  close(): Promise<void>;
1088
1129
  }
1089
1130
 
@@ -85,8 +85,10 @@ export declare function bridgeMessageTransport(transport: ClientTransportInterfa
85
85
  * and the reply is surfaced on the transport's `message` event for the client's id
86
86
  * correlation. Add `options.headers` (e.g. an `Authorization` bearer) to reach a guarded
87
87
  * server. `start` / `close` hold no connection; against a STATEFUL server it captures the
88
- * `mcp-session-id` from `initialize` and echoes it on later requests, so the same
89
- * `MCPClient` passes session validation (a stateless server sends none).
88
+ * `mcp-session-id` from `initialize` and echoes it on later requests. It also captures
89
+ * the initialize result's `protocolVersion` and sends `mcp-protocol-version` on every
90
+ * subsequent request, so the same `MCPClient` passes the session and 2025-06-18
91
+ * protocol gates without caller wiring.
90
92
  *
91
93
  * @param options - `url` (the remote endpoint; REQUIRED), optional `headers` merged onto
92
94
  * every request, optional `fetch` (default `globalThis.fetch`), and optional `timeout`
@@ -107,6 +109,34 @@ export declare function bridgeMessageTransport(transport: ClientTransportInterfa
107
109
  */
108
110
  export declare function createHTTPClientTransport(options: HTTPClientTransportOptions): ClientTransportInterface;
109
111
 
112
+ /**
113
+ * Create the Streamable-HTTP POST handler used by `createMCPRoutes`.
114
+ *
115
+ * @remarks
116
+ * A present `mcp-protocol-version` header must name a supported revision; an
117
+ * unsupported value returns an HTTP `400` JSON-RPC invalid-request error without
118
+ * dispatching. An absent header is accepted for the initialize/bootstrap request.
119
+ *
120
+ * @param mcp - The transport-agnostic MCP server to dispatch through
121
+ * @param streaming - Whether an event-stream response may be negotiated
122
+ * @returns A request handler for the stateless MCP POST route
123
+ *
124
+ * @example
125
+ * ```ts
126
+ * import { createMCPServer } from '@orkestrel/mcp'
127
+ * import { createMCPPostHandler } from '@orkestrel/mcp/server'
128
+ * import { createToolManager } from '@orkestrel/agent'
129
+ *
130
+ * const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
131
+ * const handler = createMCPPostHandler(mcp, true)
132
+ * await handler(new Request('http://localhost/mcp', {
133
+ * method: 'POST',
134
+ * body: '{"jsonrpc":"2.0","method":"ping","id":1}',
135
+ * }))
136
+ * ```
137
+ */
138
+ export declare function createMCPPostHandler(mcp: MCPServerInterface, streaming: boolean): (request: Request) => Promise<Response>;
139
+
110
140
  /**
111
141
  * Create the MCP Streamable-HTTP transport routes — mounts a transport-agnostic
112
142
  * {@link MCPServerInterface} (the `@src/core` dispatch core) on the fetch-standard router
@@ -122,6 +152,9 @@ export declare function createHTTPClientTransport(options: HTTPClientTransportOp
122
152
  * - A **transport** failure — a malformed JSON body, or a parsed value that is not a
123
153
  * JSON-RPC REQUEST — is an HTTP `400` carrying a JSON-RPC error BODY (`-32700` Parse
124
154
  * error / `-32600` Invalid Request, id `null`).
155
+ * - A present `mcp-protocol-version` header is validated before dispatch: a supported
156
+ * value proceeds, while an unsupported value returns HTTP `400` with a JSON-RPC
157
+ * `-32600` body. An absent value proceeds for initialize/bootstrap compatibility.
125
158
  * - A **dispatch** result — a success OR an IN-BAND JSON-RPC error from `mcp.dispatch`
126
159
  * (e.g. `-32601` method-not-found) — is an HTTP `200` carrying the JSON-RPC response
127
160
  * envelope (the error is in-band per JSON-RPC, NOT an HTTP error).
@@ -468,7 +501,7 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
468
501
  *
469
502
  * @remarks
470
503
  * - **Request/response over `fetch`.** `send(message)` POSTs the JSON-serialized
471
- * message (or batch) to `options.url` with `content-type: application/json` and an
504
+ * message to `options.url` with `content-type: application/json` and an
472
505
  * `Accept` of BOTH `application/json` and `text/event-stream` (so the server may
473
506
  * answer with either framing) — plus any `options.headers` (e.g. an `Authorization`
474
507
  * bearer). It then decodes the reply and emits each decoded {@link JSONRPCMessage} on
@@ -480,13 +513,18 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
480
513
  * readEventStream}) — the inverse of the server's `openStream` seam, so the wire
481
514
  * round-trips. A `202`
482
515
  * Accepted (a notification) carries no body and emits nothing.
483
- * - **Session echo.** `start()` / `close()` are no-ops (a request/response transport
484
- * holds no long-lived connection). The `mcp-session-id` response header, when a
485
- * STATEFUL server sends one (on `initialize`), is captured into `session` and then
486
- * ECHOED as the `mcp-session-id` request header on every SUBSEQUENT request — so an
487
- * `MCPClient` passes a stateful server's session validation. Before initialize returns
488
- * an id, `session` is `undefined` and no header is sent (safe against a stateless
489
- * server, which neither sends nor expects one).
516
+ * - **Session and protocol echo.** `start()` is a no-op (a
517
+ * request/response transport opens no long-lived connection). The
518
+ * `mcp-session-id` response header, when a STATEFUL server sends one (on
519
+ * `initialize`), is captured into `session` and then ECHOED as the
520
+ * `mcp-session-id` request header on every SUBSEQUENT request so an
521
+ * `MCPClient` passes a stateful server's session validation. The
522
+ * initialize result's `protocolVersion` is likewise captured, but only
523
+ * when it is a SUPPORTED value, and echoed as `mcp-protocol-version` on
524
+ * every subsequent request, as required by the 2025-06-18 Streamable-HTTP
525
+ * transport. Before initialize returns, neither captured header is sent.
526
+ * `close()` clears the captured protocol so a reconnect's `initialize`
527
+ * POST is headerless; the captured `session` persists across `close()`.
490
528
  * - **Total at the boundary (§14).** Every reply is narrowed (`parseJSONRPCMessage`,
491
529
  * the SSE decoder) — a non-message reply is dropped, never asserted; a `fetch` /
492
530
  * decode failure surfaces on the `error` event rather than escaping `send`.
@@ -506,7 +544,7 @@ export declare class HTTPClientTransport implements ClientTransportInterface_2 {
506
544
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
507
545
  get session(): string | undefined;
508
546
  start(): Promise<void>;
509
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
547
+ send(message: JSONRPCMessage_2): Promise<void>;
510
548
  close(): Promise<void>;
511
549
  }
512
550
 
@@ -574,10 +612,13 @@ export declare interface LineExtraction {
574
612
  }
575
613
 
576
614
  /**
577
- * The Streamable-HTTP transport header that carries the negotiated MCP protocol version
578
- * on a subsequent request. The version is negotiated in the `initialize` JSON-RPC result
579
- * body; a stateful transport MAY additionally read this header to pin the per-request
580
- * protocol version (optional — the result body remains the source of truth).
615
+ * The Streamable-HTTP transport header carrying the negotiated MCP protocol version
616
+ * on every post-initialize client request.
617
+ *
618
+ * @remarks
619
+ * Required by MCP 2025-06-18 after initialization. Both HTTP client transports
620
+ * capture the initialize result's `protocolVersion` and send it on subsequent
621
+ * requests; `createMCPRoutes` rejects a present unsupported value before dispatch.
581
622
  */
582
623
  export declare const MCP_PROTOCOL_VERSION_HEADER = "mcp-protocol-version";
583
624
 
@@ -675,12 +716,12 @@ export declare class MCPSession implements MCPSessionInterface {
675
716
  *
676
717
  * @remarks
677
718
  * - `session` — the live {@link MCPSession} entity the store keys by session id.
678
- * - `touched` — the epoch-ms instant of the last access; mutated (not replaced) on every
719
+ * - `touched` — the epoch-ms instant of the last access; the entry is replaced on every
679
720
  * resolved request so the middleware's lazy sweep can evict an idle entry past `ttl`.
680
721
  */
681
722
  export declare interface MCPSessionEntry {
682
723
  readonly session: MCPSession;
683
- touched: number;
724
+ readonly touched: number;
684
725
  }
685
726
 
686
727
  /**
@@ -755,7 +796,7 @@ export declare interface MCPSessionOptions {
755
796
  * before calling `next`).
756
797
  */
757
798
  export declare interface MCPSessionState {
758
- session?: MCPSessionInterface;
799
+ readonly session?: MCPSessionInterface;
759
800
  }
760
801
 
761
802
  /**
@@ -846,8 +887,8 @@ export declare function rejectUnknownSession(): Response;
846
887
  * {@link dispatchLines} helper — a well-formed {@link JSONRPCMessage} emits
847
888
  * `message`, a malformed line emits `error` (§14, never throws). The child's
848
889
  * `close` bridges to this transport's `close`.
849
- * - **Outbound (`send`).** `send(message | messages)` writes ONE newline-terminated
850
- * `JSON.stringify`d line per message to the child's `stdin`.
890
+ * - **Outbound (`send`).** `send(message)` writes one newline-terminated
891
+ * `JSON.stringify`d line to the child's `stdin`.
851
892
  * - **`close()`** kills the child process and fires `close` (idempotent).
852
893
  * - **Observable (§13).** Owns the `emitter` ({@link ClientTransportEventMap}); the
853
894
  * emitter isolates a listener throw; `error` is a DOMAIN event (a transport-level
@@ -866,7 +907,7 @@ export declare class StdioClientTransport implements ClientTransportInterface_2
866
907
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
867
908
  get session(): string | undefined;
868
909
  start(): Promise<void>;
869
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
910
+ send(message: JSONRPCMessage_2): Promise<void>;
870
911
  close(): Promise<void>;
871
912
  }
872
913
 
@@ -923,8 +964,8 @@ export declare interface StdioServerOptions {
923
964
  * well-formed {@link JSONRPCMessage} re-emits on `message`, a malformed line
924
965
  * emits `error` (§14, never throws). `input`'s `close` bridges to this
925
966
  * transport's `close`.
926
- * - **Outbound (`send`).** `send(message | messages)` writes ONE newline-terminated
927
- * `JSON.stringify`d line per message to `output`.
967
+ * - **Outbound (`send`).** `send(message)` writes one newline-terminated
968
+ * `JSON.stringify`d line to `output`.
928
969
  * - **`close()`** fires this transport's `close` (idempotent) — the injected streams
929
970
  * are owned by the caller (typically `process.stdin`/`process.stdout`, which must
930
971
  * never be closed out from under the process) and are not torn down here.
@@ -938,7 +979,7 @@ export declare class StdioServerTransport implements ClientTransportInterface_2
938
979
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
939
980
  get session(): string | undefined;
940
981
  start(): Promise<void>;
941
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
982
+ send(message: JSONRPCMessage_2): Promise<void>;
942
983
  close(): Promise<void>;
943
984
  }
944
985
 
@@ -979,7 +1020,7 @@ export declare function upgradeRequestPath(request: IncomingMessage): string;
979
1020
  * event (the reply the {@link import('@src/core').MCPClientInterface} correlates by `id`); a
980
1021
  * non-JSON / non-message frame surfaces on `error` and is dropped (§14). The socket's `close`
981
1022
  * / `error` bridge to this transport's events.
982
- * - **Outbound (`send`).** `send(message | messages)` writes ONE masked text frame per message.
1023
+ * - **Outbound (`send`).** `send(message)` writes one masked text frame.
983
1024
  * - **`close()`** closes the underlying socket and fires `close` (idempotent).
984
1025
  * - **URL scheme.** `options.url` accepts a `ws://` / `wss://` URL or an `http://` / `https://`
985
1026
  * one; a `ws(s)` scheme is converted to `http(s)` for the underlying upgrade request (`wss`
@@ -1001,7 +1042,7 @@ export declare class WebSocketClientTransport implements ClientTransportInterfac
1001
1042
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
1002
1043
  get session(): string | undefined;
1003
1044
  start(): Promise<void>;
1004
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
1045
+ send(message: JSONRPCMessage_2): Promise<void>;
1005
1046
  close(): Promise<void>;
1006
1047
  }
1007
1048
 
@@ -1067,8 +1108,8 @@ export declare interface WebSocketServerOptions {
1067
1108
  * parsed envelope the {@link import('@src/core').MCPServerInterface} pump dispatches), while
1068
1109
  * a non-JSON or non-message frame is surfaced on `error` and DROPPED, never thrown (§14). It
1069
1110
  * also bridges the socket's `close` → this transport's `close`, and the socket's `error`.
1070
- * - **Outbound (`send`).** `send(message | messages)` writes ONE text frame per message
1071
- * (`nodeWs.send(JSON.stringify(...))`); the underlying wrapper no-ops a write on a
1111
+ * - **Outbound (`send`).** `send(message)` writes one text frame
1112
+ * (`nodeWs.send(JSON.stringify(message))`); the underlying wrapper no-ops a write on a
1072
1113
  * non-open socket, so a closed connection drops silently rather than throwing.
1073
1114
  * - **`close()`** closes the underlying socket (the RFC 6455 close handshake) and fires the
1074
1115
  * transport's `close` event (idempotent — a second `close`, or a socket-driven close, emits
@@ -1083,7 +1124,7 @@ export declare class WebSocketServerTransport implements ClientTransportInterfac
1083
1124
  get emitter(): EmitterInterface<ClientTransportEventMap_2>;
1084
1125
  get session(): string | undefined;
1085
1126
  start(): Promise<void>;
1086
- send(message: JSONRPCMessage_2 | readonly JSONRPCMessage_2[]): Promise<void>;
1127
+ send(message: JSONRPCMessage_2): Promise<void>;
1087
1128
  close(): Promise<void>;
1088
1129
  }
1089
1130