mcp-trellis 1.0.0 → 2.2.0
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 +65 -93
- package/dist/adapters/node-request.d.ts +53 -0
- package/dist/adapters/node-request.d.ts.map +1 -0
- package/dist/adapters/node-request.js +165 -0
- package/dist/adapters/node-request.js.map +1 -0
- package/dist/adapters/node.d.ts +13 -30
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +55 -101
- package/dist/adapters/node.js.map +1 -1
- package/dist/advanced.d.ts +18 -0
- package/dist/advanced.d.ts.map +1 -0
- package/dist/advanced.js +18 -0
- package/dist/advanced.js.map +1 -0
- package/dist/app-options.d.ts +132 -0
- package/dist/app-options.d.ts.map +1 -0
- package/dist/app-options.js +2 -0
- package/dist/app-options.js.map +1 -0
- package/dist/app.d.ts +2 -89
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +143 -63
- package/dist/app.js.map +1 -1
- package/dist/audit.d.ts +5 -5
- package/dist/audit.d.ts.map +1 -1
- package/dist/audit.js +19 -8
- package/dist/audit.js.map +1 -1
- package/dist/auth/bearer.d.ts +4 -1
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +19 -4
- package/dist/auth/bearer.js.map +1 -1
- package/dist/auth/signed-token.d.ts +26 -0
- package/dist/auth/signed-token.d.ts.map +1 -0
- package/dist/auth/signed-token.js +96 -0
- package/dist/auth/signed-token.js.map +1 -0
- package/dist/clients.js +1 -1
- package/dist/clients.js.map +1 -1
- package/dist/deprecated.d.ts +42 -0
- package/dist/deprecated.d.ts.map +1 -0
- package/dist/deprecated.js +35 -0
- package/dist/deprecated.js.map +1 -0
- package/dist/{body.d.ts → http/body.d.ts} +27 -6
- package/dist/http/body.d.ts.map +1 -0
- package/dist/{body.js → http/body.js} +33 -13
- package/dist/http/body.js.map +1 -0
- package/dist/http/http.d.ts +42 -0
- package/dist/http/http.d.ts.map +1 -0
- package/dist/http/http.js +100 -0
- package/dist/http/http.js.map +1 -0
- package/dist/http/origins.d.ts +37 -0
- package/dist/http/origins.d.ts.map +1 -0
- package/dist/http/origins.js +87 -0
- package/dist/http/origins.js.map +1 -0
- package/dist/{dispatch.d.ts → mcp/dispatch.d.ts} +1 -1
- package/dist/mcp/dispatch.d.ts.map +1 -0
- package/dist/mcp/dispatch.js +99 -0
- package/dist/mcp/dispatch.js.map +1 -0
- package/dist/{jsonrpc.d.ts → mcp/jsonrpc.d.ts} +9 -0
- package/dist/mcp/jsonrpc.d.ts.map +1 -0
- package/dist/mcp/jsonrpc.js +88 -0
- package/dist/mcp/jsonrpc.js.map +1 -0
- package/dist/{methods.d.ts → mcp/methods.d.ts} +60 -11
- package/dist/mcp/methods.d.ts.map +1 -0
- package/dist/mcp/methods.js +84 -0
- package/dist/mcp/methods.js.map +1 -0
- package/dist/{protocol.d.ts → mcp/protocol.d.ts} +1 -3
- package/dist/mcp/protocol.d.ts.map +1 -0
- package/dist/{protocol.js → mcp/protocol.js} +1 -3
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +58 -0
- package/dist/mcp/registry.d.ts.map +1 -0
- package/dist/mcp/registry.js +81 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/rpc-handlers.d.ts +11 -0
- package/dist/mcp/rpc-handlers.d.ts.map +1 -0
- package/dist/mcp/rpc-handlers.js +133 -0
- package/dist/mcp/rpc-handlers.js.map +1 -0
- package/dist/{tools.d.ts → mcp/tools.d.ts} +20 -1
- package/dist/mcp/tools.d.ts.map +1 -0
- package/dist/mcp/tools.js +166 -0
- package/dist/mcp/tools.js.map +1 -0
- package/dist/{validate.d.ts → mcp/validate.d.ts} +18 -21
- package/dist/mcp/validate.d.ts.map +1 -0
- package/dist/{validate.js → mcp/validate.js} +59 -41
- package/dist/mcp/validate.js.map +1 -0
- package/dist/oauth/audit.d.ts +20 -0
- package/dist/oauth/audit.d.ts.map +1 -0
- package/dist/oauth/audit.js +29 -0
- package/dist/oauth/audit.js.map +1 -0
- package/dist/oauth/cimd/cimd-parse.d.ts +4 -0
- package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-parse.js +70 -0
- package/dist/oauth/cimd/cimd-parse.js.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -0
- package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd-ssrf.js +193 -0
- package/dist/oauth/cimd/cimd-ssrf.js.map +1 -0
- package/dist/oauth/cimd/cimd.d.ts +36 -0
- package/dist/oauth/cimd/cimd.d.ts.map +1 -0
- package/dist/oauth/cimd/cimd.js +132 -0
- package/dist/oauth/cimd/cimd.js.map +1 -0
- package/dist/oauth/cimd/types.d.ts +12 -0
- package/dist/oauth/cimd/types.d.ts.map +1 -0
- package/dist/oauth/cimd/types.js +3 -0
- package/dist/oauth/cimd/types.js.map +1 -0
- package/dist/oauth/config.d.ts +51 -0
- package/dist/oauth/config.d.ts.map +1 -0
- package/dist/oauth/config.js +108 -0
- package/dist/oauth/config.js.map +1 -0
- package/dist/oauth/constants.d.ts +11 -0
- package/dist/oauth/constants.d.ts.map +1 -1
- package/dist/oauth/constants.js +11 -0
- package/dist/oauth/constants.js.map +1 -1
- package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +0 -1
- package/dist/oauth/crypto/base64url.d.ts.map +1 -0
- package/dist/oauth/{base64url.js → crypto/base64url.js} +0 -1
- package/dist/oauth/crypto/base64url.js.map +1 -0
- package/dist/oauth/crypto/clientauth.d.ts +13 -0
- package/dist/oauth/crypto/clientauth.d.ts.map +1 -0
- package/dist/oauth/crypto/clientauth.js +195 -0
- package/dist/oauth/crypto/clientauth.js.map +1 -0
- package/dist/oauth/crypto/codes.d.ts +65 -0
- package/dist/oauth/crypto/codes.d.ts.map +1 -0
- package/dist/oauth/crypto/codes.js +121 -0
- package/dist/oauth/crypto/codes.js.map +1 -0
- package/dist/oauth/crypto/hkdf.d.ts +13 -0
- package/dist/oauth/crypto/hkdf.d.ts.map +1 -0
- package/dist/oauth/crypto/hkdf.js +30 -0
- package/dist/oauth/crypto/hkdf.js.map +1 -0
- package/dist/oauth/crypto/keycache.d.ts +19 -0
- package/dist/oauth/crypto/keycache.d.ts.map +1 -0
- package/dist/oauth/crypto/keycache.js +44 -0
- package/dist/oauth/crypto/keycache.js.map +1 -0
- package/dist/oauth/crypto/pkce.d.ts.map +1 -0
- package/dist/oauth/{pkce.js → crypto/pkce.js} +1 -1
- package/dist/oauth/crypto/pkce.js.map +1 -0
- package/dist/oauth/{sealed.d.ts → crypto/sealed.d.ts} +12 -3
- package/dist/oauth/crypto/sealed.d.ts.map +1 -0
- package/dist/oauth/{sealed.js → crypto/sealed.js} +22 -14
- package/dist/oauth/crypto/sealed.js.map +1 -0
- package/dist/oauth/{secrethash.d.ts → crypto/secrethash.d.ts} +14 -0
- package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
- package/dist/oauth/{secrethash.js → crypto/secrethash.js} +27 -11
- package/dist/oauth/crypto/secrethash.js.map +1 -0
- package/dist/oauth/deprecated.d.ts +52 -0
- package/dist/oauth/deprecated.d.ts.map +1 -0
- package/dist/oauth/deprecated.js +49 -0
- package/dist/oauth/deprecated.js.map +1 -0
- package/dist/oauth/endpoints/authorize.d.ts +3 -0
- package/dist/oauth/endpoints/authorize.d.ts.map +1 -0
- package/dist/oauth/endpoints/authorize.js +209 -0
- package/dist/oauth/endpoints/authorize.js.map +1 -0
- package/dist/oauth/endpoints/callback.d.ts +20 -0
- package/dist/oauth/endpoints/callback.d.ts.map +1 -0
- package/dist/oauth/endpoints/callback.js +31 -0
- package/dist/oauth/endpoints/callback.js.map +1 -0
- package/dist/oauth/endpoints/consent-page.d.ts +5 -0
- package/dist/oauth/endpoints/consent-page.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent-page.js +63 -0
- package/dist/oauth/endpoints/consent-page.js.map +1 -0
- package/dist/oauth/endpoints/consent.d.ts +29 -0
- package/dist/oauth/endpoints/consent.d.ts.map +1 -0
- package/dist/oauth/endpoints/consent.js +98 -0
- package/dist/oauth/endpoints/consent.js.map +1 -0
- package/dist/oauth/{metadata.d.ts → endpoints/metadata.d.ts} +8 -2
- package/dist/oauth/endpoints/metadata.d.ts.map +1 -0
- package/dist/oauth/{metadata.js → endpoints/metadata.js} +10 -4
- package/dist/oauth/endpoints/metadata.js.map +1 -0
- package/dist/oauth/endpoints/register.d.ts +10 -0
- package/dist/oauth/endpoints/register.d.ts.map +1 -0
- package/dist/oauth/endpoints/register.js +96 -0
- package/dist/oauth/endpoints/register.js.map +1 -0
- package/dist/oauth/{revoke.d.ts → endpoints/revoke.d.ts} +1 -1
- package/dist/oauth/endpoints/revoke.d.ts.map +1 -0
- package/dist/oauth/{revoke.js → endpoints/revoke.js} +8 -18
- package/dist/oauth/endpoints/revoke.js.map +1 -0
- package/dist/oauth/endpoints/token.d.ts +3 -0
- package/dist/oauth/endpoints/token.d.ts.map +1 -0
- package/dist/oauth/{token.js → endpoints/token.js} +32 -25
- package/dist/oauth/endpoints/token.js.map +1 -0
- package/dist/oauth/{wellknown.d.ts → endpoints/wellknown.d.ts} +1 -1
- package/dist/oauth/endpoints/wellknown.d.ts.map +1 -0
- package/dist/oauth/{wellknown.js → endpoints/wellknown.js} +7 -9
- package/dist/oauth/endpoints/wellknown.js.map +1 -0
- package/dist/oauth/policy/redirect.d.ts.map +1 -0
- package/dist/oauth/policy/redirect.js.map +1 -0
- package/dist/oauth/policy/reqbody.d.ts +18 -0
- package/dist/oauth/policy/reqbody.d.ts.map +1 -0
- package/dist/oauth/policy/reqbody.js +68 -0
- package/dist/oauth/policy/reqbody.js.map +1 -0
- package/dist/oauth/{resource.d.ts → policy/resource.d.ts} +1 -1
- package/dist/oauth/policy/resource.d.ts.map +1 -0
- package/dist/oauth/{resource.js → policy/resource.js} +2 -2
- package/dist/oauth/policy/resource.js.map +1 -0
- package/dist/oauth/{scope.d.ts → policy/scope.d.ts} +2 -2
- package/dist/oauth/policy/scope.d.ts.map +1 -0
- package/dist/oauth/{scope.js → policy/scope.js} +3 -3
- package/dist/oauth/policy/scope.js.map +1 -0
- package/dist/oauth/router.d.ts +10 -13
- package/dist/oauth/router.d.ts.map +1 -1
- package/dist/oauth/router.js +93 -115
- package/dist/oauth/router.js.map +1 -1
- package/dist/oauth/types.d.ts +99 -45
- package/dist/oauth/types.d.ts.map +1 -1
- package/dist/oauth/types.js +1 -90
- package/dist/oauth/types.js.map +1 -1
- package/dist/server.d.ts +13 -12
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +10 -8
- package/dist/server.js.map +1 -1
- package/dist/util/defined.d.ts +11 -0
- package/dist/util/defined.d.ts.map +1 -0
- package/dist/util/defined.js +15 -0
- package/dist/util/defined.js.map +1 -0
- package/dist/util/json.d.ts +3 -0
- package/dist/util/json.d.ts.map +1 -0
- package/dist/util/json.js +3 -0
- package/dist/util/json.js.map +1 -0
- package/docs/ROADMAP.md +37 -47
- package/docs/compatibility.md +86 -0
- package/docs/diagrams/demo-tool-result.png +0 -0
- package/docs/diagrams/mcp-trellis-architecture.html +305 -0
- package/docs/guide.md +46 -16
- package/docs/reference.md +55 -22
- package/docs/security.md +58 -9
- package/docs/troubleshooting.md +19 -0
- package/package.json +27 -10
- package/dist/adapters/origins.d.ts +0 -19
- package/dist/adapters/origins.d.ts.map +0 -1
- package/dist/adapters/origins.js +0 -52
- package/dist/adapters/origins.js.map +0 -1
- package/dist/body.d.ts.map +0 -1
- package/dist/body.js.map +0 -1
- package/dist/dispatch.d.ts.map +0 -1
- package/dist/dispatch.js +0 -119
- package/dist/dispatch.js.map +0 -1
- package/dist/http.d.ts +0 -17
- package/dist/http.d.ts.map +0 -1
- package/dist/http.js +0 -38
- package/dist/http.js.map +0 -1
- package/dist/jsonrpc.d.ts.map +0 -1
- package/dist/jsonrpc.js +0 -18
- package/dist/jsonrpc.js.map +0 -1
- package/dist/methods.d.ts.map +0 -1
- package/dist/methods.js +0 -130
- package/dist/methods.js.map +0 -1
- package/dist/oauth/authorize.d.ts +0 -3
- package/dist/oauth/authorize.d.ts.map +0 -1
- package/dist/oauth/authorize.js +0 -141
- package/dist/oauth/authorize.js.map +0 -1
- package/dist/oauth/base64url.d.ts.map +0 -1
- package/dist/oauth/base64url.js.map +0 -1
- package/dist/oauth/clientauth.d.ts +0 -24
- package/dist/oauth/clientauth.d.ts.map +0 -1
- package/dist/oauth/clientauth.js +0 -119
- package/dist/oauth/clientauth.js.map +0 -1
- package/dist/oauth/codes.d.ts +0 -30
- package/dist/oauth/codes.d.ts.map +0 -1
- package/dist/oauth/codes.js +0 -85
- package/dist/oauth/codes.js.map +0 -1
- package/dist/oauth/consent.d.ts +0 -65
- package/dist/oauth/consent.d.ts.map +0 -1
- package/dist/oauth/consent.js +0 -173
- package/dist/oauth/consent.js.map +0 -1
- package/dist/oauth/metadata.d.ts.map +0 -1
- package/dist/oauth/metadata.js.map +0 -1
- package/dist/oauth/pkce.d.ts.map +0 -1
- package/dist/oauth/pkce.js.map +0 -1
- package/dist/oauth/redirect.d.ts.map +0 -1
- package/dist/oauth/redirect.js.map +0 -1
- package/dist/oauth/reqbody.d.ts +0 -10
- package/dist/oauth/reqbody.d.ts.map +0 -1
- package/dist/oauth/reqbody.js +0 -29
- package/dist/oauth/reqbody.js.map +0 -1
- package/dist/oauth/resource.d.ts.map +0 -1
- package/dist/oauth/resource.js.map +0 -1
- package/dist/oauth/revoke.d.ts.map +0 -1
- package/dist/oauth/revoke.js.map +0 -1
- package/dist/oauth/scope.d.ts.map +0 -1
- package/dist/oauth/scope.js.map +0 -1
- package/dist/oauth/sealed.d.ts.map +0 -1
- package/dist/oauth/sealed.js.map +0 -1
- package/dist/oauth/secrethash.d.ts.map +0 -1
- package/dist/oauth/secrethash.js.map +0 -1
- package/dist/oauth/token.d.ts +0 -3
- package/dist/oauth/token.d.ts.map +0 -1
- package/dist/oauth/token.js.map +0 -1
- package/dist/oauth/wellknown.d.ts.map +0 -1
- package/dist/oauth/wellknown.js.map +0 -1
- package/dist/protocol.d.ts.map +0 -1
- package/dist/protocol.js.map +0 -1
- package/dist/registry.d.ts +0 -37
- package/dist/registry.d.ts.map +0 -1
- package/dist/registry.js +0 -77
- package/dist/registry.js.map +0 -1
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -98
- package/dist/tools.js.map +0 -1
- package/dist/validate.d.ts.map +0 -1
- package/dist/validate.js.map +0 -1
- /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
- /package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +0 -0
- /package/dist/oauth/{redirect.js → policy/redirect.js} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatch.js","sourceRoot":"","sources":["../../src/mcp/dispatch.ts"],"names":[],"mappings":"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"}
|
|
@@ -28,6 +28,15 @@ export declare const JSONRPC_INVALID_PARAMS = -32602;
|
|
|
28
28
|
export declare const JSONRPC_INTERNAL_ERROR = -32603;
|
|
29
29
|
export declare const JSONRPC_UNAUTHORIZED = -32001;
|
|
30
30
|
export declare const JSONRPC_PAYLOAD_TOO_LARGE = -32002;
|
|
31
|
+
/** Authenticated but missing required scope — paired with HTTP 403. */
|
|
32
|
+
export declare const JSONRPC_INSUFFICIENT_SCOPE = -32003;
|
|
31
33
|
export declare const rpcResult: (id: JsonRpcId, result: unknown) => JsonRpcSuccess;
|
|
32
34
|
export declare const rpcError: (id: JsonRpcId, code: number, message: string) => JsonRpcFailure;
|
|
35
|
+
/** Batch / jsonrpc version / shape — returns a Response or a validated request. */
|
|
36
|
+
export declare const validateJsonRpcEnvelope: (parsed: unknown) => Response | JsonRpcRequest;
|
|
37
|
+
/**
|
|
38
|
+
* Spec requires `MCP-Protocol-Version` past `initialize`. Unknown → 400.
|
|
39
|
+
* Missing → assume `2025-03-26` (header BC rule; see `protocol.ts`).
|
|
40
|
+
*/
|
|
41
|
+
export declare const protocolVersionHeaderError: (request: Request, jsonRpcRequest: JsonRpcRequest) => Response | null;
|
|
33
42
|
//# sourceMappingURL=jsonrpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.d.ts","sourceRoot":"","sources":["../../src/mcp/jsonrpc.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,MAAM,GAAG,IAAI,CAAC;AAE/C,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,CAAC,EAAE,SAAS,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACjC,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,SAAS,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,OAAO,EAAE,KAAK,CAAC;IACf,EAAE,EAAE,SAAS,CAAC;IACd,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAC1C,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG,cAAc,GAAG,cAAc,CAAC;AAE9D,eAAO,MAAM,mBAAmB,SAAS,CAAC;AAC1C,eAAO,MAAM,uBAAuB,SAAS,CAAC;AAC9C,eAAO,MAAM,wBAAwB,SAAS,CAAC;AAC/C,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAC7C,eAAO,MAAM,oBAAoB,SAAS,CAAC;AAC3C,eAAO,MAAM,yBAAyB,SAAS,CAAC;AAChD,uEAAuE;AACvE,eAAO,MAAM,0BAA0B,SAAS,CAAC;AAEjD,eAAO,MAAM,SAAS,GAAI,IAAI,SAAS,EAAE,QAAQ,OAAO,KAAG,cAIzD,CAAC;AAEH,eAAO,MAAM,QAAQ,GAAI,IAAI,SAAS,EAAE,MAAM,MAAM,EAAE,SAAS,MAAM,KAAG,cAItE,CAAC;AAwCH,mFAAmF;AACnF,eAAO,MAAM,uBAAuB,GAAI,QAAQ,OAAO,KAAG,QAAQ,GAAG,cAkBpE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GACrC,SAAS,OAAO,EAChB,gBAAgB,cAAc,KAC7B,QAAQ,GAAG,IAYb,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { jsonResponse } from "../http/http.js";
|
|
2
|
+
import { PROTOCOL_VERSIONS } from "./protocol.js";
|
|
3
|
+
export const JSONRPC_PARSE_ERROR = -32700;
|
|
4
|
+
export const JSONRPC_INVALID_REQUEST = -32600;
|
|
5
|
+
export const JSONRPC_METHOD_NOT_FOUND = -32601;
|
|
6
|
+
export const JSONRPC_INVALID_PARAMS = -32602;
|
|
7
|
+
export const JSONRPC_INTERNAL_ERROR = -32603;
|
|
8
|
+
export const JSONRPC_UNAUTHORIZED = -32001;
|
|
9
|
+
export const JSONRPC_PAYLOAD_TOO_LARGE = -32002;
|
|
10
|
+
/** Authenticated but missing required scope — paired with HTTP 403. */
|
|
11
|
+
export const JSONRPC_INSUFFICIENT_SCOPE = -32003;
|
|
12
|
+
export const rpcResult = (id, result) => ({
|
|
13
|
+
jsonrpc: "2.0",
|
|
14
|
+
id,
|
|
15
|
+
result,
|
|
16
|
+
});
|
|
17
|
+
export const rpcError = (id, code, message) => ({
|
|
18
|
+
jsonrpc: "2.0",
|
|
19
|
+
id,
|
|
20
|
+
error: { code, message },
|
|
21
|
+
});
|
|
22
|
+
const isJsonRpcId = (id) => id === null || typeof id === "string" || typeof id === "number";
|
|
23
|
+
/**
|
|
24
|
+
* RFC-shaped JSON-RPC id for an error response — omitted → `null`; valid ids
|
|
25
|
+
* echoed; invalid shapes → `null` so we never reflect an illegal id.
|
|
26
|
+
*/
|
|
27
|
+
const errorId = (jsonRpcRequest) => {
|
|
28
|
+
if (jsonRpcRequest.id === undefined)
|
|
29
|
+
return null;
|
|
30
|
+
return isJsonRpcId(jsonRpcRequest.id) ? jsonRpcRequest.id : null;
|
|
31
|
+
};
|
|
32
|
+
/** Runtime JSON-RPC Request shape — types alone do not enforce this. */
|
|
33
|
+
const jsonRpcShapeError = (jsonRpcRequest) => {
|
|
34
|
+
if (jsonRpcRequest.id !== undefined && !isJsonRpcId(jsonRpcRequest.id)) {
|
|
35
|
+
return jsonResponse({
|
|
36
|
+
data: rpcError(null, JSONRPC_INVALID_REQUEST, "id must be string, number, or null"),
|
|
37
|
+
status: 400,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
const orphanResult = jsonRpcRequest.method === undefined &&
|
|
41
|
+
jsonRpcRequest.id === undefined &&
|
|
42
|
+
"result" in jsonRpcRequest;
|
|
43
|
+
if (orphanResult)
|
|
44
|
+
return null;
|
|
45
|
+
if (typeof jsonRpcRequest.method !== "string" || jsonRpcRequest.method.length === 0) {
|
|
46
|
+
return jsonResponse({
|
|
47
|
+
data: rpcError(errorId(jsonRpcRequest), JSONRPC_INVALID_REQUEST, "method must be a non-empty string"),
|
|
48
|
+
status: 400,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
return null;
|
|
52
|
+
};
|
|
53
|
+
/** Batch / jsonrpc version / shape — returns a Response or a validated request. */
|
|
54
|
+
export const validateJsonRpcEnvelope = (parsed) => {
|
|
55
|
+
if (Array.isArray(parsed)) {
|
|
56
|
+
return jsonResponse({
|
|
57
|
+
data: rpcError(null, JSONRPC_INVALID_REQUEST, "Batch requests not supported"),
|
|
58
|
+
status: 400,
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
if (!parsed || typeof parsed !== "object") {
|
|
62
|
+
return jsonResponse({ data: rpcError(null, JSONRPC_PARSE_ERROR, "Parse error"), status: 400 });
|
|
63
|
+
}
|
|
64
|
+
const jsonRpcRequest = parsed;
|
|
65
|
+
if (jsonRpcRequest.jsonrpc !== "2.0") {
|
|
66
|
+
return jsonResponse({
|
|
67
|
+
data: rpcError(errorId(jsonRpcRequest), JSONRPC_INVALID_REQUEST, 'jsonrpc must be "2.0"'),
|
|
68
|
+
status: 400,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return jsonRpcShapeError(jsonRpcRequest) ?? jsonRpcRequest;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Spec requires `MCP-Protocol-Version` past `initialize`. Unknown → 400.
|
|
75
|
+
* Missing → assume `2025-03-26` (header BC rule; see `protocol.ts`).
|
|
76
|
+
*/
|
|
77
|
+
export const protocolVersionHeaderError = (request, jsonRpcRequest) => {
|
|
78
|
+
if (jsonRpcRequest.method === "initialize")
|
|
79
|
+
return null;
|
|
80
|
+
const header = request.headers.get("MCP-Protocol-Version");
|
|
81
|
+
if (!header || PROTOCOL_VERSIONS.has(header))
|
|
82
|
+
return null;
|
|
83
|
+
return jsonResponse({
|
|
84
|
+
data: rpcError(errorId(jsonRpcRequest), JSONRPC_INVALID_REQUEST, `Unsupported MCP-Protocol-Version: ${header}`),
|
|
85
|
+
status: 400,
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
//# sourceMappingURL=jsonrpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc.js","sourceRoot":"","sources":["../../src/mcp/jsonrpc.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import { type WwwAuthenticateOptions } from "
|
|
1
|
+
import { type WwwAuthenticateOptions } from "../auth/bearer.js";
|
|
2
2
|
import { type JsonRpcId, type JsonRpcRequest } from "./jsonrpc.js";
|
|
3
3
|
import type { ToolRegistry } from "./registry.js";
|
|
4
4
|
export type Principal = {
|
|
5
5
|
id: string;
|
|
6
|
+
/**
|
|
7
|
+
* Granted scopes. The literal `"*"` is a wildcard that satisfies **every**
|
|
8
|
+
* tool `scope` check (see `hasScope`) — reserve it for trusted internal
|
|
9
|
+
* principals; never mint it for an external connector.
|
|
10
|
+
*/
|
|
6
11
|
scopes: string[];
|
|
7
12
|
/** Optional host claims from `verifyToken` (tenant, plan, role, …). */
|
|
8
13
|
claims?: Record<string, unknown> | undefined;
|
|
@@ -19,6 +24,12 @@ export type AuditEntry = {
|
|
|
19
24
|
};
|
|
20
25
|
export type McpPorts<TCtx> = {
|
|
21
26
|
authenticate: (req: Request, method: string, tool?: string) => Promise<Principal | null>;
|
|
27
|
+
/**
|
|
28
|
+
* Builds the tool context. Called only for a `tools/call` that passed the
|
|
29
|
+
* unknown-tool and scope checks — never for `initialize`, `ping` or
|
|
30
|
+
* `tools/list`. `principal` is null only when a host adds `tools/call`
|
|
31
|
+
* to `publicMethods`.
|
|
32
|
+
*/
|
|
22
33
|
context: (req: Request, principal: Principal | null) => TCtx | Promise<TCtx>;
|
|
23
34
|
/**
|
|
24
35
|
* Opt-in metrics hook. Pass any function to receive tool results and auth
|
|
@@ -51,10 +62,46 @@ export type McpHandlerOptions<TCtx> = {
|
|
|
51
62
|
* indefinitely — "can't fail" isn't "can't delay."
|
|
52
63
|
*/
|
|
53
64
|
auditTimeoutMs?: number;
|
|
65
|
+
/**
|
|
66
|
+
* Browser `Origin` header allowlist for MCP (DNS rebinding / CSRF).
|
|
67
|
+
* Distinct from Node Host `allowedOrigins` on `asNodeHandler`.
|
|
68
|
+
* No `Origin` → allowed (native clients). Omitted/empty → reject any
|
|
69
|
+
* present `Origin`. `"*"` admits any Origin.
|
|
70
|
+
*/
|
|
71
|
+
allowedRequestOrigins?: string[];
|
|
72
|
+
/**
|
|
73
|
+
* Filter `tools/list` down to tools the calling principal's scopes
|
|
74
|
+
* actually satisfy (an unscoped tool is always listed). Default
|
|
75
|
+
* **false** — every tool is always listed, `tools/call` is what enforces
|
|
76
|
+
* scope (with a **403** `insufficient_scope`, see `insufficientScope`).
|
|
77
|
+
* Turning this on trades that step-up signal away: a client can no
|
|
78
|
+
* longer discover "this tool exists, ask for its scope" from `tools/list`
|
|
79
|
+
* for a scope it doesn't hold — only worth it if listing a tool at all
|
|
80
|
+
* would leak something (its name, description, or schema) you don't want
|
|
81
|
+
* a lesser-scoped principal to see.
|
|
82
|
+
*/
|
|
83
|
+
hideToolsOutsideScope?: boolean;
|
|
84
|
+
};
|
|
85
|
+
/** `McpHandlerOptions` after `createMcpHandler` resolved its defaults. */
|
|
86
|
+
export type ResolvedMcpHandlerOptions<TCtx> = McpHandlerOptions<TCtx> & {
|
|
87
|
+
publicMethods: Set<string>;
|
|
88
|
+
};
|
|
89
|
+
/** `AuditEntry.error` values for requests the handler itself denied. */
|
|
90
|
+
export declare const DENIAL_REASONS: {
|
|
91
|
+
readonly unauthorized: "unauthorized";
|
|
92
|
+
readonly queryStringToken: "query_string_token";
|
|
93
|
+
readonly originNotAllowed: "origin_not_allowed";
|
|
94
|
+
readonly unknownTool: "unknown_tool";
|
|
95
|
+
readonly missingScope: "missing_scope";
|
|
54
96
|
};
|
|
55
97
|
export declare const DEFAULT_PUBLIC_METHODS: Set<string>;
|
|
98
|
+
/**
|
|
99
|
+
* JSON-RPC 2.0: a notification omits `id` (no response). MCP also treats
|
|
100
|
+
* `notifications/*` and legacy `initialized` as notifications even when an
|
|
101
|
+
* `id` is present. Orphan result-shaped bodies (no method/id) get 202 too.
|
|
102
|
+
*/
|
|
56
103
|
export declare const isNotification: (body: JsonRpcRequest) => boolean;
|
|
57
|
-
export declare const
|
|
104
|
+
export declare const resolveWwwAuthenticate: <TCtx>(options: McpHandlerOptions<TCtx>, request: Request) => WwwAuthenticateOptions;
|
|
58
105
|
/**
|
|
59
106
|
* `id` defaults to `null` for the transport-level call sites in
|
|
60
107
|
* `dispatch.ts` — a body hasn't been parsed yet there, so there's no real
|
|
@@ -62,7 +109,16 @@ export declare const resolveWww: <TCtx>(options: McpHandlerOptions<TCtx>, req: R
|
|
|
62
109
|
* method handlers) have one and must pass it, or a client correlating
|
|
63
110
|
* responses by id sees `null` on every 401 regardless of what it sent.
|
|
64
111
|
*/
|
|
65
|
-
export declare const unauthorized: (
|
|
112
|
+
export declare const unauthorized: (wwwAuthenticate: WwwAuthenticateOptions, message?: string, id?: JsonRpcId) => Response;
|
|
113
|
+
/**
|
|
114
|
+
* RFC 6750 §3.1: a request that authenticated but lacks the required scope
|
|
115
|
+
* gets **403**, not 401 — 401 tells the client "authenticate", which a
|
|
116
|
+
* scope-step-up client obeys by re-running the exact same OAuth flow,
|
|
117
|
+
* getting back the exact same scopes, and retrying forever. 403 with
|
|
118
|
+
* `error="insufficient_scope"` says what's actually wrong: re-consent with
|
|
119
|
+
* a broader `scope` request, not re-authenticate.
|
|
120
|
+
*/
|
|
121
|
+
export declare const insufficientScope: (wwwAuthenticate: WwwAuthenticateOptions, scope: string, id?: JsonRpcId) => Response;
|
|
66
122
|
/**
|
|
67
123
|
* Invoke the audit metrics hook, swallowing any failure and racing it
|
|
68
124
|
* against `auditTimeoutMs` so a hanging sink can't stall the response
|
|
@@ -72,13 +128,6 @@ export declare const unauthorized: (www: WwwAuthenticateOptions, message?: strin
|
|
|
72
128
|
* an unhandled rejection whenever it does finish.
|
|
73
129
|
*/
|
|
74
130
|
export declare const safeAudit: <TCtx>(options: McpHandlerOptions<TCtx>, entry: AuditEntry) => Promise<void>;
|
|
131
|
+
/** True when `scope` is unset, granted, or covered by the `"*"` wildcard scope. */
|
|
75
132
|
export declare const hasScope: (principal: Principal, scope: string | undefined) => boolean;
|
|
76
|
-
export declare const dispatchRpc: <TCtx>(input: {
|
|
77
|
-
req: Request;
|
|
78
|
-
body: JsonRpcRequest;
|
|
79
|
-
options: McpHandlerOptions<TCtx>;
|
|
80
|
-
publicMethods: Set<string>;
|
|
81
|
-
/** Request start (captured in `createMcpHandler.fetch`), for denial-path audit timing. */
|
|
82
|
-
startedAt: number;
|
|
83
|
-
}) => Promise<Response>;
|
|
84
133
|
//# sourceMappingURL=methods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.d.ts","sourceRoot":"","sources":["../../src/mcp/methods.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,sBAAsB,EAAyB,MAAM,mBAAmB,CAAC;AAEvF,OAAO,EAGL,KAAK,SAAS,EACd,KAAK,cAAc,EAEpB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAC;IACX;;;;OAIG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;CAC9C,CAAC;AAEF,qEAAqE;AACrE,MAAM,MAAM,UAAU,GAAG;IACvB,mFAAmF;IACnF,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;CACpB,CAAC;AAEF,MAAM,MAAM,QAAQ,CAAC,IAAI,IAAI;IAC3B,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IACzF;;;;;OAKG;IACH,OAAO,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,SAAS,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7E;;;;;;;;;OASG;IACH,KAAK,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAAC,IAAI,IAAI;IACpC,QAAQ,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;IAC7B,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,CAAC;IACtB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,sBAAsB,GAAG,CAAC,CAAC,GAAG,EAAE,OAAO,KAAK,sBAAsB,CAAC,CAAC;IACrF,2EAA2E;IAC3E,aAAa,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC5B;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,qBAAqB,CAAC,EAAE,MAAM,EAAE,CAAC;IACjC;;;;;;;;;;OAUG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;CACjC,CAAC;AAEF,0EAA0E;AAC1E,MAAM,MAAM,yBAAyB,CAAC,IAAI,IAAI,iBAAiB,CAAC,IAAI,CAAC,GAAG;IACtE,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;CAC5B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,cAAc;;;;;;CAMjB,CAAC;AAEX,eAAO,MAAM,sBAAsB,aAKjC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,cAAc,KAAG,OAQrD,CAAC;AAEF,eAAO,MAAM,sBAAsB,GAAI,IAAI,EACzC,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAChC,SAAS,OAAO,KACf,sBAG0B,CAAC;AAE9B;;;;;;GAMG;AACH,eAAO,MAAM,YAAY,GACvB,iBAAiB,sBAAsB,EACvC,gBAAwB,EACxB,KAAI,SAAgB,KACnB,QAKC,CAAC;AAEL;;;;;;;GAOG;AACH,eAAO,MAAM,iBAAiB,GAC5B,iBAAiB,sBAAsB,EACvC,OAAO,MAAM,EACb,KAAI,SAAgB,KACnB,QAWC,CAAC;AAEL;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAU,IAAI,EAClC,SAAS,iBAAiB,CAAC,IAAI,CAAC,EAChC,OAAO,UAAU,KAChB,OAAO,CAAC,IAAI,CAKd,CAAC;AAEF,mFAAmF;AACnF,eAAO,MAAM,QAAQ,GAAI,WAAW,SAAS,EAAE,OAAO,MAAM,GAAG,SAAS,KAAG,OAG1E,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { wwwAuthenticateHeader } from "../auth/bearer.js";
|
|
2
|
+
import { DEFAULT_AUDIT_TIMEOUT_MS, jsonResponse, runAuditBounded } from "../http/http.js";
|
|
3
|
+
import { JSONRPC_INSUFFICIENT_SCOPE, JSONRPC_UNAUTHORIZED, rpcError, } from "./jsonrpc.js";
|
|
4
|
+
/** `AuditEntry.error` values for requests the handler itself denied. */
|
|
5
|
+
export const DENIAL_REASONS = {
|
|
6
|
+
unauthorized: "unauthorized",
|
|
7
|
+
queryStringToken: "query_string_token",
|
|
8
|
+
originNotAllowed: "origin_not_allowed",
|
|
9
|
+
unknownTool: "unknown_tool",
|
|
10
|
+
missingScope: "missing_scope",
|
|
11
|
+
};
|
|
12
|
+
export const DEFAULT_PUBLIC_METHODS = new Set([
|
|
13
|
+
"initialize",
|
|
14
|
+
"ping",
|
|
15
|
+
"notifications/initialized",
|
|
16
|
+
"initialized",
|
|
17
|
+
]);
|
|
18
|
+
/**
|
|
19
|
+
* JSON-RPC 2.0: a notification omits `id` (no response). MCP also treats
|
|
20
|
+
* `notifications/*` and legacy `initialized` as notifications even when an
|
|
21
|
+
* `id` is present. Orphan result-shaped bodies (no method/id) get 202 too.
|
|
22
|
+
*/
|
|
23
|
+
export const isNotification = (body) => {
|
|
24
|
+
if (body.id === undefined) {
|
|
25
|
+
return typeof body.method === "string" || (body.method === undefined && "result" in body);
|
|
26
|
+
}
|
|
27
|
+
return ((typeof body.method === "string" && body.method.startsWith("notifications/")) ||
|
|
28
|
+
body.method === "initialized");
|
|
29
|
+
};
|
|
30
|
+
export const resolveWwwAuthenticate = (options, request) => typeof options.wwwAuthenticate === "function"
|
|
31
|
+
? options.wwwAuthenticate(request)
|
|
32
|
+
: options.wwwAuthenticate;
|
|
33
|
+
/**
|
|
34
|
+
* `id` defaults to `null` for the transport-level call sites in
|
|
35
|
+
* `dispatch.ts` — a body hasn't been parsed yet there, so there's no real
|
|
36
|
+
* id to echo. Call sites past that point (inside `dispatchRpc` and the
|
|
37
|
+
* method handlers) have one and must pass it, or a client correlating
|
|
38
|
+
* responses by id sees `null` on every 401 regardless of what it sent.
|
|
39
|
+
*/
|
|
40
|
+
export const unauthorized = (wwwAuthenticate, message = "Unauthorized", id = null) => jsonResponse({
|
|
41
|
+
data: rpcError(id, JSONRPC_UNAUTHORIZED, message),
|
|
42
|
+
status: 401,
|
|
43
|
+
headers: { "WWW-Authenticate": wwwAuthenticateHeader(wwwAuthenticate) },
|
|
44
|
+
});
|
|
45
|
+
/**
|
|
46
|
+
* RFC 6750 §3.1: a request that authenticated but lacks the required scope
|
|
47
|
+
* gets **403**, not 401 — 401 tells the client "authenticate", which a
|
|
48
|
+
* scope-step-up client obeys by re-running the exact same OAuth flow,
|
|
49
|
+
* getting back the exact same scopes, and retrying forever. 403 with
|
|
50
|
+
* `error="insufficient_scope"` says what's actually wrong: re-consent with
|
|
51
|
+
* a broader `scope` request, not re-authenticate.
|
|
52
|
+
*/
|
|
53
|
+
export const insufficientScope = (wwwAuthenticate, scope, id = null) => jsonResponse({
|
|
54
|
+
data: rpcError(id, JSONRPC_INSUFFICIENT_SCOPE, `Missing scope: ${scope}`),
|
|
55
|
+
status: 403,
|
|
56
|
+
headers: {
|
|
57
|
+
"WWW-Authenticate": wwwAuthenticateHeader({
|
|
58
|
+
...wwwAuthenticate,
|
|
59
|
+
error: "insufficient_scope",
|
|
60
|
+
scope,
|
|
61
|
+
}),
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
/**
|
|
65
|
+
* Invoke the audit metrics hook, swallowing any failure and racing it
|
|
66
|
+
* against `auditTimeoutMs` so a hanging sink can't stall the response
|
|
67
|
+
* either — "can't fail a request" was already true; this adds "can't
|
|
68
|
+
* delay one" past a bound. The audit call keeps running in the background
|
|
69
|
+
* if the timer wins; its own `catch` below means it can never surface as
|
|
70
|
+
* an unhandled rejection whenever it does finish.
|
|
71
|
+
*/
|
|
72
|
+
export const safeAudit = async (options, entry) => {
|
|
73
|
+
const audit = options.ports.audit;
|
|
74
|
+
if (!audit)
|
|
75
|
+
return;
|
|
76
|
+
await runAuditBounded(() => audit(entry), options.auditTimeoutMs ?? DEFAULT_AUDIT_TIMEOUT_MS);
|
|
77
|
+
};
|
|
78
|
+
/** True when `scope` is unset, granted, or covered by the `"*"` wildcard scope. */
|
|
79
|
+
export const hasScope = (principal, scope) => {
|
|
80
|
+
if (!scope)
|
|
81
|
+
return true;
|
|
82
|
+
return principal.scopes.includes(scope) || principal.scopes.includes("*");
|
|
83
|
+
};
|
|
84
|
+
//# sourceMappingURL=methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/mcp/methods.ts"],"names":[],"mappings":"AAAA,OAAO,EAA+B,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AACvF,OAAO,EAAE,wBAAwB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC1F,OAAO,EACL,0BAA0B,EAC1B,oBAAoB,EAGpB,QAAQ,GACT,MAAM,cAAc,CAAC;AA8FtB,wEAAwE;AACxE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,YAAY,EAAE,cAAc;IAC5B,gBAAgB,EAAE,oBAAoB;IACtC,gBAAgB,EAAE,oBAAoB;IACtC,WAAW,EAAE,cAAc;IAC3B,YAAY,EAAE,eAAe;CACrB,CAAC;AAEX,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC;IAC5C,YAAY;IACZ,MAAM;IACN,2BAA2B;IAC3B,aAAa;CACd,CAAC,CAAC;AAEH;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,IAAoB,EAAW,EAAE;IAC9D,IAAI,IAAI,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,IAAI,CAAC,MAAM,KAAK,SAAS,IAAI,QAAQ,IAAI,IAAI,CAAC,CAAC;IAC5F,CAAC;IACD,OAAO,CACL,CAAC,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;QAC7E,IAAI,CAAC,MAAM,KAAK,aAAa,CAC9B,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CACpC,OAAgC,EAChC,OAAgB,EACQ,EAAE,CAC1B,OAAO,OAAO,CAAC,eAAe,KAAK,UAAU;IAC3C,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC,OAAO,CAAC;IAClC,CAAC,CAAC,OAAO,CAAC,eAAe,CAAC;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAC1B,eAAuC,EACvC,OAAO,GAAG,cAAc,EACxB,KAAgB,IAAI,EACV,EAAE,CACZ,YAAY,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,oBAAoB,EAAE,OAAO,CAAC;IACjD,MAAM,EAAE,GAAG;IACX,OAAO,EAAE,EAAE,kBAAkB,EAAE,qBAAqB,CAAC,eAAe,CAAC,EAAE;CACxE,CAAC,CAAC;AAEL;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,eAAuC,EACvC,KAAa,EACb,KAAgB,IAAI,EACV,EAAE,CACZ,YAAY,CAAC;IACX,IAAI,EAAE,QAAQ,CAAC,EAAE,EAAE,0BAA0B,EAAE,kBAAkB,KAAK,EAAE,CAAC;IACzE,MAAM,EAAE,GAAG;IACX,OAAO,EAAE;QACP,kBAAkB,EAAE,qBAAqB,CAAC;YACxC,GAAG,eAAe;YAClB,KAAK,EAAE,oBAAoB;YAC3B,KAAK;SACN,CAAC;KACH;CACF,CAAC,CAAC;AAEL;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAC5B,OAAgC,EAChC,KAAiB,EACF,EAAE;IACjB,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC;IAClC,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,MAAM,eAAe,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,cAAc,IAAI,wBAAwB,CAAC,CAAC;AAChG,CAAC,CAAC;AAEF,mFAAmF;AACnF,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,SAAoB,EAAE,KAAyB,EAAW,EAAE;IACnF,IAAI,CAAC,KAAK;QAAE,OAAO,IAAI,CAAC;IACxB,OAAO,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;AAC5E,CAAC,CAAC"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export declare const PROTOCOL_VERSIONS: Set<string>;
|
|
2
2
|
/**
|
|
3
3
|
* Answered on `initialize` when the client's requested version is missing
|
|
4
|
-
* or unrecognized
|
|
5
|
-
* server supports, preferring the latest — not the oldest one, which is
|
|
6
|
-
* what this constant did before.
|
|
4
|
+
* or unrecognized: per the spec, the latest version this server supports.
|
|
7
5
|
*/
|
|
8
6
|
export declare const DEFAULT_PROTOCOL_VERSION = "2025-06-18";
|
|
9
7
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.d.ts","sourceRoot":"","sources":["../../src/mcp/protocol.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,aAAsD,CAAC;AAErF;;;GAGG;AACH,eAAO,MAAM,wBAAwB,eAAe,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,eAAe,CAAC;AAE5D,eAAO,MAAM,mBAAmB,GAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAG,MAMtE,CAAC"}
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
export const PROTOCOL_VERSIONS = new Set(["2024-11-05", "2025-03-26", "2025-06-18"]);
|
|
2
2
|
/**
|
|
3
3
|
* Answered on `initialize` when the client's requested version is missing
|
|
4
|
-
* or unrecognized
|
|
5
|
-
* server supports, preferring the latest — not the oldest one, which is
|
|
6
|
-
* what this constant did before.
|
|
4
|
+
* or unrecognized: per the spec, the latest version this server supports.
|
|
7
5
|
*/
|
|
8
6
|
export const DEFAULT_PROTOCOL_VERSION = "2025-06-18";
|
|
9
7
|
/**
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"protocol.js","sourceRoot":"","sources":["../../src/mcp/protocol.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,iBAAiB,GAAG,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC,CAAC;AAErF;;;GAGG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AAErD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,+BAA+B,GAAG,YAAY,CAAC;AAE5D,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAgC,EAAU,EAAE;IAC9E,MAAM,SAAS,GAAG,MAAM,EAAE,eAAe,CAAC;IAC1C,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACtE,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,wBAAwB,CAAC;AAClC,CAAC,CAAC"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { JsonSchema } from "./validate.js";
|
|
2
|
+
export type ToolResult = {
|
|
3
|
+
content: Array<{
|
|
4
|
+
type: "text";
|
|
5
|
+
text: string;
|
|
6
|
+
}>;
|
|
7
|
+
isError?: boolean | undefined;
|
|
8
|
+
};
|
|
9
|
+
export type ToolHandler<TCtx> = (ctx: TCtx, args: Record<string, unknown>) => Promise<ToolResult | string> | ToolResult | string;
|
|
10
|
+
export type ToolDef<TCtx> = {
|
|
11
|
+
name: string;
|
|
12
|
+
description: string;
|
|
13
|
+
inputSchema: JsonSchema;
|
|
14
|
+
/**
|
|
15
|
+
* Required scope, or `undefined`/omitted for "any authenticated
|
|
16
|
+
* principal, whatever its scopes." On a `createMcpApp` server advertising
|
|
17
|
+
* more than one scope, an omitted `scope` is a construction-time error —
|
|
18
|
+
* see `assertToolScopesConfigured` — precisely because "any authenticated
|
|
19
|
+
* principal" silently includes a principal with zero scopes, which is
|
|
20
|
+
* rarely the intent on a multi-scope server. Pass `scope: null` to state
|
|
21
|
+
* that intentionally instead of by omission.
|
|
22
|
+
*/
|
|
23
|
+
scope?: string | null | undefined;
|
|
24
|
+
handler: ToolHandler<TCtx>;
|
|
25
|
+
};
|
|
26
|
+
export type ToolListEntry = {
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
inputSchema: JsonSchema;
|
|
30
|
+
};
|
|
31
|
+
export type ToolRegistry<TCtx> = {
|
|
32
|
+
/**
|
|
33
|
+
* `allowScope`, when passed, is consulted per tool with that tool's
|
|
34
|
+
* `scope` — omit a tool by returning `false`. Lets a caller (see
|
|
35
|
+
* `McpHandlerOptions.hideToolsOutsideScope`) filter `tools/list` by a
|
|
36
|
+
* principal's granted scopes without the registry itself knowing what a
|
|
37
|
+
* "principal" or "scope check" is — it only ever sees the raw `scope`
|
|
38
|
+
* value already on each `ToolDef`.
|
|
39
|
+
*/
|
|
40
|
+
list: (allowScope?: (scope: string | null | undefined) => boolean) => ToolListEntry[];
|
|
41
|
+
get: (name: string) => ToolDef<TCtx> | undefined;
|
|
42
|
+
call: (name: string, ctx: TCtx, args: Record<string, unknown>) => Promise<ToolResult>;
|
|
43
|
+
};
|
|
44
|
+
export type RegistryOptions = {
|
|
45
|
+
/**
|
|
46
|
+
* Validate tools/call args against inputSchema. Default **true** since 2.0 —
|
|
47
|
+
* forgetting this was a silent injection path into handlers. Set `false`
|
|
48
|
+
* only when you intentionally skip schema checks.
|
|
49
|
+
*/
|
|
50
|
+
validateArgs?: boolean | undefined;
|
|
51
|
+
/**
|
|
52
|
+
* Map tool exceptions to client-visible text.
|
|
53
|
+
* Default: `"Tool execution failed"` (no exception leakage).
|
|
54
|
+
*/
|
|
55
|
+
onToolError?: ((error: unknown) => string) | undefined;
|
|
56
|
+
};
|
|
57
|
+
export declare const createToolRegistry: <TCtx>(tools: ToolDef<TCtx>[], options?: RegistryOptions) => ToolRegistry<TCtx>;
|
|
58
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/mcp/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAGhD,MAAM,MAAM,UAAU,GAAG;IACvB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/C,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;CAC/B,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,IAAI,IAAI,CAC9B,GAAG,EAAE,IAAI,EACT,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAC1B,OAAO,CAAC,UAAU,GAAG,MAAM,CAAC,GAAG,UAAU,GAAG,MAAM,CAAC;AAExD,MAAM,MAAM,OAAO,CAAC,IAAI,IAAI;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;IACxB;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC;IAClC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;CAC5B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,UAAU,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,YAAY,CAAC,IAAI,IAAI;IAC/B;;;;;;;OAOG;IACH,IAAI,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,KAAK,OAAO,KAAK,aAAa,EAAE,CAAC;IACtF,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC;IACjD,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;CACvF,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACnC;;;OAGG;IACH,WAAW,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,KAAK,MAAM,CAAC,GAAG,SAAS,CAAC;CACxD,CAAC;AA8DF,eAAO,MAAM,kBAAkB,GAAI,IAAI,EACrC,OAAO,OAAO,CAAC,IAAI,CAAC,EAAE,EACtB,UAAS,eAAoB,KAC5B,YAAY,CAAC,IAAI,CAqCnB,CAAC"}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { missingObjectType, unsupportedKeywords, validateAgainstSchema } from "./validate.js";
|
|
2
|
+
const DEFAULT_TOOL_ERROR = "Tool execution failed";
|
|
3
|
+
/**
|
|
4
|
+
* Map a tool exception to client-visible text.
|
|
5
|
+
* A throwing or non-string `onToolError` falls back to the redacted default —
|
|
6
|
+
* a mapper must never turn a tool failure into a transport failure.
|
|
7
|
+
*/
|
|
8
|
+
const resolveToolError = (caught, onToolError) => {
|
|
9
|
+
if (!onToolError)
|
|
10
|
+
return DEFAULT_TOOL_ERROR;
|
|
11
|
+
try {
|
|
12
|
+
const mapped = onToolError(caught);
|
|
13
|
+
return typeof mapped === "string" && mapped.length > 0 ? mapped : DEFAULT_TOOL_ERROR;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return DEFAULT_TOOL_ERROR;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
const asToolResult = (out) => {
|
|
20
|
+
if (typeof out === "string") {
|
|
21
|
+
return { content: [{ type: "text", text: out }], isError: false };
|
|
22
|
+
}
|
|
23
|
+
return out;
|
|
24
|
+
};
|
|
25
|
+
const errorResult = (message) => ({
|
|
26
|
+
content: [{ type: "text", text: message }],
|
|
27
|
+
isError: true,
|
|
28
|
+
});
|
|
29
|
+
/** Throws with every violation listed at once, rather than failing on the first tool found. */
|
|
30
|
+
const assertToolSchemasValid = (tools) => {
|
|
31
|
+
const keywordViolations = tools.flatMap((tool) => unsupportedKeywords(tool.inputSchema).map((path) => `${tool.name}: unsupported JSON Schema keyword at ${path}`));
|
|
32
|
+
if (keywordViolations.length > 0) {
|
|
33
|
+
throw new Error(`validateArgs: true but inputSchema uses unsupported keywords:\n` +
|
|
34
|
+
keywordViolations.join("\n") +
|
|
35
|
+
"\nRemove the keyword, enforce it in the handler, or set validateArgs: false");
|
|
36
|
+
}
|
|
37
|
+
// `properties`/`required` without `type: "object"` validates nothing at
|
|
38
|
+
// that node, and passes the keyword check above. See `missingObjectType`.
|
|
39
|
+
const typeViolations = tools.flatMap((tool) => missingObjectType(tool.inputSchema).map((path) => `${tool.name}: ${path} uses properties/required without type: "object"`));
|
|
40
|
+
if (typeViolations.length > 0) {
|
|
41
|
+
throw new Error(`validateArgs: true but inputSchema implies an object shape without declaring it:\n` +
|
|
42
|
+
typeViolations.join("\n") +
|
|
43
|
+
'\nAdd type: "object" (or include it in a union), or set validateArgs: false');
|
|
44
|
+
}
|
|
45
|
+
};
|
|
46
|
+
export const createToolRegistry = (tools, options = {}) => {
|
|
47
|
+
const byName = new Map(tools.map((t) => [t.name, t]));
|
|
48
|
+
if (byName.size !== tools.length) {
|
|
49
|
+
throw new Error("duplicate tool names in registry");
|
|
50
|
+
}
|
|
51
|
+
const validateArgs = options.validateArgs !== false;
|
|
52
|
+
if (validateArgs)
|
|
53
|
+
assertToolSchemasValid(tools);
|
|
54
|
+
return {
|
|
55
|
+
list: (allowScope) => tools
|
|
56
|
+
.filter((tool) => !allowScope || allowScope(tool.scope))
|
|
57
|
+
.map(({ name, description, inputSchema }) => ({
|
|
58
|
+
name,
|
|
59
|
+
description,
|
|
60
|
+
inputSchema,
|
|
61
|
+
})),
|
|
62
|
+
get: (name) => byName.get(name),
|
|
63
|
+
call: async (name, ctx, args) => {
|
|
64
|
+
const tool = byName.get(name);
|
|
65
|
+
if (!tool)
|
|
66
|
+
return errorResult(`Unknown tool: ${name}`);
|
|
67
|
+
if (validateArgs) {
|
|
68
|
+
const errors = validateAgainstSchema(args, tool.inputSchema);
|
|
69
|
+
if (errors.length > 0)
|
|
70
|
+
return errorResult(errors.join("; "));
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
return asToolResult(await tool.handler(ctx, args));
|
|
74
|
+
}
|
|
75
|
+
catch (caught) {
|
|
76
|
+
return errorResult(resolveToolError(caught, options.onToolError));
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
};
|
|
81
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/mcp/registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** JSON-RPC method handlers and authenticated dispatch. */
|
|
2
|
+
import { type JsonRpcRequest } from "./jsonrpc.js";
|
|
3
|
+
import { type ResolvedMcpHandlerOptions } from "./methods.js";
|
|
4
|
+
export declare const dispatchRpc: <TCtx>(input: {
|
|
5
|
+
req: Request;
|
|
6
|
+
body: JsonRpcRequest;
|
|
7
|
+
options: ResolvedMcpHandlerOptions<TCtx>;
|
|
8
|
+
/** Request start (captured in `createMcpHandler.fetch`), for denial-path audit timing. */
|
|
9
|
+
startedAt: number;
|
|
10
|
+
}) => Promise<Response>;
|
|
11
|
+
//# sourceMappingURL=rpc-handlers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc-handlers.d.ts","sourceRoot":"","sources":["../../src/mcp/rpc-handlers.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAI3D,OAAO,EAIL,KAAK,cAAc,EAGpB,MAAM,cAAc,CAAC;AACtB,OAAO,EAOL,KAAK,yBAAyB,EAI/B,MAAM,cAAc,CAAC;AA8ItB,eAAO,MAAM,WAAW,GAAU,IAAI,EAAE,OAAO;IAC7C,GAAG,EAAE,OAAO,CAAC;IACb,IAAI,EAAE,cAAc,CAAC;IACrB,OAAO,EAAE,yBAAyB,CAAC,IAAI,CAAC,CAAC;IACzC,0FAA0F;IAC1F,SAAS,EAAE,MAAM,CAAC;CACnB,KAAG,OAAO,CAAC,QAAQ,CAkCnB,CAAC"}
|