@orkestrel/mcp 0.0.26 → 0.0.27
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 +13 -4
- package/dist/src/browser/index.js +68 -15
- package/dist/src/browser/index.js.map +1 -1
- package/dist/src/core/index.cjs +754 -68
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +657 -44
- package/dist/src/core/index.d.ts +657 -44
- package/dist/src/core/index.js +734 -69
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +212 -33
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +123 -22
- package/dist/src/server/index.d.ts +123 -22
- package/dist/src/server/index.js +213 -36
- package/dist/src/server/index.js.map +1 -1
- package/package.json +8 -7
|
@@ -11,6 +11,7 @@ import { MCPClientTransportInterface as MCPClientTransportInterface_2 } from '@o
|
|
|
11
11
|
import { MCPContinuationInterface } from '@orkestrel/mcp';
|
|
12
12
|
import { MCPDispatcherInterface } from '@orkestrel/mcp';
|
|
13
13
|
import { MCPEra } from '@orkestrel/mcp';
|
|
14
|
+
import { MCPHeaderParameter } from '@orkestrel/mcp';
|
|
14
15
|
import { MCPLegacyVersion } from '@orkestrel/mcp';
|
|
15
16
|
import { MCPStreamControllerInterface } from '@orkestrel/mcp';
|
|
16
17
|
import { MCPTransportInterface } from '@orkestrel/mcp';
|
|
@@ -172,12 +173,17 @@ export declare function createMCPContinuation(secret: TokenSecret): MCPContinuat
|
|
|
172
173
|
* Creates the Streamable-HTTP POST handler used by `createMCPRoutes`.
|
|
173
174
|
*
|
|
174
175
|
* @remarks
|
|
175
|
-
* Modern requests require matching protocol/method headers and a matching name header
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
176
|
+
* Modern requests require matching protocol/method headers and a matching name header on each
|
|
177
|
+
* method carrying a named target — `tools/call` and `prompts/get` against `params.name`,
|
|
178
|
+
* `resources/read` against `params.uri` — with a Base64-sentinel value decoded before the
|
|
179
|
+
* comparison; a missing, mismatched, or invalidly encoded value returns HTTP `400` + `-32020`.
|
|
180
|
+
* A protocol header naming a MODERN revision holds the request to that revision whatever shape
|
|
181
|
+
* its body arrived in, so a body with no parsable modern `_meta` returns HTTP `400` + `-32602`.
|
|
182
|
+
* Headerless `initialize` is accepted, while every other headerless request needs a live legacy
|
|
183
|
+
* session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
184
|
+
* otherwise admitted only for a legacy revision; a revision this server does not implement
|
|
185
|
+
* returns HTTP `400` + `-32022` whose `supported` names the legacy revisions this door accepts.
|
|
186
|
+
* A present origin must occur in `origin.origins` unless validation is
|
|
181
187
|
* explicitly delegated upstream. Modern dispatch errors use their protocol status map; legacy
|
|
182
188
|
* errors remain in-band at HTTP `200`. A streamed response composes the fetch-standard request
|
|
183
189
|
* signal with response-body cancellation and supplies the result to every dispatched modern
|
|
@@ -397,7 +403,8 @@ export declare function createStdioClientTransport(options: StdioClientTransport
|
|
|
397
403
|
* @param mcp - The transport-agnostic {@link MCPDispatcherInterface} to expose over stdio
|
|
398
404
|
* @param options - Optional injectable `input` / `output` streams; see
|
|
399
405
|
* {@link StdioServerOptions}
|
|
400
|
-
* @returns A
|
|
406
|
+
* @returns A {@link StdioServerInterface} handle to arm / tear down the pump; `stop()` ends
|
|
407
|
+
* that handle's lifetime permanently
|
|
401
408
|
*
|
|
402
409
|
* @example
|
|
403
410
|
* ```ts
|
|
@@ -410,10 +417,7 @@ export declare function createStdioClientTransport(options: StdioClientTransport
|
|
|
410
417
|
* createStdioServer(createMCPLegacy(mcp)).start() // answers `initialize` too; pass `mcp` alone for modern-only
|
|
411
418
|
* ```
|
|
412
419
|
*/
|
|
413
|
-
export declare function createStdioServer(mcp: MCPDispatcherInterface, options?: StdioServerOptions):
|
|
414
|
-
start(): void;
|
|
415
|
-
stop(): void;
|
|
416
|
-
};
|
|
420
|
+
export declare function createStdioServer(mcp: MCPDispatcherInterface, options?: StdioServerOptions): StdioServerInterface;
|
|
417
421
|
|
|
418
422
|
/**
|
|
419
423
|
* Creates the WebSocket CLIENT transport for an {@link import('@orkestrel/mcp').MCPClientInterface}
|
|
@@ -655,7 +659,8 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
|
|
|
655
659
|
* initialize result's `protocolVersion` is likewise captured, but only
|
|
656
660
|
* when it is a SUPPORTED value, and echoed as `mcp-protocol-version` alone on
|
|
657
661
|
* subsequent legacy requests. Modern requests instead derive protocol and method
|
|
658
|
-
* headers from the message, plus the name header only for `tools/call
|
|
662
|
+
* headers from the message, plus the name header only for `tools/call` — carried in the
|
|
663
|
+
* protocol's Base64 sentinel form whenever the tool name cannot ride as plain ASCII.
|
|
659
664
|
* Before initialize returns, neither captured legacy header is sent.
|
|
660
665
|
* `close()` clears the captured protocol so a reconnect's `initialize`
|
|
661
666
|
* POST is headerless; the captured `session` persists across `close()`.
|
|
@@ -837,10 +842,15 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
837
842
|
* Infers the first required MCP HTTP header that is missing or mismatched.
|
|
838
843
|
*
|
|
839
844
|
* @remarks
|
|
840
|
-
* A modern request derives its protocol, method, and
|
|
841
|
-
* the
|
|
842
|
-
*
|
|
843
|
-
*
|
|
845
|
+
* A modern request derives its protocol, method, and name expectations from the JSON-RPC body,
|
|
846
|
+
* the name expectation scoped to the methods {@link inferHeaderTarget} reads a target for. A
|
|
847
|
+
* name header carrying the Base64 sentinel is decoded through
|
|
848
|
+
* {@link import('@orkestrel/mcp').decodeSentinel} before the comparison, so a peer that had
|
|
849
|
+
* to encode its value still matches; a sentinel whose payload is invalid decodes to nothing
|
|
850
|
+
* and therefore mismatches, which is how an invalid header value is refused. A legacy request
|
|
851
|
+
* body requires a protocol header after initialization, while a supplied legacy session
|
|
852
|
+
* version additionally diagnoses a header that disagrees with the active session. Messages
|
|
853
|
+
* name the expected value but never echo the client-supplied one.
|
|
844
854
|
*
|
|
845
855
|
* @param request - The HTTP request carrying the headers
|
|
846
856
|
* @param reference - The parsed invocation body, or the active legacy session version
|
|
@@ -854,6 +864,31 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
854
864
|
*/
|
|
855
865
|
export declare function inferHeaderIssue(request: Request, reference: JSONRPCInvocation | MCPVersion): MCPHeaderIssue | undefined;
|
|
856
866
|
|
|
867
|
+
/**
|
|
868
|
+
* Infers the target one modern request's `Mcp-Name` header must carry.
|
|
869
|
+
*
|
|
870
|
+
* @remarks
|
|
871
|
+
* The protocol scopes the header to the methods whose body carries a name-shaped field, and
|
|
872
|
+
* names the field per method: `tools/call` and `prompts/get` carry `params.name`, and
|
|
873
|
+
* `resources/read` carries `params.uri`. Every other method — `server/discover`, `tools/list`,
|
|
874
|
+
* `resources/list`, `prompts/list` — has nothing to derive a target from, so the header is not
|
|
875
|
+
* required there and a peer that sent one anyway is not held to it.
|
|
876
|
+
*
|
|
877
|
+
* A method within the scope whose named member is absent or is not a string reads as no
|
|
878
|
+
* target. There is nothing for a header to match, and refusing the request over a body member
|
|
879
|
+
* the header rule does not own would report a parameter fault as a header fault. Total.
|
|
880
|
+
*
|
|
881
|
+
* @param request - The parsed modern invocation to read the target from
|
|
882
|
+
* @returns The target the header must carry, or `undefined` when the method carries none
|
|
883
|
+
*
|
|
884
|
+
* @example
|
|
885
|
+
* ```ts
|
|
886
|
+
* inferHeaderTarget({ jsonrpc: '2.0', id: 1, method: 'resources/read', params: { uri: 'file:///a' } })
|
|
887
|
+
* // → 'file:///a'
|
|
888
|
+
* ```
|
|
889
|
+
*/
|
|
890
|
+
export declare function inferHeaderTarget(request: JSONRPCInvocation): string | undefined;
|
|
891
|
+
|
|
857
892
|
/**
|
|
858
893
|
* Infers the legacy revision an `initialize` request negotiates.
|
|
859
894
|
*
|
|
@@ -872,6 +907,41 @@ export declare function inferHeaderIssue(request: Request, reference: JSONRPCInv
|
|
|
872
907
|
*/
|
|
873
908
|
export declare function inferLegacyVersion(request: JSONRPCInvocation): MCPLegacyVersion;
|
|
874
909
|
|
|
910
|
+
/**
|
|
911
|
+
* Infers the refusal one `tools/call` earns for a `Mcp-Param-*` header the body contradicts.
|
|
912
|
+
*
|
|
913
|
+
* @remarks
|
|
914
|
+
* The custom-header half of the standard-header seam {@link inferHeaderIssue} owns, and it
|
|
915
|
+
* takes the SERVED definition's projections rather than a header issue: SEP-2243 scopes the
|
|
916
|
+
* rule to the `Mcp-Param-*` names the server's OWN tool definitions annotate, so a name no
|
|
917
|
+
* parameter claims is another party's header and travels through untouched.
|
|
918
|
+
*
|
|
919
|
+
* For each recognized parameter the body's value at the parameter's own property path fixes
|
|
920
|
+
* the expectation. A value the call omits or supplies as `null` requires no header, and a
|
|
921
|
+
* header sent anyway is refused because it asserts something the body never said. A value the
|
|
922
|
+
* call does supply requires its header: an absent one, a Base64 sentinel whose payload is
|
|
923
|
+
* invalid, and a decoded value that disagrees are each refused. An `integer` parameter
|
|
924
|
+
* compares numerically, so a peer that padded its decimal still matches. A supplied value
|
|
925
|
+
* whose runtime shape contradicts the declared type is left alone — the tool's own argument
|
|
926
|
+
* validation owns that disagreement, and refusing it here would report an argument fault as a
|
|
927
|
+
* header fault.
|
|
928
|
+
*
|
|
929
|
+
* Messages name the field and the body path the expectation came from, and never echo the
|
|
930
|
+
* value the peer supplied.
|
|
931
|
+
*
|
|
932
|
+
* @param request - The HTTP request carrying the headers
|
|
933
|
+
* @param parameters - The projections the served tool definition declares
|
|
934
|
+
* @param values - The call's `arguments` record
|
|
935
|
+
* @returns The refusal message for the first disagreeing parameter, or `undefined`
|
|
936
|
+
*
|
|
937
|
+
* @example
|
|
938
|
+
* ```ts
|
|
939
|
+
* inferParameterRefusal(request, [{ name: 'Region', path: ['region'], primitive: 'string' }], {})
|
|
940
|
+
* // → undefined when the request carries no `Mcp-Param-Region` either
|
|
941
|
+
* ```
|
|
942
|
+
*/
|
|
943
|
+
export declare function inferParameterRefusal(request: Request, parameters: readonly MCPHeaderParameter[], values: unknown): string | undefined;
|
|
944
|
+
|
|
875
945
|
/**
|
|
876
946
|
* Infers the HTTP status for one MCP dispatch outcome without changing its JSON-RPC body.
|
|
877
947
|
*
|
|
@@ -1474,6 +1544,30 @@ export declare interface StdioClientTransportOptions {
|
|
|
1474
1544
|
readonly delivery?: number;
|
|
1475
1545
|
}
|
|
1476
1546
|
|
|
1547
|
+
/**
|
|
1548
|
+
* The stdio INGRESS handle {@link import('./factories.js').createStdioServer} returns — arms
|
|
1549
|
+
* and tears down the newline-delimited JSON-RPC pump over the {@link StdioServerOptions}
|
|
1550
|
+
* stream pair.
|
|
1551
|
+
*
|
|
1552
|
+
* @remarks
|
|
1553
|
+
* - `start()` — arm the pump: subscribe to `input`, and dispatch every complete line through
|
|
1554
|
+
* the bound {@link import('@src/core').MCPDispatcherInterface}, writing each defined
|
|
1555
|
+
* response back to `output`. The subscriptions are attached by the time the call returns.
|
|
1556
|
+
* The pump arms ONCE, so a repeated `start()` attaches nothing further and an inbound
|
|
1557
|
+
* request still draws exactly one reply.
|
|
1558
|
+
* - `stop()` — unbind the pump and close the transport: the listeners `start()` put on
|
|
1559
|
+
* `input` / `output` are removed, every pending `send` rejects, and `input` is released so
|
|
1560
|
+
* the process can exit. The release is complete by the time the call returns, and a
|
|
1561
|
+
* repeated `stop()` does nothing.
|
|
1562
|
+
* - **One lifetime per handle.** `stop()` ends it permanently: a `start()` issued afterwards
|
|
1563
|
+
* arms nothing, and serving again takes a fresh
|
|
1564
|
+
* {@link import('./factories.js').createStdioServer} over a live stream pair.
|
|
1565
|
+
*/
|
|
1566
|
+
export declare interface StdioServerInterface {
|
|
1567
|
+
start(): void;
|
|
1568
|
+
stop(): void;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1477
1571
|
/**
|
|
1478
1572
|
* Options for `createStdioServer` — the injectable stdin/stdout streams the server
|
|
1479
1573
|
* transport reads newline-delimited JSON-RPC requests from and writes responses to.
|
|
@@ -1597,10 +1691,12 @@ export declare function upgradeRequestPath(request: IncomingMessage): string;
|
|
|
1597
1691
|
* non-JSON / non-message frame surfaces on `error` and is dropped. The socket's `close`
|
|
1598
1692
|
* / `error` bridge to this transport's events.
|
|
1599
1693
|
* - **Outbound (`send`).** `send(message)` writes one masked text frame. A socket write is not
|
|
1600
|
-
* confirmed, so this transport answers a closed channel from its
|
|
1601
|
-
* bound socket — before `start()`, after `close()`, or after the
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1694
|
+
* confirmed, so this transport answers a closed channel from its own state AND the socket's
|
|
1695
|
+
* `readyState`: a `send` with no bound socket — before `start()`, after `close()`, or after the
|
|
1696
|
+
* peer ended the socket — and a `send` on a bound socket that is not `OPEN` both REJECT with
|
|
1697
|
+
* `WebSocket transport is not connected`. It neither drops the message nor queues it for a
|
|
1698
|
+
* connection this transport is not holding — the browser face queues a pre-open send, and this
|
|
1699
|
+
* one, holding no connection to flush it onto, rejects that too.
|
|
1604
1700
|
* - **`close()`** unsubscribes from the socket, closes it, and fires `close` (idempotent). An
|
|
1605
1701
|
* upgrade still on the wire is DESTROYED, so a `close()` during the handshake ends the
|
|
1606
1702
|
* transport at once instead of waiting for a peer that may never answer — the suspended
|
|
@@ -1706,8 +1802,13 @@ export declare interface WebSocketServerOptions {
|
|
|
1706
1802
|
* a non-JSON or non-message frame is surfaced on `error` and DROPPED, never thrown. It
|
|
1707
1803
|
* also bridges the socket's `close` → this transport's `close`, and the socket's `error`.
|
|
1708
1804
|
* - **Outbound (`send`).** `send(message)` writes one text frame
|
|
1709
|
-
* (`nodeWs.send(JSON.stringify(message))`)
|
|
1710
|
-
* non-open socket, so a closed
|
|
1805
|
+
* (`nodeWs.send(JSON.stringify(message))`). The underlying wrapper no-ops a write on a
|
|
1806
|
+
* non-open socket and confirms nothing, so this bridge answers a closed channel from its own
|
|
1807
|
+
* state and the socket's `readyState`: a `send` after `close()`, after the peer's close, or on
|
|
1808
|
+
* a socket that is not `OPEN` REJECTS with `WebSocket transport is not connected` rather than
|
|
1809
|
+
* resolving on a frame nobody wrote. `bindServer` catches that rejection and routes it to the
|
|
1810
|
+
* dispatcher's `error` event, and it aborts every in-flight request the moment this transport's
|
|
1811
|
+
* `close` fires — so a peer that disconnects mid-request is answered by no write at all.
|
|
1711
1812
|
* - **`close()`** removes the subscriptions `start()` installed on the socket, closes the
|
|
1712
1813
|
* underlying socket (the RFC 6455 close handshake), and fires the transport's `close` event
|
|
1713
1814
|
* (idempotent — a second `close`, or a socket-driven close, emits once). A frame that arrives
|
|
@@ -11,6 +11,7 @@ import { MCPClientTransportInterface as MCPClientTransportInterface_2 } from '@o
|
|
|
11
11
|
import { MCPContinuationInterface } from '@orkestrel/mcp';
|
|
12
12
|
import { MCPDispatcherInterface } from '@orkestrel/mcp';
|
|
13
13
|
import { MCPEra } from '@orkestrel/mcp';
|
|
14
|
+
import { MCPHeaderParameter } from '@orkestrel/mcp';
|
|
14
15
|
import { MCPLegacyVersion } from '@orkestrel/mcp';
|
|
15
16
|
import { MCPStreamControllerInterface } from '@orkestrel/mcp';
|
|
16
17
|
import { MCPTransportInterface } from '@orkestrel/mcp';
|
|
@@ -172,12 +173,17 @@ export declare function createMCPContinuation(secret: TokenSecret): MCPContinuat
|
|
|
172
173
|
* Creates the Streamable-HTTP POST handler used by `createMCPRoutes`.
|
|
173
174
|
*
|
|
174
175
|
* @remarks
|
|
175
|
-
* Modern requests require matching protocol/method headers and a matching name header
|
|
176
|
-
*
|
|
177
|
-
*
|
|
178
|
-
*
|
|
179
|
-
*
|
|
180
|
-
*
|
|
176
|
+
* Modern requests require matching protocol/method headers and a matching name header on each
|
|
177
|
+
* method carrying a named target — `tools/call` and `prompts/get` against `params.name`,
|
|
178
|
+
* `resources/read` against `params.uri` — with a Base64-sentinel value decoded before the
|
|
179
|
+
* comparison; a missing, mismatched, or invalidly encoded value returns HTTP `400` + `-32020`.
|
|
180
|
+
* A protocol header naming a MODERN revision holds the request to that revision whatever shape
|
|
181
|
+
* its body arrived in, so a body with no parsable modern `_meta` returns HTTP `400` + `-32602`.
|
|
182
|
+
* Headerless `initialize` is accepted, while every other headerless request needs a live legacy
|
|
183
|
+
* session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
184
|
+
* otherwise admitted only for a legacy revision; a revision this server does not implement
|
|
185
|
+
* returns HTTP `400` + `-32022` whose `supported` names the legacy revisions this door accepts.
|
|
186
|
+
* A present origin must occur in `origin.origins` unless validation is
|
|
181
187
|
* explicitly delegated upstream. Modern dispatch errors use their protocol status map; legacy
|
|
182
188
|
* errors remain in-band at HTTP `200`. A streamed response composes the fetch-standard request
|
|
183
189
|
* signal with response-body cancellation and supplies the result to every dispatched modern
|
|
@@ -397,7 +403,8 @@ export declare function createStdioClientTransport(options: StdioClientTransport
|
|
|
397
403
|
* @param mcp - The transport-agnostic {@link MCPDispatcherInterface} to expose over stdio
|
|
398
404
|
* @param options - Optional injectable `input` / `output` streams; see
|
|
399
405
|
* {@link StdioServerOptions}
|
|
400
|
-
* @returns A
|
|
406
|
+
* @returns A {@link StdioServerInterface} handle to arm / tear down the pump; `stop()` ends
|
|
407
|
+
* that handle's lifetime permanently
|
|
401
408
|
*
|
|
402
409
|
* @example
|
|
403
410
|
* ```ts
|
|
@@ -410,10 +417,7 @@ export declare function createStdioClientTransport(options: StdioClientTransport
|
|
|
410
417
|
* createStdioServer(createMCPLegacy(mcp)).start() // answers `initialize` too; pass `mcp` alone for modern-only
|
|
411
418
|
* ```
|
|
412
419
|
*/
|
|
413
|
-
export declare function createStdioServer(mcp: MCPDispatcherInterface, options?: StdioServerOptions):
|
|
414
|
-
start(): void;
|
|
415
|
-
stop(): void;
|
|
416
|
-
};
|
|
420
|
+
export declare function createStdioServer(mcp: MCPDispatcherInterface, options?: StdioServerOptions): StdioServerInterface;
|
|
417
421
|
|
|
418
422
|
/**
|
|
419
423
|
* Creates the WebSocket CLIENT transport for an {@link import('@orkestrel/mcp').MCPClientInterface}
|
|
@@ -655,7 +659,8 @@ export declare function extractLines(buffer: string, chunk: string): LineExtract
|
|
|
655
659
|
* initialize result's `protocolVersion` is likewise captured, but only
|
|
656
660
|
* when it is a SUPPORTED value, and echoed as `mcp-protocol-version` alone on
|
|
657
661
|
* subsequent legacy requests. Modern requests instead derive protocol and method
|
|
658
|
-
* headers from the message, plus the name header only for `tools/call
|
|
662
|
+
* headers from the message, plus the name header only for `tools/call` — carried in the
|
|
663
|
+
* protocol's Base64 sentinel form whenever the tool name cannot ride as plain ASCII.
|
|
659
664
|
* Before initialize returns, neither captured legacy header is sent.
|
|
660
665
|
* `close()` clears the captured protocol so a reconnect's `initialize`
|
|
661
666
|
* POST is headerless; the captured `session` persists across `close()`.
|
|
@@ -837,10 +842,15 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
837
842
|
* Infers the first required MCP HTTP header that is missing or mismatched.
|
|
838
843
|
*
|
|
839
844
|
* @remarks
|
|
840
|
-
* A modern request derives its protocol, method, and
|
|
841
|
-
* the
|
|
842
|
-
*
|
|
843
|
-
*
|
|
845
|
+
* A modern request derives its protocol, method, and name expectations from the JSON-RPC body,
|
|
846
|
+
* the name expectation scoped to the methods {@link inferHeaderTarget} reads a target for. A
|
|
847
|
+
* name header carrying the Base64 sentinel is decoded through
|
|
848
|
+
* {@link import('@orkestrel/mcp').decodeSentinel} before the comparison, so a peer that had
|
|
849
|
+
* to encode its value still matches; a sentinel whose payload is invalid decodes to nothing
|
|
850
|
+
* and therefore mismatches, which is how an invalid header value is refused. A legacy request
|
|
851
|
+
* body requires a protocol header after initialization, while a supplied legacy session
|
|
852
|
+
* version additionally diagnoses a header that disagrees with the active session. Messages
|
|
853
|
+
* name the expected value but never echo the client-supplied one.
|
|
844
854
|
*
|
|
845
855
|
* @param request - The HTTP request carrying the headers
|
|
846
856
|
* @param reference - The parsed invocation body, or the active legacy session version
|
|
@@ -854,6 +864,31 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
854
864
|
*/
|
|
855
865
|
export declare function inferHeaderIssue(request: Request, reference: JSONRPCInvocation | MCPVersion): MCPHeaderIssue | undefined;
|
|
856
866
|
|
|
867
|
+
/**
|
|
868
|
+
* Infers the target one modern request's `Mcp-Name` header must carry.
|
|
869
|
+
*
|
|
870
|
+
* @remarks
|
|
871
|
+
* The protocol scopes the header to the methods whose body carries a name-shaped field, and
|
|
872
|
+
* names the field per method: `tools/call` and `prompts/get` carry `params.name`, and
|
|
873
|
+
* `resources/read` carries `params.uri`. Every other method — `server/discover`, `tools/list`,
|
|
874
|
+
* `resources/list`, `prompts/list` — has nothing to derive a target from, so the header is not
|
|
875
|
+
* required there and a peer that sent one anyway is not held to it.
|
|
876
|
+
*
|
|
877
|
+
* A method within the scope whose named member is absent or is not a string reads as no
|
|
878
|
+
* target. There is nothing for a header to match, and refusing the request over a body member
|
|
879
|
+
* the header rule does not own would report a parameter fault as a header fault. Total.
|
|
880
|
+
*
|
|
881
|
+
* @param request - The parsed modern invocation to read the target from
|
|
882
|
+
* @returns The target the header must carry, or `undefined` when the method carries none
|
|
883
|
+
*
|
|
884
|
+
* @example
|
|
885
|
+
* ```ts
|
|
886
|
+
* inferHeaderTarget({ jsonrpc: '2.0', id: 1, method: 'resources/read', params: { uri: 'file:///a' } })
|
|
887
|
+
* // → 'file:///a'
|
|
888
|
+
* ```
|
|
889
|
+
*/
|
|
890
|
+
export declare function inferHeaderTarget(request: JSONRPCInvocation): string | undefined;
|
|
891
|
+
|
|
857
892
|
/**
|
|
858
893
|
* Infers the legacy revision an `initialize` request negotiates.
|
|
859
894
|
*
|
|
@@ -872,6 +907,41 @@ export declare function inferHeaderIssue(request: Request, reference: JSONRPCInv
|
|
|
872
907
|
*/
|
|
873
908
|
export declare function inferLegacyVersion(request: JSONRPCInvocation): MCPLegacyVersion;
|
|
874
909
|
|
|
910
|
+
/**
|
|
911
|
+
* Infers the refusal one `tools/call` earns for a `Mcp-Param-*` header the body contradicts.
|
|
912
|
+
*
|
|
913
|
+
* @remarks
|
|
914
|
+
* The custom-header half of the standard-header seam {@link inferHeaderIssue} owns, and it
|
|
915
|
+
* takes the SERVED definition's projections rather than a header issue: SEP-2243 scopes the
|
|
916
|
+
* rule to the `Mcp-Param-*` names the server's OWN tool definitions annotate, so a name no
|
|
917
|
+
* parameter claims is another party's header and travels through untouched.
|
|
918
|
+
*
|
|
919
|
+
* For each recognized parameter the body's value at the parameter's own property path fixes
|
|
920
|
+
* the expectation. A value the call omits or supplies as `null` requires no header, and a
|
|
921
|
+
* header sent anyway is refused because it asserts something the body never said. A value the
|
|
922
|
+
* call does supply requires its header: an absent one, a Base64 sentinel whose payload is
|
|
923
|
+
* invalid, and a decoded value that disagrees are each refused. An `integer` parameter
|
|
924
|
+
* compares numerically, so a peer that padded its decimal still matches. A supplied value
|
|
925
|
+
* whose runtime shape contradicts the declared type is left alone — the tool's own argument
|
|
926
|
+
* validation owns that disagreement, and refusing it here would report an argument fault as a
|
|
927
|
+
* header fault.
|
|
928
|
+
*
|
|
929
|
+
* Messages name the field and the body path the expectation came from, and never echo the
|
|
930
|
+
* value the peer supplied.
|
|
931
|
+
*
|
|
932
|
+
* @param request - The HTTP request carrying the headers
|
|
933
|
+
* @param parameters - The projections the served tool definition declares
|
|
934
|
+
* @param values - The call's `arguments` record
|
|
935
|
+
* @returns The refusal message for the first disagreeing parameter, or `undefined`
|
|
936
|
+
*
|
|
937
|
+
* @example
|
|
938
|
+
* ```ts
|
|
939
|
+
* inferParameterRefusal(request, [{ name: 'Region', path: ['region'], primitive: 'string' }], {})
|
|
940
|
+
* // → undefined when the request carries no `Mcp-Param-Region` either
|
|
941
|
+
* ```
|
|
942
|
+
*/
|
|
943
|
+
export declare function inferParameterRefusal(request: Request, parameters: readonly MCPHeaderParameter[], values: unknown): string | undefined;
|
|
944
|
+
|
|
875
945
|
/**
|
|
876
946
|
* Infers the HTTP status for one MCP dispatch outcome without changing its JSON-RPC body.
|
|
877
947
|
*
|
|
@@ -1474,6 +1544,30 @@ export declare interface StdioClientTransportOptions {
|
|
|
1474
1544
|
readonly delivery?: number;
|
|
1475
1545
|
}
|
|
1476
1546
|
|
|
1547
|
+
/**
|
|
1548
|
+
* The stdio INGRESS handle {@link import('./factories.js').createStdioServer} returns — arms
|
|
1549
|
+
* and tears down the newline-delimited JSON-RPC pump over the {@link StdioServerOptions}
|
|
1550
|
+
* stream pair.
|
|
1551
|
+
*
|
|
1552
|
+
* @remarks
|
|
1553
|
+
* - `start()` — arm the pump: subscribe to `input`, and dispatch every complete line through
|
|
1554
|
+
* the bound {@link import('@src/core').MCPDispatcherInterface}, writing each defined
|
|
1555
|
+
* response back to `output`. The subscriptions are attached by the time the call returns.
|
|
1556
|
+
* The pump arms ONCE, so a repeated `start()` attaches nothing further and an inbound
|
|
1557
|
+
* request still draws exactly one reply.
|
|
1558
|
+
* - `stop()` — unbind the pump and close the transport: the listeners `start()` put on
|
|
1559
|
+
* `input` / `output` are removed, every pending `send` rejects, and `input` is released so
|
|
1560
|
+
* the process can exit. The release is complete by the time the call returns, and a
|
|
1561
|
+
* repeated `stop()` does nothing.
|
|
1562
|
+
* - **One lifetime per handle.** `stop()` ends it permanently: a `start()` issued afterwards
|
|
1563
|
+
* arms nothing, and serving again takes a fresh
|
|
1564
|
+
* {@link import('./factories.js').createStdioServer} over a live stream pair.
|
|
1565
|
+
*/
|
|
1566
|
+
export declare interface StdioServerInterface {
|
|
1567
|
+
start(): void;
|
|
1568
|
+
stop(): void;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1477
1571
|
/**
|
|
1478
1572
|
* Options for `createStdioServer` — the injectable stdin/stdout streams the server
|
|
1479
1573
|
* transport reads newline-delimited JSON-RPC requests from and writes responses to.
|
|
@@ -1597,10 +1691,12 @@ export declare function upgradeRequestPath(request: IncomingMessage): string;
|
|
|
1597
1691
|
* non-JSON / non-message frame surfaces on `error` and is dropped. The socket's `close`
|
|
1598
1692
|
* / `error` bridge to this transport's events.
|
|
1599
1693
|
* - **Outbound (`send`).** `send(message)` writes one masked text frame. A socket write is not
|
|
1600
|
-
* confirmed, so this transport answers a closed channel from its
|
|
1601
|
-
* bound socket — before `start()`, after `close()`, or after the
|
|
1602
|
-
*
|
|
1603
|
-
*
|
|
1694
|
+
* confirmed, so this transport answers a closed channel from its own state AND the socket's
|
|
1695
|
+
* `readyState`: a `send` with no bound socket — before `start()`, after `close()`, or after the
|
|
1696
|
+
* peer ended the socket — and a `send` on a bound socket that is not `OPEN` both REJECT with
|
|
1697
|
+
* `WebSocket transport is not connected`. It neither drops the message nor queues it for a
|
|
1698
|
+
* connection this transport is not holding — the browser face queues a pre-open send, and this
|
|
1699
|
+
* one, holding no connection to flush it onto, rejects that too.
|
|
1604
1700
|
* - **`close()`** unsubscribes from the socket, closes it, and fires `close` (idempotent). An
|
|
1605
1701
|
* upgrade still on the wire is DESTROYED, so a `close()` during the handshake ends the
|
|
1606
1702
|
* transport at once instead of waiting for a peer that may never answer — the suspended
|
|
@@ -1706,8 +1802,13 @@ export declare interface WebSocketServerOptions {
|
|
|
1706
1802
|
* a non-JSON or non-message frame is surfaced on `error` and DROPPED, never thrown. It
|
|
1707
1803
|
* also bridges the socket's `close` → this transport's `close`, and the socket's `error`.
|
|
1708
1804
|
* - **Outbound (`send`).** `send(message)` writes one text frame
|
|
1709
|
-
* (`nodeWs.send(JSON.stringify(message))`)
|
|
1710
|
-
* non-open socket, so a closed
|
|
1805
|
+
* (`nodeWs.send(JSON.stringify(message))`). The underlying wrapper no-ops a write on a
|
|
1806
|
+
* non-open socket and confirms nothing, so this bridge answers a closed channel from its own
|
|
1807
|
+
* state and the socket's `readyState`: a `send` after `close()`, after the peer's close, or on
|
|
1808
|
+
* a socket that is not `OPEN` REJECTS with `WebSocket transport is not connected` rather than
|
|
1809
|
+
* resolving on a frame nobody wrote. `bindServer` catches that rejection and routes it to the
|
|
1810
|
+
* dispatcher's `error` event, and it aborts every in-flight request the moment this transport's
|
|
1811
|
+
* `close` fires — so a peer that disconnects mid-request is answered by no write at all.
|
|
1711
1812
|
* - **`close()`** removes the subscriptions `start()` installed on the socket, closes the
|
|
1712
1813
|
* underlying socket (the RFC 6455 close handshake), and fires the transport's `close` event
|
|
1713
1814
|
* (idempotent — a second `close`, or a socket-driven close, emits once). A frame that arrives
|