mcp-trellis 2.2.0 → 3.1.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.
Files changed (173) hide show
  1. package/README.md +61 -52
  2. package/dist/adapters/node-request.d.ts +5 -0
  3. package/dist/adapters/node-request.d.ts.map +1 -1
  4. package/dist/adapters/node-request.js +17 -1
  5. package/dist/adapters/node-request.js.map +1 -1
  6. package/dist/adapters/node.d.ts +15 -0
  7. package/dist/adapters/node.d.ts.map +1 -1
  8. package/dist/adapters/node.js +38 -0
  9. package/dist/adapters/node.js.map +1 -1
  10. package/dist/app.d.ts.map +1 -1
  11. package/dist/app.js +1 -0
  12. package/dist/app.js.map +1 -1
  13. package/dist/audit.d.ts.map +1 -1
  14. package/dist/audit.js +63 -6
  15. package/dist/audit.js.map +1 -1
  16. package/dist/auth/signed/payload.d.ts +31 -0
  17. package/dist/auth/signed/payload.d.ts.map +1 -0
  18. package/dist/auth/signed/payload.js +85 -0
  19. package/dist/auth/signed/payload.js.map +1 -0
  20. package/dist/auth/signed/refresh.d.ts +34 -0
  21. package/dist/auth/signed/refresh.d.ts.map +1 -0
  22. package/dist/auth/signed/refresh.js +95 -0
  23. package/dist/auth/signed/refresh.js.map +1 -0
  24. package/dist/auth/signed/token.d.ts +41 -0
  25. package/dist/auth/signed/token.d.ts.map +1 -0
  26. package/dist/auth/signed/token.js +103 -0
  27. package/dist/auth/signed/token.js.map +1 -0
  28. package/dist/clients.js +2 -2
  29. package/dist/clients.js.map +1 -1
  30. package/dist/deprecated.d.ts +15 -15
  31. package/dist/deprecated.d.ts.map +1 -1
  32. package/dist/deprecated.js +15 -15
  33. package/dist/deprecated.js.map +1 -1
  34. package/dist/http/body.d.ts +4 -0
  35. package/dist/http/body.d.ts.map +1 -1
  36. package/dist/http/body.js +9 -2
  37. package/dist/http/body.js.map +1 -1
  38. package/dist/http/origins.d.ts.map +1 -1
  39. package/dist/http/origins.js +13 -2
  40. package/dist/http/origins.js.map +1 -1
  41. package/dist/mcp/dispatch.d.ts.map +1 -1
  42. package/dist/mcp/dispatch.js +2 -1
  43. package/dist/mcp/dispatch.js.map +1 -1
  44. package/dist/mcp/methods.d.ts +8 -0
  45. package/dist/mcp/methods.d.ts.map +1 -1
  46. package/dist/mcp/methods.js +14 -1
  47. package/dist/mcp/methods.js.map +1 -1
  48. package/dist/mcp/registry.d.ts.map +1 -1
  49. package/dist/mcp/registry.js +15 -3
  50. package/dist/mcp/registry.js.map +1 -1
  51. package/dist/mcp/rpc-handlers.d.ts.map +1 -1
  52. package/dist/mcp/rpc-handlers.js +60 -13
  53. package/dist/mcp/rpc-handlers.js.map +1 -1
  54. package/dist/mcp/tools.d.ts +14 -0
  55. package/dist/mcp/tools.d.ts.map +1 -1
  56. package/dist/mcp/tools.js +118 -23
  57. package/dist/mcp/tools.js.map +1 -1
  58. package/dist/mcp/validate.d.ts +7 -1
  59. package/dist/mcp/validate.d.ts.map +1 -1
  60. package/dist/mcp/validate.js +58 -24
  61. package/dist/mcp/validate.js.map +1 -1
  62. package/dist/oauth/audit.d.ts +10 -0
  63. package/dist/oauth/audit.d.ts.map +1 -1
  64. package/dist/oauth/audit.js +25 -1
  65. package/dist/oauth/audit.js.map +1 -1
  66. package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -1
  67. package/dist/oauth/cimd/cimd-parse.js +27 -14
  68. package/dist/oauth/cimd/cimd-parse.js.map +1 -1
  69. package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -4
  70. package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -1
  71. package/dist/oauth/cimd/cimd-ssrf.js +13 -39
  72. package/dist/oauth/cimd/cimd-ssrf.js.map +1 -1
  73. package/dist/oauth/cimd/cimd.d.ts +14 -18
  74. package/dist/oauth/cimd/cimd.d.ts.map +1 -1
  75. package/dist/oauth/cimd/cimd.js +53 -37
  76. package/dist/oauth/cimd/cimd.js.map +1 -1
  77. package/dist/oauth/cimd/dns.d.ts +4 -0
  78. package/dist/oauth/cimd/dns.d.ts.map +1 -0
  79. package/dist/oauth/cimd/dns.js +45 -0
  80. package/dist/oauth/cimd/dns.js.map +1 -0
  81. package/dist/oauth/cimd/failure.d.ts +19 -0
  82. package/dist/oauth/cimd/failure.d.ts.map +1 -0
  83. package/dist/oauth/cimd/failure.js +31 -0
  84. package/dist/oauth/cimd/failure.js.map +1 -0
  85. package/dist/oauth/cimd/types.d.ts +15 -1
  86. package/dist/oauth/cimd/types.d.ts.map +1 -1
  87. package/dist/oauth/cimd/types.js +1 -1
  88. package/dist/oauth/cimd/types.js.map +1 -1
  89. package/dist/oauth/cimd/url-guard.d.ts +5 -0
  90. package/dist/oauth/cimd/url-guard.d.ts.map +1 -0
  91. package/dist/oauth/cimd/url-guard.js +53 -0
  92. package/dist/oauth/cimd/url-guard.js.map +1 -0
  93. package/dist/oauth/config.d.ts +3 -0
  94. package/dist/oauth/config.d.ts.map +1 -1
  95. package/dist/oauth/config.js +5 -1
  96. package/dist/oauth/config.js.map +1 -1
  97. package/dist/oauth/crypto/clientauth.d.ts.map +1 -1
  98. package/dist/oauth/crypto/clientauth.js +7 -6
  99. package/dist/oauth/crypto/clientauth.js.map +1 -1
  100. package/dist/oauth/deprecated.d.ts +22 -22
  101. package/dist/oauth/deprecated.d.ts.map +1 -1
  102. package/dist/oauth/deprecated.js +22 -22
  103. package/dist/oauth/deprecated.js.map +1 -1
  104. package/dist/oauth/endpoints/authorize.d.ts.map +1 -1
  105. package/dist/oauth/endpoints/authorize.js +25 -7
  106. package/dist/oauth/endpoints/authorize.js.map +1 -1
  107. package/dist/oauth/endpoints/consent/error-page.d.ts +6 -0
  108. package/dist/oauth/endpoints/consent/error-page.d.ts.map +1 -0
  109. package/dist/oauth/endpoints/consent/error-page.js +60 -0
  110. package/dist/oauth/endpoints/consent/error-page.js.map +1 -0
  111. package/dist/oauth/endpoints/{consent.d.ts → consent/handler.d.ts} +2 -2
  112. package/dist/oauth/endpoints/consent/handler.d.ts.map +1 -0
  113. package/dist/oauth/endpoints/{consent.js → consent/handler.js} +20 -13
  114. package/dist/oauth/endpoints/consent/handler.js.map +1 -0
  115. package/dist/oauth/endpoints/{consent-page.d.ts → consent/page.d.ts} +2 -2
  116. package/dist/oauth/endpoints/consent/page.d.ts.map +1 -0
  117. package/dist/oauth/endpoints/consent/page.js +106 -0
  118. package/dist/oauth/endpoints/consent/page.js.map +1 -0
  119. package/dist/oauth/endpoints/metadata.d.ts +0 -1
  120. package/dist/oauth/endpoints/metadata.d.ts.map +1 -1
  121. package/dist/oauth/endpoints/metadata.js.map +1 -1
  122. package/dist/oauth/endpoints/register.js +3 -3
  123. package/dist/oauth/endpoints/register.js.map +1 -1
  124. package/dist/oauth/endpoints/token.d.ts.map +1 -1
  125. package/dist/oauth/endpoints/token.js +9 -6
  126. package/dist/oauth/endpoints/token.js.map +1 -1
  127. package/dist/oauth/endpoints/wellknown.d.ts.map +1 -1
  128. package/dist/oauth/endpoints/wellknown.js +2 -9
  129. package/dist/oauth/endpoints/wellknown.js.map +1 -1
  130. package/dist/oauth/policy/redirect.d.ts +4 -0
  131. package/dist/oauth/policy/redirect.d.ts.map +1 -1
  132. package/dist/oauth/policy/redirect.js +15 -1
  133. package/dist/oauth/policy/redirect.js.map +1 -1
  134. package/dist/oauth/policy/reqbody.d.ts +6 -1
  135. package/dist/oauth/policy/reqbody.d.ts.map +1 -1
  136. package/dist/oauth/policy/reqbody.js +8 -3
  137. package/dist/oauth/policy/reqbody.js.map +1 -1
  138. package/dist/oauth/router.js +1 -1
  139. package/dist/oauth/router.js.map +1 -1
  140. package/dist/oauth/types.d.ts +3 -1
  141. package/dist/oauth/types.d.ts.map +1 -1
  142. package/dist/server.d.ts +1 -1
  143. package/dist/server.js +1 -1
  144. package/dist/util/clip.d.ts +7 -0
  145. package/dist/util/clip.d.ts.map +1 -0
  146. package/dist/util/clip.js +13 -0
  147. package/dist/util/clip.js.map +1 -0
  148. package/dist/util/json.d.ts +5 -0
  149. package/dist/util/json.d.ts.map +1 -1
  150. package/dist/util/json.js +21 -0
  151. package/dist/util/json.js.map +1 -1
  152. package/dist/util/own.d.ts +8 -0
  153. package/dist/util/own.d.ts.map +1 -0
  154. package/dist/util/own.js +8 -0
  155. package/dist/util/own.js.map +1 -0
  156. package/docs/ROADMAP.md +17 -229
  157. package/docs/compatibility.md +15 -3
  158. package/docs/guide.md +15 -4
  159. package/docs/reference.md +5 -3
  160. package/docs/security.md +63 -7
  161. package/docs/troubleshooting.md +4 -0
  162. package/package.json +7 -4
  163. package/dist/auth/signed-token.d.ts +0 -26
  164. package/dist/auth/signed-token.d.ts.map +0 -1
  165. package/dist/auth/signed-token.js +0 -96
  166. package/dist/auth/signed-token.js.map +0 -1
  167. package/dist/oauth/endpoints/consent-page.d.ts.map +0 -1
  168. package/dist/oauth/endpoints/consent-page.js +0 -63
  169. package/dist/oauth/endpoints/consent-page.js.map +0 -1
  170. package/dist/oauth/endpoints/consent.d.ts.map +0 -1
  171. package/dist/oauth/endpoints/consent.js.map +0 -1
  172. package/docs/diagrams/demo-tool-result.png +0 -0
  173. package/docs/diagrams/mcp-trellis-architecture.html +0 -305
@@ -0,0 +1,85 @@
1
+ /**
2
+ * HMAC-signed JSON payloads for `signedTokenAuth`. Internal: not exported
3
+ * from the package.
4
+ *
5
+ * The HKDF `info` string is the only thing that stops one token type being
6
+ * presented as another (they share the `body.signature` shape), so the kind
7
+ * is a closed set here and never a caller-chosen label.
8
+ */
9
+ import { bytesToBase64Url, fromBase64Url } from "../../oauth/crypto/base64url.js";
10
+ import { hkdfKey } from "../../oauth/crypto/hkdf.js";
11
+ import { isJsonObject } from "../../util/json.js";
12
+ const TOKEN_LABELS = {
13
+ access: "mcp-trellis:signed-access-token:v1",
14
+ refresh: "mcp-trellis:signed-refresh-token:v1",
15
+ };
16
+ /**
17
+ * Refresh tokens are capped, and `signPayload` enforces it so an oversized one
18
+ * fails when issued, not on every later use. Access tokens are bounded only by
19
+ * the server's header limit, so a long user id still verifies.
20
+ */
21
+ const MAX_REFRESH_TOKEN_LENGTH = 4096;
22
+ const exceedsCap = (kind, token) => kind === "refresh" && token.length > MAX_REFRESH_TOKEN_LENGTH;
23
+ const HMAC_SHA256 = { name: "HMAC", hash: "SHA-256", length: 256 };
24
+ const tokenKey = (secret, kind, usage) => hkdfKey(secret, { info: TOKEN_LABELS[kind], algorithm: HMAC_SHA256, usage });
25
+ export const signPayload = async (secret, kind, payload) => {
26
+ const key = await tokenKey(secret, kind, "sign");
27
+ const body = bytesToBase64Url(new TextEncoder().encode(JSON.stringify(payload)));
28
+ const signature = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(body));
29
+ const token = `${body}.${bytesToBase64Url(signature)}`;
30
+ if (exceedsCap(kind, token)) {
31
+ throw new Error(`signedTokenAuth: a refresh token would be ${token.length} characters, over the ` +
32
+ `${MAX_REFRESH_TOKEN_LENGTH} limit — shorten the user id or the scope list`);
33
+ }
34
+ return token;
35
+ };
36
+ /**
37
+ * True when `signature` verifies `body` under any of `secrets`, tried in order.
38
+ * ponytail: one HMAC per rotation entry for a forged token; `signedTokenAuth`
39
+ * caps the list at 8. Upgrade: carry a key id in the token and look the key up.
40
+ */
41
+ const signedByAny = async (secrets, kind, token) => {
42
+ const signature = fromBase64Url(token.signature);
43
+ const message = new TextEncoder().encode(token.body);
44
+ for (const secret of secrets) {
45
+ const key = await tokenKey(secret, kind, "verify");
46
+ if (await crypto.subtle.verify("HMAC", key, signature, message))
47
+ return true;
48
+ }
49
+ return false;
50
+ };
51
+ /**
52
+ * The decoded payload of a token of `kind` signed by one of `secrets`, or
53
+ * null for anything else. Callers still shape-check what comes back: a valid
54
+ * signature proves who signed it, not what it contains.
55
+ */
56
+ export const verifyPayload = async (secrets, kind, token) => {
57
+ if (exceedsCap(kind, token))
58
+ return null;
59
+ const parts = token.split(".");
60
+ const [body, signature] = parts;
61
+ if (parts.length !== 2 || !body || !signature)
62
+ return null;
63
+ try {
64
+ if (!(await signedByAny(secrets, kind, { body, signature })))
65
+ return null;
66
+ return JSON.parse(new TextDecoder().decode(fromBase64Url(body)));
67
+ }
68
+ catch {
69
+ return null;
70
+ }
71
+ };
72
+ const isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
73
+ /** The shared claims of a verified payload, or null if one is missing, malformed or expired. */
74
+ export const parseGrantClaims = (payload) => {
75
+ if (!isJsonObject(payload))
76
+ return null;
77
+ const { userId, scopes, audience, exp } = payload;
78
+ if (typeof userId !== "string" || typeof audience !== "string" || !isStringArray(scopes)) {
79
+ return null;
80
+ }
81
+ if (typeof exp !== "number" || !Number.isFinite(exp) || exp < Date.now())
82
+ return null;
83
+ return { userId, scopes, audience, exp };
84
+ };
85
+ //# sourceMappingURL=payload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"payload.js","sourceRoot":"","sources":["../../../src/auth/signed/payload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Stateless refresh tokens for `signedTokenAuth`. Internal: not exported
3
+ * from the package.
4
+ *
5
+ * Signed, not stored. The only state is the single-use `jti` mark in the
6
+ * shared `codeStore`, which is what makes rotation work: a refresh token is
7
+ * accepted once and its successor is a different token. The mark lives until
8
+ * the grant's `exp`, one per refresh.
9
+ *
10
+ * ponytail: a replayed, already-rotated token is refused, but there is no
11
+ * token family to revoke when that happens, so the thief's successor stays
12
+ * valid until `exp` or until `isUserActive` turns false. Upgrade: an opaque
13
+ * server-side refresh store (see `examples/project-desk/src/tokens.ts`).
14
+ */
15
+ import type { CodeStore } from "../../oauth/crypto/codes.js";
16
+ import type { MintAccessTokenInput, MintedToken, RefreshAccessTokenInput, RevokeTokenInput } from "../../oauth/types.js";
17
+ export type SecretList = readonly [string, ...string[]];
18
+ export type UserCheck = (userId: string) => boolean | Promise<boolean>;
19
+ export type AccessMinter = (input: MintAccessTokenInput) => Promise<MintedToken>;
20
+ type RefreshTokenConfig = {
21
+ secrets: SecretList;
22
+ lifetimeMs: number;
23
+ codeStore: CodeStore;
24
+ isUserActive: UserCheck;
25
+ mintAccess: AccessMinter;
26
+ };
27
+ export type RefreshTokens = {
28
+ issue: (grant: MintAccessTokenInput) => Promise<string>;
29
+ refresh: (input: RefreshAccessTokenInput) => Promise<MintedToken | null>;
30
+ revoke: (input: RevokeTokenInput) => Promise<void>;
31
+ };
32
+ export declare const createRefreshTokens: (config: RefreshTokenConfig) => RefreshTokens;
33
+ export {};
34
+ //# sourceMappingURL=refresh.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.d.ts","sourceRoot":"","sources":["../../../src/auth/signed/refresh.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAI7D,OAAO,KAAK,EACV,oBAAoB,EACpB,WAAW,EACX,uBAAuB,EACvB,gBAAgB,EACjB,MAAM,sBAAsB,CAAC;AAoB9B,MAAM,MAAM,UAAU,GAAG,SAAS,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;AACxD,MAAM,MAAM,SAAS,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AACvE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;AAEjF,KAAK,kBAAkB,GAAG;IACxB,OAAO,EAAE,UAAU,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,CAAC;IACrB,YAAY,EAAE,SAAS,CAAC;IACxB,UAAU,EAAE,YAAY,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,CAAC,KAAK,EAAE,oBAAoB,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACxD,OAAO,EAAE,CAAC,KAAK,EAAE,uBAAuB,KAAK,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,CAAC;IACzE,MAAM,EAAE,CAAC,KAAK,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD,CAAC;AAqFF,eAAO,MAAM,mBAAmB,GAAI,QAAQ,kBAAkB,KAAG,aAI/D,CAAC"}
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Stateless refresh tokens for `signedTokenAuth`. Internal: not exported
3
+ * from the package.
4
+ *
5
+ * Signed, not stored. The only state is the single-use `jti` mark in the
6
+ * shared `codeStore`, which is what makes rotation work: a refresh token is
7
+ * accepted once and its successor is a different token. The mark lives until
8
+ * the grant's `exp`, one per refresh.
9
+ *
10
+ * ponytail: a replayed, already-rotated token is refused, but there is no
11
+ * token family to revoke when that happens, so the thief's successor stays
12
+ * valid until `exp` or until `isUserActive` turns false. Upgrade: an opaque
13
+ * server-side refresh store (see `examples/project-desk/src/tokens.ts`).
14
+ */
15
+ import { randomBase64Url, sha256Base64Url } from "../../oauth/crypto/pkce.js";
16
+ import { resourcesEqual } from "../../oauth/policy/resource.js";
17
+ import { formatScope, parseScope } from "../../oauth/policy/scope.js";
18
+ import { isJsonObject } from "../../util/json.js";
19
+ import { parseGrantClaims, signPayload, verifyPayload } from "./payload.js";
20
+ const JTI_BYTES = 16;
21
+ const MAX_JTI_LENGTH = 64;
22
+ /** Keeps a refresh `jti` apart from auth-code jtis (bare) and consent tickets (`ct:`). */
23
+ const JTI_KEY_PREFIX = "rt:";
24
+ const hasText = (value) => typeof value === "string" && value !== "";
25
+ const parseRefreshPayload = (payload) => {
26
+ if (!isJsonObject(payload))
27
+ return null;
28
+ const claims = parseGrantClaims(payload);
29
+ if (!claims || claims.userId === "" || claims.audience === "")
30
+ return null;
31
+ const { clientHash, jti } = payload;
32
+ if (!hasText(clientHash) || !hasText(jti) || jti.length > MAX_JTI_LENGTH)
33
+ return null;
34
+ return { ...claims, clientHash, jti };
35
+ };
36
+ /** The requested scope narrowed to what the grant holds, or null if it asks for more. */
37
+ const narrowedScopes = (granted, requested) => {
38
+ if (requested === undefined)
39
+ return granted;
40
+ const wanted = parseScope(requested);
41
+ return wanted.length > 0 && wanted.every((scope) => granted.includes(scope)) ? wanted : null;
42
+ };
43
+ const signRefresh = (config, payload) => signPayload(config.secrets[0], "refresh", payload);
44
+ const readRefresh = async (config, token) => parseRefreshPayload(await verifyPayload(config.secrets, "refresh", token));
45
+ // `=== true`: only a store that says so burns the token; a throw propagates
46
+ // as a 500 instead of letting a replay through.
47
+ const burnRefresh = async (config, payload) => (await config.codeStore.consume(`${JTI_KEY_PREFIX}${payload.jti}`, payload.exp)) === true;
48
+ const issueRefresh = async (config, grant) => signRefresh(config, {
49
+ userId: grant.userId,
50
+ scopes: parseScope(grant.scope),
51
+ audience: grant.resource,
52
+ clientHash: await sha256Base64Url(grant.clientId),
53
+ exp: Date.now() + config.lifetimeMs,
54
+ jti: randomBase64Url(JTI_BYTES),
55
+ });
56
+ /**
57
+ * Order matters: every check that can fail on the caller's input runs before
58
+ * the burn, so a wrong-client or wrong-resource attempt cannot spend the
59
+ * rightful holder's token.
60
+ */
61
+ const rotateRefresh = async (config, input) => {
62
+ const payload = await readRefresh(config, input.refreshToken);
63
+ if (!payload || payload.clientHash !== (await sha256Base64Url(input.clientId)))
64
+ return null;
65
+ if (!resourcesEqual(payload.audience, input.resource))
66
+ return null;
67
+ const scopes = narrowedScopes(payload.scopes, input.scope);
68
+ if (!scopes)
69
+ return null;
70
+ if ((await config.isUserActive(payload.userId)) !== true)
71
+ return null;
72
+ if (!(await burnRefresh(config, payload)))
73
+ return null;
74
+ const access = await config.mintAccess({
75
+ userId: payload.userId,
76
+ clientId: input.clientId,
77
+ scope: formatScope(scopes),
78
+ resource: payload.audience,
79
+ });
80
+ const successor = await signRefresh(config, { ...payload, jti: randomBase64Url(JTI_BYTES) });
81
+ return { ...access, refreshToken: successor };
82
+ };
83
+ /** RFC 7009: an unusable or foreign token is a silent no-op; a store failure is not. */
84
+ const revokeRefresh = async (config, input) => {
85
+ const payload = await readRefresh(config, input.token);
86
+ if (payload && payload.clientHash === (await sha256Base64Url(input.clientId))) {
87
+ await burnRefresh(config, payload);
88
+ }
89
+ };
90
+ export const createRefreshTokens = (config) => ({
91
+ issue: (grant) => issueRefresh(config, grant),
92
+ refresh: (input) => rotateRefresh(config, input),
93
+ revoke: (input) => revokeRefresh(config, input),
94
+ });
95
+ //# sourceMappingURL=refresh.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refresh.js","sourceRoot":"","sources":["../../../src/auth/signed/refresh.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
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 tokens, refresh tokens and sealed codes each use their own label.
5
+ *
6
+ * Tokens are stateless, so an issued access token stays valid until `exp`
7
+ * whatever happens to the login session. Pass `isUserActive` to close that:
8
+ * it runs on every verified token. Refresh is opt-in (`refreshTtlSeconds`);
9
+ * see `refresh.ts` for its limits.
10
+ *
11
+ * ponytail: access tokens cannot be revoked before `exp`; `/revoke` burns
12
+ * refresh tokens only. Upgrade: supply your own `mintAccessToken` /
13
+ * `verifyToken` over a store (see `examples/project-desk/src/tokens.ts`).
14
+ */
15
+ import type { McpAppAuth } from "../../app-options.js";
16
+ import type { CodeStore } from "../../oauth/crypto/codes.js";
17
+ import type { OAuthUser } from "../../oauth/types.js";
18
+ import { type UserCheck } from "./refresh.js";
19
+ export type SignedTokenAuthOptions = {
20
+ /** One secret, or a rotation list: the first signs, every entry verifies (and seals codes). */
21
+ secret: string | string[];
22
+ resolveUser: (request: Request) => Promise<OAuthUser | null>;
23
+ loginUrl: (request: Request, nextPath: string) => string;
24
+ /** Access-token lifetime in seconds. Default 3600. Must be finite and > 0. */
25
+ ttlSeconds?: number;
26
+ /** Passthrough — production still needs a shared store across instances. */
27
+ codeStore?: CodeStore;
28
+ /**
29
+ * Checked on every verified token and every refresh; only `true` passes and a
30
+ * throw is a 500. See docs/security.md#sessions-and-expiry.
31
+ */
32
+ isUserActive?: UserCheck;
33
+ /**
34
+ * Enables rotating refresh tokens; also the absolute lifetime of one grant, counted from the code exchange.
35
+ * Needs `codeStore` and `isUserActive`. See docs/security.md#sessions-and-expiry.
36
+ */
37
+ refreshTtlSeconds?: number;
38
+ };
39
+ /** Builds a complete `McpAppAuth` from one secret plus your session resolver. */
40
+ export declare const signedTokenAuth: (options: SignedTokenAuthOptions) => McpAppAuth;
41
+ //# sourceMappingURL=token.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.d.ts","sourceRoot":"","sources":["../../../src/auth/signed/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAiB,MAAM,sBAAsB,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AAMtB,MAAM,MAAM,sBAAsB,GAAG;IACnC,+FAA+F;IAC/F,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAC1B,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;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AA8EF,iFAAiF;AACjF,eAAO,MAAM,eAAe,GAAI,SAAS,sBAAsB,KAAG,UAoBjE,CAAC"}
@@ -0,0 +1,103 @@
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 tokens, refresh tokens and sealed codes each use their own label.
5
+ *
6
+ * Tokens are stateless, so an issued access token stays valid until `exp`
7
+ * whatever happens to the login session. Pass `isUserActive` to close that:
8
+ * it runs on every verified token. Refresh is opt-in (`refreshTtlSeconds`);
9
+ * see `refresh.ts` for its limits.
10
+ *
11
+ * ponytail: access tokens cannot be revoked before `exp`; `/revoke` burns
12
+ * refresh tokens only. Upgrade: supply your own `mintAccessToken` /
13
+ * `verifyToken` over a store (see `examples/project-desk/src/tokens.ts`).
14
+ */
15
+ import { assertCodeSecret } from "../../oauth/config.js";
16
+ import { parseScope } from "../../oauth/policy/scope.js";
17
+ import { parseGrantClaims, signPayload, verifyPayload } from "./payload.js";
18
+ import { createRefreshTokens, } from "./refresh.js";
19
+ const DEFAULT_TTL_SECONDS = 3600;
20
+ /** Each secret costs a key derivation per token kind, so rotation lists stay short. */
21
+ const MAX_SECRETS = 8;
22
+ const toVerified = ({ userId, scopes, audience }) => ({
23
+ userId,
24
+ scopes,
25
+ audience,
26
+ });
27
+ const assertPositiveSeconds = (name, value) => {
28
+ if (!Number.isFinite(value) || value <= 0) {
29
+ throw new Error(`signedTokenAuth: ${name} must be a finite number > 0 (got ${value})`);
30
+ }
31
+ };
32
+ const resolveSecretList = (secret) => {
33
+ const secrets = Array.isArray(secret) ? [...secret] : [secret];
34
+ const [first, ...rest] = secrets;
35
+ if (first === undefined || secrets.length > MAX_SECRETS) {
36
+ throw new Error(`signedTokenAuth: secret needs 1 to ${MAX_SECRETS} entries (got ${secrets.length})`);
37
+ }
38
+ secrets.forEach(assertCodeSecret);
39
+ return [first, ...rest];
40
+ };
41
+ const accessMinter = (secrets, ttlSeconds) => async (input) => ({
42
+ accessToken: await signPayload(secrets[0], "access", {
43
+ userId: input.userId,
44
+ scopes: parseScope(input.scope),
45
+ audience: input.resource,
46
+ exp: Date.now() + ttlSeconds * 1000,
47
+ }),
48
+ expiresIn: ttlSeconds,
49
+ scope: input.scope,
50
+ });
51
+ /** Signature, then expiry and shape, then the user check: a garbage token never reaches the host. */
52
+ const accessVerifier = (secrets, isUserActive) => async (token) => {
53
+ const payload = parseGrantClaims(await verifyPayload(secrets, "access", token));
54
+ if (!payload)
55
+ return null;
56
+ if (isUserActive && (await isUserActive(payload.userId)) !== true)
57
+ return null;
58
+ return toVerified(payload);
59
+ };
60
+ /** The refresh machinery, or undefined when `refreshTtlSeconds` is unset. */
61
+ const refreshTokensFor = (options, secrets, mintAccess) => {
62
+ const { refreshTtlSeconds, codeStore, isUserActive } = options;
63
+ if (refreshTtlSeconds === undefined)
64
+ return undefined;
65
+ assertPositiveSeconds("refreshTtlSeconds", refreshTtlSeconds);
66
+ if (!codeStore) {
67
+ throw new Error("signedTokenAuth: refreshTtlSeconds needs an explicit codeStore (single-use refresh tokens " +
68
+ "must share the router's store; allowInMemoryCodeStore's hidden default is not visible here)");
69
+ }
70
+ if (!isUserActive) {
71
+ throw new Error("signedTokenAuth: refreshTtlSeconds needs isUserActive, or a removed user keeps the connector until the refresh token expires");
72
+ }
73
+ return createRefreshTokens({
74
+ secrets,
75
+ lifetimeMs: refreshTtlSeconds * 1000,
76
+ codeStore,
77
+ isUserActive,
78
+ mintAccess,
79
+ });
80
+ };
81
+ /** Builds a complete `McpAppAuth` from one secret plus your session resolver. */
82
+ export const signedTokenAuth = (options) => {
83
+ const ttlSeconds = options.ttlSeconds ?? DEFAULT_TTL_SECONDS;
84
+ assertPositiveSeconds("ttlSeconds", ttlSeconds);
85
+ const secrets = resolveSecretList(options.secret);
86
+ const mintAccess = accessMinter(secrets, ttlSeconds);
87
+ const refresh = refreshTokensFor(options, secrets, mintAccess);
88
+ return {
89
+ codeSecret: [...secrets],
90
+ resolveUser: options.resolveUser,
91
+ loginUrl: options.loginUrl,
92
+ mintAccessToken: async (input) => {
93
+ if (!refresh)
94
+ return mintAccess(input);
95
+ const [access, refreshToken] = await Promise.all([mintAccess(input), refresh.issue(input)]);
96
+ return { ...access, refreshToken };
97
+ },
98
+ verifyToken: accessVerifier(secrets, options.isUserActive),
99
+ ...(refresh ? { refreshAccessToken: refresh.refresh, revokeToken: refresh.revoke } : {}),
100
+ ...(options.codeStore !== undefined ? { codeStore: options.codeStore } : {}),
101
+ };
102
+ };
103
+ //# sourceMappingURL=token.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token.js","sourceRoot":"","sources":["../../../src/auth/signed/token.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAEzD,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAEzD,OAAO,EAAoB,gBAAgB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC9F,OAAO,EAEL,mBAAmB,GAIpB,MAAM,cAAc,CAAC;AAEtB,MAAM,mBAAmB,GAAG,IAAI,CAAC;AACjC,uFAAuF;AACvF,MAAM,WAAW,GAAG,CAAC,CAAC;AAuBtB,MAAM,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAe,EAAiB,EAAE,CAAC,CAAC;IAChF,MAAM;IACN,MAAM;IACN,QAAQ;CACT,CAAC,CAAC;AAEH,MAAM,qBAAqB,GAAG,CAAC,IAAY,EAAE,KAAa,EAAQ,EAAE;IAClE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC1C,MAAM,IAAI,KAAK,CAAC,oBAAoB,IAAI,qCAAqC,KAAK,GAAG,CAAC,CAAC;IACzF,CAAC;AACH,CAAC,CAAC;AAEF,MAAM,iBAAiB,GAAG,CAAC,MAAyB,EAAc,EAAE;IAClE,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC;IACjC,IAAI,KAAK,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,WAAW,EAAE,CAAC;QACxD,MAAM,IAAI,KAAK,CACb,sCAAsC,WAAW,iBAAiB,OAAO,CAAC,MAAM,GAAG,CACpF,CAAC;IACJ,CAAC;IACD,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;IAClC,OAAO,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,CAAC;AAC1B,CAAC,CAAC;AAEF,MAAM,YAAY,GAChB,CAAC,OAAmB,EAAE,UAAkB,EAAgB,EAAE,CAC1D,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC;IAChB,WAAW,EAAE,MAAM,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE;QACnD,MAAM,EAAE,KAAK,CAAC,MAAM;QACpB,MAAM,EAAE,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC;QAC/B,QAAQ,EAAE,KAAK,CAAC,QAAQ;QACxB,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI;KACd,CAAC;IACxB,SAAS,EAAE,UAAU;IACrB,KAAK,EAAE,KAAK,CAAC,KAAK;CACnB,CAAC,CAAC;AAEL,qGAAqG;AACrG,MAAM,cAAc,GAClB,CAAC,OAAmB,EAAE,YAAmC,EAAE,EAAE,CAC7D,KAAK,EAAE,KAAa,EAAiC,EAAE;IACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,MAAM,aAAa,CAAC,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IAChF,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IAC1B,IAAI,YAAY,IAAI,CAAC,MAAM,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC/E,OAAO,UAAU,CAAC,OAAO,CAAC,CAAC;AAC7B,CAAC,CAAC;AAEJ,6EAA6E;AAC7E,MAAM,gBAAgB,GAAG,CACvB,OAA+B,EAC/B,OAAmB,EACnB,UAAwB,EACG,EAAE;IAC7B,MAAM,EAAE,iBAAiB,EAAE,SAAS,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC;IAC/D,IAAI,iBAAiB,KAAK,SAAS;QAAE,OAAO,SAAS,CAAC;IACtD,qBAAqB,CAAC,mBAAmB,EAAE,iBAAiB,CAAC,CAAC;IAC9D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CACb,4FAA4F;YAC1F,6FAA6F,CAChG,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,MAAM,IAAI,KAAK,CACb,8HAA8H,CAC/H,CAAC;IACJ,CAAC;IACD,OAAO,mBAAmB,CAAC;QACzB,OAAO;QACP,UAAU,EAAE,iBAAiB,GAAG,IAAI;QACpC,SAAS;QACT,YAAY;QACZ,UAAU;KACX,CAAC,CAAC;AACL,CAAC,CAAC;AAEF,iFAAiF;AACjF,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAA+B,EAAc,EAAE;IAC7E,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,mBAAmB,CAAC;IAC7D,qBAAqB,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAChD,MAAM,OAAO,GAAG,iBAAiB,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACrD,MAAM,OAAO,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;IAE/D,OAAO;QACL,UAAU,EAAE,CAAC,GAAG,OAAO,CAAC;QACxB,WAAW,EAAE,OAAO,CAAC,WAAW;QAChC,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,eAAe,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;YAC/B,IAAI,CAAC,OAAO;gBAAE,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC;YACvC,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5F,OAAO,EAAE,GAAG,MAAM,EAAE,YAAY,EAAE,CAAC;QACrC,CAAC;QACD,WAAW,EAAE,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,YAAY,CAAC;QAC1D,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,OAAO,CAAC,OAAO,EAAE,WAAW,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACxF,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC7E,CAAC;AACJ,CAAC,CAAC"}
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/policy/redirect.js";
9
+ import { CHATGPT_CALLBACK, 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: {
@@ -25,7 +25,7 @@ export const CLIENT_PROFILES = {
25
25
  },
26
26
  /** OpenAI Codex / ChatGPT connectors — OAuth 2.1 per the MCP auth spec. */
27
27
  codex: {
28
- redirectUris: [],
28
+ redirectUris: [CHATGPT_CALLBACK],
29
29
  tokenEndpointAuthMethods: [TOKEN_ENDPOINT_AUTH_METHODS.none],
30
30
  preRegistered: false,
31
31
  },
@@ -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,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"}
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,gBAAgB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAiB/E,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,CAAC,gBAAgB,CAAC;QAChC,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"}
@@ -1,31 +1,31 @@
1
1
  /**
2
2
  * Root-entry aliases for symbols that moved to `mcp-trellis/advanced`.
3
3
  * Declared as consts (not `export { } from`) so `@deprecated` reaches
4
- * editors. Removed in 3.0.
4
+ * editors. Removed in the next major release.
5
5
  */
6
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
6
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
7
7
  export declare const timingSafeEqual: (a: string, b: string) => boolean;
8
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
8
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
9
9
  export declare const matchesAny: (presented: string, accepted: string[]) => boolean;
10
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
10
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
11
11
  export declare const corsHeaders: (extra?: Record<string, string>) => Record<string, string>;
12
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
12
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
13
13
  export declare const emptyResponse: (status: number) => Response;
14
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
14
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
15
15
  export declare const methodNotAllowed: (message?: string, options?: import("./server.js").JsonResponseOptions) => Response;
16
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
16
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
17
17
  export declare const optionsResponse: (options?: import("./server.js").JsonResponseOptions) => Response;
18
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
18
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
19
19
  export declare const pickProtocolVersion: (params?: Record<string, unknown>) => string;
20
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
20
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
21
21
  export declare const ASSUMED_HEADER_PROTOCOL_VERSION = "2025-03-26";
22
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
22
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
23
23
  export declare const validateAgainstSchema: (value: unknown, schema: import("./server.js").JsonSchema) => string[];
24
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
24
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
25
25
  export declare const unsupportedKeywords: (schema: import("./server.js").JsonSchema, path?: string) => string[];
26
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
26
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
27
27
  export declare const missingObjectType: (schema: import("./server.js").JsonSchema, path?: string) => string[];
28
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
28
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
29
29
  export declare const JSON_SCHEMA_TYPES: {
30
30
  readonly string: "string";
31
31
  readonly number: "number";
@@ -35,8 +35,8 @@ export declare const JSON_SCHEMA_TYPES: {
35
35
  readonly array: "array";
36
36
  readonly null: "null";
37
37
  };
38
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
38
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
39
39
  export declare const SUPPORTED_SCHEMA_KEYWORDS: ReadonlySet<string>;
40
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
40
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
41
41
  export declare const IGNORED_SCHEMA_KEYWORDS: ReadonlySet<string>;
42
42
  //# sourceMappingURL=deprecated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"deprecated.d.ts","sourceRoot":"","sources":["../src/deprecated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,sEAAsE;AACtE,eAAO,MAAM,eAAe,mCAA2B,CAAC;AACxD,sEAAsE;AACtE,eAAO,MAAM,UAAU,oDAAsB,CAAC;AAC9C,sEAAsE;AACtE,eAAO,MAAM,WAAW,4DAAuB,CAAC;AAChD,sEAAsE;AACtE,eAAO,MAAM,aAAa,8BAAyB,CAAC;AACpD,sEAAsE;AACtE,eAAO,MAAM,gBAAgB,qFAA4B,CAAC;AAC1D,sEAAsE;AACtE,eAAO,MAAM,eAAe,mEAA2B,CAAC;AACxD,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,8CAA+B,CAAC;AAChE,sEAAsE;AACtE,eAAO,MAAM,+BAA+B,eAA2C,CAAC;AACxF,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,wEAAiC,CAAC;AACpE,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,uEAA+B,CAAC;AAChE,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,uEAA6B,CAAC;AAC5D,sEAAsE;AACtE,eAAO,MAAM,iBAAiB;;;;;;;;CAA6B,CAAC;AAC5D,sEAAsE;AACtE,eAAO,MAAM,yBAAyB,qBAAqC,CAAC;AAC5E,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,qBAAmC,CAAC"}
1
+ {"version":3,"file":"deprecated.d.ts","sourceRoot":"","sources":["../src/deprecated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,yFAAyF;AACzF,eAAO,MAAM,eAAe,mCAA2B,CAAC;AACxD,yFAAyF;AACzF,eAAO,MAAM,UAAU,oDAAsB,CAAC;AAC9C,yFAAyF;AACzF,eAAO,MAAM,WAAW,4DAAuB,CAAC;AAChD,yFAAyF;AACzF,eAAO,MAAM,aAAa,8BAAyB,CAAC;AACpD,yFAAyF;AACzF,eAAO,MAAM,gBAAgB,qFAA4B,CAAC;AAC1D,yFAAyF;AACzF,eAAO,MAAM,eAAe,mEAA2B,CAAC;AACxD,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,8CAA+B,CAAC;AAChE,yFAAyF;AACzF,eAAO,MAAM,+BAA+B,eAA2C,CAAC;AACxF,yFAAyF;AACzF,eAAO,MAAM,qBAAqB,wEAAiC,CAAC;AACpE,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,uEAA+B,CAAC;AAChE,yFAAyF;AACzF,eAAO,MAAM,iBAAiB,uEAA6B,CAAC;AAC5D,yFAAyF;AACzF,eAAO,MAAM,iBAAiB;;;;;;;;CAA6B,CAAC;AAC5D,yFAAyF;AACzF,eAAO,MAAM,yBAAyB,qBAAqC,CAAC;AAC5E,yFAAyF;AACzF,eAAO,MAAM,uBAAuB,qBAAmC,CAAC"}
@@ -1,35 +1,35 @@
1
1
  /**
2
2
  * Root-entry aliases for symbols that moved to `mcp-trellis/advanced`.
3
3
  * Declared as consts (not `export { } from`) so `@deprecated` reaches
4
- * editors. Removed in 3.0.
4
+ * editors. Removed in the next major release.
5
5
  */
6
6
  import * as advanced from "./advanced.js";
7
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
7
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
8
8
  export const timingSafeEqual = advanced.timingSafeEqual;
9
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
9
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
10
10
  export const matchesAny = advanced.matchesAny;
11
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
11
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
12
12
  export const corsHeaders = advanced.corsHeaders;
13
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
13
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
14
14
  export const emptyResponse = advanced.emptyResponse;
15
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
15
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
16
16
  export const methodNotAllowed = advanced.methodNotAllowed;
17
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
17
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
18
18
  export const optionsResponse = advanced.optionsResponse;
19
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
19
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
20
20
  export const pickProtocolVersion = advanced.pickProtocolVersion;
21
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
21
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
22
22
  export const ASSUMED_HEADER_PROTOCOL_VERSION = advanced.ASSUMED_HEADER_PROTOCOL_VERSION;
23
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
23
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
24
24
  export const validateAgainstSchema = advanced.validateAgainstSchema;
25
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
25
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
26
26
  export const unsupportedKeywords = advanced.unsupportedKeywords;
27
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
27
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
28
28
  export const missingObjectType = advanced.missingObjectType;
29
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
29
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
30
30
  export const JSON_SCHEMA_TYPES = advanced.JSON_SCHEMA_TYPES;
31
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
31
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
32
32
  export const SUPPORTED_SCHEMA_KEYWORDS = advanced.SUPPORTED_SCHEMA_KEYWORDS;
33
- /** @deprecated Import from "mcp-trellis/advanced". Removed in 3.0. */
33
+ /** @deprecated Import from "mcp-trellis/advanced". Removed in the next major release. */
34
34
  export const IGNORED_SCHEMA_KEYWORDS = advanced.IGNORED_SCHEMA_KEYWORDS;
35
35
  //# sourceMappingURL=deprecated.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"deprecated.js","sourceRoot":"","sources":["../src/deprecated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,sEAAsE;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AACxD,sEAAsE;AACtE,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;AAC9C,sEAAsE;AACtE,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;AAChD,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;AACpD,sEAAsE;AACtE,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;AAC1D,sEAAsE;AACtE,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AACxD,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,CAAC;AAChE,sEAAsE;AACtE,MAAM,CAAC,MAAM,+BAA+B,GAAG,QAAQ,CAAC,+BAA+B,CAAC;AACxF,sEAAsE;AACtE,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC;AACpE,sEAAsE;AACtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,CAAC;AAChE,sEAAsE;AACtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC;AAC5D,sEAAsE;AACtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC;AAC5D,sEAAsE;AACtE,MAAM,CAAC,MAAM,yBAAyB,GAAG,QAAQ,CAAC,yBAAyB,CAAC;AAC5E,sEAAsE;AACtE,MAAM,CAAC,MAAM,uBAAuB,GAAG,QAAQ,CAAC,uBAAuB,CAAC"}
1
+ {"version":3,"file":"deprecated.js","sourceRoot":"","sources":["../src/deprecated.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,QAAQ,MAAM,eAAe,CAAC;AAE1C,yFAAyF;AACzF,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AACxD,yFAAyF;AACzF,MAAM,CAAC,MAAM,UAAU,GAAG,QAAQ,CAAC,UAAU,CAAC;AAC9C,yFAAyF;AACzF,MAAM,CAAC,MAAM,WAAW,GAAG,QAAQ,CAAC,WAAW,CAAC;AAChD,yFAAyF;AACzF,MAAM,CAAC,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC;AACpD,yFAAyF;AACzF,MAAM,CAAC,MAAM,gBAAgB,GAAG,QAAQ,CAAC,gBAAgB,CAAC;AAC1D,yFAAyF;AACzF,MAAM,CAAC,MAAM,eAAe,GAAG,QAAQ,CAAC,eAAe,CAAC;AACxD,yFAAyF;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,CAAC;AAChE,yFAAyF;AACzF,MAAM,CAAC,MAAM,+BAA+B,GAAG,QAAQ,CAAC,+BAA+B,CAAC;AACxF,yFAAyF;AACzF,MAAM,CAAC,MAAM,qBAAqB,GAAG,QAAQ,CAAC,qBAAqB,CAAC;AACpE,yFAAyF;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAG,QAAQ,CAAC,mBAAmB,CAAC;AAChE,yFAAyF;AACzF,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC;AAC5D,yFAAyF;AACzF,MAAM,CAAC,MAAM,iBAAiB,GAAG,QAAQ,CAAC,iBAAiB,CAAC;AAC5D,yFAAyF;AACzF,MAAM,CAAC,MAAM,yBAAyB,GAAG,QAAQ,CAAC,yBAAyB,CAAC;AAC5E,yFAAyF;AACzF,MAAM,CAAC,MAAM,uBAAuB,GAAG,QAAQ,CAAC,uBAAuB,CAAC"}
@@ -8,6 +8,10 @@ export declare class BodyTooLargeError extends Error {
8
8
  readonly maxBytes: number;
9
9
  constructor(maxBytes: number);
10
10
  }
11
+ /** The caller's `signal` aborted the read — a timeout everywhere this library passes one. */
12
+ export declare class BodyReadAbortedError extends Error {
13
+ constructor();
14
+ }
11
15
  /** Default cap for `/mcp` — JSON-RPC payloads, generally small but tool args can be text-heavy. */
12
16
  export declare const DEFAULT_MCP_BODY_LIMIT = 1048576;
13
17
  /** Default cap for OAuth endpoints (`/token`, `/revoke`, `/register`, `/consent`) — tiny form/JSON. */
@@ -1 +1 @@
1
- {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../../src/http/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;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE;QAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAClD,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACxC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,iBAAiB,EACzB,UAAU,MAAM,EAChB,SAAS,WAAW,KACnB,OAAO,CAAC,UAAU,CA6CpB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,eAAe,GAC1B,QAAQ,iBAAiB,EACzB,UAAU,MAAM,EAChB,SAAS,WAAW,KACnB,OAAO,CAAC,MAAM,CAA+E,CAAC;AAEjG,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"}
1
+ {"version":3,"file":"body.d.ts","sourceRoot":"","sources":["../../src/http/body.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,qBAAa,iBAAkB,SAAQ,KAAK;IAC9B,QAAQ,CAAC,QAAQ,EAAE,MAAM;gBAAhB,QAAQ,EAAE,MAAM;CAItC;AAED,6FAA6F;AAC7F,qBAAa,oBAAqB,SAAQ,KAAK;;CAK9C;AAED,mGAAmG;AACnG,eAAO,MAAM,sBAAsB,UAAY,CAAC;AAEhD,uGAAuG;AACvG,eAAO,MAAM,wBAAwB,QAAS,CAAC;AAuB/C;;;;;GAKG;AACH,MAAM,MAAM,iBAAiB,GAAG;IAC9B,OAAO,EAAE;QAAE,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IAClD,IAAI,EAAE,cAAc,CAAC,UAAU,CAAC,GAAG,IAAI,CAAC;IACxC,IAAI,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,qFAAqF;IACrF,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAC;CAC1C,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,gBAAgB,GAC3B,QAAQ,iBAAiB,EACzB,UAAU,MAAM,EAChB,SAAS,WAAW,KACnB,OAAO,CAAC,UAAU,CA6CpB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,eAAe,GAC1B,QAAQ,iBAAiB,EACzB,UAAU,MAAM,EAChB,SAAS,WAAW,KACnB,OAAO,CAAC,MAAM,CAA+E,CAAC;AAEjG,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"}
package/dist/http/body.js CHANGED
@@ -12,6 +12,13 @@ export class BodyTooLargeError extends Error {
12
12
  this.name = "BodyTooLargeError";
13
13
  }
14
14
  }
15
+ /** The caller's `signal` aborted the read — a timeout everywhere this library passes one. */
16
+ export class BodyReadAbortedError extends Error {
17
+ constructor() {
18
+ super("body read aborted");
19
+ this.name = "BodyReadAbortedError";
20
+ }
21
+ }
15
22
  /** Default cap for `/mcp` — JSON-RPC payloads, generally small but tool args can be text-heavy. */
16
23
  export const DEFAULT_MCP_BODY_LIMIT = 1_048_576; // 1 MiB
17
24
  /** Default cap for OAuth endpoints (`/token`, `/revoke`, `/register`, `/consent`) — tiny form/JSON. */
@@ -45,7 +52,7 @@ const toBytes = (chunk) => typeof chunk === "string" ? new TextEncoder().encode(
45
52
  */
46
53
  export const readBoundedBytes = async (source, maxBytes, signal) => {
47
54
  if (signal?.aborted)
48
- throw new Error("body read aborted");
55
+ throw new BodyReadAbortedError();
49
56
  const declared = declaredContentLength(source.headers);
50
57
  if (declared !== null && declared > maxBytes) {
51
58
  throw new BodyTooLargeError(maxBytes);
@@ -73,7 +80,7 @@ export const readBoundedBytes = async (source, maxBytes, signal) => {
73
80
  const { done, value } = await reader.read();
74
81
  // Cancel may settle read() as done — still treat abort as failure.
75
82
  if (signal?.aborted)
76
- throw new Error("body read aborted");
83
+ throw new BodyReadAbortedError();
77
84
  if (done)
78
85
  break;
79
86
  // ponytail: one oversized chunk can briefly allocate maxBytes + highWaterMark