mcp-trellis 0.2.1 → 2.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 (293) hide show
  1. package/README.md +70 -620
  2. package/dist/adapters/node-request.d.ts +53 -0
  3. package/dist/adapters/node-request.d.ts.map +1 -0
  4. package/dist/adapters/node-request.js +165 -0
  5. package/dist/adapters/node-request.js.map +1 -0
  6. package/dist/adapters/node.d.ts +16 -24
  7. package/dist/adapters/node.d.ts.map +1 -1
  8. package/dist/adapters/node.js +69 -88
  9. package/dist/adapters/node.js.map +1 -1
  10. package/dist/advanced.d.ts +18 -0
  11. package/dist/advanced.d.ts.map +1 -0
  12. package/dist/advanced.js +18 -0
  13. package/dist/advanced.js.map +1 -0
  14. package/dist/app-options.d.ts +132 -0
  15. package/dist/app-options.d.ts.map +1 -0
  16. package/dist/app-options.js +2 -0
  17. package/dist/app-options.js.map +1 -0
  18. package/dist/app.d.ts +2 -66
  19. package/dist/app.d.ts.map +1 -1
  20. package/dist/app.js +150 -57
  21. package/dist/app.js.map +1 -1
  22. package/dist/audit.d.ts +5 -5
  23. package/dist/audit.d.ts.map +1 -1
  24. package/dist/audit.js +19 -8
  25. package/dist/audit.js.map +1 -1
  26. package/dist/auth/bearer.d.ts +4 -1
  27. package/dist/auth/bearer.d.ts.map +1 -1
  28. package/dist/auth/bearer.js +25 -5
  29. package/dist/auth/bearer.js.map +1 -1
  30. package/dist/clients.d.ts.map +1 -1
  31. package/dist/clients.js +3 -6
  32. package/dist/clients.js.map +1 -1
  33. package/dist/deprecated.d.ts +42 -0
  34. package/dist/deprecated.d.ts.map +1 -0
  35. package/dist/deprecated.js +35 -0
  36. package/dist/deprecated.js.map +1 -0
  37. package/dist/http/body.d.ts +69 -0
  38. package/dist/http/body.d.ts.map +1 -0
  39. package/dist/http/body.js +165 -0
  40. package/dist/http/body.js.map +1 -0
  41. package/dist/http/http.d.ts +42 -0
  42. package/dist/http/http.d.ts.map +1 -0
  43. package/dist/http/http.js +100 -0
  44. package/dist/http/http.js.map +1 -0
  45. package/dist/http/origins.d.ts +37 -0
  46. package/dist/http/origins.d.ts.map +1 -0
  47. package/dist/http/origins.js +87 -0
  48. package/dist/http/origins.js.map +1 -0
  49. package/dist/mcp/dispatch.d.ts +7 -0
  50. package/dist/mcp/dispatch.d.ts.map +1 -0
  51. package/dist/mcp/dispatch.js +99 -0
  52. package/dist/mcp/dispatch.js.map +1 -0
  53. package/dist/{jsonrpc.d.ts → mcp/jsonrpc.d.ts} +10 -0
  54. package/dist/mcp/jsonrpc.d.ts.map +1 -0
  55. package/dist/mcp/jsonrpc.js +88 -0
  56. package/dist/mcp/jsonrpc.js.map +1 -0
  57. package/dist/mcp/methods.d.ts +133 -0
  58. package/dist/mcp/methods.d.ts.map +1 -0
  59. package/dist/mcp/methods.js +84 -0
  60. package/dist/mcp/methods.js.map +1 -0
  61. package/dist/mcp/protocol.d.ts +16 -0
  62. package/dist/mcp/protocol.d.ts.map +1 -0
  63. package/dist/mcp/protocol.js +22 -0
  64. package/dist/mcp/protocol.js.map +1 -0
  65. package/dist/mcp/registry.d.ts +58 -0
  66. package/dist/mcp/registry.d.ts.map +1 -0
  67. package/dist/mcp/registry.js +81 -0
  68. package/dist/mcp/registry.js.map +1 -0
  69. package/dist/mcp/rpc-handlers.d.ts +11 -0
  70. package/dist/mcp/rpc-handlers.d.ts.map +1 -0
  71. package/dist/mcp/rpc-handlers.js +133 -0
  72. package/dist/mcp/rpc-handlers.js.map +1 -0
  73. package/dist/{tools.d.ts → mcp/tools.d.ts} +30 -2
  74. package/dist/mcp/tools.d.ts.map +1 -0
  75. package/dist/mcp/tools.js +166 -0
  76. package/dist/mcp/tools.js.map +1 -0
  77. package/dist/{validate.d.ts → mcp/validate.d.ts} +24 -12
  78. package/dist/mcp/validate.d.ts.map +1 -0
  79. package/dist/mcp/validate.js +186 -0
  80. package/dist/mcp/validate.js.map +1 -0
  81. package/dist/oauth/audit.d.ts +20 -0
  82. package/dist/oauth/audit.d.ts.map +1 -0
  83. package/dist/oauth/audit.js +29 -0
  84. package/dist/oauth/audit.js.map +1 -0
  85. package/dist/oauth/cimd/cimd-parse.d.ts +4 -0
  86. package/dist/oauth/cimd/cimd-parse.d.ts.map +1 -0
  87. package/dist/oauth/cimd/cimd-parse.js +70 -0
  88. package/dist/oauth/cimd/cimd-parse.js.map +1 -0
  89. package/dist/oauth/cimd/cimd-ssrf.d.ts +8 -0
  90. package/dist/oauth/cimd/cimd-ssrf.d.ts.map +1 -0
  91. package/dist/oauth/cimd/cimd-ssrf.js +193 -0
  92. package/dist/oauth/cimd/cimd-ssrf.js.map +1 -0
  93. package/dist/oauth/cimd/cimd.d.ts +36 -0
  94. package/dist/oauth/cimd/cimd.d.ts.map +1 -0
  95. package/dist/oauth/cimd/cimd.js +132 -0
  96. package/dist/oauth/cimd/cimd.js.map +1 -0
  97. package/dist/oauth/cimd/types.d.ts +12 -0
  98. package/dist/oauth/cimd/types.d.ts.map +1 -0
  99. package/dist/oauth/cimd/types.js +3 -0
  100. package/dist/oauth/cimd/types.js.map +1 -0
  101. package/dist/oauth/config.d.ts +51 -0
  102. package/dist/oauth/config.d.ts.map +1 -0
  103. package/dist/oauth/config.js +108 -0
  104. package/dist/oauth/config.js.map +1 -0
  105. package/dist/oauth/constants.d.ts +15 -0
  106. package/dist/oauth/constants.d.ts.map +1 -1
  107. package/dist/oauth/constants.js +15 -0
  108. package/dist/oauth/constants.js.map +1 -1
  109. package/dist/oauth/{base64url.d.ts → crypto/base64url.d.ts} +1 -2
  110. package/dist/oauth/crypto/base64url.d.ts.map +1 -0
  111. package/dist/oauth/{base64url.js → crypto/base64url.js} +1 -5
  112. package/dist/oauth/crypto/base64url.js.map +1 -0
  113. package/dist/oauth/crypto/clientauth.d.ts +13 -0
  114. package/dist/oauth/crypto/clientauth.d.ts.map +1 -0
  115. package/dist/oauth/crypto/clientauth.js +195 -0
  116. package/dist/oauth/crypto/clientauth.js.map +1 -0
  117. package/dist/oauth/crypto/codes.d.ts +65 -0
  118. package/dist/oauth/crypto/codes.d.ts.map +1 -0
  119. package/dist/oauth/crypto/codes.js +121 -0
  120. package/dist/oauth/crypto/codes.js.map +1 -0
  121. package/dist/oauth/crypto/hkdf.d.ts +13 -0
  122. package/dist/oauth/crypto/hkdf.d.ts.map +1 -0
  123. package/dist/oauth/crypto/hkdf.js +30 -0
  124. package/dist/oauth/crypto/hkdf.js.map +1 -0
  125. package/dist/oauth/crypto/keycache.d.ts +19 -0
  126. package/dist/oauth/crypto/keycache.d.ts.map +1 -0
  127. package/dist/oauth/crypto/keycache.js +44 -0
  128. package/dist/oauth/crypto/keycache.js.map +1 -0
  129. package/dist/oauth/crypto/pkce.d.ts.map +1 -0
  130. package/dist/oauth/{pkce.js → crypto/pkce.js} +1 -1
  131. package/dist/oauth/crypto/pkce.js.map +1 -0
  132. package/dist/oauth/crypto/sealed.d.ts +26 -0
  133. package/dist/oauth/crypto/sealed.d.ts.map +1 -0
  134. package/dist/oauth/crypto/sealed.js +65 -0
  135. package/dist/oauth/crypto/sealed.js.map +1 -0
  136. package/dist/oauth/crypto/secrethash.d.ts +58 -0
  137. package/dist/oauth/crypto/secrethash.d.ts.map +1 -0
  138. package/dist/oauth/crypto/secrethash.js +82 -0
  139. package/dist/oauth/crypto/secrethash.js.map +1 -0
  140. package/dist/oauth/deprecated.d.ts +52 -0
  141. package/dist/oauth/deprecated.d.ts.map +1 -0
  142. package/dist/oauth/deprecated.js +49 -0
  143. package/dist/oauth/deprecated.js.map +1 -0
  144. package/dist/oauth/endpoints/authorize.d.ts +3 -0
  145. package/dist/oauth/endpoints/authorize.d.ts.map +1 -0
  146. package/dist/oauth/endpoints/authorize.js +209 -0
  147. package/dist/oauth/endpoints/authorize.js.map +1 -0
  148. package/dist/oauth/endpoints/callback.d.ts +20 -0
  149. package/dist/oauth/endpoints/callback.d.ts.map +1 -0
  150. package/dist/oauth/endpoints/callback.js +31 -0
  151. package/dist/oauth/endpoints/callback.js.map +1 -0
  152. package/dist/oauth/endpoints/consent-page.d.ts +5 -0
  153. package/dist/oauth/endpoints/consent-page.d.ts.map +1 -0
  154. package/dist/oauth/endpoints/consent-page.js +63 -0
  155. package/dist/oauth/endpoints/consent-page.js.map +1 -0
  156. package/dist/oauth/endpoints/consent.d.ts +29 -0
  157. package/dist/oauth/endpoints/consent.d.ts.map +1 -0
  158. package/dist/oauth/endpoints/consent.js +98 -0
  159. package/dist/oauth/endpoints/consent.js.map +1 -0
  160. package/dist/oauth/{metadata.d.ts → endpoints/metadata.d.ts} +14 -8
  161. package/dist/oauth/endpoints/metadata.d.ts.map +1 -0
  162. package/dist/oauth/{metadata.js → endpoints/metadata.js} +10 -4
  163. package/dist/oauth/endpoints/metadata.js.map +1 -0
  164. package/dist/oauth/endpoints/register.d.ts +10 -0
  165. package/dist/oauth/endpoints/register.d.ts.map +1 -0
  166. package/dist/oauth/endpoints/register.js +96 -0
  167. package/dist/oauth/endpoints/register.js.map +1 -0
  168. package/dist/oauth/{revoke.d.ts → endpoints/revoke.d.ts} +1 -1
  169. package/dist/oauth/endpoints/revoke.d.ts.map +1 -0
  170. package/dist/oauth/{revoke.js → endpoints/revoke.js} +11 -9
  171. package/dist/oauth/endpoints/revoke.js.map +1 -0
  172. package/dist/oauth/endpoints/token.d.ts +3 -0
  173. package/dist/oauth/endpoints/token.d.ts.map +1 -0
  174. package/dist/oauth/{token.js → endpoints/token.js} +33 -47
  175. package/dist/oauth/endpoints/token.js.map +1 -0
  176. package/dist/oauth/{wellknown.d.ts → endpoints/wellknown.d.ts} +1 -1
  177. package/dist/oauth/endpoints/wellknown.d.ts.map +1 -0
  178. package/dist/oauth/{wellknown.js → endpoints/wellknown.js} +7 -7
  179. package/dist/oauth/endpoints/wellknown.js.map +1 -0
  180. package/dist/oauth/{redirect.d.ts → policy/redirect.d.ts} +6 -1
  181. package/dist/oauth/policy/redirect.d.ts.map +1 -0
  182. package/dist/oauth/policy/redirect.js +39 -0
  183. package/dist/oauth/policy/redirect.js.map +1 -0
  184. package/dist/oauth/policy/reqbody.d.ts +18 -0
  185. package/dist/oauth/policy/reqbody.d.ts.map +1 -0
  186. package/dist/oauth/policy/reqbody.js +68 -0
  187. package/dist/oauth/policy/reqbody.js.map +1 -0
  188. package/dist/oauth/policy/resource.d.ts +37 -0
  189. package/dist/oauth/policy/resource.d.ts.map +1 -0
  190. package/dist/oauth/policy/resource.js +74 -0
  191. package/dist/oauth/policy/resource.js.map +1 -0
  192. package/dist/oauth/policy/scope.d.ts +20 -0
  193. package/dist/oauth/policy/scope.d.ts.map +1 -0
  194. package/dist/oauth/policy/scope.js +35 -0
  195. package/dist/oauth/policy/scope.js.map +1 -0
  196. package/dist/oauth/router.d.ts +12 -12
  197. package/dist/oauth/router.d.ts.map +1 -1
  198. package/dist/oauth/router.js +105 -87
  199. package/dist/oauth/router.js.map +1 -1
  200. package/dist/oauth/types.d.ts +177 -26
  201. package/dist/oauth/types.d.ts.map +1 -1
  202. package/dist/oauth/types.js +1 -27
  203. package/dist/oauth/types.js.map +1 -1
  204. package/dist/server.d.ts +14 -13
  205. package/dist/server.d.ts.map +1 -1
  206. package/dist/server.js +10 -9
  207. package/dist/server.js.map +1 -1
  208. package/dist/util/defined.d.ts +11 -0
  209. package/dist/util/defined.d.ts.map +1 -0
  210. package/dist/util/defined.js +15 -0
  211. package/dist/util/defined.js.map +1 -0
  212. package/dist/util/json.d.ts +3 -0
  213. package/dist/util/json.d.ts.map +1 -0
  214. package/dist/util/json.js +3 -0
  215. package/dist/util/json.js.map +1 -0
  216. package/docs/ROADMAP.md +283 -0
  217. package/docs/compatibility.md +84 -0
  218. package/docs/diagrams/mcp-trellis-architecture.html +305 -0
  219. package/docs/guide.md +441 -0
  220. package/docs/reference.md +210 -0
  221. package/docs/security.md +112 -0
  222. package/docs/troubleshooting.md +19 -0
  223. package/package.json +24 -8
  224. package/dist/adapters/origins.d.ts +0 -19
  225. package/dist/adapters/origins.d.ts.map +0 -1
  226. package/dist/adapters/origins.js +0 -55
  227. package/dist/adapters/origins.js.map +0 -1
  228. package/dist/dispatch.d.ts +0 -7
  229. package/dist/dispatch.d.ts.map +0 -1
  230. package/dist/dispatch.js +0 -79
  231. package/dist/dispatch.js.map +0 -1
  232. package/dist/http.d.ts +0 -17
  233. package/dist/http.d.ts.map +0 -1
  234. package/dist/http.js +0 -38
  235. package/dist/http.js.map +0 -1
  236. package/dist/jsonrpc.d.ts.map +0 -1
  237. package/dist/jsonrpc.js +0 -17
  238. package/dist/jsonrpc.js.map +0 -1
  239. package/dist/methods.d.ts +0 -61
  240. package/dist/methods.d.ts.map +0 -1
  241. package/dist/methods.js +0 -114
  242. package/dist/methods.js.map +0 -1
  243. package/dist/oauth/authorize.d.ts +0 -3
  244. package/dist/oauth/authorize.d.ts.map +0 -1
  245. package/dist/oauth/authorize.js +0 -109
  246. package/dist/oauth/authorize.js.map +0 -1
  247. package/dist/oauth/base64url.d.ts.map +0 -1
  248. package/dist/oauth/base64url.js.map +0 -1
  249. package/dist/oauth/clientauth.d.ts +0 -19
  250. package/dist/oauth/clientauth.d.ts.map +0 -1
  251. package/dist/oauth/clientauth.js +0 -76
  252. package/dist/oauth/clientauth.js.map +0 -1
  253. package/dist/oauth/codes.d.ts +0 -30
  254. package/dist/oauth/codes.d.ts.map +0 -1
  255. package/dist/oauth/codes.js +0 -93
  256. package/dist/oauth/codes.js.map +0 -1
  257. package/dist/oauth/metadata.d.ts.map +0 -1
  258. package/dist/oauth/metadata.js.map +0 -1
  259. package/dist/oauth/pkce.d.ts.map +0 -1
  260. package/dist/oauth/pkce.js.map +0 -1
  261. package/dist/oauth/redirect.d.ts.map +0 -1
  262. package/dist/oauth/redirect.js +0 -26
  263. package/dist/oauth/redirect.js.map +0 -1
  264. package/dist/oauth/resource.d.ts +0 -7
  265. package/dist/oauth/resource.d.ts.map +0 -1
  266. package/dist/oauth/resource.js +0 -44
  267. package/dist/oauth/resource.js.map +0 -1
  268. package/dist/oauth/revoke.d.ts.map +0 -1
  269. package/dist/oauth/revoke.js.map +0 -1
  270. package/dist/oauth/scope.d.ts +0 -11
  271. package/dist/oauth/scope.d.ts.map +0 -1
  272. package/dist/oauth/scope.js +0 -24
  273. package/dist/oauth/scope.js.map +0 -1
  274. package/dist/oauth/token.d.ts +0 -3
  275. package/dist/oauth/token.d.ts.map +0 -1
  276. package/dist/oauth/token.js.map +0 -1
  277. package/dist/oauth/wellknown.d.ts.map +0 -1
  278. package/dist/oauth/wellknown.js.map +0 -1
  279. package/dist/protocol.d.ts +0 -4
  280. package/dist/protocol.d.ts.map +0 -1
  281. package/dist/protocol.js +0 -14
  282. package/dist/protocol.js.map +0 -1
  283. package/dist/registry.d.ts +0 -37
  284. package/dist/registry.d.ts.map +0 -1
  285. package/dist/registry.js +0 -69
  286. package/dist/registry.js.map +0 -1
  287. package/dist/tools.d.ts.map +0 -1
  288. package/dist/tools.js +0 -97
  289. package/dist/tools.js.map +0 -1
  290. package/dist/validate.d.ts.map +0 -1
  291. package/dist/validate.js +0 -130
  292. package/dist/validate.js.map +0 -1
  293. /package/dist/oauth/{pkce.d.ts → crypto/pkce.d.ts} +0 -0
@@ -0,0 +1,132 @@
1
+ import type { ClientName } from "./clients.js";
2
+ import type { AuditEntry, Principal, ServerInfo } from "./mcp/methods.js";
3
+ import type { ToolDef } from "./mcp/registry.js";
4
+ import type { CimdCache } from "./oauth/cimd/types.js";
5
+ import type { CodeStore } from "./oauth/crypto/codes.js";
6
+ import type { ClientStore, ConsentOptions, MintAccessTokenInput, MintedToken, OAuthAuditEntry, OAuthUser, RefreshAccessTokenInput, RevokeTokenInput } from "./oauth/types.js";
7
+ /** One sink for both MCP tool-call and OAuth AS audit events. */
8
+ export type UnifiedAuditEntry = ({
9
+ source: "mcp";
10
+ } & AuditEntry) | ({
11
+ source: "oauth";
12
+ } & OAuthAuditEntry);
13
+ /** What your token verification returns. The library checks the audience. */
14
+ export type VerifiedToken = {
15
+ userId: string;
16
+ scopes: string[];
17
+ /** RFC 8707 audience the token was minted for. */
18
+ audience: string;
19
+ /** Optional host claims passed through to `context` via `Principal`. */
20
+ claims?: Record<string, unknown>;
21
+ };
22
+ export type McpAppAuth = {
23
+ /**
24
+ * Secret(s) that seal auth codes, consent tickets, and self-issued DCR
25
+ * client assertions, and key `ClientStore.secretHash`. Pass a string, or
26
+ * an array for key rotation — the first
27
+ * entry seals new material, every entry is tried when unsealing/verifying.
28
+ * See `OAuthPorts.codeSecret` for the full rotation contract.
29
+ */
30
+ codeSecret: string | string[] | ((req: Request) => string | string[] | Promise<string | string[]>);
31
+ /** Resolve the logged-in user, or null → redirect to `loginUrl`. */
32
+ resolveUser: (req: Request) => Promise<OAuthUser | null>;
33
+ /** Where to send unauthenticated authorize requests. */
34
+ loginUrl: (req: Request, nextPath: string) => string;
35
+ /** Mint an access token; embed `resource` as the audience. */
36
+ mintAccessToken: (input: MintAccessTokenInput) => Promise<MintedToken>;
37
+ /**
38
+ * Decode and validate a bearer token. Return its `audience` —
39
+ * `createMcpApp` rejects tokens minted for a different resource itself,
40
+ * so this check cannot be forgotten.
41
+ */
42
+ verifyToken: (token: string, req: Request) => Promise<VerifiedToken | null>;
43
+ refreshAccessToken?: (input: RefreshAccessTokenInput) => Promise<MintedToken | null>;
44
+ /** RFC 7009 — presence mounts `/revoke` and advertises it. */
45
+ revokeToken?: (input: RevokeTokenInput) => Promise<void>;
46
+ codeStore?: CodeStore;
47
+ /** Required when any configured client is pre-registered (e.g. Gemini). */
48
+ clientStore?: ClientStore;
49
+ /**
50
+ * Opt-in OAuth-side metrics hook — see the tool-call `audit` below for
51
+ * the general shape. This one sees the real reason behind a collapsed
52
+ * `invalid_client` or a rejected `codeSecret`, which the caller never
53
+ * does. Omit for silence.
54
+ */
55
+ audit?: (entry: OAuthAuditEntry) => void | Promise<void>;
56
+ };
57
+ export type McpAppOptions<TCtx> = {
58
+ serverInfo: ServerInfo;
59
+ tools: ToolDef<TCtx>[];
60
+ auth: McpAppAuth;
61
+ /** Connector clients to serve. Default: `["claude"]`. */
62
+ clients?: ClientName[];
63
+ instructions?: string;
64
+ /** MCP endpoint path. Default `"/mcp"`. */
65
+ resourcePath?: string;
66
+ /** OAuth prefix. Default `` `${resourcePath}/oauth` ``. */
67
+ oauthPath?: string;
68
+ /** Scopes this server grants. Default `["mcp"]`. */
69
+ scopes?: string[];
70
+ /** Required when `scopes` has more than one entry — see `OAuthRouterOptions.defaultScopes`. */
71
+ defaultScopes?: string[];
72
+ realm?: string;
73
+ /** Extra exact-match redirect URIs beyond the client profiles. */
74
+ extraRedirectUris?: string[];
75
+ /** Allow loopback redirects (native clients). Default true. */
76
+ allowLoopback?: boolean;
77
+ /**
78
+ * Consent policy — policy, not a credential, so it sits alongside
79
+ * `allowLoopback` rather than under `auth`. Omit for the built-in
80
+ * hardened interstitial.
81
+ */
82
+ consent?: ConsentOptions;
83
+ /**
84
+ * Require every `client_id` to come from `clientStore` or this server's
85
+ * own `/register` (sealed assertion). Default **true** since 1.0.
86
+ * Set false only to accept invented public ids (pre-CIMD).
87
+ */
88
+ requireRegisteredClients?: boolean;
89
+ /**
90
+ * Validate tools/call args against each tool's `inputSchema`. Default
91
+ * **true** since 2.0. Set false only to skip schema checks intentionally.
92
+ */
93
+ validateArgs?: boolean;
94
+ /**
95
+ * See `OAuthRouterOptions.allowInMemoryCodeStore`. Default false.
96
+ */
97
+ allowInMemoryCodeStore?: boolean;
98
+ /**
99
+ * Opt into CIMD (HTTPS URL `client_id`s). Default **false** — see
100
+ * `OAuthRouterOptions.cimd`.
101
+ */
102
+ cimd?: boolean;
103
+ /**
104
+ * CIMD document cache. Strongly recommended with `cimd: true` — see
105
+ * `OAuthRouterOptions.cimdCache`.
106
+ */
107
+ cimdCache?: CimdCache;
108
+ /** Optional DNS lookup for CIMD SSRF checks. */
109
+ cimdLookup?: (hostname: string) => Promise<string[]>;
110
+ onToolError?: (error: unknown) => string;
111
+ /**
112
+ * Per-call context for tools, built only when a `tools/call` is about to
113
+ * run (see `McpPorts.context`). Defaults to an empty object.
114
+ */
115
+ context?: (req: Request, principal: Principal | null) => TCtx | Promise<TCtx>;
116
+ /**
117
+ * Unified metrics hook for MCP and OAuth events (`source: "mcp" | "oauth"`).
118
+ * Omit for silence. `auth.audit` overrides OAuth delivery when both are set.
119
+ * See `consoleAudit` or `examples/audit-store.ts`.
120
+ */
121
+ audit?: (entry: UnifiedAuditEntry) => void | Promise<void>;
122
+ /** Max time to wait for `audit` above before responding anyway. Default 1000ms. Also applied to `auth.audit`. */
123
+ auditTimeoutMs?: number;
124
+ /**
125
+ * Browser `Origin` allowlist for `/mcp` — see `McpHandlerOptions.allowedRequestOrigins`.
126
+ * Omitted → reject any request that sends `Origin`. Native clients omit the header.
127
+ */
128
+ allowedRequestOrigins?: string[];
129
+ /** Filter `tools/list` by scope. See `McpHandlerOptions.hideToolsOutsideScope`. Default false. */
130
+ hideToolsOutsideScope?: boolean;
131
+ };
132
+ //# sourceMappingURL=app-options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-options.d.ts","sourceRoot":"","sources":["../src/app-options.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=app-options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"app-options.js","sourceRoot":"","sources":["../src/app-options.ts"],"names":[],"mappings":""}
package/dist/app.d.ts CHANGED
@@ -4,72 +4,8 @@
4
4
  * This layers over `createMcpHandler` and `createOAuthRouter`, which stay
5
5
  * exported for anyone who wants to compose the pieces themselves.
6
6
  */
7
- import { type ClientName } from "./clients.js";
8
- import type { AuditEntry, Principal, ServerInfo } from "./methods.js";
9
- import type { CodeStore } from "./oauth/codes.js";
10
- import type { ClientStore, MintAccessTokenInput, MintedToken, OAuthUser, RefreshAccessTokenInput, RevokeTokenInput } from "./oauth/types.js";
11
- import { type ToolDef } from "./registry.js";
12
- /** What your token verification returns. The library checks the audience. */
13
- export type VerifiedToken = {
14
- userId: string;
15
- scopes: string[];
16
- /** RFC 8707 audience the token was minted for. */
17
- audience: string;
18
- /** Optional host claims passed through to `context` via `Principal`. */
19
- claims?: Record<string, unknown>;
20
- };
21
- export type McpAppAuth = {
22
- /** HMAC secret for signing auth codes. */
23
- codeSecret: string | ((req: Request) => string | Promise<string>);
24
- /** Resolve the logged-in user, or null → redirect to `loginUrl`. */
25
- resolveUser: (req: Request) => Promise<OAuthUser | null>;
26
- /** Where to send unauthenticated authorize requests. */
27
- loginUrl: (req: Request, nextPath: string) => string;
28
- /** Mint an access token; embed `resource` as the audience. */
29
- mintAccessToken: (input: MintAccessTokenInput) => Promise<MintedToken>;
30
- /**
31
- * Decode and validate a bearer token. Return its `audience` —
32
- * `createMcpApp` rejects tokens minted for a different resource itself,
33
- * so this check cannot be forgotten.
34
- */
35
- verifyToken: (token: string, req: Request) => Promise<VerifiedToken | null>;
36
- refreshAccessToken?: (input: RefreshAccessTokenInput) => Promise<MintedToken | null>;
37
- /** RFC 7009 — presence mounts `/revoke` and advertises it. */
38
- revokeToken?: (input: RevokeTokenInput) => Promise<void>;
39
- codeStore?: CodeStore;
40
- /** Required when any configured client is pre-registered (e.g. Gemini). */
41
- clientStore?: ClientStore;
42
- };
43
- export type McpAppOptions<TCtx> = {
44
- serverInfo: ServerInfo;
45
- tools: ToolDef<TCtx>[];
46
- auth: McpAppAuth;
47
- /** Connector clients to serve. Default: `["claude"]`. */
48
- clients?: ClientName[];
49
- instructions?: string;
50
- /** MCP endpoint path. Default `"/mcp"`. */
51
- resourcePath?: string;
52
- /** OAuth prefix. Default `` `${resourcePath}/oauth` ``. */
53
- oauthPath?: string;
54
- /** Scopes this server grants. Default `["mcp"]`. */
55
- scopes?: string[];
56
- realm?: string;
57
- /** Extra exact-match redirect URIs beyond the client profiles. */
58
- extraRedirectUris?: string[];
59
- /** Allow loopback redirects (native clients). Default true. */
60
- allowLoopback?: boolean;
61
- validateArgs?: boolean;
62
- onToolError?: (exc: unknown) => string;
63
- /** Per-request context for tools. Defaults to an empty object. */
64
- context?: (req: Request, principal: Principal | null) => TCtx | Promise<TCtx>;
65
- /**
66
- * Opt-in metrics hook — same as `McpPorts.audit`. Pass a function to get
67
- * per-request entries (tools + denials); omit for silence. The library
68
- * never stores or prints these itself. See `consoleAudit` or
69
- * `examples/audit-store.ts`.
70
- */
71
- audit?: (entry: AuditEntry) => void | Promise<void>;
72
- };
7
+ import type { McpAppOptions } from "./app-options.js";
8
+ export type { McpAppAuth, McpAppOptions, UnifiedAuditEntry, VerifiedToken, } from "./app-options.js";
73
9
  export type McpApp = {
74
10
  fetch: (request: Request) => Promise<Response>;
75
11
  };
package/dist/app.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AA0BtD,YAAY,EACV,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,MAAM,GAAG;IACnB,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CAChD,CAAC;AAwLF,eAAO,MAAM,YAAY,GAAI,IAAI,EAAE,SAAS,aAAa,CAAC,IAAI,CAAC,KAAG,MA8CjE,CAAC"}
package/dist/app.js CHANGED
@@ -5,65 +5,111 @@
5
5
  * exported for anyone who wants to compose the pieces themselves.
6
6
  */
7
7
  import { parseBearer } from "./auth/bearer.js";
8
- import { DEFAULT_CLIENTS, assertClientsConfigured, hasDynamicClient, authMethodsFor, redirectUrisFor, } from "./clients.js";
9
- import { createMcpHandler } from "./dispatch.js";
10
- import { INTERNAL_ERROR, jsonResponse } from "./http.js";
8
+ import { assertClientsConfigured, authMethodsFor, DEFAULT_CLIENTS, hasDynamicClient, redirectUrisFor, } from "./clients.js";
9
+ import { errorReason, INTERNAL_ERROR, jsonResponse } from "./http/http.js";
10
+ import { createMcpHandler } from "./mcp/dispatch.js";
11
+ import { safeAudit } from "./mcp/methods.js";
12
+ import { createToolRegistry } from "./mcp/registry.js";
13
+ import { safeOAuthAudit } from "./oauth/audit.js";
14
+ import { DEFAULT_SCOPE } from "./oauth/constants.js";
15
+ import { canonicalResource, DEFAULT_RESOURCE_PATH, normalizeConfiguredPath, resourcesEqual, } from "./oauth/policy/resource.js";
11
16
  import { createOAuthRouter } from "./oauth/router.js";
12
- import { DEFAULT_RESOURCE_PATH, canonicalResource, resourcesEqual, } from "./oauth/resource.js";
13
- import { createToolRegistry } from "./registry.js";
14
- export const createMcpApp = (options) => {
15
- const resourcePath = options.resourcePath ?? DEFAULT_RESOURCE_PATH;
16
- const oauthPath = options.oauthPath ?? `${resourcePath}/oauth`;
17
- const clients = options.clients ?? DEFAULT_CLIENTS;
18
- const realm = options.realm ?? options.serverInfo.name;
19
- assertClientsConfigured(clients, options.auth.clientStore);
20
- const registry = createToolRegistry(options.tools, {
21
- validateArgs: options.validateArgs,
22
- onToolError: options.onToolError,
23
- });
24
- /**
25
- * The audience check lives here, not in user code — a token minted for
26
- * another MCP server must never be accepted by this one.
27
- */
28
- const authenticate = async (req) => {
29
- const token = parseBearer(req.headers.get("authorization"));
17
+ import { pickDefined } from "./util/defined.js";
18
+ /**
19
+ * On a multi-scope server a tool with no `scope` is callable by a principal
20
+ * holding none of the advertised scopes, silently defeating
21
+ * `defaultScopes: []`. Single-scope servers have no such ambiguity. Pass
22
+ * `scope: null` on a tool to state the omission on purpose.
23
+ */
24
+ const assertToolScopesConfigured = (tools, scopes) => {
25
+ if (scopes.length <= 1)
26
+ return;
27
+ const unscoped = tools.filter((tool) => tool.scope === undefined).map((tool) => tool.name);
28
+ if (unscoped.length === 0)
29
+ return;
30
+ throw new Error(`scopes has more than one entry (${scopes.join(", ")}), but these tools have no ` +
31
+ `scope and would be callable by any authenticated principal regardless of what ` +
32
+ `scopes it holds: ${unscoped.join(", ")}. Set scope: "<one of the entries above>" ` +
33
+ `on each, or scope: null to state the omission on purpose.`);
34
+ };
35
+ /**
36
+ * The audience check lives here, not in user code — a token minted for
37
+ * another MCP server must never be accepted by this one.
38
+ */
39
+ const buildAuthenticate = (options, resourcePath) => {
40
+ return async (request) => {
41
+ const token = parseBearer(request.headers.get("authorization"));
30
42
  if (!token)
31
43
  return null;
32
- const verified = await options.auth.verifyToken(token, req);
44
+ const verified = await options.auth.verifyToken(token, request);
33
45
  if (!verified)
34
46
  return null;
35
- const expected = canonicalResource(new URL(req.url).origin, resourcePath);
47
+ const expected = canonicalResource(new URL(request.url).origin, resourcePath);
36
48
  if (!resourcesEqual(verified.audience, expected))
37
49
  return null;
38
- return { id: verified.userId, scopes: verified.scopes, claims: verified.claims };
50
+ return {
51
+ id: verified.userId,
52
+ scopes: verified.scopes,
53
+ ...(verified.claims !== undefined ? { claims: verified.claims } : {}),
54
+ };
39
55
  };
40
- const handler = createMcpHandler({
56
+ };
57
+ /** Top-level `audit` wraps MCP + OAuth; `auth.audit` wins for OAuth if both set. */
58
+ const buildAuditAdapters = (options) => {
59
+ const unifiedAudit = options.audit;
60
+ const toMcpAudit = unifiedAudit !== undefined
61
+ ? (entry) => unifiedAudit({ source: "mcp", ...entry })
62
+ : undefined;
63
+ const oauthAudit = options.auth.audit ??
64
+ (unifiedAudit !== undefined
65
+ ? (entry) => unifiedAudit({ source: "oauth", ...entry })
66
+ : undefined);
67
+ return { toMcpAudit, oauthAudit };
68
+ };
69
+ const buildMcpHandlerOptions = (options, input) => {
70
+ const { resourcePath, realm, registry, authenticate, toMcpAudit } = input;
71
+ return {
41
72
  registry,
42
73
  serverInfo: options.serverInfo,
43
- instructions: options.instructions,
44
- wwwAuthenticate: (req) => ({
74
+ ...pickDefined(options, [
75
+ "instructions",
76
+ "auditTimeoutMs",
77
+ "allowedRequestOrigins",
78
+ "hideToolsOutsideScope",
79
+ ]),
80
+ wwwAuthenticate: (request) => ({
45
81
  realm,
46
- resourceMetadataUrl: `${new URL(req.url).origin}/.well-known/oauth-protected-resource${resourcePath}`,
82
+ resourceMetadataUrl: `${new URL(request.url).origin}/.well-known/oauth-protected-resource${resourcePath}`,
47
83
  }),
48
84
  ports: {
49
85
  authenticate,
50
86
  context: options.context ?? (() => ({})),
51
- audit: options.audit,
87
+ ...(toMcpAudit !== undefined ? { audit: toMcpAudit } : {}),
52
88
  },
53
- });
54
- const oauth = createOAuthRouter({
89
+ };
90
+ };
91
+ const buildOAuthOptions = (options, input) => {
92
+ const { resourcePath, oauthPath, realm, clients, oauthAudit } = input;
93
+ return {
55
94
  resourcePath,
56
95
  oauthPath,
57
96
  realm,
58
- scopes: options.scopes,
97
+ ...pickDefined(options, [
98
+ "scopes",
99
+ "defaultScopes",
100
+ "auditTimeoutMs",
101
+ "allowInMemoryCodeStore",
102
+ "cimd",
103
+ "cimdCache",
104
+ "cimdLookup",
105
+ "requireRegisteredClients",
106
+ "consent",
107
+ ]),
59
108
  tokenEndpointAuthMethods: authMethodsFor(clients),
60
109
  allowUnregisteredClients: hasDynamicClient(clients),
61
110
  redirect: {
62
111
  // Client profiles are the source of truth for callbacks.
63
- extra: [
64
- ...redirectUrisFor(clients),
65
- ...(options.extraRedirectUris ?? []),
66
- ],
112
+ extra: [...redirectUrisFor(clients), ...(options.extraRedirectUris ?? [])],
67
113
  allowClaude: false,
68
114
  allowLoopback: options.allowLoopback ?? true,
69
115
  },
@@ -72,30 +118,77 @@ export const createMcpApp = (options) => {
72
118
  resolveUser: options.auth.resolveUser,
73
119
  loginUrl: options.auth.loginUrl,
74
120
  mintAccessToken: options.auth.mintAccessToken,
75
- refreshAccessToken: options.auth.refreshAccessToken,
76
- revokeToken: options.auth.revokeToken,
77
- codeStore: options.auth.codeStore,
78
- clientStore: options.auth.clientStore,
121
+ ...pickDefined(options.auth, [
122
+ "refreshAccessToken",
123
+ "revokeToken",
124
+ "codeStore",
125
+ "clientStore",
126
+ ]),
127
+ ...(oauthAudit !== undefined ? { audit: oauthAudit } : {}),
79
128
  },
129
+ };
130
+ };
131
+ const createAppFetch = (parts) => async (request) => {
132
+ try {
133
+ const oauthResponse = await parts.oauth.tryHandle(request);
134
+ if (oauthResponse)
135
+ return oauthResponse;
136
+ const requestPath = normalizeConfiguredPath(new URL(request.url).pathname);
137
+ if (requestPath === parts.resourcePath)
138
+ return await parts.handler.fetch(request);
139
+ return jsonResponse({ data: { error: "Not found" }, status: 404 });
140
+ }
141
+ catch (caught) {
142
+ // Defense in depth: `oauth` and `handler` already turn port failures
143
+ // into responses, but `fetch` must never reject, and this path is
144
+ // audited so it is never silent.
145
+ const reason = errorReason(caught);
146
+ await safeOAuthAudit(parts.oauthOptions, { event: "server_error", reason });
147
+ await safeAudit(parts.mcpHandlerOptions, {
148
+ method: "",
149
+ ok: false,
150
+ error: reason,
151
+ durationMs: 0,
152
+ });
153
+ return jsonResponse({ data: { error: INTERNAL_ERROR }, status: 500 });
154
+ }
155
+ };
156
+ export const createMcpApp = (options) => {
157
+ // "/mcp/" and "/mcp" must route identically.
158
+ const resourcePath = normalizeConfiguredPath(options.resourcePath ?? DEFAULT_RESOURCE_PATH);
159
+ // Avoid "//oauth" when the resource is mounted at "/".
160
+ const oauthPath = options.oauthPath ?? (resourcePath === "/" ? "/oauth" : `${resourcePath}/oauth`);
161
+ const clients = options.clients ?? DEFAULT_CLIENTS;
162
+ const realm = options.realm ?? options.serverInfo.name;
163
+ assertClientsConfigured(clients, options.auth.clientStore);
164
+ assertToolScopesConfigured(options.tools, options.scopes ?? [DEFAULT_SCOPE]);
165
+ const registry = createToolRegistry(options.tools, pickDefined(options, ["validateArgs", "onToolError"]));
166
+ const authenticate = buildAuthenticate(options, resourcePath);
167
+ const { toMcpAudit, oauthAudit } = buildAuditAdapters(options);
168
+ // Built once and shared with the `fetch` catch path below, so the fallback
169
+ // audit sees exactly the same ports/timeout as the handler itself.
170
+ const mcpHandlerOptions = buildMcpHandlerOptions(options, {
171
+ resourcePath,
172
+ realm,
173
+ registry,
174
+ authenticate,
175
+ toMcpAudit,
176
+ });
177
+ const oauthOptions = buildOAuthOptions(options, {
178
+ resourcePath,
179
+ oauthPath,
180
+ realm,
181
+ clients,
182
+ oauthAudit,
80
183
  });
81
184
  return {
82
- fetch: async (request) => {
83
- try {
84
- const oauthResponse = await oauth.tryHandle(request);
85
- if (oauthResponse)
86
- return oauthResponse;
87
- if (new URL(request.url).pathname === resourcePath) {
88
- return await handler.fetch(request);
89
- }
90
- return jsonResponse({ error: "Not found" }, 404);
91
- }
92
- catch {
93
- // Both `oauth` and `handler` already turn port failures into a
94
- // Response themselves — this is defense in depth, not the primary
95
- // guard. `fetch` must never reject.
96
- return jsonResponse({ error: INTERNAL_ERROR }, 500);
97
- }
98
- },
185
+ fetch: createAppFetch({
186
+ resourcePath,
187
+ oauth: createOAuthRouter(oauthOptions),
188
+ oauthOptions,
189
+ handler: createMcpHandler(mcpHandlerOptions),
190
+ mcpHandlerOptions,
191
+ }),
99
192
  };
100
193
  };
101
194
  //# sourceMappingURL=app.js.map
package/dist/app.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app.js","sourceRoot":"","sources":["../src/app.ts"],"names":[],"mappings":"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"}
package/dist/audit.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { AuditEntry } from "./methods.js";
1
+ import type { UnifiedAuditEntry } from "./app-options.js";
2
2
  /**
3
3
  * Convenience `audit` sink that logs each entry to the console.
4
4
  *
@@ -10,9 +10,9 @@ import type { AuditEntry } from "./methods.js";
10
10
  * createMcpApp({ ..., audit: consoleAudit })
11
11
  * createMcpApp({ ..., audit: (entry) => { void insert(entry) } })
12
12
  *
13
- * Failures (`ok: false`, including transport-level denials and tool
14
- * exceptions) go to `console.error`; everything else to `console.log`.
15
- * Entries never carry raw exceptions or stack traces (see `AuditEntry`).
13
+ * MCP failures (`ok: false`) go to `console.error`; MCP successes and
14
+ * OAuth events go to `console.log`. Entries never carry raw exceptions or
15
+ * stack traces (see `AuditEntry` / `OAuthAuditEntry`).
16
16
  */
17
- export declare const consoleAudit: (entry: AuditEntry) => void;
17
+ export declare const consoleAudit: (entry: UnifiedAuditEntry) => void;
18
18
  //# sourceMappingURL=audit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,UAAU,KAAG,IAiBhD,CAAC"}
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,YAAY,GAAI,OAAO,iBAAiB,KAAG,IA8BvD,CAAC"}
package/dist/audit.js CHANGED
@@ -9,13 +9,25 @@
9
9
  * createMcpApp({ ..., audit: consoleAudit })
10
10
  * createMcpApp({ ..., audit: (entry) => { void insert(entry) } })
11
11
  *
12
- * Failures (`ok: false`, including transport-level denials and tool
13
- * exceptions) go to `console.error`; everything else to `console.log`.
14
- * Entries never carry raw exceptions or stack traces (see `AuditEntry`).
12
+ * MCP failures (`ok: false`) go to `console.error`; MCP successes and
13
+ * OAuth events go to `console.log`. Entries never carry raw exceptions or
14
+ * stack traces (see `AuditEntry` / `OAuthAuditEntry`).
15
15
  */
16
16
  export const consoleAudit = (entry) => {
17
+ if (entry.source === "oauth") {
18
+ const line = [
19
+ `[mcp-trellis] oauth`,
20
+ entry.event,
21
+ entry.clientId ? `client=${entry.clientId}` : undefined,
22
+ `reason=${entry.reason}`,
23
+ ]
24
+ .filter(Boolean)
25
+ .join(" ");
26
+ console.log(line);
27
+ return;
28
+ }
17
29
  const line = [
18
- `[mcp-trellis] ${entry.method || "(transport)"}`,
30
+ `[mcp-trellis] mcp ${entry.method || "(transport)"}`,
19
31
  entry.tool ? `tool=${entry.tool}` : undefined,
20
32
  entry.ok ? "ok" : "fail",
21
33
  `${entry.durationMs}ms`,
@@ -24,11 +36,10 @@ export const consoleAudit = (entry) => {
24
36
  ]
25
37
  .filter(Boolean)
26
38
  .join(" ");
27
- if (entry.ok) {
28
- console.log(line);
29
- }
30
- else {
39
+ if (!entry.ok) {
31
40
  console.error(line);
41
+ return;
32
42
  }
43
+ console.log(line);
33
44
  };
34
45
  //# sourceMappingURL=audit.js.map
package/dist/audit.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAiB,EAAQ,EAAE;IACtD,MAAM,IAAI,GAAG;QACX,iBAAiB,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE;QAChD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;QAC7C,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QACxB,GAAG,KAAK,CAAC,UAAU,IAAI;QACvB,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QAC3D,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;KACjD;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACtB,CAAC;AACH,CAAC,CAAC"}
1
+ {"version":3,"file":"audit.js","sourceRoot":"","sources":["../src/audit.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,KAAwB,EAAQ,EAAE;IAC7D,IAAI,KAAK,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG;YACX,qBAAqB;YACrB,KAAK,CAAC,KAAK;YACX,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,SAAS;YACvD,UAAU,KAAK,CAAC,MAAM,EAAE;SACzB;aACE,MAAM,CAAC,OAAO,CAAC;aACf,IAAI,CAAC,GAAG,CAAC,CAAC;QACb,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClB,OAAO;IACT,CAAC;IAED,MAAM,IAAI,GAAG;QACX,qBAAqB,KAAK,CAAC,MAAM,IAAI,aAAa,EAAE;QACpD,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;QAC7C,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM;QACxB,GAAG,KAAK,CAAC,UAAU,IAAI;QACvB,KAAK,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,SAAS;QAC3D,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,SAAS;KACjD;SACE,MAAM,CAAC,OAAO,CAAC;SACf,IAAI,CAAC,GAAG,CAAC,CAAC;IAEb,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;QACd,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;AACpB,CAAC,CAAC"}
@@ -1,5 +1,4 @@
1
1
  /** Bearer auth helpers for MCP (RFC 9728 WWW-Authenticate). */
2
- export declare const BEARER_PREFIX = "Bearer ";
3
2
  /** Above any real JWT / HMAC sig; prevents allocation DoS on attacker input. */
4
3
  export declare const MAX_COMPARE_LENGTH = 4096;
5
4
  export declare const parseBearer: (authorization: string | null) => string | null;
@@ -14,6 +13,10 @@ export type WwwAuthenticateOptions = {
14
13
  realm: string;
15
14
  /** Absolute URL to RFC 9728 protected resource metadata. */
16
15
  resourceMetadataUrl: string;
16
+ /** RFC 6750 §3.1 error code, e.g. `"insufficient_scope"`. Omitted on a plain 401. */
17
+ error?: string | undefined;
18
+ /** RFC 6750 §3.1 — the scope(s) that would satisfy the request. Paired with `error`. */
19
+ scope?: string | undefined;
17
20
  };
18
21
  export declare const wwwAuthenticateHeader: (options: WwwAuthenticateOptions) => string;
19
22
  /** RFC 6750 §2.3 uses `access_token`; also reject legacy `token`. */
@@ -1 +1 @@
1
- {"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;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,OAWtD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,EAAE,KAAG,OAGhE,CAAC;AAEJ,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF,eAAO,MAAM,qBAAqB,GAChC,SAAS,sBAAsB,KAC9B,MAC6F,CAAC;AAEjG,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,GAAI,KAAK,GAAG,KAAG,OAC2B,CAAC"}
1
+ {"version":3,"file":"bearer.d.ts","sourceRoot":"","sources":["../../src/auth/bearer.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAI/D,gFAAgF;AAChF,eAAO,MAAM,kBAAkB,OAAO,CAAC;AAKvC,eAAO,MAAM,WAAW,GAAI,eAAe,MAAM,GAAG,IAAI,KAAG,MAAM,GAAG,IAMnE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,eAAe,GAAI,GAAG,MAAM,EAAE,GAAG,MAAM,KAAG,OAetD,CAAC;AAEF,eAAO,MAAM,UAAU,GAAI,WAAW,MAAM,EAAE,UAAU,MAAM,EAAE,KAAG,OACN,CAAC;AAE9D,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,4DAA4D;IAC5D,mBAAmB,EAAE,MAAM,CAAC;IAC5B,qFAAqF;IACrF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,wFAAwF;IACxF,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B,CAAC;AAMF,eAAO,MAAM,qBAAqB,GAAI,SAAS,sBAAsB,KAAG,MAQvE,CAAC;AAEF,qEAAqE;AACrE,eAAO,MAAM,gBAAgB,GAAI,KAAK,GAAG,KAAG,OAC2B,CAAC"}