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
package/dist/app.js
CHANGED
|
@@ -6,35 +6,45 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { parseBearer } from "./auth/bearer.js";
|
|
8
8
|
import { assertClientsConfigured, authMethodsFor, DEFAULT_CLIENTS, hasDynamicClient, redirectUrisFor, } from "./clients.js";
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
9
|
+
import { errorReason, INTERNAL_ERROR, jsonResponse } from "./http/http.js";
|
|
10
|
+
import { createMcpHandler } from "./mcp/dispatch.js";
|
|
11
|
+
import { safeAudit } from "./mcp/methods.js";
|
|
12
|
+
import { createToolRegistry } from "./mcp/registry.js";
|
|
13
|
+
import { safeOAuthAudit } from "./oauth/audit.js";
|
|
14
|
+
import { DEFAULT_SCOPE } from "./oauth/constants.js";
|
|
15
|
+
import { canonicalResource, DEFAULT_RESOURCE_PATH, normalizeConfiguredPath, resourcesEqual, } from "./oauth/policy/resource.js";
|
|
12
16
|
import { createOAuthRouter } from "./oauth/router.js";
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
17
|
+
import { pickDefined } from "./util/defined.js";
|
|
18
|
+
/**
|
|
19
|
+
* On a multi-scope server a tool with no `scope` is callable by a principal
|
|
20
|
+
* holding none of the advertised scopes, silently defeating
|
|
21
|
+
* `defaultScopes: []`. Single-scope servers have no such ambiguity. Pass
|
|
22
|
+
* `scope: null` on a tool to state the omission on purpose.
|
|
23
|
+
*/
|
|
24
|
+
const assertToolScopesConfigured = (tools, scopes) => {
|
|
25
|
+
if (scopes.length <= 1)
|
|
26
|
+
return;
|
|
27
|
+
const unscoped = tools.filter((tool) => tool.scope === undefined).map((tool) => tool.name);
|
|
28
|
+
if (unscoped.length === 0)
|
|
29
|
+
return;
|
|
30
|
+
throw new Error(`scopes has more than one entry (${scopes.join(", ")}), but these tools have no ` +
|
|
31
|
+
`scope and would be callable by any authenticated principal regardless of what ` +
|
|
32
|
+
`scopes it holds: ${unscoped.join(", ")}. Set scope: "<one of the entries above>" ` +
|
|
33
|
+
`on each, or scope: null to state the omission on purpose.`);
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* The audience check lives here, not in user code — a token minted for
|
|
37
|
+
* another MCP server must never be accepted by this one.
|
|
38
|
+
*/
|
|
39
|
+
const buildAuthenticate = (options, resourcePath) => {
|
|
40
|
+
return async (request) => {
|
|
41
|
+
const token = parseBearer(request.headers.get("authorization"));
|
|
32
42
|
if (!token)
|
|
33
43
|
return null;
|
|
34
|
-
const verified = await options.auth.verifyToken(token,
|
|
44
|
+
const verified = await options.auth.verifyToken(token, request);
|
|
35
45
|
if (!verified)
|
|
36
46
|
return null;
|
|
37
|
-
const expected = canonicalResource(new URL(
|
|
47
|
+
const expected = canonicalResource(new URL(request.url).origin, resourcePath);
|
|
38
48
|
if (!resourcesEqual(verified.audience, expected))
|
|
39
49
|
return null;
|
|
40
50
|
return {
|
|
@@ -43,33 +53,60 @@ export const createMcpApp = (options) => {
|
|
|
43
53
|
...(verified.claims !== undefined ? { claims: verified.claims } : {}),
|
|
44
54
|
};
|
|
45
55
|
};
|
|
46
|
-
|
|
56
|
+
};
|
|
57
|
+
/** Top-level `audit` wraps MCP + OAuth; `auth.audit` wins for OAuth if both set. */
|
|
58
|
+
const buildAuditAdapters = (options) => {
|
|
59
|
+
const unifiedAudit = options.audit;
|
|
60
|
+
const toMcpAudit = unifiedAudit !== undefined
|
|
61
|
+
? (entry) => unifiedAudit({ source: "mcp", ...entry })
|
|
62
|
+
: undefined;
|
|
63
|
+
const oauthAudit = options.auth.audit ??
|
|
64
|
+
(unifiedAudit !== undefined
|
|
65
|
+
? (entry) => unifiedAudit({ source: "oauth", ...entry })
|
|
66
|
+
: undefined);
|
|
67
|
+
return { toMcpAudit, oauthAudit };
|
|
68
|
+
};
|
|
69
|
+
const buildMcpHandlerOptions = (options, input) => {
|
|
70
|
+
const { resourcePath, realm, registry, authenticate, toMcpAudit } = input;
|
|
71
|
+
return {
|
|
47
72
|
registry,
|
|
48
73
|
serverInfo: options.serverInfo,
|
|
49
|
-
...(options
|
|
50
|
-
|
|
51
|
-
|
|
74
|
+
...pickDefined(options, [
|
|
75
|
+
"instructions",
|
|
76
|
+
"auditTimeoutMs",
|
|
77
|
+
"allowedRequestOrigins",
|
|
78
|
+
"hideToolsOutsideScope",
|
|
79
|
+
]),
|
|
80
|
+
wwwAuthenticate: (request) => ({
|
|
52
81
|
realm,
|
|
53
|
-
resourceMetadataUrl: `${new URL(
|
|
82
|
+
resourceMetadataUrl: `${new URL(request.url).origin}/.well-known/oauth-protected-resource${resourcePath}`,
|
|
54
83
|
}),
|
|
55
84
|
ports: {
|
|
56
85
|
authenticate,
|
|
57
86
|
context: options.context ?? (() => ({})),
|
|
58
|
-
...(
|
|
87
|
+
...(toMcpAudit !== undefined ? { audit: toMcpAudit } : {}),
|
|
59
88
|
},
|
|
60
|
-
}
|
|
61
|
-
|
|
89
|
+
};
|
|
90
|
+
};
|
|
91
|
+
const buildOAuthOptions = (options, input) => {
|
|
92
|
+
const { resourcePath, oauthPath, realm, clients, oauthAudit } = input;
|
|
93
|
+
return {
|
|
62
94
|
resourcePath,
|
|
63
95
|
oauthPath,
|
|
64
96
|
realm,
|
|
65
|
-
...(options
|
|
66
|
-
|
|
97
|
+
...pickDefined(options, [
|
|
98
|
+
"scopes",
|
|
99
|
+
"defaultScopes",
|
|
100
|
+
"auditTimeoutMs",
|
|
101
|
+
"allowInMemoryCodeStore",
|
|
102
|
+
"cimd",
|
|
103
|
+
"cimdCache",
|
|
104
|
+
"cimdLookup",
|
|
105
|
+
"requireRegisteredClients",
|
|
106
|
+
"consent",
|
|
107
|
+
]),
|
|
67
108
|
tokenEndpointAuthMethods: authMethodsFor(clients),
|
|
68
109
|
allowUnregisteredClients: hasDynamicClient(clients),
|
|
69
|
-
...(options.requireRegisteredClients !== undefined
|
|
70
|
-
? { requireRegisteredClients: options.requireRegisteredClients }
|
|
71
|
-
: {}),
|
|
72
|
-
...(options.consent !== undefined ? { consent: options.consent } : {}),
|
|
73
110
|
redirect: {
|
|
74
111
|
// Client profiles are the source of truth for callbacks.
|
|
75
112
|
extra: [...redirectUrisFor(clients), ...(options.extraRedirectUris ?? [])],
|
|
@@ -81,34 +118,77 @@ export const createMcpApp = (options) => {
|
|
|
81
118
|
resolveUser: options.auth.resolveUser,
|
|
82
119
|
loginUrl: options.auth.loginUrl,
|
|
83
120
|
mintAccessToken: options.auth.mintAccessToken,
|
|
84
|
-
...(options.auth
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
...(
|
|
121
|
+
...pickDefined(options.auth, [
|
|
122
|
+
"refreshAccessToken",
|
|
123
|
+
"revokeToken",
|
|
124
|
+
"codeStore",
|
|
125
|
+
"clientStore",
|
|
126
|
+
]),
|
|
127
|
+
...(oauthAudit !== undefined ? { audit: oauthAudit } : {}),
|
|
91
128
|
},
|
|
129
|
+
};
|
|
130
|
+
};
|
|
131
|
+
const createAppFetch = (parts) => async (request) => {
|
|
132
|
+
try {
|
|
133
|
+
const oauthResponse = await parts.oauth.tryHandle(request);
|
|
134
|
+
if (oauthResponse)
|
|
135
|
+
return oauthResponse;
|
|
136
|
+
const requestPath = normalizeConfiguredPath(new URL(request.url).pathname);
|
|
137
|
+
if (requestPath === parts.resourcePath)
|
|
138
|
+
return await parts.handler.fetch(request);
|
|
139
|
+
return jsonResponse({ data: { error: "Not found" }, status: 404 });
|
|
140
|
+
}
|
|
141
|
+
catch (caught) {
|
|
142
|
+
// Defense in depth: `oauth` and `handler` already turn port failures
|
|
143
|
+
// into responses, but `fetch` must never reject, and this path is
|
|
144
|
+
// audited so it is never silent.
|
|
145
|
+
const reason = errorReason(caught);
|
|
146
|
+
await safeOAuthAudit(parts.oauthOptions, { event: "server_error", reason });
|
|
147
|
+
await safeAudit(parts.mcpHandlerOptions, {
|
|
148
|
+
method: "",
|
|
149
|
+
ok: false,
|
|
150
|
+
error: reason,
|
|
151
|
+
durationMs: 0,
|
|
152
|
+
});
|
|
153
|
+
return jsonResponse({ data: { error: INTERNAL_ERROR }, status: 500 });
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
export const createMcpApp = (options) => {
|
|
157
|
+
// "/mcp/" and "/mcp" must route identically.
|
|
158
|
+
const resourcePath = normalizeConfiguredPath(options.resourcePath ?? DEFAULT_RESOURCE_PATH);
|
|
159
|
+
// Avoid "//oauth" when the resource is mounted at "/".
|
|
160
|
+
const oauthPath = options.oauthPath ?? (resourcePath === "/" ? "/oauth" : `${resourcePath}/oauth`);
|
|
161
|
+
const clients = options.clients ?? DEFAULT_CLIENTS;
|
|
162
|
+
const realm = options.realm ?? options.serverInfo.name;
|
|
163
|
+
assertClientsConfigured(clients, options.auth.clientStore);
|
|
164
|
+
assertToolScopesConfigured(options.tools, options.scopes ?? [DEFAULT_SCOPE]);
|
|
165
|
+
const registry = createToolRegistry(options.tools, pickDefined(options, ["validateArgs", "onToolError"]));
|
|
166
|
+
const authenticate = buildAuthenticate(options, resourcePath);
|
|
167
|
+
const { toMcpAudit, oauthAudit } = buildAuditAdapters(options);
|
|
168
|
+
// Built once and shared with the `fetch` catch path below, so the fallback
|
|
169
|
+
// audit sees exactly the same ports/timeout as the handler itself.
|
|
170
|
+
const mcpHandlerOptions = buildMcpHandlerOptions(options, {
|
|
171
|
+
resourcePath,
|
|
172
|
+
realm,
|
|
173
|
+
registry,
|
|
174
|
+
authenticate,
|
|
175
|
+
toMcpAudit,
|
|
176
|
+
});
|
|
177
|
+
const oauthOptions = buildOAuthOptions(options, {
|
|
178
|
+
resourcePath,
|
|
179
|
+
oauthPath,
|
|
180
|
+
realm,
|
|
181
|
+
clients,
|
|
182
|
+
oauthAudit,
|
|
92
183
|
});
|
|
93
184
|
return {
|
|
94
|
-
fetch:
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
return await handler.fetch(request);
|
|
102
|
-
}
|
|
103
|
-
return jsonResponse({ error: "Not found" }, 404);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
// Both `oauth` and `handler` already turn port failures into a
|
|
107
|
-
// Response themselves — this is defense in depth, not the primary
|
|
108
|
-
// guard. `fetch` must never reject.
|
|
109
|
-
return jsonResponse({ error: INTERNAL_ERROR }, 500);
|
|
110
|
-
}
|
|
111
|
-
},
|
|
185
|
+
fetch: createAppFetch({
|
|
186
|
+
resourcePath,
|
|
187
|
+
oauth: createOAuthRouter(oauthOptions),
|
|
188
|
+
oauthOptions,
|
|
189
|
+
handler: createMcpHandler(mcpHandlerOptions),
|
|
190
|
+
mcpHandlerOptions,
|
|
191
|
+
}),
|
|
112
192
|
};
|
|
113
193
|
};
|
|
114
194
|
//# sourceMappingURL=app.js.map
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/audit.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { UnifiedAuditEntry } from "./app-options.js";
|
|
2
2
|
/**
|
|
3
3
|
* Convenience `audit` sink that logs each entry to the console.
|
|
4
4
|
*
|
|
@@ -10,9 +10,9 @@ import type { AuditEntry } from "./methods.js";
|
|
|
10
10
|
* createMcpApp({ ..., audit: consoleAudit })
|
|
11
11
|
* createMcpApp({ ..., audit: (entry) => { void insert(entry) } })
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* MCP failures (`ok: false`) go to `console.error`; MCP successes and
|
|
14
|
+
* OAuth events go to `console.log`. Entries never carry raw exceptions or
|
|
15
|
+
* stack traces (see `AuditEntry` / `OAuthAuditEntry`).
|
|
16
16
|
*/
|
|
17
|
-
export declare const consoleAudit: (entry:
|
|
17
|
+
export declare const consoleAudit: (entry: UnifiedAuditEntry) => void;
|
|
18
18
|
//# sourceMappingURL=audit.d.ts.map
|
package/dist/audit.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,iBAAiB,KAAG,IA8BvD,CAAC"}
|
package/dist/audit.js
CHANGED
|
@@ -9,13 +9,25 @@
|
|
|
9
9
|
* createMcpApp({ ..., audit: consoleAudit })
|
|
10
10
|
* createMcpApp({ ..., audit: (entry) => { void insert(entry) } })
|
|
11
11
|
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
12
|
+
* MCP failures (`ok: false`) go to `console.error`; MCP successes and
|
|
13
|
+
* OAuth events go to `console.log`. Entries never carry raw exceptions or
|
|
14
|
+
* stack traces (see `AuditEntry` / `OAuthAuditEntry`).
|
|
15
15
|
*/
|
|
16
16
|
export const consoleAudit = (entry) => {
|
|
17
|
+
if (entry.source === "oauth") {
|
|
18
|
+
const line = [
|
|
19
|
+
`[mcp-trellis] oauth`,
|
|
20
|
+
entry.event,
|
|
21
|
+
entry.clientId ? `client=${entry.clientId}` : undefined,
|
|
22
|
+
`reason=${entry.reason}`,
|
|
23
|
+
]
|
|
24
|
+
.filter(Boolean)
|
|
25
|
+
.join(" ");
|
|
26
|
+
console.log(line);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
17
29
|
const line = [
|
|
18
|
-
`[mcp-trellis] ${entry.method || "(transport)"}`,
|
|
30
|
+
`[mcp-trellis] mcp ${entry.method || "(transport)"}`,
|
|
19
31
|
entry.tool ? `tool=${entry.tool}` : undefined,
|
|
20
32
|
entry.ok ? "ok" : "fail",
|
|
21
33
|
`${entry.durationMs}ms`,
|
|
@@ -24,11 +36,10 @@ export const consoleAudit = (entry) => {
|
|
|
24
36
|
]
|
|
25
37
|
.filter(Boolean)
|
|
26
38
|
.join(" ");
|
|
27
|
-
if (entry.ok) {
|
|
28
|
-
console.log(line);
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
39
|
+
if (!entry.ok) {
|
|
31
40
|
console.error(line);
|
|
41
|
+
return;
|
|
32
42
|
}
|
|
43
|
+
console.log(line);
|
|
33
44
|
};
|
|
34
45
|
//# sourceMappingURL=audit.js.map
|
package/dist/audit.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,
|
|
1
|
+
{"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAQ,EAAE;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG;YACX,qBAAqB;YACrB,KAAK,CAAC,KAAK;YACX,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;YACvD,UAAU,KAAK,CAAC,MAAM,EAAE;SACzB;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG;QACX,qBAAqB,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE;QACpD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;QAC7C,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QACxB,GAAG,KAAK,CAAC,UAAU,IAAI;QACvB,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QAC3D,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;KACjD;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC,CAAC"}
|
package/dist/auth/bearer.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
/** Bearer auth helpers for MCP (RFC 9728 WWW-Authenticate). */
|
|
2
|
-
export declare const BEARER_PREFIX = "Bearer ";
|
|
3
2
|
/** Above any real JWT / HMAC sig; prevents allocation DoS on attacker input. */
|
|
4
3
|
export declare const MAX_COMPARE_LENGTH = 4096;
|
|
5
4
|
export declare const parseBearer: (authorization: string | null) => string | null;
|
|
@@ -14,6 +13,10 @@ export type WwwAuthenticateOptions = {
|
|
|
14
13
|
realm: string;
|
|
15
14
|
/** Absolute URL to RFC 9728 protected resource metadata. */
|
|
16
15
|
resourceMetadataUrl: string;
|
|
16
|
+
/** RFC 6750 §3.1 error code, e.g. `"insufficient_scope"`. Omitted on a plain 401. */
|
|
17
|
+
error?: string | undefined;
|
|
18
|
+
/** RFC 6750 §3.1 — the scope(s) that would satisfy the request. Paired with `error`. */
|
|
19
|
+
scope?: string | undefined;
|
|
17
20
|
};
|
|
18
21
|
export declare const wwwAuthenticateHeader: (options: WwwAuthenticateOptions) => string;
|
|
19
22
|
/** RFC 6750 §2.3 uses `access_token`; also reject legacy `token`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;
|
|
1
|
+
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAI/D,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAKvC,eAAO,MAAM,WAAW,GAAI,eAAe,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAMnE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAetD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,EAAE,KAAG,OACN,CAAC;AAE9D,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAMF,eAAO,MAAM,qBAAqB,GAAI,SAAS,sBAAsB,KAAG,MAQvE,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,GAAI,KAAK,GAAG,KAAG,OAC2B,CAAC"}
|
package/dist/auth/bearer.js
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
/** Bearer auth helpers for MCP (RFC 9728 WWW-Authenticate). */
|
|
2
|
-
|
|
2
|
+
const BEARER_PREFIX = "Bearer ";
|
|
3
3
|
/** Above any real JWT / HMAC sig; prevents allocation DoS on attacker input. */
|
|
4
4
|
export const MAX_COMPARE_LENGTH = 4096;
|
|
5
|
+
/** RFC 7235 §2.1 — the auth-scheme token is case-insensitive ("bearer", "BEARER", "Bearer" all valid). */
|
|
6
|
+
const BEARER_SCHEME_RE = /^bearer\s+/i;
|
|
5
7
|
export const parseBearer = (authorization) => {
|
|
6
|
-
if (!authorization
|
|
8
|
+
if (!authorization)
|
|
7
9
|
return null;
|
|
8
|
-
const
|
|
10
|
+
const match = BEARER_SCHEME_RE.exec(authorization);
|
|
11
|
+
if (!match)
|
|
12
|
+
return null;
|
|
13
|
+
const token = authorization.slice(match[0].length).trim();
|
|
9
14
|
return token.length > 0 ? token : null;
|
|
10
15
|
};
|
|
11
16
|
/**
|
|
@@ -31,7 +36,17 @@ export const timingSafeEqual = (a, b) => {
|
|
|
31
36
|
return diff === 0;
|
|
32
37
|
};
|
|
33
38
|
export const matchesAny = (presented, accepted) => accepted.some((token) => timingSafeEqual(presented, token));
|
|
34
|
-
|
|
39
|
+
/** RFC 6750 / RFC 7235 quoted-string — escape `\` and `"` so host-controlled values cannot break or inject header params. */
|
|
40
|
+
const escapeWwwAuthenticateValue = (value) => value.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
|
|
41
|
+
export const wwwAuthenticateHeader = (options) => {
|
|
42
|
+
const parts = [
|
|
43
|
+
`realm="${escapeWwwAuthenticateValue(options.realm)}"`,
|
|
44
|
+
`resource_metadata="${escapeWwwAuthenticateValue(options.resourceMetadataUrl)}"`,
|
|
45
|
+
...(options.error ? [`error="${escapeWwwAuthenticateValue(options.error)}"`] : []),
|
|
46
|
+
...(options.scope ? [`scope="${escapeWwwAuthenticateValue(options.scope)}"`] : []),
|
|
47
|
+
];
|
|
48
|
+
return `${BEARER_PREFIX}${parts.join(", ")}`;
|
|
49
|
+
};
|
|
35
50
|
/** RFC 6750 §2.3 uses `access_token`; also reject legacy `token`. */
|
|
36
51
|
export const rejectQueryToken = (url) => url.searchParams.has("token") || url.searchParams.has("access_token");
|
|
37
52
|
//# sourceMappingURL=bearer.js.map
|
package/dist/auth/bearer.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,MAAM,
|
|
1
|
+
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience auth: one secret seals OAuth codes (via `codeSecret`) and
|
|
3
|
+
* signs short-lived access tokens. Domain separation is HKDF, not luck —
|
|
4
|
+
* access-token HMAC uses `mcp-trellis:signed-access-token:v1`, distinct from
|
|
5
|
+
* the sealed-code and client-secret-hash labels.
|
|
6
|
+
*
|
|
7
|
+
* ponytail: stateless tokens cannot be revoked before `exp`. No
|
|
8
|
+
* `refreshAccessToken` / `revokeToken` — `/revoke` stays unmounted and
|
|
9
|
+
* refresh unadvertised. Upgrade: supply those ports plus a store (see
|
|
10
|
+
* `examples/project-desk/src/tokens.ts`).
|
|
11
|
+
*/
|
|
12
|
+
import type { McpAppAuth } from "../app-options.js";
|
|
13
|
+
import type { CodeStore } from "../oauth/crypto/codes.js";
|
|
14
|
+
import type { OAuthUser } from "../oauth/types.js";
|
|
15
|
+
export type SignedTokenAuthOptions = {
|
|
16
|
+
secret: string;
|
|
17
|
+
resolveUser: (request: Request) => Promise<OAuthUser | null>;
|
|
18
|
+
loginUrl: (request: Request, nextPath: string) => string;
|
|
19
|
+
/** Access-token lifetime in seconds. Default 3600. Must be finite and > 0. */
|
|
20
|
+
ttlSeconds?: number;
|
|
21
|
+
/** Passthrough — production still needs a shared store across instances. */
|
|
22
|
+
codeStore?: CodeStore;
|
|
23
|
+
};
|
|
24
|
+
/** Builds a complete `McpAppAuth` from one secret plus your session resolver. */
|
|
25
|
+
export declare const signedTokenAuth: (options: SignedTokenAuthOptions) => McpAppAuth;
|
|
26
|
+
//# sourceMappingURL=signed-token.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-token.d.ts","sourceRoot":"","sources":["../../src/auth/signed-token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,mBAAmB,CAAC;AAEnE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,KAAK,EAAqC,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAMtF,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAAC;IAC7D,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,KAAK,MAAM,CAAC;IACzD,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB,CAAC;AA8EF,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,UAiBjE,CAAC"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convenience auth: one secret seals OAuth codes (via `codeSecret`) and
|
|
3
|
+
* signs short-lived access tokens. Domain separation is HKDF, not luck —
|
|
4
|
+
* access-token HMAC uses `mcp-trellis:signed-access-token:v1`, distinct from
|
|
5
|
+
* the sealed-code and client-secret-hash labels.
|
|
6
|
+
*
|
|
7
|
+
* ponytail: stateless tokens cannot be revoked before `exp`. No
|
|
8
|
+
* `refreshAccessToken` / `revokeToken` — `/revoke` stays unmounted and
|
|
9
|
+
* refresh unadvertised. Upgrade: supply those ports plus a store (see
|
|
10
|
+
* `examples/project-desk/src/tokens.ts`).
|
|
11
|
+
*/
|
|
12
|
+
import { bytesToBase64Url, fromBase64Url } from "../oauth/crypto/base64url.js";
|
|
13
|
+
import { hkdfKey } from "../oauth/crypto/hkdf.js";
|
|
14
|
+
const HKDF_INFO = "mcp-trellis:signed-access-token:v1";
|
|
15
|
+
const HMAC_SHA256 = { name: "HMAC", hash: "SHA-256", length: 256 };
|
|
16
|
+
const DEFAULT_TTL_SECONDS = 3600;
|
|
17
|
+
const accessKey = (secret, usage) => hkdfKey(secret, { info: HKDF_INFO, algorithm: HMAC_SHA256, usage });
|
|
18
|
+
const signPayload = async (secret, payload) => {
|
|
19
|
+
const key = await accessKey(secret, "sign");
|
|
20
|
+
const body = bytesToBase64Url(new TextEncoder().encode(JSON.stringify(payload)));
|
|
21
|
+
const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
|
|
22
|
+
return `${body}.${bytesToBase64Url(signature)}`;
|
|
23
|
+
};
|
|
24
|
+
const parsePayload = (raw) => {
|
|
25
|
+
if (raw === null || typeof raw !== "object")
|
|
26
|
+
return null;
|
|
27
|
+
const record = raw;
|
|
28
|
+
if (typeof record.userId !== "string" || typeof record.audience !== "string")
|
|
29
|
+
return null;
|
|
30
|
+
if (typeof record.exp !== "number" || !Number.isFinite(record.exp))
|
|
31
|
+
return null;
|
|
32
|
+
if (record.exp < Date.now())
|
|
33
|
+
return null;
|
|
34
|
+
if (!Array.isArray(record.scopes) || !record.scopes.every((s) => typeof s === "string")) {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
return {
|
|
38
|
+
userId: record.userId,
|
|
39
|
+
scopes: record.scopes,
|
|
40
|
+
audience: record.audience,
|
|
41
|
+
exp: record.exp,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
const verifyPayload = async (secret, token) => {
|
|
45
|
+
const parts = token.split(".");
|
|
46
|
+
if (parts.length !== 2)
|
|
47
|
+
return null;
|
|
48
|
+
const [body, signature] = parts;
|
|
49
|
+
if (!body || !signature)
|
|
50
|
+
return null;
|
|
51
|
+
try {
|
|
52
|
+
const key = await accessKey(secret, "verify");
|
|
53
|
+
const ok = await crypto.subtle.verify("HMAC", key, fromBase64Url(signature), new TextEncoder().encode(body));
|
|
54
|
+
if (!ok)
|
|
55
|
+
return null;
|
|
56
|
+
return parsePayload(JSON.parse(new TextDecoder().decode(fromBase64Url(body))));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
const mint = async (secret, ttlSeconds, input) => {
|
|
63
|
+
const scopes = input.scope.split(" ").filter(Boolean);
|
|
64
|
+
const accessToken = await signPayload(secret, {
|
|
65
|
+
userId: input.userId,
|
|
66
|
+
scopes,
|
|
67
|
+
audience: input.resource,
|
|
68
|
+
exp: Date.now() + ttlSeconds * 1000,
|
|
69
|
+
});
|
|
70
|
+
return { accessToken, expiresIn: ttlSeconds, scope: input.scope };
|
|
71
|
+
};
|
|
72
|
+
const toVerified = (payload) => ({
|
|
73
|
+
userId: payload.userId,
|
|
74
|
+
scopes: payload.scopes,
|
|
75
|
+
audience: payload.audience,
|
|
76
|
+
});
|
|
77
|
+
/** Builds a complete `McpAppAuth` from one secret plus your session resolver. */
|
|
78
|
+
export const signedTokenAuth = (options) => {
|
|
79
|
+
const ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;
|
|
80
|
+
if (!Number.isFinite(ttlSeconds) || ttlSeconds <= 0) {
|
|
81
|
+
throw new Error(`signedTokenAuth: ttlSeconds must be a finite number > 0 (got ${ttlSeconds})`);
|
|
82
|
+
}
|
|
83
|
+
const { secret } = options;
|
|
84
|
+
return {
|
|
85
|
+
codeSecret: secret,
|
|
86
|
+
resolveUser: options.resolveUser,
|
|
87
|
+
loginUrl: options.loginUrl,
|
|
88
|
+
mintAccessToken: (input) => mint(secret, ttlSeconds, input),
|
|
89
|
+
verifyToken: async (token) => {
|
|
90
|
+
const payload = await verifyPayload(secret, token);
|
|
91
|
+
return payload ? toVerified(payload) : null;
|
|
92
|
+
},
|
|
93
|
+
...(options.codeStore !== undefined ? { codeStore: options.codeStore } : {}),
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
//# sourceMappingURL=signed-token.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"signed-token.js","sourceRoot":"","sources":["../../src/auth/signed-token.ts"],"names":[],"mappings":"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"}
|
package/dist/clients.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* point: you name your clients, the library configures the AS to match.
|
|
7
7
|
*/
|
|
8
8
|
import { TOKEN_ENDPOINT_AUTH_METHODS } from "./oauth/constants.js";
|
|
9
|
-
import { CLAUDE_CALLBACK } from "./oauth/redirect.js";
|
|
9
|
+
import { CLAUDE_CALLBACK } from "./oauth/policy/redirect.js";
|
|
10
10
|
export const CLIENT_PROFILES = {
|
|
11
11
|
/** Claude Custom Connectors — dynamic registration, public client + PKCE. */
|
|
12
12
|
claude: {
|
package/dist/clients.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAgC,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"clients.js","sourceRoot":"","sources":["../src/clients.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,2BAA2B,EAAgC,MAAM,sBAAsB,CAAC;AACjG,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAiB7D,MAAM,CAAC,MAAM,eAAe,GAAsC;IAChE,6EAA6E;IAC7E,MAAM,EAAE;QACN,YAAY,EAAE,CAAC,eAAe,CAAC;QAC/B,wBAAwB,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC;QAC5D,aAAa,EAAE,KAAK;KACrB;IACD;;;OAGG;IACH,MAAM,EAAE;QACN,YAAY,EAAE,EAAE;QAChB,wBAAwB,EAAE,CAAC,2BAA2B,CAAC,KAAK,EAAE,2BAA2B,CAAC,IAAI,CAAC;QAC/F,aAAa,EAAE,IAAI;KACpB;IACD,2EAA2E;IAC3E,KAAK,EAAE;QACL,YAAY,EAAE,EAAE;QAChB,wBAAwB,EAAE,CAAC,2BAA2B,CAAC,IAAI,CAAC;QAC5D,aAAa,EAAE,KAAK;KACrB;CACF,CAAC;AAEF,MAAM,CAAC,MAAM,eAAe,GAAiB,CAAC,QAAQ,CAAC,CAAC;AAExD,kEAAkE;AAClE,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAqB,EAAY,EAAE,CAAC;IAClE,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,CAAC;CAC1E,CAAC;AAEF,oDAAoD;AACpD,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAqB,EAA6B,EAAE;IACjF,MAAM,OAAO,GAAG,IAAI,GAAG,CACrB,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,wBAAwB,CAAC,CAC1E,CAAC;IACF,OAAO;QACL,2BAA2B,CAAC,IAAI;QAChC,2BAA2B,CAAC,KAAK;QACjC,2BAA2B,CAAC,IAAI;KACjC,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC;AAC5C,CAAC,CAAC;AAEF,wDAAwD;AACxD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAqB,EAAgB,EAAE,CAC1E,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC;AAEhE,2FAA2F;AAC3F,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAqB,EAAW,EAAE,CACjE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC;AAE/D,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,OAAqB,EACrB,WAAoC,EAC9B,EAAE;IACR,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC,CAAC;IACtF,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;IACjD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CACb,YAAY,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB;YACxD,0EAA0E,CAC7E,CAAC;IACJ,CAAC;AACH,CAAC,CAAC"}
|