@orkestrel/mcp 0.0.24 → 0.0.26
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.js.map +1 -1
- package/dist/src/core/index.cjs +797 -212
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +496 -111
- package/dist/src/core/index.d.ts +496 -111
- package/dist/src/core/index.js +780 -210
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +47 -18
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +31 -6
- package/dist/src/server/index.d.ts +31 -6
- package/dist/src/server/index.js +48 -20
- package/dist/src/server/index.js.map +1 -1
- package/package.json +10 -10
|
@@ -100,6 +100,24 @@ var DEFAULT_MCP_DELIVERY = 1e4;
|
|
|
100
100
|
//#endregion
|
|
101
101
|
//#region src/server/helpers.ts
|
|
102
102
|
/**
|
|
103
|
+
* Builds the error for a non-success HTTP response that carried no JSON-RPC message.
|
|
104
|
+
*
|
|
105
|
+
* @param response - The response whose status is reported
|
|
106
|
+
* @param type - The response's content type, or an empty string when absent
|
|
107
|
+
* @returns An error naming the HTTP status and unsupported response shape
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* const error = buildResponseError(new Response('', { status: 500 }), '')
|
|
112
|
+
* ```
|
|
113
|
+
*/
|
|
114
|
+
function buildResponseError(response, type) {
|
|
115
|
+
if (type.includes("application/json")) return /* @__PURE__ */ new Error(`HTTP ${response.status} response contained an application/json body that was not a JSON-RPC message`);
|
|
116
|
+
if (type.includes("text/event-stream")) return /* @__PURE__ */ new Error(`HTTP ${response.status} response contained a text/event-stream body without a JSON-RPC message`);
|
|
117
|
+
const shape = type === "" ? "a body without a content type" : `an unsupported '${type}' body`;
|
|
118
|
+
return /* @__PURE__ */ new Error(`HTTP ${response.status} response contained ${shape}`);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
103
121
|
* Creates a readable stream from its pull and cancellation behaviours.
|
|
104
122
|
*
|
|
105
123
|
* @param pull - The behaviour that supplies the stream's next chunk
|
|
@@ -547,7 +565,7 @@ function inferHeaderIssue(request, reference) {
|
|
|
547
565
|
return {
|
|
548
566
|
header: "MCP-Protocol-Version",
|
|
549
567
|
reason: "missing",
|
|
550
|
-
message: `Required MCP-Protocol-Version header is missing; this server offers '${_src_core.
|
|
568
|
+
message: `Required MCP-Protocol-Version header is missing; this server offers '${_src_core.MCP_HANDSHAKE_VERSION}'.`
|
|
551
569
|
};
|
|
552
570
|
}
|
|
553
571
|
const message = reference;
|
|
@@ -594,16 +612,20 @@ function inferHeaderIssue(request, reference) {
|
|
|
594
612
|
*
|
|
595
613
|
* @remarks
|
|
596
614
|
* A supported legacy request is pinned exactly. A modern, malformed, absent, or unsupported
|
|
597
|
-
* request selects the newest supported legacy revision
|
|
615
|
+
* request selects the newest supported legacy revision. The read is deliberately the SAME one
|
|
616
|
+
* {@link import('@orkestrel/mcp').buildInitializeResult} performs — `isMCPLegacyVersion` over
|
|
617
|
+
* the requested revision — because the session version this pins and the version that result
|
|
618
|
+
* echoes must be the one value. Routing through `inferVersion` cannot do it: that inferer is
|
|
619
|
+
* modern-only, so it answers `undefined` for every legacy offer and the session would pin
|
|
620
|
+
* `2025-11-25` while the handshake echoed `2025-06-18`, which the client's own protocol
|
|
621
|
+
* header then contradicts.
|
|
598
622
|
*
|
|
599
623
|
* @param request - The legacy initialize invocation
|
|
600
624
|
* @returns The negotiated legacy protocol revision
|
|
601
625
|
*/
|
|
602
626
|
function inferLegacyVersion(request) {
|
|
603
627
|
const requested = request.params?.["protocolVersion"];
|
|
604
|
-
|
|
605
|
-
if (version !== void 0 && (0, _src_core.inferEra)(version) === "legacy") return version;
|
|
606
|
-
return _src_core.MCP_PROTOCOL_VERSION;
|
|
628
|
+
return (0, _src_core.isMCPLegacyVersion)(requested) ? requested : _src_core.MCP_HANDSHAKE_VERSION;
|
|
607
629
|
}
|
|
608
630
|
/**
|
|
609
631
|
* Infers the HTTP status for one MCP dispatch outcome without changing its JSON-RPC body.
|
|
@@ -766,7 +788,9 @@ var HTTPDisconnect = class {
|
|
|
766
788
|
* Modern requests require matching protocol/method headers and a matching name header only
|
|
767
789
|
* for `tools/call`; mismatch returns HTTP `400` + `-32020`. Headerless `initialize` is
|
|
768
790
|
* accepted, while every other headerless request needs a live legacy session to supply its
|
|
769
|
-
* pinned version. A
|
|
791
|
+
* pinned version. A legacy-shaped request carrying a protocol header is admitted only for a
|
|
792
|
+
* legacy revision; any other value, the modern revision included, returns HTTP `400` + `-32022`
|
|
793
|
+
* whose `supported` names the legacy revisions this door accepts. A present origin must occur in `origin.origins` unless validation is
|
|
770
794
|
* explicitly delegated upstream. Modern dispatch errors use their protocol status map; legacy
|
|
771
795
|
* errors remain in-band at HTTP `200`. A streamed response composes the fetch-standard request
|
|
772
796
|
* signal with response-body cancellation and supplies the result to every dispatched modern
|
|
@@ -821,8 +845,8 @@ function createMCPPostHandler(mcp, options) {
|
|
|
821
845
|
const issue = inferHeaderIssue(request, invocation);
|
|
822
846
|
if (issue !== void 0) return Response.json((0, _src_core.buildJSONRPCError)(id, _src_core.MCP_HEADER_MISMATCH, issue.message), { status: 400 });
|
|
823
847
|
if (era === "legacy") {
|
|
824
|
-
if (protocol !== null && !(0, _src_core.
|
|
825
|
-
supported: _src_core.
|
|
848
|
+
if (protocol !== null && !(0, _src_core.isMCPLegacyVersion)(protocol)) return Response.json((0, _src_core.buildJSONRPCError)(id, _src_core.MCP_UNSUPPORTED_VERSION, `Unsupported MCP protocol version '${protocol}'`, {
|
|
849
|
+
supported: _src_core.SUPPORTED_LEGACY_PROTOCOL_VERSIONS,
|
|
826
850
|
requested: protocol
|
|
827
851
|
}), { status: 400 });
|
|
828
852
|
}
|
|
@@ -890,8 +914,10 @@ function createMCPPostHandler(mcp, options) {
|
|
|
890
914
|
* aborted read surfaces on `error` and the `send` reporting it resolves. `close()` is
|
|
891
915
|
* idempotent (one `close` event per connected lifetime), and `start()` opens the next one.
|
|
892
916
|
* - **Total at the boundary.** Every reply is narrowed (`parseJSONRPCMessage`,
|
|
893
|
-
* the SSE decoder)
|
|
894
|
-
*
|
|
917
|
+
* the SSE decoder). A non-message success reply is dropped, never asserted. A non-success
|
|
918
|
+
* reply that carries no valid JSON-RPC message rejects `send` with its HTTP status and body
|
|
919
|
+
* shape. A valid JSON-RPC error body is emitted at any HTTP status. A `fetch` / decode failure
|
|
920
|
+
* on a success response surfaces on the `error` event rather than escaping `send`.
|
|
895
921
|
* - **Observable.** Owns the `emitter` ({@link MCPClientTransportEventMap}); fires
|
|
896
922
|
* `message` per decoded reply, `error` on a fault, and `close` on `close()`.
|
|
897
923
|
*
|
|
@@ -986,18 +1012,20 @@ var HTTPClientTransport = class {
|
|
|
986
1012
|
async #deliver(response) {
|
|
987
1013
|
if (response.status === 202) return;
|
|
988
1014
|
const type = response.headers.get("content-type") ?? "";
|
|
1015
|
+
let messages = [];
|
|
1016
|
+
let failure;
|
|
989
1017
|
try {
|
|
990
|
-
if (type.includes("text/event-stream"))
|
|
991
|
-
|
|
992
|
-
return;
|
|
993
|
-
}
|
|
994
|
-
if (type.includes("application/json")) {
|
|
1018
|
+
if (type.includes("text/event-stream")) messages = await readEventStream(response);
|
|
1019
|
+
else if (type.includes("application/json")) {
|
|
995
1020
|
const message = (0, _src_core.parseJSONRPCMessage)(await response.json());
|
|
996
|
-
if (message !== void 0)
|
|
1021
|
+
if (message !== void 0) messages = [message];
|
|
997
1022
|
}
|
|
998
1023
|
} catch (error) {
|
|
999
|
-
|
|
1024
|
+
failure = { error };
|
|
1000
1025
|
}
|
|
1026
|
+
for (const message of messages) this.#capture(message);
|
|
1027
|
+
if (!response.ok && messages.length === 0) throw buildResponseError(response, type);
|
|
1028
|
+
if (failure !== void 0) this.#emitter.emit("error", failure.error);
|
|
1001
1029
|
}
|
|
1002
1030
|
#capture(message) {
|
|
1003
1031
|
if ((0, _src_core.isJSONRPCResponse)(message) && (0, _orkestrel_contract.isRecord)(message.result) && (0, _src_core.isMCPVersion)(message.result["protocolVersion"])) this.#protocol = message.result["protocolVersion"];
|
|
@@ -1468,7 +1496,7 @@ var WebSocketClientTransport = class {
|
|
|
1468
1496
|
* ```ts
|
|
1469
1497
|
* const transport = new StdioClientTransport({ command: 'node', args: ['./server.js'] })
|
|
1470
1498
|
* const client = new MCPClient({ transport })
|
|
1471
|
-
* await client.connect() // start() spawns the child, then
|
|
1499
|
+
* await client.connect() // start() spawns the child, then modern discovery runs over stdio
|
|
1472
1500
|
* ```
|
|
1473
1501
|
*/
|
|
1474
1502
|
var StdioClientTransport = class {
|
|
@@ -2228,6 +2256,7 @@ exports.WebSocketServerTransport = WebSocketServerTransport;
|
|
|
2228
2256
|
exports.acceptsEventStream = acceptsEventStream;
|
|
2229
2257
|
exports.allowsOrigin = allowsOrigin;
|
|
2230
2258
|
exports.bridgeMessageTransport = bridgeMessageTransport;
|
|
2259
|
+
exports.buildResponseError = buildResponseError;
|
|
2231
2260
|
exports.createHTTPClientTransport = createHTTPClientTransport;
|
|
2232
2261
|
exports.createMCPContinuation = createMCPContinuation;
|
|
2233
2262
|
exports.createMCPPostHandler = createMCPPostHandler;
|