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,53 @@
1
+ /**
2
+ * Node request-side plumbing for the `(req, res)` adapter: origin
3
+ * resolution, Web `Request` construction, and bounded body reading.
4
+ * Response-side glue (`sendWebResponse`, `asNodeHandler`) lives in `node.ts`.
5
+ */
6
+ export type NodeRequestLike = {
7
+ method?: string | undefined;
8
+ url?: string | undefined;
9
+ headers: Record<string, string | string[] | undefined>;
10
+ body?: unknown;
11
+ /** Destroy the underlying socket — called only after a 413 has flushed. */
12
+ destroy?: (() => void) | undefined;
13
+ [Symbol.asyncIterator]?: () => AsyncIterator<Uint8Array | string>;
14
+ };
15
+ export type ToWebRequestOptions = {
16
+ /** Absolute origin, e.g. https://app.example.com. */
17
+ origin: string;
18
+ /** Pre-read body. Overrides `req.body` when supplied. */
19
+ body?: unknown;
20
+ };
21
+ export type ResolveOriginOptions = {
22
+ /** Trust last `X-Forwarded-Host` / `X-Forwarded-Proto` hop. */
23
+ trustProxy?: boolean;
24
+ };
25
+ /**
26
+ * A Host (or `X-Forwarded-*`) header that can't safely become an origin —
27
+ * missing, carrying a path/query/fragment/credentials, malformed, or a
28
+ * non-`http(s)` scheme. Distinct from a generic `Error` so `asNodeHandler`
29
+ * can answer this with a client-facing 400 instead of the same 500 it gives
30
+ * an actual unexpected failure.
31
+ */
32
+ export declare class InvalidOriginError extends Error {
33
+ }
34
+ /**
35
+ * Derive origin from Host, or from forwarded headers when `trustProxy`.
36
+ * Always parsed through `URL` and rejected unless it is a bare `host[:port]`
37
+ * over http(s): a Host carrying a path (`evil.test/../trusted.test`) or
38
+ * credentials (`user:pass@evil.test`) must not become an origin-shaped string.
39
+ */
40
+ export declare const resolveOrigin: (req: NodeRequestLike, options?: ResolveOriginOptions) => string;
41
+ export declare const toWebRequest: (req: NodeRequestLike, options: ToWebRequestOptions) => Request;
42
+ export declare const requestPath: (req: NodeRequestLike) => string;
43
+ /** True for a path under an `…/oauth` segment — the default OAuth mount. */
44
+ export declare const isOAuthPath: (path: string) => boolean;
45
+ /** OAuth routes under `…/oauth/…` get the 64 KiB cap; everything else gets 1 MiB. */
46
+ export declare const bodyLimitForPath: (path: string) => number;
47
+ /**
48
+ * Prefer `req.body`; else drain the stream (raw `http.createServer`), capped
49
+ * at `maxBytes`. Throws `BodyTooLargeError` past the cap without destroying
50
+ * the socket — `asNodeHandler` writes 413 first, then destroys after flush.
51
+ */
52
+ export declare const readNodeBody: (req: NodeRequestLike, maxBytes?: number) => Promise<unknown>;
53
+ //# sourceMappingURL=node-request.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-request.d.ts","sourceRoot":"","sources":["../../src/adapters/node-request.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAWH,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2EAA2E;IAC3E,OAAO,CAAC,EAAE,CAAC,MAAM,IAAI,CAAC,GAAG,SAAS,CAAC;IACnC,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,aAAa,CAAC,UAAU,GAAG,MAAM,CAAC,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAQF;;;;;;GAMG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;CAAG;AAOhD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GAAI,KAAK,eAAe,EAAE,UAAS,oBAAyB,KAAG,MA+BxF,CAAC;AA6CF,eAAO,MAAM,YAAY,GAAI,KAAK,eAAe,EAAE,SAAS,mBAAmB,KAAG,OAkCjF,CAAC;AAMF,eAAO,MAAM,WAAW,GAAI,KAAK,eAAe,KAAG,MAA+C,CAAC;AAEnG,4EAA4E;AAC5E,eAAO,MAAM,WAAW,GAAI,MAAM,MAAM,KAAG,OAAuC,CAAC;AAEnF,qFAAqF;AACrF,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG,MACuB,CAAC;AAqBxE;;;;GAIG;AACH,eAAO,MAAM,YAAY,GACvB,KAAK,eAAe,EACpB,WAAU,MAA+B,KACxC,OAAO,CAAC,OAAO,CAcjB,CAAC"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * Node request-side plumbing for the `(req, res)` adapter: origin
3
+ * resolution, Web `Request` construction, and bounded body reading.
4
+ * Response-side glue (`sendWebResponse`, `asNodeHandler`) lives in `node.ts`.
5
+ */
6
+ import { BodyTooLargeError, DEFAULT_MCP_BODY_LIMIT, DEFAULT_OAUTH_BODY_LIMIT, isNodeReadable, readBoundedNodeBody, } from "../http/body.js";
7
+ import { isJsonObject } from "../util/json.js";
8
+ const headerValue = (value) => Array.isArray(value) ? value[0] : value;
9
+ const lastForwarded = (value) => value?.split(",").pop()?.trim();
10
+ /**
11
+ * A Host (or `X-Forwarded-*`) header that can't safely become an origin —
12
+ * missing, carrying a path/query/fragment/credentials, malformed, or a
13
+ * non-`http(s)` scheme. Distinct from a generic `Error` so `asNodeHandler`
14
+ * can answer this with a client-facing 400 instead of the same 500 it gives
15
+ * an actual unexpected failure.
16
+ */
17
+ export class InvalidOriginError extends Error {
18
+ }
19
+ /** A bare `host[:port]` must not carry any of these — they'd mean a path, query, fragment, or credentials smuggled into what should be just the authority. */
20
+ const HOST_HEADER_STRUCTURAL_CHARS = /[/?#@\\]/;
21
+ const ALLOWED_ORIGIN_PROTOCOLS = new Set(["http:", "https:"]);
22
+ /**
23
+ * Derive origin from Host, or from forwarded headers when `trustProxy`.
24
+ * Always parsed through `URL` and rejected unless it is a bare `host[:port]`
25
+ * over http(s): a Host carrying a path (`evil.test/../trusted.test`) or
26
+ * credentials (`user:pass@evil.test`) must not become an origin-shaped string.
27
+ */
28
+ export const resolveOrigin = (req, options = {}) => {
29
+ const trustProxy = options.trustProxy === true;
30
+ const proto = trustProxy
31
+ ? lastForwarded(headerValue(req.headers["x-forwarded-proto"])) || "https"
32
+ : "https";
33
+ const host = trustProxy
34
+ ? lastForwarded(headerValue(req.headers["x-forwarded-host"])) || headerValue(req.headers.host)
35
+ : headerValue(req.headers.host);
36
+ if (!host) {
37
+ throw new InvalidOriginError("Cannot resolve origin: pass options.origin or set Host" +
38
+ (trustProxy ? " / X-Forwarded-Host" : ""));
39
+ }
40
+ if (HOST_HEADER_STRUCTURAL_CHARS.test(host)) {
41
+ throw new InvalidOriginError(`Cannot resolve origin: Host header "${host}" must be a bare host[:port], not a full URL`);
42
+ }
43
+ let parsed;
44
+ try {
45
+ parsed = new URL(`${proto}://${host}`);
46
+ }
47
+ catch {
48
+ throw new InvalidOriginError(`Cannot resolve origin: Host header "${host}" is not valid`);
49
+ }
50
+ if (!ALLOWED_ORIGIN_PROTOCOLS.has(parsed.protocol)) {
51
+ throw new InvalidOriginError(`Cannot resolve origin: unsupported protocol "${parsed.protocol}"`);
52
+ }
53
+ return parsed.origin;
54
+ };
55
+ const isPlainRecord = (value) => isJsonObject(value) && !(value instanceof Uint8Array);
56
+ const isFormContentType = (contentType) => (contentType ?? "").toLowerCase().includes("application/x-www-form-urlencoded");
57
+ const appendFormValue = (params, key, value) => {
58
+ if (Array.isArray(value)) {
59
+ for (const entry of value)
60
+ appendFormValue(params, key, entry);
61
+ return;
62
+ }
63
+ if (value === undefined || value === null)
64
+ return;
65
+ params.append(key, typeof value === "string" ? value : String(value));
66
+ };
67
+ /** Re-serialize a pre-parsed `express.urlencoded()`-shaped body back to `a=1&b=2`. */
68
+ const objectToUrlEncoded = (body) => {
69
+ const params = new URLSearchParams();
70
+ for (const [key, value] of Object.entries(body))
71
+ appendFormValue(params, key, value);
72
+ return params.toString();
73
+ };
74
+ /**
75
+ * `req.body` from a body-parsing middleware (Express `json()`/`urlencoded()`,
76
+ * multer, …) arrives as an already-parsed object, not raw bytes — the
77
+ * `Content-Type` header says what shape it round-trips back to. A form body
78
+ * must be re-encoded as a form, or `/token` and `/consent` behind
79
+ * `express.urlencoded()` receive one unparseable JSON-shaped key.
80
+ */
81
+ const toBodyInit = (body, contentType) => {
82
+ if (body === undefined || body === null)
83
+ return undefined;
84
+ if (typeof body === "string")
85
+ return body;
86
+ if (body instanceof Uint8Array) {
87
+ return body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength);
88
+ }
89
+ if (isPlainRecord(body) && isFormContentType(contentType)) {
90
+ return objectToUrlEncoded(body);
91
+ }
92
+ return JSON.stringify(body);
93
+ };
94
+ const BODYLESS_METHODS = new Set(["GET", "HEAD"]);
95
+ export const toWebRequest = (req, options) => {
96
+ // Never trust an absolute-form request target — rebase onto the validated origin.
97
+ const target = new URL(req.url ?? "/", options.origin);
98
+ const url = `${options.origin}${target.pathname}${target.search}`;
99
+ const headers = new Headers(Object.entries(req.headers)
100
+ .map(([key, value]) => {
101
+ const resolved = headerValue(value);
102
+ return resolved === undefined ? null : [key, resolved];
103
+ })
104
+ .filter((entry) => entry !== null));
105
+ const method = (req.method ?? "GET").toUpperCase();
106
+ if (BODYLESS_METHODS.has(method)) {
107
+ return new Request(url, { method, headers });
108
+ }
109
+ const body = options.body !== undefined ? options.body : req.body;
110
+ const bodyInit = toBodyInit(body, headers.get("content-type") ?? undefined);
111
+ if (isPlainRecord(body)) {
112
+ // The re-serialized body's byte length no longer matches whatever
113
+ // Content-Length the original (already-parsed) request declared — a
114
+ // stale header here can make the body-size precheck reject a body well
115
+ // within the cap, or let an oversized one slip past it (still caught by
116
+ // the streaming fallback either way).
117
+ headers.delete("content-length");
118
+ headers.delete("transfer-encoding");
119
+ }
120
+ return new Request(url, {
121
+ method,
122
+ headers,
123
+ ...(bodyInit !== undefined ? { body: bodyInit } : {}),
124
+ });
125
+ };
126
+ const isAsyncIterable = (value) => typeof value?.[Symbol.asyncIterator] ===
127
+ "function";
128
+ export const requestPath = (req) => (req.url ?? "/").split("?")[0] ?? "/";
129
+ /** True for a path under an `…/oauth` segment — the default OAuth mount. */
130
+ export const isOAuthPath = (path) => /\/oauth(?:\/|$)/.test(path);
131
+ /** OAuth routes under `…/oauth/…` get the 64 KiB cap; everything else gets 1 MiB. */
132
+ export const bodyLimitForPath = (path) => isOAuthPath(path) ? DEFAULT_OAUTH_BODY_LIMIT : DEFAULT_MCP_BODY_LIMIT;
133
+ const enforcePresetBodySize = (body, maxBytes) => {
134
+ if (typeof body === "string" && new TextEncoder().encode(body).byteLength > maxBytes) {
135
+ throw new BodyTooLargeError(maxBytes);
136
+ }
137
+ if (body instanceof Uint8Array && body.byteLength > maxBytes) {
138
+ throw new BodyTooLargeError(maxBytes);
139
+ }
140
+ };
141
+ const emptyToUndefined = (bytes) => bytes.byteLength > 0 ? bytes : undefined;
142
+ const asBodyStream = (req) => {
143
+ if (isNodeReadable(req) || isAsyncIterable(req)) {
144
+ return req;
145
+ }
146
+ return undefined;
147
+ };
148
+ /**
149
+ * Prefer `req.body`; else drain the stream (raw `http.createServer`), capped
150
+ * at `maxBytes`. Throws `BodyTooLargeError` past the cap without destroying
151
+ * the socket — `asNodeHandler` writes 413 first, then destroys after flush.
152
+ */
153
+ export const readNodeBody = async (req, maxBytes = DEFAULT_MCP_BODY_LIMIT) => {
154
+ if (req.body !== undefined && req.body !== null) {
155
+ enforcePresetBodySize(req.body, maxBytes);
156
+ return req.body;
157
+ }
158
+ const stream = asBodyStream(req);
159
+ if (!stream)
160
+ return undefined;
161
+ return emptyToUndefined(await readBoundedNodeBody(stream, maxBytes, {
162
+ contentLength: headerValue(req.headers["content-length"]),
163
+ }));
164
+ };
165
+ //# sourceMappingURL=node-request.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-request.js","sourceRoot":"","sources":["../../src/adapters/node-request.ts"],"names":[],"mappings":"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"}
@@ -1,29 +1,17 @@
1
1
  /**
2
2
  * Node HTTP `(req, res)` adapter — Express, Cloud Functions, `http.createServer`, etc.
3
3
  * Bridges duck-typed Node request/response objects to Web `Request`/`Response`.
4
+ * Request-side plumbing (origin resolution, `toWebRequest`, body reading)
5
+ * lives in `node-request.ts` and is re-exported below unchanged.
4
6
  */
5
- import { isAllowedOrigin, type OriginAllowlistOptions } from "./origins.js";
6
- export { isAllowedOrigin, type OriginAllowlistOptions };
7
- export type NodeRequestLike = {
8
- method?: string;
9
- url?: string;
10
- headers: Record<string, string | string[] | undefined>;
11
- body?: unknown;
12
- };
7
+ import { type OriginAllowlistOptions } from "../http/origins.js";
8
+ import { type NodeRequestLike } from "./node-request.js";
9
+ export { isAllowedOrigin, isAllowedRequestOrigin, type OriginAllowlistOptions, } from "../http/origins.js";
10
+ export { bodyLimitForPath, InvalidOriginError, type NodeRequestLike, type ResolveOriginOptions, readNodeBody, resolveOrigin, type ToWebRequestOptions, toWebRequest, } from "./node-request.js";
13
11
  export type NodeResponseLike = {
14
12
  statusCode: number;
15
13
  setHeader: (name: string, value: string | number | readonly string[]) => void;
16
- end: (chunk?: string | Uint8Array) => void;
17
- };
18
- export type ToWebRequestOptions = {
19
- /** Absolute origin, e.g. https://app.example.com. */
20
- origin: string;
21
- /** Pre-read body. Overrides `req.body` when supplied. */
22
- body?: unknown;
23
- };
24
- export type ResolveOriginOptions = {
25
- /** Trust last `X-Forwarded-Host` / `X-Forwarded-Proto` hop. */
26
- trustProxy?: boolean;
14
+ end: (chunk?: string | Uint8Array, callback?: () => void) => void;
27
15
  };
28
16
  export type AsNodeHandlerOptions = OriginAllowlistOptions & {
29
17
  /**
@@ -34,11 +22,15 @@ export type AsNodeHandlerOptions = OriginAllowlistOptions & {
34
22
  origin?: string;
35
23
  trustProxy?: boolean;
36
24
  };
37
- /** Derive origin from Host, or from forwarded headers when trustProxy. */
38
- export declare const resolveOrigin: (req: NodeRequestLike, options?: ResolveOriginOptions) => string;
39
- export declare const toWebRequest: (req: NodeRequestLike, options: ToWebRequestOptions) => Request;
40
- /** Prefer `req.body`; else drain the stream (raw `http.createServer`). */
41
- export declare const readNodeBody: (req: NodeRequestLike) => Promise<unknown>;
25
+ /**
26
+ * Unlike every other header, `Set-Cookie` cannot be folded into one
27
+ * comma-joined value — a cookie's own `Expires` attribute contains a comma.
28
+ * The Fetch `Headers` object accordingly keeps duplicates apart internally
29
+ * and exposes them via `getSetCookie()`, but `forEach`/`entries()` still
30
+ * yields one `"set-cookie"` pair per cookie — calling `res.setHeader` once
31
+ * per pair (as for any other header) makes each call overwrite the last,
32
+ * silently dropping every cookie but the final one.
33
+ */
42
34
  export declare const sendWebResponse: (res: NodeResponseLike, response: Response) => Promise<void>;
43
35
  /** One-liner: Node `(req, res)` → MCP / OAuth Web handler. */
44
36
  export declare const asNodeHandler: (mcp: {
@@ -1 +1 @@
1
- {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,eAAe,EACf,KAAK,sBAAsB,EAC5B,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,eAAe,EAAE,KAAK,sBAAsB,EAAE,CAAC;AAExD,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,CAAC;IACvD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9E,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,KAAK,IAAI,CAAC;CAC5C,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,+DAA+D;IAC/D,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG;IAC1D;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AASF,0EAA0E;AAC1E,eAAO,MAAM,aAAa,GACxB,KAAK,eAAe,EACpB,UAAS,oBAAyB,KACjC,MAgBF,CAAC;AAcF,eAAO,MAAM,YAAY,GACvB,KAAK,eAAe,EACpB,SAAS,mBAAmB,KAC3B,OAwBF,CAAC;AAiBF,0EAA0E;AAC1E,eAAO,MAAM,YAAY,GACvB,KAAK,eAAe,KACnB,OAAO,CAAC,OAAO,CAWjB,CAAC;AAEF,eAAO,MAAM,eAAe,GAC1B,KAAK,gBAAgB,EACrB,UAAU,QAAQ,KACjB,OAAO,CAAC,IAAI,CAId,CAAC;AAaF,8DAA8D;AAC9D,eAAO,MAAM,aAAa,GACxB,KAAK;IAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,EACvD,UAAU,oBAAoB,MAyBhB,KAAK,eAAe,EAAE,KAAK,gBAAgB,KAAG,OAAO,CAAC,IAAI,CAezE,CAAC"}
1
+ {"version":3,"file":"node.d.ts","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EAAmB,KAAK,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAElF,OAAO,EAIL,KAAK,eAAe,EAKrB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,KAAK,sBAAsB,GAC5B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,KAAK,eAAe,EACpB,KAAK,oBAAoB,EACzB,YAAY,EACZ,aAAa,EACb,KAAK,mBAAmB,EACxB,YAAY,GACb,MAAM,mBAAmB,CAAC;AAE3B,MAAM,MAAM,gBAAgB,GAAG;IAC7B,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,MAAM,EAAE,KAAK,IAAI,CAAC;IAC9E,GAAG,EAAE,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;CACnE,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG,sBAAsB,GAAG;IAC1D;;;;OAIG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe,GAAU,KAAK,gBAAgB,EAAE,UAAU,QAAQ,KAAG,OAAO,CAAC,IAAI,CAS7F,CAAC;AAkDF,8DAA8D;AAC9D,eAAO,MAAM,aAAa,GACxB,KAAK;IAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;CAAE,EACvD,UAAU,oBAAoB,MAIhB,KAAK,eAAe,EAAE,KAAK,gBAAgB,KAAG,OAAO,CAAC,IAAI,CA2BzE,CAAC"}
@@ -1,101 +1,65 @@
1
1
  /**
2
2
  * Node HTTP `(req, res)` adapter — Express, Cloud Functions, `http.createServer`, etc.
3
3
  * Bridges duck-typed Node request/response objects to Web `Request`/`Response`.
4
+ * Request-side plumbing (origin resolution, `toWebRequest`, body reading)
5
+ * lives in `node-request.ts` and is re-exported below unchanged.
6
+ */
7
+ import { BodyTooLargeError } from "../http/body.js";
8
+ import { INTERNAL_ERROR } from "../http/http.js";
9
+ import { isAllowedOrigin } from "../http/origins.js";
10
+ import { JSONRPC_PAYLOAD_TOO_LARGE, rpcError } from "../mcp/jsonrpc.js";
11
+ import { bodyLimitForPath, InvalidOriginError, isOAuthPath, readNodeBody, requestPath, resolveOrigin, toWebRequest, } from "./node-request.js";
12
+ export { isAllowedOrigin, isAllowedRequestOrigin, } from "../http/origins.js";
13
+ export { bodyLimitForPath, InvalidOriginError, readNodeBody, resolveOrigin, toWebRequest, } from "./node-request.js";
14
+ /**
15
+ * Unlike every other header, `Set-Cookie` cannot be folded into one
16
+ * comma-joined value — a cookie's own `Expires` attribute contains a comma.
17
+ * The Fetch `Headers` object accordingly keeps duplicates apart internally
18
+ * and exposes them via `getSetCookie()`, but `forEach`/`entries()` still
19
+ * yields one `"set-cookie"` pair per cookie — calling `res.setHeader` once
20
+ * per pair (as for any other header) makes each call overwrite the last,
21
+ * silently dropping every cookie but the final one.
4
22
  */
5
- import { INTERNAL_ERROR } from "../http.js";
6
- import { isAllowedOrigin, } from "./origins.js";
7
- export { isAllowedOrigin };
8
- const headerValue = (value) => (Array.isArray(value) ? value[0] : value);
9
- const lastForwarded = (value) => value?.split(",").pop()?.trim();
10
- /** Derive origin from Host, or from forwarded headers when trustProxy. */
11
- export const resolveOrigin = (req, options = {}) => {
12
- const trustProxy = options.trustProxy === true;
13
- const proto = trustProxy
14
- ? lastForwarded(headerValue(req.headers["x-forwarded-proto"])) || "https"
15
- : "https";
16
- const host = trustProxy
17
- ? lastForwarded(headerValue(req.headers["x-forwarded-host"])) ||
18
- headerValue(req.headers.host)
19
- : headerValue(req.headers.host);
20
- if (!host) {
21
- throw new Error("Cannot resolve origin: pass options.origin or set Host" +
22
- (trustProxy ? " / X-Forwarded-Host" : ""));
23
- }
24
- return `${proto}://${host}`;
25
- };
26
- const toBodyInit = (body) => {
27
- if (body === undefined || body === null)
28
- return undefined;
29
- if (typeof body === "string")
30
- return body;
31
- if (body instanceof Uint8Array) {
32
- return body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength);
33
- }
34
- return JSON.stringify(body);
35
- };
36
- export const toWebRequest = (req, options) => {
37
- // Never trust an absolute-form request target — rebase onto the validated origin.
38
- const target = new URL(req.url ?? "/", options.origin);
39
- const url = `${options.origin}${target.pathname}${target.search}`;
40
- const headers = new Headers(Object.entries(req.headers)
41
- .map(([key, value]) => {
42
- const resolved = headerValue(value);
43
- return resolved === undefined ? null : [key, resolved];
44
- })
45
- .filter((entry) => entry !== null));
46
- const method = (req.method ?? "GET").toUpperCase();
47
- if (method === "GET" || method === "HEAD") {
48
- return new Request(url, { method, headers });
49
- }
50
- const body = options.body !== undefined ? options.body : req.body;
51
- return new Request(url, {
52
- method,
53
- headers,
54
- body: toBodyInit(body),
55
- });
56
- };
57
- const isAsyncIterable = (value) => typeof value?.[Symbol.asyncIterator] === "function";
58
- const concatChunks = (chunks) => {
59
- const total = chunks.reduce((sum, chunk) => sum + chunk.byteLength, 0);
60
- const out = new Uint8Array(total);
61
- chunks.reduce((offset, chunk) => {
62
- out.set(chunk, offset);
63
- return offset + chunk.byteLength;
64
- }, 0);
65
- return out;
66
- };
67
- /** Prefer `req.body`; else drain the stream (raw `http.createServer`). */
68
- export const readNodeBody = async (req) => {
69
- if (req.body !== undefined && req.body !== null)
70
- return req.body;
71
- if (!isAsyncIterable(req))
72
- return undefined;
73
- const chunks = [];
74
- for await (const chunk of req) {
75
- chunks.push(typeof chunk === "string" ? new TextEncoder().encode(chunk) : chunk);
76
- }
77
- return chunks.length > 0 ? concatChunks(chunks) : undefined;
78
- };
79
23
  export const sendWebResponse = async (res, response) => {
80
24
  res.statusCode = response.status;
81
- response.headers.forEach((value, key) => res.setHeader(key, value));
25
+ response.headers.forEach((value, key) => {
26
+ if (key.toLowerCase() === "set-cookie")
27
+ return;
28
+ res.setHeader(key, value);
29
+ });
30
+ const cookies = response.headers.getSetCookie();
31
+ if (cookies.length > 0)
32
+ res.setHeader("set-cookie", cookies);
82
33
  res.end(new Uint8Array(await response.arrayBuffer()));
83
34
  };
84
- /** Always answer — an unhandled rejection on `http.createServer` hangs the client. */
85
- const sendJsonError = (res, status, error) => {
86
- res.statusCode = status;
35
+ /**
36
+ * Always answer — an unhandled rejection on `http.createServer` hangs the
37
+ * client. `onFlushed` also closes the connection once the body is written.
38
+ */
39
+ const sendJsonError = (res, error, onFlushed) => {
40
+ res.statusCode = error.status;
87
41
  res.setHeader("Content-Type", "application/json");
88
- res.end(JSON.stringify({ error }));
42
+ if (onFlushed)
43
+ res.setHeader("Connection", "close");
44
+ res.end(error.body, onFlushed);
89
45
  };
90
- /** One-liner: Node `(req, res)` → MCP / OAuth Web handler. */
91
- export const asNodeHandler = (mcp, options) => {
46
+ const ORIGIN_NOT_ALLOWED = { status: 400, body: JSON.stringify({ error: "origin not allowed" }) };
47
+ const payloadTooLargeBody = (path) => isOAuthPath(path)
48
+ ? JSON.stringify({ error: "request body too large" })
49
+ : JSON.stringify(rpcError(null, JSONRPC_PAYLOAD_TOO_LARGE, "Payload too large"));
50
+ /**
51
+ * Validates that `options` resolves to an origin `asNodeHandler` can trust —
52
+ * either an explicit `options.origin` already covered by `allowedOrigins`,
53
+ * or (Host-derived) an `allowedOrigins` that isn't empty. A forgettable Host
54
+ * spoof would otherwise leak straight into the AS issuer / PRM /
55
+ * WWW-Authenticate values every request produces.
56
+ */
57
+ const assertNodeHandlerOptions = (options) => {
92
58
  const hostDerived = !options?.origin;
93
59
  if (hostDerived && options?.trustProxy !== true) {
94
60
  throw new Error("asNodeHandler requires options.origin or options.trustProxy: true");
95
61
  }
96
- // Forgettable Host spoof → AS issuer / PRM / WWW-Authenticate. Require an
97
- // explicit allowlist whenever origin comes from the request.
98
- if (hostDerived && !options.allowedOrigins?.length) {
62
+ if (hostDerived && !options?.allowedOrigins?.length) {
99
63
  throw new Error('asNodeHandler with Host-derived origin requires options.allowedOrigins (use ["*"] to admit any Host)');
100
64
  }
101
65
  if (options?.origin &&
@@ -103,19 +67,36 @@ export const asNodeHandler = (mcp, options) => {
103
67
  !isAllowedOrigin(options.origin, options)) {
104
68
  throw new Error("asNodeHandler: options.origin is not in options.allowedOrigins");
105
69
  }
70
+ };
71
+ /** One-liner: Node `(req, res)` → MCP / OAuth Web handler. */
72
+ export const asNodeHandler = (mcp, options) => {
73
+ assertNodeHandlerOptions(options);
106
74
  return async (req, res) => {
75
+ const path = requestPath(req);
107
76
  try {
108
77
  const origin = options?.origin ?? resolveOrigin(req, { trustProxy: true });
109
78
  if (!isAllowedOrigin(origin, options)) {
110
- sendJsonError(res, 400, "origin not allowed");
79
+ sendJsonError(res, ORIGIN_NOT_ALLOWED);
111
80
  return;
112
81
  }
113
- const body = await readNodeBody(req);
82
+ const body = await readNodeBody(req, bodyLimitForPath(path));
114
83
  const request = toWebRequest(req, { origin, body });
115
84
  await sendWebResponse(res, await mcp.fetch(request));
116
85
  }
117
- catch {
118
- sendJsonError(res, 500, INTERNAL_ERROR);
86
+ catch (caught) {
87
+ if (caught instanceof BodyTooLargeError) {
88
+ sendJsonError(res, { status: 413, body: payloadTooLargeBody(path) }, () => {
89
+ req.destroy?.();
90
+ });
91
+ return;
92
+ }
93
+ if (caught instanceof InvalidOriginError) {
94
+ // Bad client input (a malformed or missing Host / X-Forwarded-*),
95
+ // not a server fault — 400, not the generic 500 below.
96
+ sendJsonError(res, ORIGIN_NOT_ALLOWED);
97
+ return;
98
+ }
99
+ sendJsonError(res, { status: 500, body: JSON.stringify({ error: INTERNAL_ERROR }) });
119
100
  }
120
101
  };
121
102
  };
@@ -1 +1 @@
1
- {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/adapters/node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `mcp-trellis/advanced` — low-level building blocks for hosts assembling
3
+ * their own MCP transport or OAuth flow. Less stable than the root and
4
+ * `mcp-trellis/oauth` entry points: these follow the internals more closely
5
+ * and may change in a minor release when the protocol work requires it.
6
+ */
7
+ export { matchesAny, timingSafeEqual } from "./auth/bearer.js";
8
+ export { corsHeaders, emptyResponse, methodNotAllowed, optionsResponse } from "./http/http.js";
9
+ export { ASSUMED_HEADER_PROTOCOL_VERSION, pickProtocolVersion } from "./mcp/protocol.js";
10
+ export { IGNORED_SCHEMA_KEYWORDS, JSON_SCHEMA_TYPES, missingObjectType, SUPPORTED_SCHEMA_KEYWORDS, unsupportedKeywords, validateAgainstSchema, } from "./mcp/validate.js";
11
+ export { advertisedScopes, defaultScopes, registeredClientsRequired, unregisteredClientsAllowed, } from "./oauth/config.js";
12
+ export { type ClientAuth, firstClientAuthError, readClientAuth, } from "./oauth/crypto/clientauth.js";
13
+ export { type AuthCodeRecord, type CodeStore, consumeAuthCode, issueAuthCode, newClientId, } from "./oauth/crypto/codes.js";
14
+ export { randomBase64Url, sha256Base64Url, verifyPkceS256 } from "./oauth/crypto/pkce.js";
15
+ export { buildErrorRedirectUrl } from "./oauth/endpoints/callback.js";
16
+ export { firstResourceError, normalizeConfiguredPath, resourceErrorInfo, } from "./oauth/policy/resource.js";
17
+ export { firstScopeError, formatScope, parseScope, requestedScopes, scopeErrorInfo, } from "./oauth/policy/scope.js";
18
+ //# sourceMappingURL=advanced.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced.d.ts","sourceRoot":"","sources":["../src/advanced.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,KAAK,UAAU,EACf,oBAAoB,EACpB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,SAAS,EACd,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,GACf,MAAM,yBAAyB,CAAC"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * `mcp-trellis/advanced` — low-level building blocks for hosts assembling
3
+ * their own MCP transport or OAuth flow. Less stable than the root and
4
+ * `mcp-trellis/oauth` entry points: these follow the internals more closely
5
+ * and may change in a minor release when the protocol work requires it.
6
+ */
7
+ export { matchesAny, timingSafeEqual } from "./auth/bearer.js";
8
+ export { corsHeaders, emptyResponse, methodNotAllowed, optionsResponse } from "./http/http.js";
9
+ export { ASSUMED_HEADER_PROTOCOL_VERSION, pickProtocolVersion } from "./mcp/protocol.js";
10
+ export { IGNORED_SCHEMA_KEYWORDS, JSON_SCHEMA_TYPES, missingObjectType, SUPPORTED_SCHEMA_KEYWORDS, unsupportedKeywords, validateAgainstSchema, } from "./mcp/validate.js";
11
+ export { advertisedScopes, defaultScopes, registeredClientsRequired, unregisteredClientsAllowed, } from "./oauth/config.js";
12
+ export { firstClientAuthError, readClientAuth, } from "./oauth/crypto/clientauth.js";
13
+ export { consumeAuthCode, issueAuthCode, newClientId, } from "./oauth/crypto/codes.js";
14
+ export { randomBase64Url, sha256Base64Url, verifyPkceS256 } from "./oauth/crypto/pkce.js";
15
+ export { buildErrorRedirectUrl } from "./oauth/endpoints/callback.js";
16
+ export { firstResourceError, normalizeConfiguredPath, resourceErrorInfo, } from "./oauth/policy/resource.js";
17
+ export { firstScopeError, formatScope, parseScope, requestedScopes, scopeErrorInfo, } from "./oauth/policy/scope.js";
18
+ //# sourceMappingURL=advanced.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"advanced.js","sourceRoot":"","sources":["../src/advanced.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAC/D,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAC/F,OAAO,EAAE,+BAA+B,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AACzF,OAAO,EACL,uBAAuB,EACvB,iBAAiB,EACjB,iBAAiB,EACjB,yBAAyB,EACzB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAEL,oBAAoB,EACpB,cAAc,GACf,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAGL,eAAe,EACf,aAAa,EACb,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,GAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EACL,eAAe,EACf,WAAW,EACX,UAAU,EACV,eAAe,EACf,cAAc,GACf,MAAM,yBAAyB,CAAC"}