@orkestrel/mcp 0.0.36 → 0.0.38
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/core/index.cjs +26 -5
- package/dist/src/core/index.cjs.map +1 -1
- package/dist/src/core/index.d.cts +27 -1
- package/dist/src/core/index.d.ts +27 -1
- package/dist/src/core/index.js +26 -6
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/server/index.cjs +15 -7
- package/dist/src/server/index.cjs.map +1 -1
- package/dist/src/server/index.d.cts +7 -5
- package/dist/src/server/index.d.ts +7 -5
- package/dist/src/server/index.js +16 -8
- package/dist/src/server/index.js.map +1 -1
- package/package.json +19 -19
|
@@ -170,8 +170,8 @@ export declare function createMCPContinuation(secret: TokenSecret): MCPContinuat
|
|
|
170
170
|
* comparison; a missing, mismatched, or invalidly encoded value returns HTTP `400` + `-32020`.
|
|
171
171
|
* A protocol header naming a modern revision holds the request to that revision whatever shape
|
|
172
172
|
* its body arrived in, so a body with no parsable modern `_meta` returns HTTP `400` + `-32602`.
|
|
173
|
-
* Headerless `initialize`
|
|
174
|
-
* session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
173
|
+
* Headerless `initialize` and id-bearing legacy `ping` are accepted; other headerless requests
|
|
174
|
+
* need a live legacy session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
175
175
|
* otherwise admitted only for a legacy revision; a revision this server does not implement
|
|
176
176
|
* returns HTTP `400` + `-32022` whose `supported` names the legacy revisions this door accepts.
|
|
177
177
|
* A present origin must occur in `origin.origins` unless validation is
|
|
@@ -282,7 +282,9 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPDispatcherInte
|
|
|
282
282
|
* readSessionHeader}: a valid id touches the entry and sets `context.state.session`; an
|
|
283
283
|
* absent / unknown id whose (guarded) body parses to an `initialize` request ({@link
|
|
284
284
|
* isInitializeRequest}) mints a fresh {@link MCPSession} (`crypto.randomUUID()`, the `session`
|
|
285
|
-
* options group) and sets `context.state.session
|
|
285
|
+
* options group) and sets `context.state.session`. An id-bearing legacy `ping` with no
|
|
286
|
+
* session header passes through without session state, a supplied protocol header, or a
|
|
287
|
+
* response stamp. Other unresolved requests → {@link rejectUnknownSession}
|
|
286
288
|
* (`404`). The
|
|
287
289
|
* minted entry pins the negotiated legacy revision, which is supplied to a later headerless
|
|
288
290
|
* live-session request. It then
|
|
@@ -713,8 +715,8 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
713
715
|
* {@link import('@orkestrel/mcp').decodeSentinel} before the comparison, so a peer that had
|
|
714
716
|
* to encode its value still matches; a sentinel whose payload is invalid decodes to nothing
|
|
715
717
|
* and therefore mismatches, which is how an invalid header value is refused. A legacy request
|
|
716
|
-
* body requires a protocol header
|
|
717
|
-
* never echo the client-supplied one.
|
|
718
|
+
* body requires a protocol header except for `initialize` and an id-bearing legacy `ping`.
|
|
719
|
+
* Messages name the expected value but never echo the client-supplied one.
|
|
718
720
|
*
|
|
719
721
|
* The expectation a live session supplies is a different rule over a different input, so it
|
|
720
722
|
* is {@link inferSessionHeaderIssue} rather than a second arm of this one.
|
|
@@ -170,8 +170,8 @@ export declare function createMCPContinuation(secret: TokenSecret): MCPContinuat
|
|
|
170
170
|
* comparison; a missing, mismatched, or invalidly encoded value returns HTTP `400` + `-32020`.
|
|
171
171
|
* A protocol header naming a modern revision holds the request to that revision whatever shape
|
|
172
172
|
* its body arrived in, so a body with no parsable modern `_meta` returns HTTP `400` + `-32602`.
|
|
173
|
-
* Headerless `initialize`
|
|
174
|
-
* session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
173
|
+
* Headerless `initialize` and id-bearing legacy `ping` are accepted; other headerless requests
|
|
174
|
+
* need a live legacy session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
175
175
|
* otherwise admitted only for a legacy revision; a revision this server does not implement
|
|
176
176
|
* returns HTTP `400` + `-32022` whose `supported` names the legacy revisions this door accepts.
|
|
177
177
|
* A present origin must occur in `origin.origins` unless validation is
|
|
@@ -282,7 +282,9 @@ export declare function createMCPRoutes<TState = unknown>(mcp: MCPDispatcherInte
|
|
|
282
282
|
* readSessionHeader}: a valid id touches the entry and sets `context.state.session`; an
|
|
283
283
|
* absent / unknown id whose (guarded) body parses to an `initialize` request ({@link
|
|
284
284
|
* isInitializeRequest}) mints a fresh {@link MCPSession} (`crypto.randomUUID()`, the `session`
|
|
285
|
-
* options group) and sets `context.state.session
|
|
285
|
+
* options group) and sets `context.state.session`. An id-bearing legacy `ping` with no
|
|
286
|
+
* session header passes through without session state, a supplied protocol header, or a
|
|
287
|
+
* response stamp. Other unresolved requests → {@link rejectUnknownSession}
|
|
286
288
|
* (`404`). The
|
|
287
289
|
* minted entry pins the negotiated legacy revision, which is supplied to a later headerless
|
|
288
290
|
* live-session request. It then
|
|
@@ -713,8 +715,8 @@ export declare interface HTTPTransportOptions<TState = unknown> extends HTTPHand
|
|
|
713
715
|
* {@link import('@orkestrel/mcp').decodeSentinel} before the comparison, so a peer that had
|
|
714
716
|
* to encode its value still matches; a sentinel whose payload is invalid decodes to nothing
|
|
715
717
|
* and therefore mismatches, which is how an invalid header value is refused. A legacy request
|
|
716
|
-
* body requires a protocol header
|
|
717
|
-
* never echo the client-supplied one.
|
|
718
|
+
* body requires a protocol header except for `initialize` and an id-bearing legacy `ping`.
|
|
719
|
+
* Messages name the expected value but never echo the client-supplied one.
|
|
718
720
|
*
|
|
719
721
|
* The expectation a live session supplies is a different rule over a different input, so it
|
|
720
722
|
* is {@link inferSessionHeaderIssue} rather than a second arm of this one.
|
package/dist/src/server/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PROCESS_GRACE } from "@orkestrel/process";
|
|
2
|
-
import { HTTPClientTransport, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, MCP_HANDSHAKE_VERSION, MCP_HEADER_MISMATCH, MCP_LOOKUP_PAGES, MCP_META_VERSION, MCP_METHOD_HEADER, MCP_MISSING_CAPABILITY, MCP_NAME_HEADER, MCP_PARAM_PREFIX, MCP_PROTOCOL_VERSION_HEADER, MCP_SESSION_HEADER, MCP_UNSUPPORTED_VERSION, MCP_WEBSOCKET_SUBPROTOCOL, SUPPORTED_LEGACY_PROTOCOL_VERSIONS, bindServer, buildHeaderParameters, buildJSONRPCError, decodeEvent, decodeSentinel, deliverMessage, extractToolSchema, inferRequestEra, isInitializeRequest, isJSONRPCInvocation, isMCPLegacyVersion, isMCPModernVersion, isModernRequest, parseJSONRPCMessage, parseRequestContext, renderHeaderValue } from "../core/index.js";
|
|
2
|
+
import { HTTPClientTransport, JSONRPC_INVALID_PARAMS, JSONRPC_INVALID_REQUEST, JSONRPC_METHOD_NOT_FOUND, JSONRPC_PARSE_ERROR, MCP_HANDSHAKE_VERSION, MCP_HEADER_MISMATCH, MCP_LOOKUP_PAGES, MCP_META_VERSION, MCP_METHOD_HEADER, MCP_MISSING_CAPABILITY, MCP_NAME_HEADER, MCP_PARAM_PREFIX, MCP_PROTOCOL_VERSION_HEADER, MCP_SESSION_HEADER, MCP_UNSUPPORTED_VERSION, MCP_WEBSOCKET_SUBPROTOCOL, SUPPORTED_LEGACY_PROTOCOL_VERSIONS, bindServer, buildHeaderParameters, buildJSONRPCError, decodeEvent, decodeSentinel, deliverMessage, extractToolSchema, inferRequestEra, isInitializeRequest, isJSONRPCInvocation, isMCPLegacyVersion, isMCPModernVersion, isModernRequest, isPingRequest, parseJSONRPCMessage, parseRequestContext, renderHeaderValue } from "../core/index.js";
|
|
3
3
|
import { isError, isObject, isRecord, isString, parseJSON, sanitizeBudget } from "@orkestrel/contract";
|
|
4
4
|
import { createStream, signToken, verifyToken } from "@orkestrel/server";
|
|
5
5
|
import { Emitter } from "@orkestrel/emitter";
|
|
@@ -371,8 +371,8 @@ function inferHeaderTarget(request) {
|
|
|
371
371
|
* {@link import('@orkestrel/mcp').decodeSentinel} before the comparison, so a peer that had
|
|
372
372
|
* to encode its value still matches; a sentinel whose payload is invalid decodes to nothing
|
|
373
373
|
* and therefore mismatches, which is how an invalid header value is refused. A legacy request
|
|
374
|
-
* body requires a protocol header
|
|
375
|
-
* never echo the client-supplied one.
|
|
374
|
+
* body requires a protocol header except for `initialize` and an id-bearing legacy `ping`.
|
|
375
|
+
* Messages name the expected value but never echo the client-supplied one.
|
|
376
376
|
*
|
|
377
377
|
* The expectation a live session supplies is a different rule over a different input, so it
|
|
378
378
|
* is {@link inferSessionHeaderIssue} rather than a second arm of this one.
|
|
@@ -390,7 +390,7 @@ function inferHeaderTarget(request) {
|
|
|
390
390
|
function inferHeaderIssue(request, invocation) {
|
|
391
391
|
const protocol = request.headers.get(MCP_PROTOCOL_VERSION_HEADER);
|
|
392
392
|
if (!isModernRequest(invocation)) {
|
|
393
|
-
if (isInitializeRequest(invocation) || protocol !== null) return void 0;
|
|
393
|
+
if (isInitializeRequest(invocation) || isPingRequest(invocation) || protocol !== null) return void 0;
|
|
394
394
|
return {
|
|
395
395
|
header: "MCP-Protocol-Version",
|
|
396
396
|
reason: "missing",
|
|
@@ -718,8 +718,8 @@ var HTTPDisconnect = class {
|
|
|
718
718
|
* comparison; a missing, mismatched, or invalidly encoded value returns HTTP `400` + `-32020`.
|
|
719
719
|
* A protocol header naming a modern revision holds the request to that revision whatever shape
|
|
720
720
|
* its body arrived in, so a body with no parsable modern `_meta` returns HTTP `400` + `-32602`.
|
|
721
|
-
* Headerless `initialize`
|
|
722
|
-
* session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
721
|
+
* Headerless `initialize` and id-bearing legacy `ping` are accepted; other headerless requests
|
|
722
|
+
* need a live legacy session to supply its pinned version. A legacy-shaped request carrying a protocol header is
|
|
723
723
|
* otherwise admitted only for a legacy revision; a revision this server does not implement
|
|
724
724
|
* returns HTTP `400` + `-32022` whose `supported` names the legacy revisions this door accepts.
|
|
725
725
|
* A present origin must occur in `origin.origins` unless validation is
|
|
@@ -1978,7 +1978,9 @@ function createStdioServer(mcp, options) {
|
|
|
1978
1978
|
* readSessionHeader}: a valid id touches the entry and sets `context.state.session`; an
|
|
1979
1979
|
* absent / unknown id whose (guarded) body parses to an `initialize` request ({@link
|
|
1980
1980
|
* isInitializeRequest}) mints a fresh {@link MCPSession} (`crypto.randomUUID()`, the `session`
|
|
1981
|
-
* options group) and sets `context.state.session
|
|
1981
|
+
* options group) and sets `context.state.session`. An id-bearing legacy `ping` with no
|
|
1982
|
+
* session header passes through without session state, a supplied protocol header, or a
|
|
1983
|
+
* response stamp. Other unresolved requests → {@link rejectUnknownSession}
|
|
1982
1984
|
* (`404`). The
|
|
1983
1985
|
* minted entry pins the negotiated legacy revision, which is supplied to a later headerless
|
|
1984
1986
|
* live-session request. It then
|
|
@@ -2107,7 +2109,13 @@ function createMCPSession(options) {
|
|
|
2107
2109
|
version: inferLegacyVersion(parsed)
|
|
2108
2110
|
};
|
|
2109
2111
|
entry = created;
|
|
2110
|
-
} else return
|
|
2112
|
+
} else if (id === void 0 && isPingRequest(parsed)) return next(new Request(context.url, {
|
|
2113
|
+
method: "POST",
|
|
2114
|
+
headers: request.headers,
|
|
2115
|
+
body: text,
|
|
2116
|
+
signal: request.signal
|
|
2117
|
+
}));
|
|
2118
|
+
else return rejectUnknownSession();
|
|
2111
2119
|
}
|
|
2112
2120
|
if (!Reflect.set(context.state, "session", entry.session)) throw new Error("MCP session state is not writable");
|
|
2113
2121
|
const headers = new Headers(request.headers);
|