mcp-trellis 0.2.1 → 1.0.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 +41 -561
- package/dist/adapters/node.d.ts +14 -5
- package/dist/adapters/node.d.ts.map +1 -1
- package/dist/adapters/node.js +56 -29
- package/dist/adapters/node.js.map +1 -1
- package/dist/adapters/origins.d.ts.map +1 -1
- package/dist/adapters/origins.js +1 -4
- package/dist/adapters/origins.js.map +1 -1
- package/dist/app.d.ts +27 -4
- package/dist/app.d.ts.map +1 -1
- package/dist/app.js +31 -18
- package/dist/app.js.map +1 -1
- package/dist/auth/bearer.d.ts.map +1 -1
- package/dist/auth/bearer.js +6 -1
- package/dist/auth/bearer.js.map +1 -1
- package/dist/body.d.ts +48 -0
- package/dist/body.d.ts.map +1 -0
- package/dist/body.js +145 -0
- package/dist/body.js.map +1 -0
- package/dist/clients.d.ts.map +1 -1
- package/dist/clients.js +2 -5
- package/dist/clients.js.map +1 -1
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.d.ts.map +1 -1
- package/dist/dispatch.js +58 -18
- package/dist/dispatch.js.map +1 -1
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js.map +1 -1
- package/dist/jsonrpc.d.ts +1 -0
- package/dist/jsonrpc.d.ts.map +1 -1
- package/dist/jsonrpc.js +1 -0
- package/dist/jsonrpc.js.map +1 -1
- package/dist/methods.d.ts +38 -15
- package/dist/methods.d.ts.map +1 -1
- package/dist/methods.js +38 -22
- package/dist/methods.js.map +1 -1
- package/dist/oauth/authorize.d.ts.map +1 -1
- package/dist/oauth/authorize.js +100 -68
- package/dist/oauth/authorize.js.map +1 -1
- package/dist/oauth/base64url.d.ts +1 -1
- package/dist/oauth/base64url.d.ts.map +1 -1
- package/dist/oauth/base64url.js +1 -4
- package/dist/oauth/base64url.js.map +1 -1
- package/dist/oauth/clientauth.d.ts +7 -2
- package/dist/oauth/clientauth.d.ts.map +1 -1
- package/dist/oauth/clientauth.js +59 -16
- package/dist/oauth/clientauth.js.map +1 -1
- package/dist/oauth/codes.d.ts +4 -4
- package/dist/oauth/codes.d.ts.map +1 -1
- package/dist/oauth/codes.js +43 -51
- package/dist/oauth/codes.js.map +1 -1
- package/dist/oauth/consent.d.ts +65 -0
- package/dist/oauth/consent.d.ts.map +1 -0
- package/dist/oauth/consent.js +173 -0
- package/dist/oauth/consent.js.map +1 -0
- package/dist/oauth/constants.d.ts +4 -0
- package/dist/oauth/constants.d.ts.map +1 -1
- package/dist/oauth/constants.js +4 -0
- package/dist/oauth/constants.js.map +1 -1
- package/dist/oauth/metadata.d.ts +6 -6
- package/dist/oauth/metadata.d.ts.map +1 -1
- package/dist/oauth/metadata.js.map +1 -1
- package/dist/oauth/pkce.d.ts.map +1 -1
- package/dist/oauth/pkce.js +1 -1
- package/dist/oauth/pkce.js.map +1 -1
- package/dist/oauth/redirect.d.ts +6 -1
- package/dist/oauth/redirect.d.ts.map +1 -1
- package/dist/oauth/redirect.js +23 -10
- package/dist/oauth/redirect.js.map +1 -1
- package/dist/oauth/reqbody.d.ts +10 -0
- package/dist/oauth/reqbody.d.ts.map +1 -0
- package/dist/oauth/reqbody.js +29 -0
- package/dist/oauth/reqbody.js.map +1 -0
- package/dist/oauth/resource.d.ts +30 -0
- package/dist/oauth/resource.d.ts.map +1 -1
- package/dist/oauth/resource.js +38 -8
- package/dist/oauth/resource.js.map +1 -1
- package/dist/oauth/revoke.d.ts.map +1 -1
- package/dist/oauth/revoke.js +15 -3
- package/dist/oauth/revoke.js.map +1 -1
- package/dist/oauth/router.d.ts +14 -11
- package/dist/oauth/router.d.ts.map +1 -1
- package/dist/oauth/router.js +62 -22
- package/dist/oauth/router.js.map +1 -1
- package/dist/oauth/scope.d.ts +11 -2
- package/dist/oauth/scope.d.ts.map +1 -1
- package/dist/oauth/scope.js +18 -7
- package/dist/oauth/scope.js.map +1 -1
- package/dist/oauth/sealed.d.ts +17 -0
- package/dist/oauth/sealed.d.ts.map +1 -0
- package/dist/oauth/sealed.js +57 -0
- package/dist/oauth/sealed.js.map +1 -0
- package/dist/oauth/secrethash.d.ts +44 -0
- package/dist/oauth/secrethash.d.ts.map +1 -0
- package/dist/oauth/secrethash.js +66 -0
- package/dist/oauth/secrethash.js.map +1 -0
- package/dist/oauth/token.d.ts.map +1 -1
- package/dist/oauth/token.js +13 -34
- package/dist/oauth/token.js.map +1 -1
- package/dist/oauth/types.d.ts +106 -9
- package/dist/oauth/types.d.ts.map +1 -1
- package/dist/oauth/types.js +67 -4
- package/dist/oauth/types.js.map +1 -1
- package/dist/oauth/wellknown.d.ts.map +1 -1
- package/dist/oauth/wellknown.js +6 -4
- package/dist/oauth/wellknown.js.map +1 -1
- package/dist/protocol.d.ts +15 -1
- package/dist/protocol.d.ts.map +1 -1
- package/dist/protocol.js +16 -6
- package/dist/protocol.js.map +1 -1
- package/dist/registry.d.ts +4 -4
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +15 -7
- package/dist/registry.js.map +1 -1
- package/dist/server.d.ts +14 -13
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +8 -8
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +11 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +14 -13
- package/dist/tools.js.map +1 -1
- package/dist/validate.d.ts +16 -1
- package/dist/validate.d.ts.map +1 -1
- package/dist/validate.js +46 -8
- package/dist/validate.js.map +1 -1
- package/docs/ROADMAP.md +295 -0
- package/docs/guide.md +417 -0
- package/docs/reference.md +178 -0
- package/docs/security.md +63 -0
- package/package.json +6 -3
package/dist/adapters/node.d.ts
CHANGED
|
@@ -5,15 +5,18 @@
|
|
|
5
5
|
import { isAllowedOrigin, type OriginAllowlistOptions } from "./origins.js";
|
|
6
6
|
export { isAllowedOrigin, type OriginAllowlistOptions };
|
|
7
7
|
export type NodeRequestLike = {
|
|
8
|
-
method?: string;
|
|
9
|
-
url?: string;
|
|
8
|
+
method?: string | undefined;
|
|
9
|
+
url?: string | undefined;
|
|
10
10
|
headers: Record<string, string | string[] | undefined>;
|
|
11
11
|
body?: unknown;
|
|
12
|
+
/** Destroy the underlying socket — called only after a 413 has flushed. */
|
|
13
|
+
destroy?: (() => void) | undefined;
|
|
14
|
+
[Symbol.asyncIterator]?: () => AsyncIterator<Uint8Array | string>;
|
|
12
15
|
};
|
|
13
16
|
export type NodeResponseLike = {
|
|
14
17
|
statusCode: number;
|
|
15
18
|
setHeader: (name: string, value: string | number | readonly string[]) => void;
|
|
16
|
-
end: (chunk?: string | Uint8Array) => void;
|
|
19
|
+
end: (chunk?: string | Uint8Array, callback?: () => void) => void;
|
|
17
20
|
};
|
|
18
21
|
export type ToWebRequestOptions = {
|
|
19
22
|
/** Absolute origin, e.g. https://app.example.com. */
|
|
@@ -37,8 +40,14 @@ export type AsNodeHandlerOptions = OriginAllowlistOptions & {
|
|
|
37
40
|
/** Derive origin from Host, or from forwarded headers when trustProxy. */
|
|
38
41
|
export declare const resolveOrigin: (req: NodeRequestLike, options?: ResolveOriginOptions) => string;
|
|
39
42
|
export declare const toWebRequest: (req: NodeRequestLike, options: ToWebRequestOptions) => Request;
|
|
40
|
-
/**
|
|
41
|
-
export declare const
|
|
43
|
+
/** OAuth routes under `…/oauth/…` get the 64 KiB cap; everything else gets 1 MiB. */
|
|
44
|
+
export declare const bodyLimitForPath: (path: string) => number;
|
|
45
|
+
/**
|
|
46
|
+
* Prefer `req.body`; else drain the stream (raw `http.createServer`), capped
|
|
47
|
+
* at `maxBytes`. Throws `BodyTooLargeError` past the cap without destroying
|
|
48
|
+
* the socket — `asNodeHandler` writes 413 first, then destroys after flush.
|
|
49
|
+
*/
|
|
50
|
+
export declare const readNodeBody: (req: NodeRequestLike, maxBytes?: number) => Promise<unknown>;
|
|
42
51
|
export declare const sendWebResponse: (res: NodeResponseLike, response: Response) => Promise<void>;
|
|
43
52
|
/** One-liner: Node `(req, res)` → MCP / OAuth Web handler. */
|
|
44
53
|
export declare const asNodeHandler: (mcp: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAWH,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAE5E,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9E,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG;IAC1D;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAQF,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GAAI,KAAK,eAAe,EAAE,UAAS,oBAAyB,KAAG,MAexF,CAAC;AAWF,eAAO,MAAM,YAAY,GAAI,KAAK,eAAe,EAAE,SAAS,mBAAmB,KAAG,OAyBjF,CAAC;AAQF,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MACkC,CAAC;AAWnF;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,eAAe,EACpB,WAAU,MAA+B,KACxC,OAAO,CAAC,OAAO,CAmBjB,CAAC;AAEF,eAAO,MAAM,eAAe,GAAU,KAAK,gBAAgB,EAAE,UAAU,QAAQ,KAAG,OAAO,CAAC,IAAI,CAM7F,CAAC;AAoBF,8DAA8D;AAC9D,eAAO,MAAM,aAAa,GACxB,KAAK;IAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,EACvD,UAAU,oBAAoB,MAqBhB,KAAK,eAAe,EAAE,KAAK,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAqBzE,CAAC"}
|
package/dist/adapters/node.js
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
* Node HTTP `(req, res)` adapter — Express, Cloud Functions, `http.createServer`, etc.
|
|
3
3
|
* Bridges duck-typed Node request/response objects to Web `Request`/`Response`.
|
|
4
4
|
*/
|
|
5
|
+
import { BodyTooLargeError, DEFAULT_MCP_BODY_LIMIT, DEFAULT_OAUTH_BODY_LIMIT, isNodeReadable, readBoundedNodeBody, } from "../body.js";
|
|
5
6
|
import { INTERNAL_ERROR } from "../http.js";
|
|
6
|
-
import {
|
|
7
|
+
import { JSONRPC_PAYLOAD_TOO_LARGE, rpcError } from "../jsonrpc.js";
|
|
8
|
+
import { isAllowedOrigin } from "./origins.js";
|
|
7
9
|
export { isAllowedOrigin };
|
|
8
|
-
const headerValue = (value) =>
|
|
10
|
+
const headerValue = (value) => Array.isArray(value) ? value[0] : value;
|
|
9
11
|
const lastForwarded = (value) => value?.split(",").pop()?.trim();
|
|
10
12
|
/** Derive origin from Host, or from forwarded headers when trustProxy. */
|
|
11
13
|
export const resolveOrigin = (req, options = {}) => {
|
|
@@ -14,8 +16,7 @@ export const resolveOrigin = (req, options = {}) => {
|
|
|
14
16
|
? lastForwarded(headerValue(req.headers["x-forwarded-proto"])) || "https"
|
|
15
17
|
: "https";
|
|
16
18
|
const host = trustProxy
|
|
17
|
-
? lastForwarded(headerValue(req.headers["x-forwarded-host"])) ||
|
|
18
|
-
headerValue(req.headers.host)
|
|
19
|
+
? lastForwarded(headerValue(req.headers["x-forwarded-host"])) || headerValue(req.headers.host)
|
|
19
20
|
: headerValue(req.headers.host);
|
|
20
21
|
if (!host) {
|
|
21
22
|
throw new Error("Cannot resolve origin: pass options.origin or set Host" +
|
|
@@ -48,45 +49,64 @@ export const toWebRequest = (req, options) => {
|
|
|
48
49
|
return new Request(url, { method, headers });
|
|
49
50
|
}
|
|
50
51
|
const body = options.body !== undefined ? options.body : req.body;
|
|
52
|
+
const bodyInit = toBodyInit(body);
|
|
51
53
|
return new Request(url, {
|
|
52
54
|
method,
|
|
53
55
|
headers,
|
|
54
|
-
body:
|
|
56
|
+
...(bodyInit !== undefined ? { body: bodyInit } : {}),
|
|
55
57
|
});
|
|
56
58
|
};
|
|
57
|
-
const isAsyncIterable = (value) => typeof value?.[Symbol.asyncIterator] ===
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
59
|
+
const isAsyncIterable = (value) => typeof value?.[Symbol.asyncIterator] ===
|
|
60
|
+
"function";
|
|
61
|
+
const requestPath = (req) => (req.url ?? "/").split("?")[0] ?? "/";
|
|
62
|
+
/** OAuth routes under `…/oauth/…` get the 64 KiB cap; everything else gets 1 MiB. */
|
|
63
|
+
export const bodyLimitForPath = (path) => /\/oauth(?:\/|$)/.test(path) ? DEFAULT_OAUTH_BODY_LIMIT : DEFAULT_MCP_BODY_LIMIT;
|
|
64
|
+
const enforcePresetBodySize = (body, maxBytes) => {
|
|
65
|
+
if (typeof body === "string" && new TextEncoder().encode(body).byteLength > maxBytes) {
|
|
66
|
+
throw new BodyTooLargeError(maxBytes);
|
|
67
|
+
}
|
|
68
|
+
if (body instanceof Uint8Array && body.byteLength > maxBytes) {
|
|
69
|
+
throw new BodyTooLargeError(maxBytes);
|
|
70
|
+
}
|
|
66
71
|
};
|
|
67
|
-
/**
|
|
68
|
-
|
|
69
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Prefer `req.body`; else drain the stream (raw `http.createServer`), capped
|
|
74
|
+
* at `maxBytes`. Throws `BodyTooLargeError` past the cap without destroying
|
|
75
|
+
* the socket — `asNodeHandler` writes 413 first, then destroys after flush.
|
|
76
|
+
*/
|
|
77
|
+
export const readNodeBody = async (req, maxBytes = DEFAULT_MCP_BODY_LIMIT) => {
|
|
78
|
+
if (req.body !== undefined && req.body !== null) {
|
|
79
|
+
enforcePresetBodySize(req.body, maxBytes);
|
|
70
80
|
return req.body;
|
|
81
|
+
}
|
|
82
|
+
const opts = { contentLength: headerValue(req.headers["content-length"]) };
|
|
83
|
+
if (isNodeReadable(req)) {
|
|
84
|
+
const bytes = await readBoundedNodeBody(req, maxBytes, opts);
|
|
85
|
+
return bytes.byteLength > 0 ? bytes : undefined;
|
|
86
|
+
}
|
|
71
87
|
if (!isAsyncIterable(req))
|
|
72
88
|
return undefined;
|
|
73
|
-
const
|
|
74
|
-
|
|
75
|
-
chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
|
|
76
|
-
}
|
|
77
|
-
return chunks.length > 0 ? concatChunks(chunks) : undefined;
|
|
89
|
+
const bytes = await readBoundedNodeBody(req, maxBytes, opts);
|
|
90
|
+
return bytes.byteLength > 0 ? bytes : undefined;
|
|
78
91
|
};
|
|
79
92
|
export const sendWebResponse = async (res, response) => {
|
|
80
93
|
res.statusCode = response.status;
|
|
81
|
-
response.headers.forEach((value, key) =>
|
|
94
|
+
response.headers.forEach((value, key) => {
|
|
95
|
+
res.setHeader(key, value);
|
|
96
|
+
});
|
|
82
97
|
res.end(new Uint8Array(await response.arrayBuffer()));
|
|
83
98
|
};
|
|
84
99
|
/** Always answer — an unhandled rejection on `http.createServer` hangs the client. */
|
|
85
|
-
const sendJsonError = (res, status,
|
|
100
|
+
const sendJsonError = (res, status, body, after) => {
|
|
86
101
|
res.statusCode = status;
|
|
87
102
|
res.setHeader("Content-Type", "application/json");
|
|
88
|
-
|
|
103
|
+
if (after)
|
|
104
|
+
res.setHeader("Connection", "close");
|
|
105
|
+
res.end(body, after);
|
|
89
106
|
};
|
|
107
|
+
const payloadTooLargeBody = (path) => /\/oauth(?:\/|$)/.test(path)
|
|
108
|
+
? JSON.stringify({ error: "request body too large" })
|
|
109
|
+
: JSON.stringify(rpcError(null, JSONRPC_PAYLOAD_TOO_LARGE, "Payload too large"));
|
|
90
110
|
/** One-liner: Node `(req, res)` → MCP / OAuth Web handler. */
|
|
91
111
|
export const asNodeHandler = (mcp, options) => {
|
|
92
112
|
const hostDerived = !options?.origin;
|
|
@@ -104,18 +124,25 @@ export const asNodeHandler = (mcp, options) => {
|
|
|
104
124
|
throw new Error("asNodeHandler: options.origin is not in options.allowedOrigins");
|
|
105
125
|
}
|
|
106
126
|
return async (req, res) => {
|
|
127
|
+
const path = requestPath(req);
|
|
107
128
|
try {
|
|
108
129
|
const origin = options?.origin ?? resolveOrigin(req, { trustProxy: true });
|
|
109
130
|
if (!isAllowedOrigin(origin, options)) {
|
|
110
|
-
sendJsonError(res, 400, "origin not allowed");
|
|
131
|
+
sendJsonError(res, 400, JSON.stringify({ error: "origin not allowed" }));
|
|
111
132
|
return;
|
|
112
133
|
}
|
|
113
|
-
const body = await readNodeBody(req);
|
|
134
|
+
const body = await readNodeBody(req, bodyLimitForPath(path));
|
|
114
135
|
const request = toWebRequest(req, { origin, body });
|
|
115
136
|
await sendWebResponse(res, await mcp.fetch(request));
|
|
116
137
|
}
|
|
117
|
-
catch {
|
|
118
|
-
|
|
138
|
+
catch (exc) {
|
|
139
|
+
if (exc instanceof BodyTooLargeError) {
|
|
140
|
+
sendJsonError(res, 413, payloadTooLargeBody(path), () => {
|
|
141
|
+
req.destroy?.();
|
|
142
|
+
});
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
sendJsonError(res, 500, JSON.stringify({ error: INTERNAL_ERROR }));
|
|
119
146
|
}
|
|
120
147
|
};
|
|
121
148
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,
|
|
1
|
+
{"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../../src/adapters/origins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;
|
|
1
|
+
{"version":3,"file":"origins.d.ts","sourceRoot":"","sources":["../../src/adapters/origins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,MAAM,sBAAsB,GAAG;IACnC;;;;;;;;;OASG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B,CAAC;AAyCF,eAAO,MAAM,eAAe,GAAI,QAAQ,MAAM,EAAE,UAAS,sBAA2B,KAAG,OAQtF,CAAC"}
|
package/dist/adapters/origins.js
CHANGED
|
@@ -38,10 +38,7 @@ const isWildcardSubdomain = (origin, options) => {
|
|
|
38
38
|
return false;
|
|
39
39
|
}
|
|
40
40
|
};
|
|
41
|
-
const ORIGIN_PREDICATES = [
|
|
42
|
-
isExactOrigin,
|
|
43
|
-
isWildcardSubdomain,
|
|
44
|
-
];
|
|
41
|
+
const ORIGIN_PREDICATES = [isExactOrigin, isWildcardSubdomain];
|
|
45
42
|
export const isAllowedOrigin = (origin, options = {}) => {
|
|
46
43
|
// Empty/omitted: admit all — callers that derive origin from Host must
|
|
47
44
|
// require a non-empty list before reaching here (see asNodeHandler).
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"origins.js","sourceRoot":"","sources":["../../src/adapters/origins.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"origins.js","sourceRoot":"","sources":["../../src/adapters/origins.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAkBH,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAiB,EAAE;IAChD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,aAAa,GAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IACzD,MAAM,UAAU,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,UAAU;QAAE,OAAO,KAAK,CAAC;IAC9B,OAAO,OAAO,CACZ,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACrC,IAAI,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACzC,OAAO,QAAQ,CAAC,KAAK,CAAC,KAAK,UAAU,CAAC;IACxC,CAAC,CAAC,CACH,CAAC;AACJ,CAAC,CAAC;AAEF,kFAAkF;AAClF,MAAM,mBAAmB,GAAoB,CAAC,MAAM,EAAE,OAAO,EAAE,EAAE;IAC/D,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,IAAI,EAAE,CAAC;IAC9C,IAAI,CAAC;QACH,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC;QAC/C,IAAI,QAAQ,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC;QACxC,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YAC7B,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC1C,MAAM,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,iBAAiB;YAChD,OAAO,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QACtE,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAsB,CAAC,aAAa,EAAE,mBAAmB,CAAC,CAAC;AAElF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,MAAc,EAAE,UAAkC,EAAE,EAAW,EAAE;IAC/F,uEAAuE;IACvE,qEAAqE;IACrE,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACtD,OAAO,iBAAiB,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;AAC3E,CAAC,CAAC"}
|
package/dist/app.d.ts
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
import { type ClientName } from "./clients.js";
|
|
8
8
|
import type { AuditEntry, Principal, ServerInfo } from "./methods.js";
|
|
9
9
|
import type { CodeStore } from "./oauth/codes.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { ConsentOptions } from "./oauth/consent.js";
|
|
11
|
+
import type { ClientStore, MintAccessTokenInput, MintedToken, OAuthAuditEntry, OAuthUser, RefreshAccessTokenInput, RevokeTokenInput } from "./oauth/types.js";
|
|
11
12
|
import { type ToolDef } from "./registry.js";
|
|
12
13
|
/** What your token verification returns. The library checks the audience. */
|
|
13
14
|
export type VerifiedToken = {
|
|
@@ -39,6 +40,13 @@ export type McpAppAuth = {
|
|
|
39
40
|
codeStore?: CodeStore;
|
|
40
41
|
/** Required when any configured client is pre-registered (e.g. Gemini). */
|
|
41
42
|
clientStore?: ClientStore;
|
|
43
|
+
/**
|
|
44
|
+
* Opt-in OAuth-side metrics hook — see the tool-call `audit` below for
|
|
45
|
+
* the general shape. This one sees the real reason behind a collapsed
|
|
46
|
+
* `invalid_client` or a rejected `codeSecret`, which the caller never
|
|
47
|
+
* does. Omit for silence.
|
|
48
|
+
*/
|
|
49
|
+
audit?: (entry: OAuthAuditEntry) => void | Promise<void>;
|
|
42
50
|
};
|
|
43
51
|
export type McpAppOptions<TCtx> = {
|
|
44
52
|
serverInfo: ServerInfo;
|
|
@@ -53,22 +61,37 @@ export type McpAppOptions<TCtx> = {
|
|
|
53
61
|
oauthPath?: string;
|
|
54
62
|
/** Scopes this server grants. Default `["mcp"]`. */
|
|
55
63
|
scopes?: string[];
|
|
64
|
+
/** Required when `scopes` has more than one entry — see `OAuthRouterOptions.defaultScopes`. */
|
|
65
|
+
defaultScopes?: string[];
|
|
56
66
|
realm?: string;
|
|
57
67
|
/** Extra exact-match redirect URIs beyond the client profiles. */
|
|
58
68
|
extraRedirectUris?: string[];
|
|
59
69
|
/** Allow loopback redirects (native clients). Default true. */
|
|
60
70
|
allowLoopback?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Consent policy — policy, not a credential, so it sits alongside
|
|
73
|
+
* `allowLoopback` rather than under `auth`. Omit for the built-in
|
|
74
|
+
* hardened interstitial.
|
|
75
|
+
*/
|
|
76
|
+
consent?: ConsentOptions;
|
|
77
|
+
/**
|
|
78
|
+
* Require every `client_id` to come from `clientStore` or this server's
|
|
79
|
+
* own `/register` (sealed assertion). Default **true** since 1.0.
|
|
80
|
+
* Set false only to accept invented public ids (pre-CIMD).
|
|
81
|
+
*/
|
|
82
|
+
requireRegisteredClients?: boolean;
|
|
61
83
|
validateArgs?: boolean;
|
|
62
84
|
onToolError?: (exc: unknown) => string;
|
|
63
85
|
/** Per-request context for tools. Defaults to an empty object. */
|
|
64
86
|
context?: (req: Request, principal: Principal | null) => TCtx | Promise<TCtx>;
|
|
65
87
|
/**
|
|
66
|
-
* Opt-in metrics hook — same as `McpPorts.audit`.
|
|
67
|
-
*
|
|
68
|
-
* never stores or prints these itself. See `consoleAudit` or
|
|
88
|
+
* Opt-in metrics hook — same as `McpPorts.audit`. Omit for silence. The
|
|
89
|
+
* library never stores or prints these itself. See `consoleAudit` or
|
|
69
90
|
* `examples/audit-store.ts`.
|
|
70
91
|
*/
|
|
71
92
|
audit?: (entry: AuditEntry) => void | Promise<void>;
|
|
93
|
+
/** Max time to wait for `audit` above before responding anyway. Default 1000ms. */
|
|
94
|
+
auditTimeoutMs?: number;
|
|
72
95
|
};
|
|
73
96
|
export type McpApp = {
|
|
74
97
|
fetch: (request: Request) => Promise<Response>;
|
package/dist/app.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
package/dist/app.js
CHANGED
|
@@ -5,21 +5,23 @@
|
|
|
5
5
|
* exported for anyone who wants to compose the pieces themselves.
|
|
6
6
|
*/
|
|
7
7
|
import { parseBearer } from "./auth/bearer.js";
|
|
8
|
-
import {
|
|
8
|
+
import { assertClientsConfigured, authMethodsFor, DEFAULT_CLIENTS, hasDynamicClient, redirectUrisFor, } from "./clients.js";
|
|
9
9
|
import { createMcpHandler } from "./dispatch.js";
|
|
10
10
|
import { INTERNAL_ERROR, jsonResponse } from "./http.js";
|
|
11
|
+
import { canonicalResource, DEFAULT_RESOURCE_PATH, normalizeConfiguredPath, resourcesEqual, } from "./oauth/resource.js";
|
|
11
12
|
import { createOAuthRouter } from "./oauth/router.js";
|
|
12
|
-
import { DEFAULT_RESOURCE_PATH, canonicalResource, resourcesEqual, } from "./oauth/resource.js";
|
|
13
13
|
import { createToolRegistry } from "./registry.js";
|
|
14
14
|
export const createMcpApp = (options) => {
|
|
15
|
-
|
|
15
|
+
// Normalized once here — "/mcp/" and "/mcp" must route identically, not
|
|
16
|
+
// diverge into a 404 for one of them. See `normalizeConfiguredPath`.
|
|
17
|
+
const resourcePath = normalizeConfiguredPath(options.resourcePath ?? DEFAULT_RESOURCE_PATH);
|
|
16
18
|
const oauthPath = options.oauthPath ?? `${resourcePath}/oauth`;
|
|
17
19
|
const clients = options.clients ?? DEFAULT_CLIENTS;
|
|
18
20
|
const realm = options.realm ?? options.serverInfo.name;
|
|
19
21
|
assertClientsConfigured(clients, options.auth.clientStore);
|
|
20
22
|
const registry = createToolRegistry(options.tools, {
|
|
21
|
-
validateArgs: options.validateArgs,
|
|
22
|
-
onToolError: options.onToolError,
|
|
23
|
+
...(options.validateArgs !== undefined ? { validateArgs: options.validateArgs } : {}),
|
|
24
|
+
...(options.onToolError !== undefined ? { onToolError: options.onToolError } : {}),
|
|
23
25
|
});
|
|
24
26
|
/**
|
|
25
27
|
* The audience check lives here, not in user code — a token minted for
|
|
@@ -35,12 +37,17 @@ export const createMcpApp = (options) => {
|
|
|
35
37
|
const expected = canonicalResource(new URL(req.url).origin, resourcePath);
|
|
36
38
|
if (!resourcesEqual(verified.audience, expected))
|
|
37
39
|
return null;
|
|
38
|
-
return {
|
|
40
|
+
return {
|
|
41
|
+
id: verified.userId,
|
|
42
|
+
scopes: verified.scopes,
|
|
43
|
+
...(verified.claims !== undefined ? { claims: verified.claims } : {}),
|
|
44
|
+
};
|
|
39
45
|
};
|
|
40
46
|
const handler = createMcpHandler({
|
|
41
47
|
registry,
|
|
42
48
|
serverInfo: options.serverInfo,
|
|
43
|
-
instructions: options.instructions,
|
|
49
|
+
...(options.instructions !== undefined ? { instructions: options.instructions } : {}),
|
|
50
|
+
...(options.auditTimeoutMs !== undefined ? { auditTimeoutMs: options.auditTimeoutMs } : {}),
|
|
44
51
|
wwwAuthenticate: (req) => ({
|
|
45
52
|
realm,
|
|
46
53
|
resourceMetadataUrl: `${new URL(req.url).origin}/.well-known/oauth-protected-resource${resourcePath}`,
|
|
@@ -48,22 +55,24 @@ export const createMcpApp = (options) => {
|
|
|
48
55
|
ports: {
|
|
49
56
|
authenticate,
|
|
50
57
|
context: options.context ?? (() => ({})),
|
|
51
|
-
audit: options.audit,
|
|
58
|
+
...(options.audit !== undefined ? { audit: options.audit } : {}),
|
|
52
59
|
},
|
|
53
60
|
});
|
|
54
61
|
const oauth = createOAuthRouter({
|
|
55
62
|
resourcePath,
|
|
56
63
|
oauthPath,
|
|
57
64
|
realm,
|
|
58
|
-
scopes: options.scopes,
|
|
65
|
+
...(options.scopes !== undefined ? { scopes: options.scopes } : {}),
|
|
66
|
+
...(options.defaultScopes !== undefined ? { defaultScopes: options.defaultScopes } : {}),
|
|
59
67
|
tokenEndpointAuthMethods: authMethodsFor(clients),
|
|
60
68
|
allowUnregisteredClients: hasDynamicClient(clients),
|
|
69
|
+
...(options.requireRegisteredClients !== undefined
|
|
70
|
+
? { requireRegisteredClients: options.requireRegisteredClients }
|
|
71
|
+
: {}),
|
|
72
|
+
...(options.consent !== undefined ? { consent: options.consent } : {}),
|
|
61
73
|
redirect: {
|
|
62
74
|
// Client profiles are the source of truth for callbacks.
|
|
63
|
-
extra: [
|
|
64
|
-
...redirectUrisFor(clients),
|
|
65
|
-
...(options.extraRedirectUris ?? []),
|
|
66
|
-
],
|
|
75
|
+
extra: [...redirectUrisFor(clients), ...(options.extraRedirectUris ?? [])],
|
|
67
76
|
allowClaude: false,
|
|
68
77
|
allowLoopback: options.allowLoopback ?? true,
|
|
69
78
|
},
|
|
@@ -72,10 +81,13 @@ export const createMcpApp = (options) => {
|
|
|
72
81
|
resolveUser: options.auth.resolveUser,
|
|
73
82
|
loginUrl: options.auth.loginUrl,
|
|
74
83
|
mintAccessToken: options.auth.mintAccessToken,
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
...(options.auth.refreshAccessToken !== undefined
|
|
85
|
+
? { refreshAccessToken: options.auth.refreshAccessToken }
|
|
86
|
+
: {}),
|
|
87
|
+
...(options.auth.revokeToken !== undefined ? { revokeToken: options.auth.revokeToken } : {}),
|
|
88
|
+
...(options.auth.codeStore !== undefined ? { codeStore: options.auth.codeStore } : {}),
|
|
89
|
+
...(options.auth.clientStore !== undefined ? { clientStore: options.auth.clientStore } : {}),
|
|
90
|
+
...(options.auth.audit !== undefined ? { audit: options.auth.audit } : {}),
|
|
79
91
|
},
|
|
80
92
|
});
|
|
81
93
|
return {
|
|
@@ -84,7 +96,8 @@ export const createMcpApp = (options) => {
|
|
|
84
96
|
const oauthResponse = await oauth.tryHandle(request);
|
|
85
97
|
if (oauthResponse)
|
|
86
98
|
return oauthResponse;
|
|
87
|
-
|
|
99
|
+
const requestPath = normalizeConfiguredPath(new URL(request.url).pathname);
|
|
100
|
+
if (requestPath === resourcePath) {
|
|
88
101
|
return await handler.fetch(request);
|
|
89
102
|
}
|
|
90
103
|
return jsonResponse({ error: "Not found" }, 404);
|
package/dist/app.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,eAAe,EACf,
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,eAAO,MAAM,WAAW,GAAI,eAAe,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAInE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,
|
|
1
|
+
{"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,eAAO,MAAM,aAAa,YAAY,CAAC;AAEvC,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAEvC,eAAO,MAAM,WAAW,GAAI,eAAe,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAInE,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;CAC7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAAI,SAAS,sBAAsB,KAAG,MACwB,CAAC;AAEjG,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,GAAI,KAAK,GAAG,KAAG,OAC2B,CAAC"}
|
package/dist/auth/bearer.js
CHANGED
|
@@ -14,6 +14,11 @@ export const parseBearer = (authorization) => {
|
|
|
14
14
|
* so unequal lengths do not short-circuit. Rejects over-long inputs.
|
|
15
15
|
*/
|
|
16
16
|
export const timingSafeEqual = (a, b) => {
|
|
17
|
+
// Both empty: the reduce below never runs and the seed 0 ^ 0 is 0 — "equal"
|
|
18
|
+
// by the accumulator's math, but never the right semantics for a secret
|
|
19
|
+
// comparison. An empty presented value must never authenticate.
|
|
20
|
+
if (a.length === 0 || b.length === 0)
|
|
21
|
+
return false;
|
|
17
22
|
if (a.length > MAX_COMPARE_LENGTH || b.length > MAX_COMPARE_LENGTH) {
|
|
18
23
|
return false;
|
|
19
24
|
}
|
|
@@ -25,7 +30,7 @@ export const timingSafeEqual = (a, b) => {
|
|
|
25
30
|
}, a.length ^ b.length);
|
|
26
31
|
return diff === 0;
|
|
27
32
|
};
|
|
28
|
-
export const matchesAny = (presented, accepted) => accepted.some((token) =>
|
|
33
|
+
export const matchesAny = (presented, accepted) => accepted.some((token) => timingSafeEqual(presented, token));
|
|
29
34
|
export const wwwAuthenticateHeader = (options) => `${BEARER_PREFIX}realm="${options.realm}", resource_metadata="${options.resourceMetadataUrl}"`;
|
|
30
35
|
/** RFC 6750 §2.3 uses `access_token`; also reject legacy `token`. */
|
|
31
36
|
export const rejectQueryToken = (url) => url.searchParams.has("token") || url.searchParams.has("access_token");
|
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,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AAEvC,gFAAgF;AAChF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,aAA4B,EAAiB,EAAE;IACzE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAS,EAAE,CAAS,EAAW,EAAE;IAC/D,IAAI,CAAC,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACtE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAE,QAAkB,EAAW,EAAE,CAC3E,QAAQ,CAAC,IAAI,
|
|
1
|
+
{"version":3,"file":"bearer.js","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAE/D,MAAM,CAAC,MAAM,aAAa,GAAG,SAAS,CAAC;AAEvC,gFAAgF;AAChF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,aAA4B,EAAiB,EAAE;IACzE,IAAI,CAAC,aAAa,EAAE,UAAU,CAAC,aAAa,CAAC;QAAE,OAAO,IAAI,CAAC;IAC3D,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IAC/D,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAS,EAAE,CAAS,EAAW,EAAE;IAC/D,4EAA4E;IAC5E,wEAAwE;IACxE,gEAAgE;IAChE,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,IAAI,CAAC,CAAC,MAAM,GAAG,kBAAkB,IAAI,CAAC,CAAC,MAAM,GAAG,kBAAkB,EAAE,CAAC;QACnE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE;QACtE,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9C,OAAO,GAAG,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACxB,OAAO,IAAI,KAAK,CAAC,CAAC;AACpB,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,SAAiB,EAAE,QAAkB,EAAW,EAAE,CAC3E,QAAQ,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;AAQ9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAA+B,EAAU,EAAE,CAC/E,GAAG,aAAa,UAAU,OAAO,CAAC,KAAK,yBAAyB,OAAO,CAAC,mBAAmB,GAAG,CAAC;AAEjG,qEAAqE;AACrE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,GAAQ,EAAW,EAAE,CACpD,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC"}
|
package/dist/body.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Request-body size limits. Nothing upstream caps body size on its own —
|
|
3
|
+
* `request.json()` / `request.text()` and a raw `http.createServer` stream
|
|
4
|
+
* both buffer the whole body in memory first, so an uncapped read is a
|
|
5
|
+
* straightforward memory-exhaustion DoS.
|
|
6
|
+
*/
|
|
7
|
+
export declare class BodyTooLargeError extends Error {
|
|
8
|
+
readonly maxBytes: number;
|
|
9
|
+
constructor(maxBytes: number);
|
|
10
|
+
}
|
|
11
|
+
/** Default cap for `/mcp` — JSON-RPC payloads, generally small but tool args can be text-heavy. */
|
|
12
|
+
export declare const DEFAULT_MCP_BODY_LIMIT = 1048576;
|
|
13
|
+
/** Default cap for OAuth endpoints (`/token`, `/revoke`, `/register`, `/consent`) — tiny form/JSON. */
|
|
14
|
+
export declare const DEFAULT_OAUTH_BODY_LIMIT = 65536;
|
|
15
|
+
/**
|
|
16
|
+
* Reads a Web `Request` body as text, rejecting early on an honest
|
|
17
|
+
* oversized `Content-Length`, then aborting mid-stream — before the whole
|
|
18
|
+
* body is buffered — if a chunked body (no `Content-Length`) exceeds
|
|
19
|
+
* `maxBytes`. Falls back to `request.text()` when `request.body` is null
|
|
20
|
+
* (some runtimes don't expose a streaming body), still enforcing the cap.
|
|
21
|
+
*/
|
|
22
|
+
export declare const readBoundedText: (request: Request, maxBytes: number) => Promise<string>;
|
|
23
|
+
export type BoundedNodeBodyOptions = {
|
|
24
|
+
/** Declared `Content-Length` header value, checked before reading anything. */
|
|
25
|
+
contentLength?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
/**
|
|
28
|
+
* Node `IncomingMessage`-shaped readable: event listeners + pause.
|
|
29
|
+
* Prefer this over `for await` — throwing out of `for await` on an
|
|
30
|
+
* IncomingMessage runs the async iterator's `return()`, which **destroys**
|
|
31
|
+
* the request before the caller can write a 413.
|
|
32
|
+
*/
|
|
33
|
+
export type NodeReadableLike = {
|
|
34
|
+
on(event: "data", listener: (chunk: Uint8Array | string) => void): void;
|
|
35
|
+
on(event: "end", listener: () => void): void;
|
|
36
|
+
on(event: "error", listener: (err: Error) => void): void;
|
|
37
|
+
pause(): void;
|
|
38
|
+
removeListener(event: string, listener: (...args: unknown[]) => void): void;
|
|
39
|
+
};
|
|
40
|
+
export declare const isNodeReadable: (value: unknown) => value is NodeReadableLike;
|
|
41
|
+
/**
|
|
42
|
+
* Same contract as `readBoundedText` for a raw Node request stream.
|
|
43
|
+
* Does **not** destroy the socket — that races a 413 response into EPIPE.
|
|
44
|
+
* On overflow the event path pauses and drops listeners; the caller writes
|
|
45
|
+
* 413 then tears down after flush.
|
|
46
|
+
*/
|
|
47
|
+
export declare const readBoundedNodeBody: (source: NodeReadableLike | AsyncIterable<Uint8Array | string>, maxBytes: number, options?: BoundedNodeBodyOptions) => Promise<Uint8Array>;
|
|
48
|
+
//# sourceMappingURL=body.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../src/body.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM;CAItC;AAED,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAEhD,uGAAuG;AACvG,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAuB/C;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAU,SAAS,OAAO,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,MAAM,CAgCxF,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG;IACnC,+EAA+E;IAC/E,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACpC,CAAC;AAEF;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,KAAK,EAAE,UAAU,GAAG,MAAM,KAAK,IAAI,GAAG,IAAI,CAAC;IACxE,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,IAAI,GAAG,IAAI,CAAC;IAC7C,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,GAAG,IAAI,CAAC;IACzD,KAAK,IAAI,IAAI,CAAC;IACd,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,IAAI,GAAG,IAAI,CAAC;CAC7E,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,OAAO,OAAO,KAAG,KAAK,IAAI,gBAG6B,CAAC;AA+DvF;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,gBAAgB,GAAG,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,EAC7D,UAAU,MAAM,EAChB,UAAS,sBAA2B,KACnC,OAAO,CAAC,UAAU,CAQpB,CAAC"}
|