@orkestrel/mcp 0.0.7 → 0.0.9
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/README.md +7 -7
- package/dist/src/browser/index.d.ts +26 -12
- package/dist/src/browser/index.js +43 -17
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +1277 -137
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +1113 -184
- package/dist/src/core/index.d.ts +1113 -184
- package/dist/src/core/index.js +1233 -134
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +361 -68
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +201 -33
- package/dist/src/server/index.d.ts +201 -33
- package/dist/src/server/index.js +352 -70
- package/dist/src/server/index.js.map +1 -1
- package/package.json +10 -10
|
@@ -6,8 +6,12 @@ import { EmitterInterface } from '@orkestrel/emitter';
|
|
|
6
6
|
import { IncomingMessage } from 'node:http';
|
|
7
7
|
import { JSONRPCMessage } from '../core/index.ts';
|
|
8
8
|
import { JSONRPCMessage as JSONRPCMessage_2 } from '../../core/index.ts';
|
|
9
|
+
import { JSONRPCRequest } from '../core/index.ts';
|
|
10
|
+
import { JSONRPCResponse } from '../core/index.ts';
|
|
11
|
+
import { MCPEra } from '../core/index.ts';
|
|
9
12
|
import { MCPServerInterface } from '../core/index.ts';
|
|
10
13
|
import { MCPTransportInterface } from '../core/index.ts';
|
|
14
|
+
import { MCPVersion } from '../core/index.ts';
|
|
11
15
|
import { MiddlewareHandler } from '@orkestrel/server';
|
|
12
16
|
import { NodeWebSocketInterface } from '@orkestrel/websocket';
|
|
13
17
|
import { RouteInput } from '@orkestrel/router';
|
|
@@ -29,6 +33,22 @@ import { UpgradeHandler } from '@orkestrel/server';
|
|
|
29
33
|
*/
|
|
30
34
|
export declare function acceptsEventStream(request: Request): boolean;
|
|
31
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Whether an HTTP request satisfies the endpoint's origin gate.
|
|
38
|
+
*
|
|
39
|
+
* @remarks
|
|
40
|
+
* Validation is enabled by default. A request without `Origin` is allowed. A canonical origin
|
|
41
|
+
* whose host is the `localhost` or `[::1]` literal, or belongs to the `127.0.0.0/8` literal
|
|
42
|
+
* range, is allowed without configuration; every other present origin must occur exactly in
|
|
43
|
+
* the caller-supplied list. Invalid and opaque (`null`) origins are denied. `enabled: false`
|
|
44
|
+
* delegates validation to an upstream layer and allows the request through this gate.
|
|
45
|
+
*
|
|
46
|
+
* @param request - The fetch-standard request to validate
|
|
47
|
+
* @param options - Shared origin validation and delegation options
|
|
48
|
+
* @returns `true` when the request may reach MCP dispatch
|
|
49
|
+
*/
|
|
50
|
+
export declare function allowsOrigin(request: Request, options?: MCPOriginOptions): boolean;
|
|
51
|
+
|
|
32
52
|
/**
|
|
33
53
|
* Bridge a message-channel {@link ClientTransportInterface} (the shape the stdio and
|
|
34
54
|
* WebSocket SERVER transports already implement) into the environment-agnostic
|
|
@@ -86,9 +106,9 @@ export declare function bridgeMessageTransport(transport: ClientTransportInterfa
|
|
|
86
106
|
* correlation. Add `options.headers` (e.g. an `Authorization` bearer) to reach a guarded
|
|
87
107
|
* server. `start` / `close` hold no connection; against a STATEFUL server it captures the
|
|
88
108
|
* `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
|
|
90
|
-
* subsequent request
|
|
91
|
-
*
|
|
109
|
+
* the initialize result's `protocolVersion` and sends `mcp-protocol-version` alone on each
|
|
110
|
+
* subsequent legacy request. Modern requests derive protocol and method headers directly
|
|
111
|
+
* from the message, plus a name header only for `tools/call`.
|
|
92
112
|
*
|
|
93
113
|
* @param options - `url` (the remote endpoint; REQUIRED), optional `headers` merged onto
|
|
94
114
|
* every request, optional `fetch` (default `globalThis.fetch`), and optional `timeout`
|
|
@@ -113,29 +133,38 @@ export declare function createHTTPClientTransport(options: HTTPClientTransportOp
|
|
|
113
133
|
* Create the Streamable-HTTP POST handler used by `createMCPRoutes`.
|
|
114
134
|
*
|
|
115
135
|
* @remarks
|
|
116
|
-
*
|
|
117
|
-
*
|
|
118
|
-
*
|
|
136
|
+
* Modern requests require matching protocol/method headers and a matching name header only
|
|
137
|
+
* for `tools/call`; mismatch returns HTTP `400` + `-32020`. Headerless `initialize` is
|
|
138
|
+
* accepted, while every other headerless request needs a live legacy session to supply its
|
|
139
|
+
* pinned version. A present origin must occur in `origin.origins` unless validation is
|
|
140
|
+
* explicitly delegated upstream. Modern dispatch errors use their protocol status map; legacy
|
|
141
|
+
* errors remain in-band at HTTP `200`. A streamed response composes the fetch-standard request
|
|
142
|
+
* signal with response-body cancellation and supplies the result to every dispatched modern
|
|
143
|
+
* handler through `MCPDispatchOptions.signal`.
|
|
119
144
|
*
|
|
120
145
|
* @param mcp - The transport-agnostic MCP server to dispatch through
|
|
121
|
-
* @param
|
|
146
|
+
* @param options - Optional streaming, origin-validation, and SSE keepalive options
|
|
122
147
|
* @returns A request handler for the stateless MCP POST route
|
|
123
148
|
*
|
|
124
149
|
* @example
|
|
125
150
|
* ```ts
|
|
126
151
|
* import { createMCPServer } from '@orkestrel/mcp'
|
|
127
152
|
* import { createMCPPostHandler } from '@orkestrel/mcp/server'
|
|
128
|
-
* import { createToolManager } from '@orkestrel/
|
|
153
|
+
* import { createToolManager } from '@orkestrel/tool'
|
|
129
154
|
*
|
|
130
|
-
* const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
|
|
131
|
-
* const handler = createMCPPostHandler(mcp, true)
|
|
155
|
+
* const mcp = createMCPServer({ identity: { name: 'docs', version: '1.0.0' }, tools: createToolManager() })
|
|
156
|
+
* const handler = createMCPPostHandler(mcp, { streaming: true })
|
|
132
157
|
* await handler(new Request('http://localhost/mcp', {
|
|
133
158
|
* method: 'POST',
|
|
134
159
|
* body: '{"jsonrpc":"2.0","method":"ping","id":1}',
|
|
135
160
|
* }))
|
|
136
161
|
* ```
|
|
137
162
|
*/
|
|
138
|
-
export declare function createMCPPostHandler(mcp: MCPServerInterface,
|
|
163
|
+
export declare function createMCPPostHandler(mcp: MCPServerInterface, options?: {
|
|
164
|
+
readonly streaming?: boolean;
|
|
165
|
+
readonly origin?: MCPOriginOptions;
|
|
166
|
+
readonly keepalive?: MCPKeepaliveOptions;
|
|
167
|
+
}): (request: Request) => Promise<Response>;
|
|
139
168
|
|
|
140
169
|
/**
|
|
141
170
|
* Create the MCP Streamable-HTTP transport routes — mounts a transport-agnostic
|
|
@@ -152,12 +181,11 @@ export declare function createMCPPostHandler(mcp: MCPServerInterface, streaming:
|
|
|
152
181
|
* - A **transport** failure — a malformed JSON body, or a parsed value that is not a
|
|
153
182
|
* JSON-RPC REQUEST — is an HTTP `400` carrying a JSON-RPC error BODY (`-32700` Parse
|
|
154
183
|
* error / `-32600` Invalid Request, id `null`).
|
|
155
|
-
* -
|
|
156
|
-
*
|
|
157
|
-
*
|
|
158
|
-
* -
|
|
159
|
-
*
|
|
160
|
-
* envelope (the error is in-band per JSON-RPC, NOT an HTTP error).
|
|
184
|
+
* - Modern protocol/method/name headers are validated against the body; a mismatch is
|
|
185
|
+
* HTTP `400` + `-32020`. Headerless initialize is accepted, a live legacy session supplies
|
|
186
|
+
* its pinned revision, and every other headerless request is rejected.
|
|
187
|
+
* - Legacy dispatch errors stay IN-BAND at HTTP `200`; modern errors map to `400` for
|
|
188
|
+
* `-32020` / `-32021` / `-32022` / `-32602`, `404` for `-32601`, and `200` otherwise.
|
|
161
189
|
* - A **notification** (a request with no `id`, which `dispatch` resolves to
|
|
162
190
|
* `undefined`) is a `202 Accepted` with no body.
|
|
163
191
|
*
|
|
@@ -172,13 +200,15 @@ export declare function createMCPPostHandler(mcp: MCPServerInterface, streaming:
|
|
|
172
200
|
* validates the `mcp-session-id`, and serves the resumable `GET {path}` + `DELETE {path}`,
|
|
173
201
|
* leaving this route to dispatch the validated `POST`.
|
|
174
202
|
*
|
|
175
|
-
* This is MECHANISM, not policy: compose auth /
|
|
176
|
-
*
|
|
203
|
+
* This is MECHANISM, not policy: compose auth / rate-limiting (and the session middleware)
|
|
204
|
+
* IN FRONT as ordinary middleware; the optional `origin` group carries the deployment's shared
|
|
205
|
+
* allowlist or explicitly delegates validation to an upstream layer.
|
|
177
206
|
*
|
|
178
207
|
* @typeParam TState - The consumer's opaque per-request state type
|
|
179
208
|
* @param mcp - The transport-agnostic {@link MCPServerInterface} to expose over HTTP
|
|
180
209
|
* @param options - Optional `path` (default {@link DEFAULT_MCP_PATH}) and `streaming`
|
|
181
|
-
* (default `true`); see
|
|
210
|
+
* (default `true`), plus the shared `origin` validation options; see
|
|
211
|
+
* {@link HTTPTransportOptions}
|
|
182
212
|
* @returns The {@link RouteInput}s to register with the router
|
|
183
213
|
*
|
|
184
214
|
* @example
|
|
@@ -186,7 +216,7 @@ export declare function createMCPPostHandler(mcp: MCPServerInterface, streaming:
|
|
|
186
216
|
* import { createMCPServer, createToolManager } from '@src/core'
|
|
187
217
|
* import { createMCPRoutes } from '@src/server'
|
|
188
218
|
*
|
|
189
|
-
* const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
|
|
219
|
+
* const mcp = createMCPServer({ identity: { name: 'docs', version: '1.0.0' }, tools: createToolManager() })
|
|
190
220
|
* const routes = createMCPRoutes(mcp) // POST /mcp dispatches JSON-RPC (JSON or SSE per Accept)
|
|
191
221
|
* ```
|
|
192
222
|
*/
|
|
@@ -204,12 +234,17 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPServerInterfac
|
|
|
204
234
|
* `path` (default {@link DEFAULT_MCP_PATH}); a request to any other path passes straight
|
|
205
235
|
* through (`next()`).
|
|
206
236
|
*
|
|
237
|
+
* A modern-shaped POST also passes straight through via `next()`, ignoring any session id.
|
|
238
|
+
* The remaining behavior is the legacy session layer:
|
|
239
|
+
*
|
|
207
240
|
* - **`POST {path}`.** Buffers `const text = await request.text()` (so the downstream route
|
|
208
241
|
* can re-read it via a freshly-built forwarded `Request`). Resolves a session via {@link
|
|
209
242
|
* readSessionHeader}: a VALID id touches the entry and sets `context.state.session`; an
|
|
210
243
|
* ABSENT / unknown id whose (guarded) body parses to an `initialize` request ({@link
|
|
211
244
|
* isInitializeRequest}) MINTS a fresh {@link MCPSession} (`crypto.randomUUID()`, `capacity`)
|
|
212
|
-
* and sets `context.state.session`; neither → {@link rejectUnknownSession} (`404`).
|
|
245
|
+
* and sets `context.state.session`; neither → {@link rejectUnknownSession} (`404`). The
|
|
246
|
+
* minted entry pins the negotiated legacy revision, which is supplied to a later headerless
|
|
247
|
+
* live-session request. It then
|
|
213
248
|
* FORWARDS a fresh `Request` carrying the buffered `text` (`next(forwarded)`) — never the
|
|
214
249
|
* already-consumed original — so the route re-reads the same body, and stamps the response
|
|
215
250
|
* with {@link MCP_SESSION_HEADER}.
|
|
@@ -217,8 +252,8 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPServerInterfac
|
|
|
217
252
|
* an invalid / unknown id is the same `404`. A valid session opens the resumable
|
|
218
253
|
* server→client stream via `@orkestrel/server`'s {@link import('@orkestrel/server').openStream}:
|
|
219
254
|
* replays every event after the client's `Last-Event-ID` ({@link readLastEventId}) BEFORE
|
|
220
|
-
* attaching the stream for live pushes, then attaches;
|
|
221
|
-
* detaches it. Long-lived — never `end()`ed here.
|
|
255
|
+
* attaching the stream for live pushes, then attaches; cancellation of the streamed response
|
|
256
|
+
* body composes with `request.signal` and detaches it. Long-lived — never `end()`ed here.
|
|
222
257
|
* - **`DELETE {path}`.** Resolves the session; a valid id deletes it from the store and answers
|
|
223
258
|
* `204`; an invalid / unknown id is the same `404`.
|
|
224
259
|
*
|
|
@@ -232,7 +267,8 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPServerInterfac
|
|
|
232
267
|
* @param options - Optional `path` (default {@link DEFAULT_MCP_PATH}), `ttl` (idle-session
|
|
233
268
|
* sweep window, ms — omit for sessions that live until an explicit `DELETE`), `capacity`
|
|
234
269
|
* (the folded per-session replay-log bound), and `clock` (the deterministic epoch-ms clock;
|
|
235
|
-
* defaults to `Date.now`); see
|
|
270
|
+
* defaults to `Date.now`), plus the shared `origin` validation options; see
|
|
271
|
+
* {@link MCPSessionOptions}
|
|
236
272
|
* @returns A {@link MiddlewareHandler} that mints / validates sessions + serves the resumable
|
|
237
273
|
* `GET` / `DELETE`
|
|
238
274
|
*
|
|
@@ -241,13 +277,22 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPServerInterfac
|
|
|
241
277
|
* import { createMCPServer, createToolManager } from '@src/core'
|
|
242
278
|
* import { createMCPRoutes, createMCPSession } from '@src/server'
|
|
243
279
|
*
|
|
244
|
-
* const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
|
|
280
|
+
* const mcp = createMCPServer({ identity: { name: 'docs', version: '1.0.0' }, tools: createToolManager() })
|
|
245
281
|
* router.use(createMCPSession({ ttl: 60_000 })) // stateful: mint + validate + resumable GET / DELETE
|
|
246
282
|
* router.add(createMCPRoutes(mcp)) // the route stays session-agnostic
|
|
247
283
|
* ```
|
|
248
284
|
*/
|
|
249
285
|
export declare function createMCPSession<TState extends MCPSessionState>(options?: MCPSessionOptions): MiddlewareHandler<TState>;
|
|
250
286
|
|
|
287
|
+
/**
|
|
288
|
+
* Create a readable stream from its pull and cancellation behaviours.
|
|
289
|
+
*
|
|
290
|
+
* @param pull - The behaviour that supplies the stream's next chunk
|
|
291
|
+
* @param cancel - The behaviour that releases the stream after consumer cancellation
|
|
292
|
+
* @returns A readable stream backed by the supplied behaviours
|
|
293
|
+
*/
|
|
294
|
+
export declare function createReadableStream<T>(pull: (controller: ReadableStreamDefaultController<T>) => void | PromiseLike<void>, cancel: (reason?: unknown) => void | PromiseLike<void>): ReadableStream<T>;
|
|
295
|
+
|
|
251
296
|
/**
|
|
252
297
|
* Create the stdio CLIENT transport for an {@link import('@src/core').MCPClientInterface}
|
|
253
298
|
* — a {@link ClientTransportInterface} that spawns and drives a CHILD PROCESS MCP server
|
|
@@ -307,7 +352,7 @@ export declare function createStdioClientTransport(options: StdioClientTransport
|
|
|
307
352
|
* import { createMCPServer, createToolManager } from '@src/core'
|
|
308
353
|
* import { createStdioServer } from '@src/server'
|
|
309
354
|
*
|
|
310
|
-
* const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
|
|
355
|
+
* const mcp = createMCPServer({ identity: { name: 'docs', version: '1.0.0' }, tools: createToolManager() })
|
|
311
356
|
* createStdioServer(mcp).start() // an MCP client now connects over this process's stdio
|
|
312
357
|
* ```
|
|
313
358
|
*/
|
|
@@ -390,7 +435,7 @@ export declare function createWebSocketClientTransport(options: WebSocketClientT
|
|
|
390
435
|
* import { createMCPServer, createToolManager } from '@src/core'
|
|
391
436
|
* import { createWebSocketServer } from '@src/server'
|
|
392
437
|
*
|
|
393
|
-
* const mcp = createMCPServer({ name: 'docs', version: '1.0.0', tools: createToolManager() })
|
|
438
|
+
* const mcp = createMCPServer({ identity: { name: 'docs', version: '1.0.0' }, tools: createToolManager() })
|
|
394
439
|
* server.upgrade(createWebSocketServer(mcp)) // an MCP client now connects over ws://…/mcp
|
|
395
440
|
* ```
|
|
396
441
|
*/
|
|
@@ -410,6 +455,16 @@ export declare function createWebSocketServer(mcp: MCPServerInterface, options?:
|
|
|
410
455
|
*/
|
|
411
456
|
export declare function decodeEvent(data: string): JSONRPCMessage | undefined;
|
|
412
457
|
|
|
458
|
+
/**
|
|
459
|
+
* The default interval in milliseconds between SSE keepalive comments on held-open MCP
|
|
460
|
+
* responses.
|
|
461
|
+
*
|
|
462
|
+
* @remarks
|
|
463
|
+
* Fifteen seconds is infrequent enough to avoid chatty idle connections while bounding dead
|
|
464
|
+
* client detection and staying comfortably inside common intermediary idle windows.
|
|
465
|
+
*/
|
|
466
|
+
export declare const DEFAULT_MCP_KEEPALIVE_INTERVAL = 15000;
|
|
467
|
+
|
|
413
468
|
/** The default request path `createMCPRoutes` mounts the transport's `POST` route at. */
|
|
414
469
|
export declare const DEFAULT_MCP_PATH = "/mcp";
|
|
415
470
|
|
|
@@ -513,16 +568,17 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
|
|
|
513
568
|
* readEventStream}) — the inverse of the server's `openStream` seam, so the wire
|
|
514
569
|
* round-trips. A `202`
|
|
515
570
|
* Accepted (a notification) carries no body and emits nothing.
|
|
516
|
-
* - **Session and protocol
|
|
571
|
+
* - **Session and protocol headers.** `start()` is a no-op (a
|
|
517
572
|
* request/response transport opens no long-lived connection). The
|
|
518
573
|
* `mcp-session-id` response header, when a STATEFUL server sends one (on
|
|
519
574
|
* `initialize`), is captured into `session` and then ECHOED as the
|
|
520
575
|
* `mcp-session-id` request header on every SUBSEQUENT request — so an
|
|
521
576
|
* `MCPClient` passes a stateful server's session validation. The
|
|
522
577
|
* initialize result's `protocolVersion` is likewise captured, but only
|
|
523
|
-
* when it is a SUPPORTED value, and echoed as `mcp-protocol-version` on
|
|
524
|
-
*
|
|
525
|
-
*
|
|
578
|
+
* when it is a SUPPORTED value, and echoed as `mcp-protocol-version` alone on
|
|
579
|
+
* subsequent legacy requests. Modern requests instead derive protocol and method
|
|
580
|
+
* headers from the message, plus the name header only for `tools/call`.
|
|
581
|
+
* Before initialize returns, neither captured legacy header is sent.
|
|
526
582
|
* `close()` clears the captured protocol so a reconnect's `initialize`
|
|
527
583
|
* POST is headerless; the captured `session` persists across `close()`.
|
|
528
584
|
* - **Total at the boundary (§14).** Every reply is narrowed (`parseJSONRPCMessage`,
|
|
@@ -591,12 +647,51 @@ export declare interface HTTPClientTransportOptions {
|
|
|
591
647
|
* `text/event-stream`; when `false` it always answers with a plain JSON body. Either
|
|
592
648
|
* mode carries the SAME JSON-RPC response envelope — the choice is purely the wire
|
|
593
649
|
* framing the Streamable-HTTP spec lets the client negotiate.
|
|
650
|
+
* - `origin` — the shared origin-validation options passed to both the route and session
|
|
651
|
+
* enforcement sites. Validation is enabled by default: requests without `Origin` pass,
|
|
652
|
+
* canonical loopback-literal origins pass, and every other present `Origin` must occur
|
|
653
|
+
* exactly in `origin.origins`. Set `origin.enabled` to `false` only when validation is
|
|
654
|
+
* delegated upstream; `origins` is ignored in that mode. Both enforcement sites must receive
|
|
655
|
+
* the same value.
|
|
656
|
+
* - `keepalive` — the SSE liveness options for held-open responses. `interval` defaults to
|
|
657
|
+
* {@link import('./constants.js').DEFAULT_MCP_KEEPALIVE_INTERVAL}. Keepalives never apply
|
|
658
|
+
* to unary responses.
|
|
594
659
|
*/
|
|
595
660
|
export declare interface HTTPTransportOptions {
|
|
596
661
|
readonly path?: string;
|
|
597
662
|
readonly streaming?: boolean;
|
|
663
|
+
/** Must match the session layer's value; `origins` is ignored when `enabled` is `false`. */
|
|
664
|
+
readonly origin?: MCPOriginOptions;
|
|
665
|
+
readonly keepalive?: MCPKeepaliveOptions;
|
|
598
666
|
}
|
|
599
667
|
|
|
668
|
+
/**
|
|
669
|
+
* Infer the legacy revision an `initialize` request negotiates.
|
|
670
|
+
*
|
|
671
|
+
* @remarks
|
|
672
|
+
* A supported legacy request is pinned exactly. A modern, malformed, absent, or unsupported
|
|
673
|
+
* request selects the newest supported legacy revision, matching the core initialize result.
|
|
674
|
+
*
|
|
675
|
+
* @param request - The legacy initialize request
|
|
676
|
+
* @returns The negotiated legacy protocol revision
|
|
677
|
+
*/
|
|
678
|
+
export declare function inferLegacyVersion(request: JSONRPCRequest): MCPVersion;
|
|
679
|
+
|
|
680
|
+
/**
|
|
681
|
+
* Infer the HTTP status for one MCP dispatch outcome without changing its JSON-RPC body.
|
|
682
|
+
*
|
|
683
|
+
* @remarks
|
|
684
|
+
* Notifications are accepted with `202`. Legacy response envelopes retain uniform `200`
|
|
685
|
+
* status semantics, including in-band errors. Modern header/capability/version/parameter
|
|
686
|
+
* failures map to `400`, method-not-found maps to `404`, and every other modern result maps
|
|
687
|
+
* to `200`.
|
|
688
|
+
*
|
|
689
|
+
* @param response - The dispatch response, or `undefined` for a notification
|
|
690
|
+
* @param era - The structurally selected request era
|
|
691
|
+
* @returns The HTTP response status
|
|
692
|
+
*/
|
|
693
|
+
export declare function inferStatus(response: JSONRPCResponse | undefined, era: MCPEra): number;
|
|
694
|
+
|
|
600
695
|
/**
|
|
601
696
|
* The result of folding one more chunk of raw stdio bytes into a newline-framed
|
|
602
697
|
* buffer — every COMPLETE line extracted (newline-terminated in the wire bytes) plus
|
|
@@ -611,6 +706,27 @@ export declare interface LineExtraction {
|
|
|
611
706
|
readonly remainder: string;
|
|
612
707
|
}
|
|
613
708
|
|
|
709
|
+
/**
|
|
710
|
+
* Whether a modern HTTP request's required standard headers match its JSON-RPC body.
|
|
711
|
+
*
|
|
712
|
+
* @remarks
|
|
713
|
+
* Requires `MCP-Protocol-Version` to equal the reserved `_meta` version and `Mcp-Method`
|
|
714
|
+
* to equal `method`. `Mcp-Name` is required only for `tools/call`, where it must equal
|
|
715
|
+
* `params.name`; discovery and listing requests need no name because none is derivable.
|
|
716
|
+
* Legacy requests return `false` because this predicate models the modern contract only.
|
|
717
|
+
*
|
|
718
|
+
* @param request - The HTTP request carrying the headers
|
|
719
|
+
* @param message - The parsed JSON-RPC request body
|
|
720
|
+
* @returns `true` only when every method-applicable modern header matches
|
|
721
|
+
*/
|
|
722
|
+
export declare function matchesModernHeaders(request: Request, message: JSONRPCRequest): boolean;
|
|
723
|
+
|
|
724
|
+
/** The modern Streamable-HTTP request header carrying the JSON-RPC method name. */
|
|
725
|
+
export declare const MCP_METHOD_HEADER = "mcp-method";
|
|
726
|
+
|
|
727
|
+
/** The modern Streamable-HTTP request header carrying a named method's target. */
|
|
728
|
+
export declare const MCP_NAME_HEADER = "mcp-name";
|
|
729
|
+
|
|
614
730
|
/**
|
|
615
731
|
* The Streamable-HTTP transport header carrying the negotiated MCP protocol version
|
|
616
732
|
* on every post-initialize client request.
|
|
@@ -643,6 +759,35 @@ export declare const MCP_SESSION_HEADER = "mcp-session-id";
|
|
|
643
759
|
*/
|
|
644
760
|
export declare const MCP_WEBSOCKET_SUBPROTOCOL = "mcp";
|
|
645
761
|
|
|
762
|
+
/**
|
|
763
|
+
* Shared SSE keepalive options for held-open HTTP responses.
|
|
764
|
+
*
|
|
765
|
+
* @remarks
|
|
766
|
+
* - `interval` — milliseconds between SSE comment frames. Defaults to {@link
|
|
767
|
+
* import('./constants.js').DEFAULT_MCP_KEEPALIVE_INTERVAL}. Each comment keeps an idle
|
|
768
|
+
* connection live through intermediaries and bounds how long a dead client can remain
|
|
769
|
+
* unobserved by the HTTP writer.
|
|
770
|
+
*/
|
|
771
|
+
export declare interface MCPKeepaliveOptions {
|
|
772
|
+
readonly interval?: number;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
/**
|
|
776
|
+
* Shared options for the protocol-required HTTP `Origin` validation at the route and session
|
|
777
|
+
* enforcement sites.
|
|
778
|
+
*
|
|
779
|
+
* @remarks
|
|
780
|
+
* - `enabled` — whether this package validates `Origin`; defaults to `true`. Set `false` only
|
|
781
|
+
* when an upstream layer performs the validation for the deployment.
|
|
782
|
+
* - `origins` — the exact serialized non-loopback origins accepted when an `Origin` header is
|
|
783
|
+
* present. Omission still accepts requests without `Origin` and canonical loopback-literal
|
|
784
|
+
* origins (`localhost`, `[::1]`, and `127.0.0.0/8`).
|
|
785
|
+
*/
|
|
786
|
+
export declare interface MCPOriginOptions {
|
|
787
|
+
readonly enabled?: boolean;
|
|
788
|
+
readonly origins?: readonly string[];
|
|
789
|
+
}
|
|
790
|
+
|
|
646
791
|
/**
|
|
647
792
|
* One MCP transport session — the per-session entity a {@link
|
|
648
793
|
* import('./middlewares.js').createMCPSession} middleware owns, keyed by its `id`, carrying the
|
|
@@ -718,10 +863,14 @@ export declare class MCPSession implements MCPSessionInterface {
|
|
|
718
863
|
* - `session` — the live {@link MCPSession} entity the store keys by session id.
|
|
719
864
|
* - `touched` — the epoch-ms instant of the last access; the entry is replaced on every
|
|
720
865
|
* resolved request so the middleware's lazy sweep can evict an idle entry past `ttl`.
|
|
866
|
+
* - `version` — the legacy revision negotiated by the session's initialize request, used
|
|
867
|
+
* when a later live-session request legitimately omits its protocol header.
|
|
721
868
|
*/
|
|
722
869
|
export declare interface MCPSessionEntry {
|
|
723
870
|
readonly session: MCPSession;
|
|
724
871
|
readonly touched: number;
|
|
872
|
+
/** The legacy revision negotiated when this session was minted. */
|
|
873
|
+
readonly version: MCPVersion;
|
|
725
874
|
}
|
|
726
875
|
|
|
727
876
|
/**
|
|
@@ -775,12 +924,22 @@ export declare interface MCPSessionInterface {
|
|
|
775
924
|
* uses directly for its own session-touch / TTL-sweep bookkeeping; defaults to `Date.now`. The
|
|
776
925
|
* deterministic clock a TTL test advances explicitly instead of racing a real idle window
|
|
777
926
|
* against wall-clock (AGENTS §16). Production never sets it.
|
|
927
|
+
* - `origin` — the same shared origin-validation options supplied to `createMCPRoutes`.
|
|
928
|
+
* Validation is enabled by default, accepts canonical loopback-literal origins, and rejects
|
|
929
|
+
* every other present origin outside its exact list before any session is minted. Set
|
|
930
|
+
* `origin.enabled` to `false` only when validation is delegated upstream; `origins` is ignored
|
|
931
|
+
* in that mode. Both enforcement sites must receive the same value.
|
|
932
|
+
* - `keepalive` — the SSE liveness options for the held-open resumable response. `interval`
|
|
933
|
+
* defaults to {@link import('./constants.js').DEFAULT_MCP_KEEPALIVE_INTERVAL}.
|
|
778
934
|
*/
|
|
779
935
|
export declare interface MCPSessionOptions {
|
|
780
936
|
readonly path?: string;
|
|
781
937
|
readonly ttl?: number;
|
|
782
938
|
readonly capacity?: number;
|
|
783
939
|
readonly clock?: () => number;
|
|
940
|
+
/** Must match the route layer's value; `origins` is ignored when `enabled` is `false`. */
|
|
941
|
+
readonly origin?: MCPOriginOptions;
|
|
942
|
+
readonly keepalive?: MCPKeepaliveOptions;
|
|
784
943
|
}
|
|
785
944
|
|
|
786
945
|
/**
|
|
@@ -857,7 +1016,7 @@ export declare function readSessionHeader(request: Request): string | undefined;
|
|
|
857
1016
|
* JSON-RPC error body.
|
|
858
1017
|
*
|
|
859
1018
|
* @remarks
|
|
860
|
-
* Returns `Response.json(
|
|
1019
|
+
* Returns `Response.json(buildJSONRPCError(null, JSONRPC_INVALID_REQUEST, 'Session not found'),
|
|
861
1020
|
* { status: 404 })`, mirroring `createMCPRoutes`'s `400` transport-failure shape (a
|
|
862
1021
|
* JSON-RPC error BODY with a `null` id) but at the session-not-found status. Shared by
|
|
863
1022
|
* every {@link import('./middlewares.js').createMCPSession} validation site — the
|
|
@@ -869,6 +1028,15 @@ export declare function readSessionHeader(request: Request): string | undefined;
|
|
|
869
1028
|
*/
|
|
870
1029
|
export declare function rejectUnknownSession(): Response;
|
|
871
1030
|
|
|
1031
|
+
/** The `X-Accel-Buffering` value that disables reverse-proxy buffering. */
|
|
1032
|
+
export declare const SSE_BUFFERING_DISABLED = "no";
|
|
1033
|
+
|
|
1034
|
+
/** The reverse-proxy response header controlling buffering of an SSE response. */
|
|
1035
|
+
export declare const SSE_BUFFERING_HEADER = "x-accel-buffering";
|
|
1036
|
+
|
|
1037
|
+
/** The comment text written by the held-open MCP response keepalive. */
|
|
1038
|
+
export declare const SSE_KEEPALIVE_COMMENT = "keepalive";
|
|
1039
|
+
|
|
872
1040
|
/**
|
|
873
1041
|
* The stdio CLIENT transport for the Model Context Protocol — a
|
|
874
1042
|
* {@link ClientTransportInterface} that drives a CHILD PROCESS MCP server over
|