@frontmcp/sdk 0.4.1 → 0.5.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 (558) hide show
  1. package/README.md +30 -18
  2. package/package.json +20 -5
  3. package/src/app/app.registry.d.ts +3 -2
  4. package/src/app/app.registry.js +3 -1
  5. package/src/app/app.registry.js.map +1 -1
  6. package/src/app/instances/app.local.instance.js +2 -2
  7. package/src/app/instances/app.local.instance.js.map +1 -1
  8. package/src/auth/auth.registry.d.ts +34 -2
  9. package/src/auth/auth.registry.js +162 -24
  10. package/src/auth/auth.registry.js.map +1 -1
  11. package/src/auth/auth.utils.js +8 -9
  12. package/src/auth/auth.utils.js.map +1 -1
  13. package/src/auth/authorization/authorization.class.d.ts +125 -0
  14. package/src/auth/authorization/authorization.class.js +224 -0
  15. package/src/auth/authorization/authorization.class.js.map +1 -0
  16. package/src/auth/authorization/authorization.types.d.ts +300 -0
  17. package/src/auth/authorization/authorization.types.js +79 -0
  18. package/src/auth/authorization/authorization.types.js.map +1 -0
  19. package/src/auth/authorization/index.d.ts +5 -0
  20. package/src/auth/authorization/index.js +19 -0
  21. package/src/auth/authorization/index.js.map +1 -0
  22. package/src/auth/authorization/orchestrated.authorization.d.ts +242 -0
  23. package/src/auth/authorization/orchestrated.authorization.js +306 -0
  24. package/src/auth/authorization/orchestrated.authorization.js.map +1 -0
  25. package/src/auth/authorization/public.authorization.d.ts +91 -0
  26. package/src/auth/authorization/public.authorization.js +132 -0
  27. package/src/auth/authorization/public.authorization.js.map +1 -0
  28. package/src/auth/authorization/transparent.authorization.d.ts +130 -0
  29. package/src/auth/authorization/transparent.authorization.js +147 -0
  30. package/src/auth/authorization/transparent.authorization.js.map +1 -0
  31. package/src/auth/consent/consent.types.d.ts +111 -0
  32. package/src/auth/consent/consent.types.js +119 -0
  33. package/src/auth/consent/consent.types.js.map +1 -0
  34. package/src/auth/consent/index.d.ts +1 -0
  35. package/src/auth/consent/index.js +13 -0
  36. package/src/auth/consent/index.js.map +1 -0
  37. package/src/auth/detection/auth-provider-detection.d.ts +84 -0
  38. package/src/auth/detection/auth-provider-detection.js +230 -0
  39. package/src/auth/detection/auth-provider-detection.js.map +1 -0
  40. package/src/auth/detection/index.d.ts +1 -0
  41. package/src/auth/detection/index.js +15 -0
  42. package/src/auth/detection/index.js.map +1 -0
  43. package/src/auth/flows/auth.verify.flow.d.ts +110 -0
  44. package/src/auth/flows/auth.verify.flow.js +379 -0
  45. package/src/auth/flows/auth.verify.flow.js.map +1 -0
  46. package/src/auth/flows/oauth.authorize.flow.d.ts +118 -164
  47. package/src/auth/flows/oauth.authorize.flow.js +701 -33
  48. package/src/auth/flows/oauth.authorize.flow.js.map +1 -1
  49. package/src/auth/flows/oauth.callback.flow.d.ts +117 -0
  50. package/src/auth/flows/oauth.callback.flow.js +357 -0
  51. package/src/auth/flows/oauth.callback.flow.js.map +1 -0
  52. package/src/auth/flows/oauth.register.flow.d.ts +32 -125
  53. package/src/auth/flows/oauth.token.flow.d.ts +52 -154
  54. package/src/auth/flows/oauth.token.flow.js +193 -55
  55. package/src/auth/flows/oauth.token.flow.js.map +1 -1
  56. package/src/auth/flows/session.verify.flow.d.ts +66 -321
  57. package/src/auth/flows/session.verify.flow.js +107 -18
  58. package/src/auth/flows/session.verify.flow.js.map +1 -1
  59. package/src/auth/flows/well-known.jwks.flow.d.ts +34 -205
  60. package/src/auth/flows/well-known.jwks.flow.js +15 -8
  61. package/src/auth/flows/well-known.jwks.flow.js.map +1 -1
  62. package/src/auth/flows/well-known.oauth-authorization-server.flow.d.ts +48 -223
  63. package/src/auth/flows/well-known.oauth-authorization-server.flow.js +2 -3
  64. package/src/auth/flows/well-known.oauth-authorization-server.flow.js.map +1 -1
  65. package/src/auth/flows/well-known.prm.flow.d.ts +19 -120
  66. package/src/auth/flows/well-known.prm.flow.js +3 -4
  67. package/src/auth/flows/well-known.prm.flow.js.map +1 -1
  68. package/src/auth/instances/instance.local-primary-auth.d.ts +91 -4
  69. package/src/auth/instances/instance.local-primary-auth.js +236 -6
  70. package/src/auth/instances/instance.local-primary-auth.js.map +1 -1
  71. package/src/auth/instances/instance.remote-primary-auth.d.ts +4 -3
  72. package/src/auth/instances/instance.remote-primary-auth.js +2 -2
  73. package/src/auth/instances/instance.remote-primary-auth.js.map +1 -1
  74. package/src/auth/session/authorization-vault.d.ts +611 -0
  75. package/src/auth/session/authorization-vault.js +817 -0
  76. package/src/auth/session/authorization-vault.js.map +1 -0
  77. package/src/auth/session/authorization.store.d.ts +301 -0
  78. package/src/auth/session/authorization.store.js +323 -0
  79. package/src/auth/session/authorization.store.js.map +1 -0
  80. package/src/auth/session/encrypted-authorization-vault.d.ts +181 -0
  81. package/src/auth/session/encrypted-authorization-vault.js +493 -0
  82. package/src/auth/session/encrypted-authorization-vault.js.map +1 -0
  83. package/src/auth/session/index.d.ts +4 -4
  84. package/src/auth/session/index.js +11 -7
  85. package/src/auth/session/index.js.map +1 -1
  86. package/src/auth/session/session.schema.d.ts +1 -1
  87. package/src/auth/session/session.service.d.ts +1 -1
  88. package/src/auth/session/transport-session.manager.d.ts +101 -0
  89. package/src/auth/session/transport-session.manager.js +300 -0
  90. package/src/auth/session/transport-session.manager.js.map +1 -0
  91. package/src/auth/session/transport-session.types.d.ts +457 -0
  92. package/src/auth/session/transport-session.types.js +110 -0
  93. package/src/auth/session/transport-session.types.js.map +1 -0
  94. package/src/auth/session/utils/session-id.utils.d.ts +14 -2
  95. package/src/auth/session/utils/session-id.utils.js +68 -19
  96. package/src/auth/session/utils/session-id.utils.js.map +1 -1
  97. package/src/auth/session/vault-encryption.d.ts +189 -0
  98. package/src/auth/session/vault-encryption.js +263 -0
  99. package/src/auth/session/vault-encryption.js.map +1 -0
  100. package/src/auth/ui/base-layout.d.ts +188 -0
  101. package/src/auth/ui/base-layout.js +292 -0
  102. package/src/auth/ui/base-layout.js.map +1 -0
  103. package/src/auth/ui/htmx-templates.d.ts +135 -0
  104. package/src/auth/ui/htmx-templates.js +433 -0
  105. package/src/auth/ui/htmx-templates.js.map +1 -0
  106. package/src/auth/ui/index.d.ts +11 -0
  107. package/src/auth/ui/index.js +35 -0
  108. package/src/auth/ui/index.js.map +1 -0
  109. package/src/auth/utils/audience.validator.d.ts +129 -0
  110. package/src/auth/utils/audience.validator.js +196 -0
  111. package/src/auth/utils/audience.validator.js.map +1 -0
  112. package/src/auth/utils/index.d.ts +2 -0
  113. package/src/auth/utils/index.js +7 -0
  114. package/src/auth/utils/index.js.map +1 -0
  115. package/src/auth/utils/www-authenticate.utils.d.ts +97 -0
  116. package/src/auth/utils/www-authenticate.utils.js +183 -0
  117. package/src/auth/utils/www-authenticate.utils.js.map +1 -0
  118. package/src/common/common.schema.d.ts +2 -16
  119. package/src/common/constants.d.ts +3 -0
  120. package/src/common/constants.js +6 -1
  121. package/src/common/constants.js.map +1 -1
  122. package/src/common/decorators/decorator-utils.d.ts +131 -0
  123. package/src/common/decorators/decorator-utils.js +195 -0
  124. package/src/common/decorators/decorator-utils.js.map +1 -0
  125. package/src/common/decorators/front-mcp.decorator.js +3 -2
  126. package/src/common/decorators/front-mcp.decorator.js.map +1 -1
  127. package/src/common/decorators/hook.decorator.d.ts +58 -2
  128. package/src/common/decorators/hook.decorator.js +127 -17
  129. package/src/common/decorators/hook.decorator.js.map +1 -1
  130. package/src/common/decorators/plugin.decorator.d.ts +1 -1
  131. package/src/common/decorators/plugin.decorator.js +11 -10
  132. package/src/common/decorators/plugin.decorator.js.map +1 -1
  133. package/src/common/decorators/resource.decorator.d.ts +32 -3
  134. package/src/common/decorators/resource.decorator.js +46 -4
  135. package/src/common/decorators/resource.decorator.js.map +1 -1
  136. package/src/common/decorators/tool.decorator.d.ts +54 -5
  137. package/src/common/decorators/tool.decorator.js.map +1 -1
  138. package/src/common/dynamic/dynamic.plugin.d.ts +22 -11
  139. package/src/common/dynamic/dynamic.plugin.js +7 -1
  140. package/src/common/dynamic/dynamic.plugin.js.map +1 -1
  141. package/src/common/entries/prompt.entry.d.ts +46 -2
  142. package/src/common/entries/prompt.entry.js +10 -0
  143. package/src/common/entries/prompt.entry.js.map +1 -1
  144. package/src/common/entries/resource.entry.d.ts +69 -6
  145. package/src/common/entries/resource.entry.js +27 -3
  146. package/src/common/entries/resource.entry.js.map +1 -1
  147. package/src/common/entries/scope.entry.d.ts +5 -1
  148. package/src/common/entries/scope.entry.js +3 -3
  149. package/src/common/entries/scope.entry.js.map +1 -1
  150. package/src/common/flow/flow.utils.d.ts +56 -0
  151. package/src/common/flow/flow.utils.js +96 -0
  152. package/src/common/flow/flow.utils.js.map +1 -0
  153. package/src/common/index.d.ts +2 -2
  154. package/src/common/index.js +2 -2
  155. package/src/common/index.js.map +1 -1
  156. package/src/common/interfaces/execution-context.interface.d.ts +59 -0
  157. package/src/common/interfaces/execution-context.interface.js +81 -0
  158. package/src/common/interfaces/execution-context.interface.js.map +1 -0
  159. package/src/common/interfaces/flow.interface.d.ts +1 -1
  160. package/src/common/interfaces/flow.interface.js.map +1 -1
  161. package/src/common/interfaces/index.d.ts +1 -0
  162. package/src/common/interfaces/index.js +1 -0
  163. package/src/common/interfaces/index.js.map +1 -1
  164. package/src/common/interfaces/internal/primary-auth-provider.interface.d.ts +17 -2
  165. package/src/common/interfaces/internal/primary-auth-provider.interface.js +52 -4
  166. package/src/common/interfaces/internal/primary-auth-provider.interface.js.map +1 -1
  167. package/src/common/interfaces/internal/registry.interface.d.ts +16 -2
  168. package/src/common/interfaces/internal/registry.interface.js.map +1 -1
  169. package/src/common/interfaces/plugin.interface.js.map +1 -1
  170. package/src/common/interfaces/prompt.interface.d.ts +53 -4
  171. package/src/common/interfaces/prompt.interface.js +78 -0
  172. package/src/common/interfaces/prompt.interface.js.map +1 -1
  173. package/src/common/interfaces/resource.interface.d.ts +47 -17
  174. package/src/common/interfaces/resource.interface.js +53 -0
  175. package/src/common/interfaces/resource.interface.js.map +1 -1
  176. package/src/common/interfaces/tool.interface.d.ts +39 -22
  177. package/src/common/interfaces/tool.interface.js +61 -34
  178. package/src/common/interfaces/tool.interface.js.map +1 -1
  179. package/src/common/metadata/adapter.metadata.d.ts +1 -9
  180. package/src/common/metadata/app.metadata.d.ts +425 -730
  181. package/src/common/metadata/auth-provider.metadata.d.ts +2 -12
  182. package/src/common/metadata/flow.metadata.d.ts +10 -25
  183. package/src/common/metadata/front-mcp.metadata.d.ts +602 -1023
  184. package/src/common/metadata/front-mcp.metadata.js +6 -4
  185. package/src/common/metadata/front-mcp.metadata.js.map +1 -1
  186. package/src/common/metadata/hook.metadata.d.ts +1 -1
  187. package/src/common/metadata/hook.metadata.js.map +1 -1
  188. package/src/common/metadata/index.d.ts +1 -0
  189. package/src/common/metadata/index.js +1 -0
  190. package/src/common/metadata/index.js.map +1 -1
  191. package/src/common/metadata/logger.metadata.d.ts +1 -9
  192. package/src/common/metadata/plugin.metadata.d.ts +8 -30
  193. package/src/common/metadata/prompt.metadata.d.ts +4 -161
  194. package/src/common/metadata/provider.metadata.d.ts +2 -12
  195. package/src/common/metadata/resource.metadata.d.ts +6 -98
  196. package/src/common/metadata/resource.metadata.js +15 -6
  197. package/src/common/metadata/resource.metadata.js.map +1 -1
  198. package/src/common/metadata/tool-ui.metadata.d.ts +10 -0
  199. package/src/common/metadata/tool-ui.metadata.js +12 -0
  200. package/src/common/metadata/tool-ui.metadata.js.map +1 -0
  201. package/src/common/metadata/tool.metadata.d.ts +78 -199
  202. package/src/common/metadata/tool.metadata.js +11 -14
  203. package/src/common/metadata/tool.metadata.js.map +1 -1
  204. package/src/common/providers/base-config.provider.d.ts +84 -0
  205. package/src/common/providers/base-config.provider.js +128 -0
  206. package/src/common/providers/base-config.provider.js.map +1 -0
  207. package/src/common/records/plugin.record.d.ts +5 -6
  208. package/src/common/records/plugin.record.js.map +1 -1
  209. package/src/common/records/prompt.record.js.map +1 -1
  210. package/src/common/records/resource.record.d.ts +17 -1
  211. package/src/common/records/resource.record.js +12 -6
  212. package/src/common/records/resource.record.js.map +1 -1
  213. package/src/common/records/tool.record.js.map +1 -1
  214. package/src/common/schemas/annotated-class.schema.d.ts +9 -9
  215. package/src/common/schemas/annotated-class.schema.js +92 -27
  216. package/src/common/schemas/annotated-class.schema.js.map +1 -1
  217. package/src/common/schemas/http-input.schema.d.ts +6 -30
  218. package/src/common/schemas/http-output.schema.d.ts +326 -1630
  219. package/src/common/schemas/http-output.schema.js +39 -1
  220. package/src/common/schemas/http-output.schema.js.map +1 -1
  221. package/src/common/tokens/front-mcp.tokens.js +4 -1
  222. package/src/common/tokens/front-mcp.tokens.js.map +1 -1
  223. package/src/common/tokens/resource.tokens.d.ts +2 -0
  224. package/src/common/tokens/resource.tokens.js +4 -1
  225. package/src/common/tokens/resource.tokens.js.map +1 -1
  226. package/src/common/tokens/tool.tokens.d.ts +2 -0
  227. package/src/common/tokens/tool.tokens.js +2 -0
  228. package/src/common/tokens/tool.tokens.js.map +1 -1
  229. package/src/common/types/auth/jwt.types.d.ts +5 -31
  230. package/src/common/types/auth/session.types.d.ts +97 -192
  231. package/src/common/types/auth/session.types.js +24 -11
  232. package/src/common/types/auth/session.types.js.map +1 -1
  233. package/src/common/types/options/auth.options.d.ts +1013 -490
  234. package/src/common/types/options/auth.options.js +554 -36
  235. package/src/common/types/options/auth.options.js.map +1 -1
  236. package/src/common/types/options/http.options.d.ts +1 -9
  237. package/src/common/types/options/logging.options.d.ts +7 -13
  238. package/src/common/types/options/logging.options.js +4 -0
  239. package/src/common/types/options/logging.options.js.map +1 -1
  240. package/src/common/types/options/server-info.options.d.ts +3 -31
  241. package/src/common/types/options/session.options.d.ts +90 -10
  242. package/src/common/types/options/session.options.js +26 -3
  243. package/src/common/types/options/session.options.js.map +1 -1
  244. package/src/common/utils/decide-request-intent.utils.d.ts +8 -46
  245. package/src/common/utils/decide-request-intent.utils.js +88 -23
  246. package/src/common/utils/decide-request-intent.utils.js.map +1 -1
  247. package/src/completion/flows/complete.flow.d.ts +74 -0
  248. package/src/completion/flows/complete.flow.js +199 -0
  249. package/src/completion/flows/complete.flow.js.map +1 -0
  250. package/src/errors/authorization-required.error.d.ts +189 -0
  251. package/src/errors/authorization-required.error.js +274 -0
  252. package/src/errors/authorization-required.error.js.map +1 -0
  253. package/src/errors/index.d.ts +2 -1
  254. package/src/errors/index.js +17 -1
  255. package/src/errors/index.js.map +1 -1
  256. package/src/errors/mcp.error.d.ts +101 -1
  257. package/src/errors/mcp.error.js +147 -2
  258. package/src/errors/mcp.error.js.map +1 -1
  259. package/src/flows/flow.instance.js +4 -3
  260. package/src/flows/flow.instance.js.map +1 -1
  261. package/src/flows/flow.registry.js.map +1 -1
  262. package/src/flows/flow.stages.js +14 -11
  263. package/src/flows/flow.stages.js.map +1 -1
  264. package/src/front-mcp/front-mcp.providers.d.ts +464 -102
  265. package/src/front-mcp/front-mcp.providers.js +3 -5
  266. package/src/front-mcp/front-mcp.providers.js.map +1 -1
  267. package/src/hooks/hook.instance.d.ts +1 -1
  268. package/src/hooks/hook.instance.js +5 -2
  269. package/src/hooks/hook.instance.js.map +1 -1
  270. package/src/hooks/hook.registry.js +7 -5
  271. package/src/hooks/hook.registry.js.map +1 -1
  272. package/src/index.d.ts +28 -9
  273. package/src/index.js +5 -1
  274. package/src/index.js.map +1 -1
  275. package/src/logger/instances/instance.logger.js +3 -2
  276. package/src/logger/instances/instance.logger.js.map +1 -1
  277. package/src/logger/logger.registry.js +7 -2
  278. package/src/logger/logger.registry.js.map +1 -1
  279. package/src/logging/flows/set-level.flow.d.ts +62 -0
  280. package/src/logging/flows/set-level.flow.js +108 -0
  281. package/src/logging/flows/set-level.flow.js.map +1 -0
  282. package/src/mcp-apps/csp.d.ts +111 -0
  283. package/src/mcp-apps/csp.js +267 -0
  284. package/src/mcp-apps/csp.js.map +1 -0
  285. package/src/mcp-apps/index.d.ts +23 -0
  286. package/src/mcp-apps/index.js +91 -0
  287. package/src/mcp-apps/index.js.map +1 -0
  288. package/src/mcp-apps/schemas.d.ts +403 -0
  289. package/src/mcp-apps/schemas.js +345 -0
  290. package/src/mcp-apps/schemas.js.map +1 -0
  291. package/src/mcp-apps/template.d.ts +94 -0
  292. package/src/mcp-apps/template.js +419 -0
  293. package/src/mcp-apps/template.js.map +1 -0
  294. package/src/mcp-apps/types.d.ts +323 -0
  295. package/src/mcp-apps/types.js +59 -0
  296. package/src/mcp-apps/types.js.map +1 -0
  297. package/src/notification/index.d.ts +1 -0
  298. package/src/notification/index.js +13 -0
  299. package/src/notification/index.js.map +1 -0
  300. package/src/notification/notification.service.d.ts +378 -0
  301. package/src/notification/notification.service.js +727 -0
  302. package/src/notification/notification.service.js.map +1 -0
  303. package/src/plugin/plugin.registry.js +12 -9
  304. package/src/plugin/plugin.registry.js.map +1 -1
  305. package/src/prompt/flows/get-prompt.flow.d.ts +153 -0
  306. package/src/prompt/flows/get-prompt.flow.js +214 -0
  307. package/src/prompt/flows/get-prompt.flow.js.map +1 -0
  308. package/src/prompt/flows/prompts-list.flow.d.ts +67 -0
  309. package/src/prompt/flows/prompts-list.flow.js +176 -0
  310. package/src/prompt/flows/prompts-list.flow.js.map +1 -0
  311. package/src/prompt/index.d.ts +7 -0
  312. package/src/prompt/index.js +17 -0
  313. package/src/prompt/index.js.map +1 -0
  314. package/src/prompt/prompt.events.d.ts +17 -0
  315. package/src/prompt/prompt.events.js +25 -0
  316. package/src/prompt/prompt.events.js.map +1 -0
  317. package/src/prompt/prompt.instance.d.ts +30 -0
  318. package/src/prompt/prompt.instance.js +120 -0
  319. package/src/prompt/prompt.instance.js.map +1 -0
  320. package/src/prompt/prompt.registry.d.ts +79 -12
  321. package/src/prompt/prompt.registry.js +360 -15
  322. package/src/prompt/prompt.registry.js.map +1 -1
  323. package/src/prompt/prompt.types.d.ts +26 -0
  324. package/src/prompt/prompt.types.js +11 -0
  325. package/src/prompt/prompt.types.js.map +1 -0
  326. package/src/prompt/prompt.utils.d.ts +26 -0
  327. package/src/prompt/prompt.utils.js +136 -0
  328. package/src/prompt/prompt.utils.js.map +1 -0
  329. package/src/provider/provider.registry.d.ts +12 -5
  330. package/src/provider/provider.registry.js +30 -138
  331. package/src/provider/provider.registry.js.map +1 -1
  332. package/src/regsitry/registry.base.d.ts +1 -1
  333. package/src/regsitry/registry.base.js.map +1 -1
  334. package/src/resource/flows/read-resource.flow.d.ts +91 -0
  335. package/src/resource/flows/read-resource.flow.js +270 -0
  336. package/src/resource/flows/read-resource.flow.js.map +1 -0
  337. package/src/resource/flows/resource-templates-list.flow.d.ts +64 -0
  338. package/src/resource/flows/resource-templates-list.flow.js +191 -0
  339. package/src/resource/flows/resource-templates-list.flow.js.map +1 -0
  340. package/src/resource/flows/resources-list.flow.d.ts +64 -0
  341. package/src/resource/flows/resources-list.flow.js +196 -0
  342. package/src/resource/flows/resources-list.flow.js.map +1 -0
  343. package/src/resource/flows/subscribe-resource.flow.d.ts +45 -0
  344. package/src/resource/flows/subscribe-resource.flow.js +123 -0
  345. package/src/resource/flows/subscribe-resource.flow.js.map +1 -0
  346. package/src/resource/flows/unsubscribe-resource.flow.d.ts +44 -0
  347. package/src/resource/flows/unsubscribe-resource.flow.js +107 -0
  348. package/src/resource/flows/unsubscribe-resource.flow.js.map +1 -0
  349. package/src/resource/index.d.ts +8 -0
  350. package/src/resource/index.js +20 -0
  351. package/src/resource/index.js.map +1 -0
  352. package/src/resource/resource.events.d.ts +24 -0
  353. package/src/resource/resource.events.js +17 -0
  354. package/src/resource/resource.events.js.map +1 -0
  355. package/src/resource/resource.instance.d.ts +35 -0
  356. package/src/resource/resource.instance.js +163 -0
  357. package/src/resource/resource.instance.js.map +1 -0
  358. package/src/resource/resource.registry.d.ts +106 -12
  359. package/src/resource/resource.registry.js +449 -13
  360. package/src/resource/resource.registry.js.map +1 -1
  361. package/src/resource/resource.types.d.ts +35 -0
  362. package/src/resource/resource.types.js +11 -0
  363. package/src/resource/resource.types.js.map +1 -0
  364. package/src/resource/resource.utils.d.ts +30 -0
  365. package/src/resource/resource.utils.js +151 -0
  366. package/src/resource/resource.utils.js.map +1 -0
  367. package/src/scope/flows/http.request.flow.d.ts +48 -330
  368. package/src/scope/flows/http.request.flow.js +306 -78
  369. package/src/scope/flows/http.request.flow.js.map +1 -1
  370. package/src/scope/scope.instance.d.ts +12 -0
  371. package/src/scope/scope.instance.js +145 -15
  372. package/src/scope/scope.instance.js.map +1 -1
  373. package/src/tool/flows/call-tool.flow.d.ts +64 -1110
  374. package/src/tool/flows/call-tool.flow.js +303 -15
  375. package/src/tool/flows/call-tool.flow.js.map +1 -1
  376. package/src/tool/flows/tools-list.flow.d.ts +32 -473
  377. package/src/tool/flows/tools-list.flow.js +121 -40
  378. package/src/tool/flows/tools-list.flow.js.map +1 -1
  379. package/src/tool/tool.events.d.ts +8 -1
  380. package/src/tool/tool.events.js.map +1 -1
  381. package/src/tool/tool.instance.d.ts +3 -1
  382. package/src/tool/tool.instance.js +17 -3
  383. package/src/tool/tool.instance.js.map +1 -1
  384. package/src/tool/tool.registry.d.ts +7 -1
  385. package/src/tool/tool.registry.js +26 -10
  386. package/src/tool/tool.registry.js.map +1 -1
  387. package/src/tool/tool.types.d.ts +4 -4
  388. package/src/tool/tool.types.js.map +1 -1
  389. package/src/tool/tool.utils.d.ts +3 -12
  390. package/src/tool/tool.utils.js +39 -193
  391. package/src/tool/tool.utils.js.map +1 -1
  392. package/src/tool/ui/index.d.ts +22 -0
  393. package/src/tool/ui/index.js +63 -0
  394. package/src/tool/ui/index.js.map +1 -0
  395. package/src/tool/ui/platform-adapters.d.ts +10 -0
  396. package/src/tool/ui/platform-adapters.js +18 -0
  397. package/src/tool/ui/platform-adapters.js.map +1 -0
  398. package/src/tool/ui/template-helpers.d.ts +46 -0
  399. package/src/tool/ui/template-helpers.js +112 -0
  400. package/src/tool/ui/template-helpers.js.map +1 -0
  401. package/src/tool/ui/ui-resource-template.d.ts +34 -0
  402. package/src/tool/ui/ui-resource-template.js +64 -0
  403. package/src/tool/ui/ui-resource-template.js.map +1 -0
  404. package/src/tool/ui/ui-resource.handler.d.ts +74 -0
  405. package/src/tool/ui/ui-resource.handler.js +129 -0
  406. package/src/tool/ui/ui-resource.handler.js.map +1 -0
  407. package/src/transport/adapters/transport.local.adapter.d.ts +2 -2
  408. package/src/transport/adapters/transport.local.adapter.js +28 -7
  409. package/src/transport/adapters/transport.local.adapter.js.map +1 -1
  410. package/src/transport/adapters/transport.sse.adapter.d.ts +2 -2
  411. package/src/transport/adapters/transport.sse.adapter.js +4 -3
  412. package/src/transport/adapters/transport.sse.adapter.js.map +1 -1
  413. package/src/transport/adapters/transport.streamable-http.adapter.d.ts +10 -3
  414. package/src/transport/adapters/transport.streamable-http.adapter.js +54 -8
  415. package/src/transport/adapters/transport.streamable-http.adapter.js.map +1 -1
  416. package/src/transport/flows/handle.sse.flow.d.ts +29 -63
  417. package/src/transport/flows/handle.sse.flow.js +78 -10
  418. package/src/transport/flows/handle.sse.flow.js.map +1 -1
  419. package/src/transport/flows/handle.stateless-http.flow.d.ts +29 -0
  420. package/src/transport/flows/handle.stateless-http.flow.js +102 -0
  421. package/src/transport/flows/handle.stateless-http.flow.js.map +1 -0
  422. package/src/transport/flows/handle.streamable-http.flow.d.ts +32 -64
  423. package/src/transport/flows/handle.streamable-http.flow.js +158 -26
  424. package/src/transport/flows/handle.streamable-http.flow.js.map +1 -1
  425. package/src/transport/legacy/legacy.sse.tranporter.d.ts +9 -0
  426. package/src/transport/legacy/legacy.sse.tranporter.js +17 -2
  427. package/src/transport/legacy/legacy.sse.tranporter.js.map +1 -1
  428. package/src/transport/mcp-handlers/call-tool-request.handler.js +27 -1
  429. package/src/transport/mcp-handlers/call-tool-request.handler.js.map +1 -1
  430. package/src/transport/mcp-handlers/complete-request.handler.d.ts +69 -0
  431. package/src/transport/mcp-handlers/complete-request.handler.js +11 -0
  432. package/src/transport/mcp-handlers/complete-request.handler.js.map +1 -0
  433. package/src/transport/mcp-handlers/get-prompt-request.handler.d.ts +87 -0
  434. package/src/transport/mcp-handlers/get-prompt-request.handler.js +11 -0
  435. package/src/transport/mcp-handlers/get-prompt-request.handler.js.map +1 -0
  436. package/src/transport/mcp-handlers/index.d.ts +517 -208
  437. package/src/transport/mcp-handlers/index.js +39 -2
  438. package/src/transport/mcp-handlers/index.js.map +1 -1
  439. package/src/transport/mcp-handlers/initialize-request.handler.d.ts +1 -1
  440. package/src/transport/mcp-handlers/initialize-request.handler.js +73 -7
  441. package/src/transport/mcp-handlers/initialize-request.handler.js.map +1 -1
  442. package/src/transport/mcp-handlers/list-prompts-request.handler.d.ts +54 -0
  443. package/src/transport/mcp-handlers/list-prompts-request.handler.js +11 -0
  444. package/src/transport/mcp-handlers/list-prompts-request.handler.js.map +1 -0
  445. package/src/transport/mcp-handlers/list-resource-templates-request.handler.d.ts +51 -0
  446. package/src/transport/mcp-handlers/list-resource-templates-request.handler.js +12 -0
  447. package/src/transport/mcp-handlers/list-resource-templates-request.handler.js.map +1 -0
  448. package/src/transport/mcp-handlers/list-resources-request.handler.d.ts +51 -0
  449. package/src/transport/mcp-handlers/list-resources-request.handler.js +12 -0
  450. package/src/transport/mcp-handlers/list-resources-request.handler.js.map +1 -0
  451. package/src/transport/mcp-handlers/list-tools-request.handler.d.ts +19 -146
  452. package/src/transport/mcp-handlers/logging-set-level-request.handler.d.ts +46 -0
  453. package/src/transport/mcp-handlers/logging-set-level-request.handler.js +34 -0
  454. package/src/transport/mcp-handlers/logging-set-level-request.handler.js.map +1 -0
  455. package/src/transport/mcp-handlers/mcp-handlers.types.d.ts +3 -7
  456. package/src/transport/mcp-handlers/mcp-handlers.types.js.map +1 -1
  457. package/src/transport/mcp-handlers/read-resource-request.handler.d.ts +46 -0
  458. package/src/transport/mcp-handlers/read-resource-request.handler.js +12 -0
  459. package/src/transport/mcp-handlers/read-resource-request.handler.js.map +1 -0
  460. package/src/transport/mcp-handlers/roots-list-changed-notification.handler.d.ts +11 -0
  461. package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js +26 -0
  462. package/src/transport/mcp-handlers/roots-list-changed-notification.handler.js.map +1 -0
  463. package/src/transport/mcp-handlers/subscribe-request.handler.d.ts +37 -0
  464. package/src/transport/mcp-handlers/subscribe-request.handler.js +34 -0
  465. package/src/transport/mcp-handlers/subscribe-request.handler.js.map +1 -0
  466. package/src/transport/mcp-handlers/unsubscribe-request.handler.d.ts +37 -0
  467. package/src/transport/mcp-handlers/unsubscribe-request.handler.js +34 -0
  468. package/src/transport/mcp-handlers/unsubscribe-request.handler.js.map +1 -0
  469. package/src/transport/transport.local.js +7 -2
  470. package/src/transport/transport.local.js.map +1 -1
  471. package/src/transport/transport.registry.d.ts +30 -0
  472. package/src/transport/transport.registry.js +84 -1
  473. package/src/transport/transport.registry.js.map +1 -1
  474. package/src/transport/transport.types.d.ts +3 -3
  475. package/src/transport/transport.types.js.map +1 -1
  476. package/src/utils/content.utils.d.ts +48 -0
  477. package/src/utils/content.utils.js +194 -0
  478. package/src/utils/content.utils.js.map +1 -0
  479. package/src/utils/index.d.ts +8 -0
  480. package/src/utils/index.js +55 -0
  481. package/src/utils/index.js.map +1 -0
  482. package/src/utils/lineage.utils.d.ts +40 -0
  483. package/src/utils/lineage.utils.js +82 -0
  484. package/src/utils/lineage.utils.js.map +1 -0
  485. package/src/utils/naming.utils.d.ts +46 -0
  486. package/src/utils/naming.utils.js +136 -0
  487. package/src/utils/naming.utils.js.map +1 -0
  488. package/src/utils/types.utils.d.ts +2 -2
  489. package/src/utils/types.utils.js.map +1 -1
  490. package/src/utils/uri-template.utils.d.ts +57 -0
  491. package/src/utils/uri-template.utils.js +113 -0
  492. package/src/utils/uri-template.utils.js.map +1 -0
  493. package/src/utils/uri-validation.utils.d.ts +40 -0
  494. package/src/utils/uri-validation.utils.js +76 -0
  495. package/src/utils/uri-validation.utils.js.map +1 -0
  496. package/src/__test-utils__/fixtures/hook.fixtures.d.ts +0 -46
  497. package/src/__test-utils__/fixtures/hook.fixtures.js +0 -114
  498. package/src/__test-utils__/fixtures/hook.fixtures.js.map +0 -1
  499. package/src/__test-utils__/fixtures/index.d.ts +0 -7
  500. package/src/__test-utils__/fixtures/index.js +0 -11
  501. package/src/__test-utils__/fixtures/index.js.map +0 -1
  502. package/src/__test-utils__/fixtures/plugin.fixtures.d.ts +0 -46
  503. package/src/__test-utils__/fixtures/plugin.fixtures.js +0 -127
  504. package/src/__test-utils__/fixtures/plugin.fixtures.js.map +0 -1
  505. package/src/__test-utils__/fixtures/provider.fixtures.d.ts +0 -69
  506. package/src/__test-utils__/fixtures/provider.fixtures.js +0 -131
  507. package/src/__test-utils__/fixtures/provider.fixtures.js.map +0 -1
  508. package/src/__test-utils__/fixtures/scope.fixtures.d.ts +0 -14
  509. package/src/__test-utils__/fixtures/scope.fixtures.js +0 -59
  510. package/src/__test-utils__/fixtures/scope.fixtures.js.map +0 -1
  511. package/src/__test-utils__/fixtures/tool.fixtures.d.ts +0 -36
  512. package/src/__test-utils__/fixtures/tool.fixtures.js +0 -91
  513. package/src/__test-utils__/fixtures/tool.fixtures.js.map +0 -1
  514. package/src/__test-utils__/helpers/assertion.helpers.d.ts +0 -45
  515. package/src/__test-utils__/helpers/assertion.helpers.js +0 -153
  516. package/src/__test-utils__/helpers/assertion.helpers.js.map +0 -1
  517. package/src/__test-utils__/helpers/async.helpers.d.ts +0 -48
  518. package/src/__test-utils__/helpers/async.helpers.js +0 -112
  519. package/src/__test-utils__/helpers/async.helpers.js.map +0 -1
  520. package/src/__test-utils__/helpers/index.d.ts +0 -6
  521. package/src/__test-utils__/helpers/index.js +0 -10
  522. package/src/__test-utils__/helpers/index.js.map +0 -1
  523. package/src/__test-utils__/helpers/setup.helpers.d.ts +0 -54
  524. package/src/__test-utils__/helpers/setup.helpers.js +0 -106
  525. package/src/__test-utils__/helpers/setup.helpers.js.map +0 -1
  526. package/src/__test-utils__/index.d.ts +0 -9
  527. package/src/__test-utils__/index.js +0 -14
  528. package/src/__test-utils__/index.js.map +0 -1
  529. package/src/__test-utils__/mocks/flow-instance.mock.d.ts +0 -50
  530. package/src/__test-utils__/mocks/flow-instance.mock.js +0 -72
  531. package/src/__test-utils__/mocks/flow-instance.mock.js.map +0 -1
  532. package/src/__test-utils__/mocks/hook-registry.mock.d.ts +0 -25
  533. package/src/__test-utils__/mocks/hook-registry.mock.js +0 -65
  534. package/src/__test-utils__/mocks/hook-registry.mock.js.map +0 -1
  535. package/src/__test-utils__/mocks/index.d.ts +0 -8
  536. package/src/__test-utils__/mocks/index.js +0 -12
  537. package/src/__test-utils__/mocks/index.js.map +0 -1
  538. package/src/__test-utils__/mocks/plugin-registry.mock.d.ts +0 -43
  539. package/src/__test-utils__/mocks/plugin-registry.mock.js +0 -70
  540. package/src/__test-utils__/mocks/plugin-registry.mock.js.map +0 -1
  541. package/src/__test-utils__/mocks/provider-registry.mock.d.ts +0 -39
  542. package/src/__test-utils__/mocks/provider-registry.mock.js +0 -72
  543. package/src/__test-utils__/mocks/provider-registry.mock.js.map +0 -1
  544. package/src/__test-utils__/mocks/tool-registry.mock.d.ts +0 -43
  545. package/src/__test-utils__/mocks/tool-registry.mock.js +0 -79
  546. package/src/__test-utils__/mocks/tool-registry.mock.js.map +0 -1
  547. package/src/auth/path.utils.d.ts +0 -20
  548. package/src/auth/path.utils.js +0 -71
  549. package/src/auth/path.utils.js.map +0 -1
  550. package/src/common/decorators-old/async-with.decorator.d.ts +0 -10
  551. package/src/common/decorators-old/async-with.decorator.js +0 -24
  552. package/src/common/decorators-old/async-with.decorator.js.map +0 -1
  553. package/src/common/decorators-old/auth-hook.decorator.d.ts +0 -14
  554. package/src/common/decorators-old/auth-hook.decorator.js +0 -27
  555. package/src/common/decorators-old/auth-hook.decorator.js.map +0 -1
  556. package/src/common/decorators-old/session-hook.decorator.d.ts +0 -14
  557. package/src/common/decorators-old/session-hook.decorator.js +0 -27
  558. package/src/common/decorators-old/session-hook.decorator.js.map +0 -1
@@ -0,0 +1,129 @@
1
+ /**
2
+ * Audience Validator
3
+ *
4
+ * Validates JWT audience claims per RFC 7519 and MCP Authorization spec.
5
+ * The audience (aud) claim identifies the recipients that the JWT is intended for.
6
+ */
7
+ /**
8
+ * Validation result
9
+ */
10
+ export interface AudienceValidationResult {
11
+ /** Whether the audience is valid */
12
+ valid: boolean;
13
+ /** Error message if invalid */
14
+ error?: string;
15
+ /** Matched audience value (if valid) */
16
+ matchedAudience?: string;
17
+ }
18
+ /**
19
+ * Audience validator options
20
+ */
21
+ export interface AudienceValidatorOptions {
22
+ /**
23
+ * Expected audience values
24
+ * Token must contain at least one of these audiences
25
+ */
26
+ expectedAudiences: string[];
27
+ /**
28
+ * Whether to allow tokens with no audience claim
29
+ * @default false
30
+ */
31
+ allowNoAudience?: boolean;
32
+ /**
33
+ * Case-sensitive comparison
34
+ * @default true
35
+ */
36
+ caseSensitive?: boolean;
37
+ /**
38
+ * Allow wildcard matching (e.g., *.example.com)
39
+ * @default false
40
+ */
41
+ allowWildcards?: boolean;
42
+ }
43
+ /**
44
+ * Validate JWT audience claim
45
+ *
46
+ * @param tokenAudience - The audience claim from the JWT (can be string or array)
47
+ * @param options - Validation options
48
+ * @returns Validation result
49
+ *
50
+ * @example
51
+ * ```typescript
52
+ * // Single expected audience
53
+ * validateAudience('https://api.example.com', {
54
+ * expectedAudiences: ['https://api.example.com'],
55
+ * });
56
+ * // => { valid: true, matchedAudience: 'https://api.example.com' }
57
+ *
58
+ * // Multiple audiences in token
59
+ * validateAudience(['aud1', 'aud2', 'aud3'], {
60
+ * expectedAudiences: ['aud2'],
61
+ * });
62
+ * // => { valid: true, matchedAudience: 'aud2' }
63
+ *
64
+ * // No match
65
+ * validateAudience('wrong-aud', {
66
+ * expectedAudiences: ['expected-aud'],
67
+ * });
68
+ * // => { valid: false, error: 'Token audience does not match expected audiences' }
69
+ * ```
70
+ */
71
+ export declare function validateAudience(tokenAudience: string | string[] | undefined, options: AudienceValidatorOptions): AudienceValidationResult;
72
+ /**
73
+ * Create an audience validator function
74
+ *
75
+ * @param options - Validator options
76
+ * @returns A validation function that takes token audience and returns validation result
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const validator = createAudienceValidator({
81
+ * expectedAudiences: ['https://api.example.com', 'https://api.example.org'],
82
+ * });
83
+ *
84
+ * validator('https://api.example.com'); // => { valid: true, ... }
85
+ * validator('wrong-aud'); // => { valid: false, ... }
86
+ * ```
87
+ */
88
+ export declare function createAudienceValidator(options: AudienceValidatorOptions): (audience: string | string[] | undefined) => AudienceValidationResult;
89
+ /**
90
+ * Derive expected audience from the resource URL
91
+ *
92
+ * Per MCP Authorization spec, the audience should typically be the
93
+ * resource server URL (the MCP server URL).
94
+ *
95
+ * @param resourceUrl - The resource server URL
96
+ * @returns Array of expected audiences
97
+ *
98
+ * @example
99
+ * ```typescript
100
+ * deriveExpectedAudience('https://api.example.com/v1/mcp');
101
+ * // => ['https://api.example.com/v1/mcp', 'https://api.example.com', 'api.example.com']
102
+ * ```
103
+ */
104
+ export declare function deriveExpectedAudience(resourceUrl: string): string[];
105
+ /**
106
+ * AudienceValidator class for reusable validation with configuration
107
+ */
108
+ export declare class AudienceValidator {
109
+ private options;
110
+ constructor(options?: Partial<AudienceValidatorOptions> & {
111
+ expectedAudiences?: string[];
112
+ });
113
+ /**
114
+ * Validate an audience claim
115
+ */
116
+ validate(audience: string | string[] | undefined): AudienceValidationResult;
117
+ /**
118
+ * Add expected audiences
119
+ */
120
+ addAudiences(...audiences: string[]): void;
121
+ /**
122
+ * Set expected audiences (replace existing)
123
+ */
124
+ setAudiences(audiences: string[]): void;
125
+ /**
126
+ * Create validator from resource URL
127
+ */
128
+ static fromResourceUrl(resourceUrl: string, options?: Omit<AudienceValidatorOptions, 'expectedAudiences'>): AudienceValidator;
129
+ }
@@ -0,0 +1,196 @@
1
+ "use strict";
2
+ // auth/utils/audience.validator.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AudienceValidator = void 0;
5
+ exports.validateAudience = validateAudience;
6
+ exports.createAudienceValidator = createAudienceValidator;
7
+ exports.deriveExpectedAudience = deriveExpectedAudience;
8
+ /**
9
+ * Validate JWT audience claim
10
+ *
11
+ * @param tokenAudience - The audience claim from the JWT (can be string or array)
12
+ * @param options - Validation options
13
+ * @returns Validation result
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * // Single expected audience
18
+ * validateAudience('https://api.example.com', {
19
+ * expectedAudiences: ['https://api.example.com'],
20
+ * });
21
+ * // => { valid: true, matchedAudience: 'https://api.example.com' }
22
+ *
23
+ * // Multiple audiences in token
24
+ * validateAudience(['aud1', 'aud2', 'aud3'], {
25
+ * expectedAudiences: ['aud2'],
26
+ * });
27
+ * // => { valid: true, matchedAudience: 'aud2' }
28
+ *
29
+ * // No match
30
+ * validateAudience('wrong-aud', {
31
+ * expectedAudiences: ['expected-aud'],
32
+ * });
33
+ * // => { valid: false, error: 'Token audience does not match expected audiences' }
34
+ * ```
35
+ */
36
+ function validateAudience(tokenAudience, options) {
37
+ const { expectedAudiences, allowNoAudience = false, caseSensitive = true, allowWildcards = false } = options;
38
+ // Handle missing audience
39
+ if (tokenAudience === undefined || tokenAudience === null) {
40
+ if (allowNoAudience) {
41
+ return { valid: true };
42
+ }
43
+ return {
44
+ valid: false,
45
+ error: 'Token is missing audience claim',
46
+ };
47
+ }
48
+ // Handle empty expected audiences (accept any)
49
+ if (expectedAudiences.length === 0) {
50
+ const firstAud = Array.isArray(tokenAudience) ? tokenAudience[0] : tokenAudience;
51
+ return {
52
+ valid: false,
53
+ error: 'No expected audiences configured - cannot validate token',
54
+ };
55
+ }
56
+ // Normalize token audience to array
57
+ const tokenAuds = Array.isArray(tokenAudience) ? tokenAudience : [tokenAudience];
58
+ // Check each token audience against expected audiences
59
+ for (const tokenAud of tokenAuds) {
60
+ for (const expectedAud of expectedAudiences) {
61
+ if (matchesAudience(tokenAud, expectedAud, caseSensitive, allowWildcards)) {
62
+ return { valid: true, matchedAudience: tokenAud };
63
+ }
64
+ }
65
+ }
66
+ return {
67
+ valid: false,
68
+ error: `Token audience does not match expected audiences. Got: ${tokenAuds.join(', ')}. Expected one of: ${expectedAudiences.join(', ')}`,
69
+ };
70
+ }
71
+ /**
72
+ * Check if a token audience matches an expected audience
73
+ */
74
+ function matchesAudience(tokenAud, expectedAud, caseSensitive, allowWildcards) {
75
+ // Direct match
76
+ if (caseSensitive) {
77
+ if (tokenAud === expectedAud)
78
+ return true;
79
+ }
80
+ else {
81
+ if (tokenAud.toLowerCase() === expectedAud.toLowerCase())
82
+ return true;
83
+ }
84
+ // Wildcard matching with ReDoS protection
85
+ if (allowWildcards && expectedAud.includes('*')) {
86
+ // Limit wildcards to prevent potential ReDoS from complex patterns
87
+ const wildcardCount = (expectedAud.match(/\*/g) || []).length;
88
+ if (wildcardCount > 2) {
89
+ // Reject patterns with more than 2 wildcards for safety
90
+ return false;
91
+ }
92
+ const pattern = expectedAud
93
+ .replace(/[.+?^${}()|[\]\\]/g, '\\$&') // Escape regex special chars
94
+ .replace(/\*/g, '[^.]*'); // Convert * to non-greedy segment match (safer than .*)
95
+ const regex = new RegExp(`^${pattern}$`, caseSensitive ? '' : 'i');
96
+ if (regex.test(tokenAud))
97
+ return true;
98
+ }
99
+ return false;
100
+ }
101
+ /**
102
+ * Create an audience validator function
103
+ *
104
+ * @param options - Validator options
105
+ * @returns A validation function that takes token audience and returns validation result
106
+ *
107
+ * @example
108
+ * ```typescript
109
+ * const validator = createAudienceValidator({
110
+ * expectedAudiences: ['https://api.example.com', 'https://api.example.org'],
111
+ * });
112
+ *
113
+ * validator('https://api.example.com'); // => { valid: true, ... }
114
+ * validator('wrong-aud'); // => { valid: false, ... }
115
+ * ```
116
+ */
117
+ function createAudienceValidator(options) {
118
+ return (audience) => validateAudience(audience, options);
119
+ }
120
+ /**
121
+ * Derive expected audience from the resource URL
122
+ *
123
+ * Per MCP Authorization spec, the audience should typically be the
124
+ * resource server URL (the MCP server URL).
125
+ *
126
+ * @param resourceUrl - The resource server URL
127
+ * @returns Array of expected audiences
128
+ *
129
+ * @example
130
+ * ```typescript
131
+ * deriveExpectedAudience('https://api.example.com/v1/mcp');
132
+ * // => ['https://api.example.com/v1/mcp', 'https://api.example.com', 'api.example.com']
133
+ * ```
134
+ */
135
+ function deriveExpectedAudience(resourceUrl) {
136
+ const audiences = [];
137
+ try {
138
+ const url = new URL(resourceUrl);
139
+ // Full URL (most specific)
140
+ audiences.push(resourceUrl.replace(/\/$/, ''));
141
+ // Origin only (e.g., https://api.example.com)
142
+ if (url.pathname !== '/' && url.pathname !== '') {
143
+ audiences.push(url.origin);
144
+ }
145
+ // Host only (e.g., api.example.com)
146
+ audiences.push(url.host);
147
+ }
148
+ catch {
149
+ // If not a valid URL, use as-is
150
+ audiences.push(resourceUrl);
151
+ }
152
+ return audiences;
153
+ }
154
+ /**
155
+ * AudienceValidator class for reusable validation with configuration
156
+ */
157
+ class AudienceValidator {
158
+ options;
159
+ constructor(options = {}) {
160
+ this.options = {
161
+ expectedAudiences: [...(options.expectedAudiences ?? [])],
162
+ allowNoAudience: options.allowNoAudience ?? false,
163
+ caseSensitive: options.caseSensitive ?? true,
164
+ allowWildcards: options.allowWildcards ?? false,
165
+ };
166
+ }
167
+ /**
168
+ * Validate an audience claim
169
+ */
170
+ validate(audience) {
171
+ return validateAudience(audience, this.options);
172
+ }
173
+ /**
174
+ * Add expected audiences
175
+ */
176
+ addAudiences(...audiences) {
177
+ this.options.expectedAudiences.push(...audiences);
178
+ }
179
+ /**
180
+ * Set expected audiences (replace existing)
181
+ */
182
+ setAudiences(audiences) {
183
+ this.options.expectedAudiences = audiences;
184
+ }
185
+ /**
186
+ * Create validator from resource URL
187
+ */
188
+ static fromResourceUrl(resourceUrl, options = {}) {
189
+ return new AudienceValidator({
190
+ ...options,
191
+ expectedAudiences: deriveExpectedAudience(resourceUrl),
192
+ });
193
+ }
194
+ }
195
+ exports.AudienceValidator = AudienceValidator;
196
+ //# sourceMappingURL=audience.validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audience.validator.js","sourceRoot":"","sources":["../../../../src/auth/utils/audience.validator.ts"],"names":[],"mappings":"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","sourcesContent":["// auth/utils/audience.validator.ts\n\n/**\n * Audience Validator\n *\n * Validates JWT audience claims per RFC 7519 and MCP Authorization spec.\n * The audience (aud) claim identifies the recipients that the JWT is intended for.\n */\n\n/**\n * Validation result\n */\nexport interface AudienceValidationResult {\n /** Whether the audience is valid */\n valid: boolean;\n /** Error message if invalid */\n error?: string;\n /** Matched audience value (if valid) */\n matchedAudience?: string;\n}\n\n/**\n * Audience validator options\n */\nexport interface AudienceValidatorOptions {\n /**\n * Expected audience values\n * Token must contain at least one of these audiences\n */\n expectedAudiences: string[];\n\n /**\n * Whether to allow tokens with no audience claim\n * @default false\n */\n allowNoAudience?: boolean;\n\n /**\n * Case-sensitive comparison\n * @default true\n */\n caseSensitive?: boolean;\n\n /**\n * Allow wildcard matching (e.g., *.example.com)\n * @default false\n */\n allowWildcards?: boolean;\n}\n\n/**\n * Validate JWT audience claim\n *\n * @param tokenAudience - The audience claim from the JWT (can be string or array)\n * @param options - Validation options\n * @returns Validation result\n *\n * @example\n * ```typescript\n * // Single expected audience\n * validateAudience('https://api.example.com', {\n * expectedAudiences: ['https://api.example.com'],\n * });\n * // => { valid: true, matchedAudience: 'https://api.example.com' }\n *\n * // Multiple audiences in token\n * validateAudience(['aud1', 'aud2', 'aud3'], {\n * expectedAudiences: ['aud2'],\n * });\n * // => { valid: true, matchedAudience: 'aud2' }\n *\n * // No match\n * validateAudience('wrong-aud', {\n * expectedAudiences: ['expected-aud'],\n * });\n * // => { valid: false, error: 'Token audience does not match expected audiences' }\n * ```\n */\nexport function validateAudience(\n tokenAudience: string | string[] | undefined,\n options: AudienceValidatorOptions,\n): AudienceValidationResult {\n const { expectedAudiences, allowNoAudience = false, caseSensitive = true, allowWildcards = false } = options;\n\n // Handle missing audience\n if (tokenAudience === undefined || tokenAudience === null) {\n if (allowNoAudience) {\n return { valid: true };\n }\n return {\n valid: false,\n error: 'Token is missing audience claim',\n };\n }\n\n // Handle empty expected audiences (accept any)\n if (expectedAudiences.length === 0) {\n const firstAud = Array.isArray(tokenAudience) ? tokenAudience[0] : tokenAudience;\n return {\n valid: false,\n error: 'No expected audiences configured - cannot validate token',\n };\n }\n\n // Normalize token audience to array\n const tokenAuds = Array.isArray(tokenAudience) ? tokenAudience : [tokenAudience];\n\n // Check each token audience against expected audiences\n for (const tokenAud of tokenAuds) {\n for (const expectedAud of expectedAudiences) {\n if (matchesAudience(tokenAud, expectedAud, caseSensitive, allowWildcards)) {\n return { valid: true, matchedAudience: tokenAud };\n }\n }\n }\n\n return {\n valid: false,\n error: `Token audience does not match expected audiences. Got: ${tokenAuds.join(\n ', ',\n )}. Expected one of: ${expectedAudiences.join(', ')}`,\n };\n}\n\n/**\n * Check if a token audience matches an expected audience\n */\nfunction matchesAudience(\n tokenAud: string,\n expectedAud: string,\n caseSensitive: boolean,\n allowWildcards: boolean,\n): boolean {\n // Direct match\n if (caseSensitive) {\n if (tokenAud === expectedAud) return true;\n } else {\n if (tokenAud.toLowerCase() === expectedAud.toLowerCase()) return true;\n }\n\n // Wildcard matching with ReDoS protection\n if (allowWildcards && expectedAud.includes('*')) {\n // Limit wildcards to prevent potential ReDoS from complex patterns\n const wildcardCount = (expectedAud.match(/\\*/g) || []).length;\n if (wildcardCount > 2) {\n // Reject patterns with more than 2 wildcards for safety\n return false;\n }\n\n const pattern = expectedAud\n .replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&') // Escape regex special chars\n .replace(/\\*/g, '[^.]*'); // Convert * to non-greedy segment match (safer than .*)\n const regex = new RegExp(`^${pattern}$`, caseSensitive ? '' : 'i');\n if (regex.test(tokenAud)) return true;\n }\n\n return false;\n}\n\n/**\n * Create an audience validator function\n *\n * @param options - Validator options\n * @returns A validation function that takes token audience and returns validation result\n *\n * @example\n * ```typescript\n * const validator = createAudienceValidator({\n * expectedAudiences: ['https://api.example.com', 'https://api.example.org'],\n * });\n *\n * validator('https://api.example.com'); // => { valid: true, ... }\n * validator('wrong-aud'); // => { valid: false, ... }\n * ```\n */\nexport function createAudienceValidator(\n options: AudienceValidatorOptions,\n): (audience: string | string[] | undefined) => AudienceValidationResult {\n return (audience) => validateAudience(audience, options);\n}\n\n/**\n * Derive expected audience from the resource URL\n *\n * Per MCP Authorization spec, the audience should typically be the\n * resource server URL (the MCP server URL).\n *\n * @param resourceUrl - The resource server URL\n * @returns Array of expected audiences\n *\n * @example\n * ```typescript\n * deriveExpectedAudience('https://api.example.com/v1/mcp');\n * // => ['https://api.example.com/v1/mcp', 'https://api.example.com', 'api.example.com']\n * ```\n */\nexport function deriveExpectedAudience(resourceUrl: string): string[] {\n const audiences: string[] = [];\n\n try {\n const url = new URL(resourceUrl);\n\n // Full URL (most specific)\n audiences.push(resourceUrl.replace(/\\/$/, ''));\n\n // Origin only (e.g., https://api.example.com)\n if (url.pathname !== '/' && url.pathname !== '') {\n audiences.push(url.origin);\n }\n\n // Host only (e.g., api.example.com)\n audiences.push(url.host);\n } catch {\n // If not a valid URL, use as-is\n audiences.push(resourceUrl);\n }\n\n return audiences;\n}\n\n/**\n * AudienceValidator class for reusable validation with configuration\n */\nexport class AudienceValidator {\n private options: AudienceValidatorOptions;\n\n constructor(options: Partial<AudienceValidatorOptions> & { expectedAudiences?: string[] } = {}) {\n this.options = {\n expectedAudiences: [...(options.expectedAudiences ?? [])],\n allowNoAudience: options.allowNoAudience ?? false,\n caseSensitive: options.caseSensitive ?? true,\n allowWildcards: options.allowWildcards ?? false,\n };\n }\n\n /**\n * Validate an audience claim\n */\n validate(audience: string | string[] | undefined): AudienceValidationResult {\n return validateAudience(audience, this.options);\n }\n\n /**\n * Add expected audiences\n */\n addAudiences(...audiences: string[]): void {\n this.options.expectedAudiences.push(...audiences);\n }\n\n /**\n * Set expected audiences (replace existing)\n */\n setAudiences(audiences: string[]): void {\n this.options.expectedAudiences = audiences;\n }\n\n /**\n * Create validator from resource URL\n */\n static fromResourceUrl(\n resourceUrl: string,\n options: Omit<AudienceValidatorOptions, 'expectedAudiences'> = {},\n ): AudienceValidator {\n return new AudienceValidator({\n ...options,\n expectedAudiences: deriveExpectedAudience(resourceUrl),\n });\n }\n}\n"]}
@@ -0,0 +1,2 @@
1
+ export * from './www-authenticate.utils';
2
+ export * from './audience.validator';
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ // auth/utils/index.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const tslib_1 = require("tslib");
5
+ tslib_1.__exportStar(require("./www-authenticate.utils"), exports);
6
+ tslib_1.__exportStar(require("./audience.validator"), exports);
7
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/utils/index.ts"],"names":[],"mappings":";AAAA,sBAAsB;;;AAEtB,mEAAyC;AACzC,+DAAqC","sourcesContent":["// auth/utils/index.ts\n\nexport * from './www-authenticate.utils';\nexport * from './audience.validator';\n"]}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * WWW-Authenticate Header Builder
3
+ *
4
+ * Implements RFC 9728 (OAuth 2.0 Protected Resource Metadata) and
5
+ * RFC 6750 (Bearer Token Usage) compliant WWW-Authenticate headers.
6
+ */
7
+ /**
8
+ * Error codes per RFC 6750 Section 3.1
9
+ */
10
+ export type BearerErrorCode = 'invalid_request' | 'invalid_token' | 'insufficient_scope';
11
+ /**
12
+ * Options for building WWW-Authenticate header
13
+ */
14
+ export interface WwwAuthenticateOptions {
15
+ /**
16
+ * The resource_metadata URL pointing to the PRM document
17
+ * Per RFC 9728, this is the primary mechanism for resource discovery
18
+ */
19
+ resourceMetadataUrl?: string;
20
+ /**
21
+ * OAuth 2.0 realm (optional per RFC 6750)
22
+ */
23
+ realm?: string;
24
+ /**
25
+ * Required scopes for the resource (space-delimited)
26
+ */
27
+ scope?: string | string[];
28
+ /**
29
+ * Error code when authentication fails
30
+ */
31
+ error?: BearerErrorCode;
32
+ /**
33
+ * Human-readable error description
34
+ */
35
+ errorDescription?: string;
36
+ /**
37
+ * Error URI pointing to additional information
38
+ */
39
+ errorUri?: string;
40
+ }
41
+ /**
42
+ * Build a WWW-Authenticate header for Bearer authentication
43
+ *
44
+ * @param options - Header options
45
+ * @returns The formatted WWW-Authenticate header value
46
+ *
47
+ * @example
48
+ * ```typescript
49
+ * // Basic protected resource metadata header
50
+ * buildWwwAuthenticate({
51
+ * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',
52
+ * });
53
+ * // => 'Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"'
54
+ *
55
+ * // With error information
56
+ * buildWwwAuthenticate({
57
+ * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',
58
+ * error: 'insufficient_scope',
59
+ * scope: ['read', 'write'],
60
+ * errorDescription: 'Additional permissions required',
61
+ * });
62
+ * // => 'Bearer resource_metadata="...", error="insufficient_scope", scope="read write", error_description="..."'
63
+ * ```
64
+ */
65
+ export declare function buildWwwAuthenticate(options?: WwwAuthenticateOptions): string;
66
+ /**
67
+ * Build the Protected Resource Metadata URL for a given base URL and path
68
+ *
69
+ * @param baseUrl - The server base URL
70
+ * @param entryPath - The entry path prefix
71
+ * @param routeBase - The route base path
72
+ * @returns The full PRM URL
73
+ */
74
+ export declare function buildPrmUrl(baseUrl: string, entryPath: string, routeBase: string): string;
75
+ /**
76
+ * Build WWW-Authenticate header for unauthorized requests (no token)
77
+ */
78
+ export declare function buildUnauthorizedHeader(prmUrl: string): string;
79
+ /**
80
+ * Build WWW-Authenticate header for invalid token errors
81
+ */
82
+ export declare function buildInvalidTokenHeader(prmUrl: string, description?: string): string;
83
+ /**
84
+ * Build WWW-Authenticate header for insufficient scope errors
85
+ */
86
+ export declare function buildInsufficientScopeHeader(prmUrl: string, requiredScopes: string[], description?: string): string;
87
+ /**
88
+ * Build WWW-Authenticate header for invalid request errors
89
+ */
90
+ export declare function buildInvalidRequestHeader(prmUrl: string, description?: string): string;
91
+ /**
92
+ * Parse a WWW-Authenticate header value
93
+ *
94
+ * @param header - The WWW-Authenticate header value
95
+ * @returns Parsed header options
96
+ */
97
+ export declare function parseWwwAuthenticate(header: string): WwwAuthenticateOptions;
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ // auth/utils/www-authenticate.utils.ts
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.buildWwwAuthenticate = buildWwwAuthenticate;
5
+ exports.buildPrmUrl = buildPrmUrl;
6
+ exports.buildUnauthorizedHeader = buildUnauthorizedHeader;
7
+ exports.buildInvalidTokenHeader = buildInvalidTokenHeader;
8
+ exports.buildInsufficientScopeHeader = buildInsufficientScopeHeader;
9
+ exports.buildInvalidRequestHeader = buildInvalidRequestHeader;
10
+ exports.parseWwwAuthenticate = parseWwwAuthenticate;
11
+ /**
12
+ * Build a WWW-Authenticate header for Bearer authentication
13
+ *
14
+ * @param options - Header options
15
+ * @returns The formatted WWW-Authenticate header value
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * // Basic protected resource metadata header
20
+ * buildWwwAuthenticate({
21
+ * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',
22
+ * });
23
+ * // => 'Bearer resource_metadata="https://api.example.com/.well-known/oauth-protected-resource"'
24
+ *
25
+ * // With error information
26
+ * buildWwwAuthenticate({
27
+ * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',
28
+ * error: 'insufficient_scope',
29
+ * scope: ['read', 'write'],
30
+ * errorDescription: 'Additional permissions required',
31
+ * });
32
+ * // => 'Bearer resource_metadata="...", error="insufficient_scope", scope="read write", error_description="..."'
33
+ * ```
34
+ */
35
+ function buildWwwAuthenticate(options = {}) {
36
+ const parts = ['Bearer'];
37
+ const params = [];
38
+ // Resource metadata URL (RFC 9728)
39
+ if (options.resourceMetadataUrl) {
40
+ params.push(`resource_metadata="${escapeQuotedString(options.resourceMetadataUrl)}"`);
41
+ }
42
+ // Realm (RFC 6750)
43
+ if (options.realm) {
44
+ params.push(`realm="${escapeQuotedString(options.realm)}"`);
45
+ }
46
+ // Error code (RFC 6750)
47
+ if (options.error) {
48
+ params.push(`error="${options.error}"`);
49
+ }
50
+ // Error description (RFC 6750)
51
+ if (options.errorDescription) {
52
+ params.push(`error_description="${escapeQuotedString(options.errorDescription)}"`);
53
+ }
54
+ // Error URI (RFC 6750)
55
+ if (options.errorUri) {
56
+ params.push(`error_uri="${escapeQuotedString(options.errorUri)}"`);
57
+ }
58
+ // Scope (RFC 6750) - space-delimited
59
+ if (options.scope) {
60
+ const scopeValue = Array.isArray(options.scope) ? options.scope.join(' ') : options.scope;
61
+ params.push(`scope="${escapeQuotedString(scopeValue)}"`);
62
+ }
63
+ if (params.length > 0) {
64
+ parts.push(params.join(', '));
65
+ }
66
+ return parts.join(' ');
67
+ }
68
+ /**
69
+ * Build the Protected Resource Metadata URL for a given base URL and path
70
+ *
71
+ * @param baseUrl - The server base URL
72
+ * @param entryPath - The entry path prefix
73
+ * @param routeBase - The route base path
74
+ * @returns The full PRM URL
75
+ */
76
+ function buildPrmUrl(baseUrl, entryPath, routeBase) {
77
+ const normalizedEntry = normalizePathSegment(entryPath);
78
+ const normalizedRoute = normalizePathSegment(routeBase);
79
+ return `${baseUrl}/.well-known/oauth-protected-resource${normalizedEntry}${normalizedRoute}`;
80
+ }
81
+ /**
82
+ * Build WWW-Authenticate header for unauthorized requests (no token)
83
+ */
84
+ function buildUnauthorizedHeader(prmUrl) {
85
+ return buildWwwAuthenticate({
86
+ resourceMetadataUrl: prmUrl,
87
+ });
88
+ }
89
+ /**
90
+ * Build WWW-Authenticate header for invalid token errors
91
+ */
92
+ function buildInvalidTokenHeader(prmUrl, description) {
93
+ return buildWwwAuthenticate({
94
+ resourceMetadataUrl: prmUrl,
95
+ error: 'invalid_token',
96
+ errorDescription: description ?? 'The access token is invalid or expired',
97
+ });
98
+ }
99
+ /**
100
+ * Build WWW-Authenticate header for insufficient scope errors
101
+ */
102
+ function buildInsufficientScopeHeader(prmUrl, requiredScopes, description) {
103
+ return buildWwwAuthenticate({
104
+ resourceMetadataUrl: prmUrl,
105
+ error: 'insufficient_scope',
106
+ scope: requiredScopes,
107
+ errorDescription: description ?? 'The request requires higher privileges',
108
+ });
109
+ }
110
+ /**
111
+ * Build WWW-Authenticate header for invalid request errors
112
+ */
113
+ function buildInvalidRequestHeader(prmUrl, description) {
114
+ return buildWwwAuthenticate({
115
+ resourceMetadataUrl: prmUrl,
116
+ error: 'invalid_request',
117
+ errorDescription: description ?? 'The request is missing required parameters',
118
+ });
119
+ }
120
+ /**
121
+ * Parse a WWW-Authenticate header value
122
+ *
123
+ * @param header - The WWW-Authenticate header value
124
+ * @returns Parsed header options
125
+ */
126
+ function parseWwwAuthenticate(header) {
127
+ const result = {};
128
+ // Check for Bearer scheme
129
+ if (!header.toLowerCase().startsWith('bearer')) {
130
+ return result;
131
+ }
132
+ // Extract parameters
133
+ const paramString = header.substring(6).trim();
134
+ const paramRegex = /(\w+)="([^"\\]*(?:\\.[^"\\]*)*)"/g;
135
+ let match;
136
+ while ((match = paramRegex.exec(paramString)) !== null) {
137
+ const [, key, value] = match;
138
+ const unescapedValue = unescapeQuotedString(value);
139
+ switch (key.toLowerCase()) {
140
+ case 'resource_metadata':
141
+ result.resourceMetadataUrl = unescapedValue;
142
+ break;
143
+ case 'realm':
144
+ result.realm = unescapedValue;
145
+ break;
146
+ case 'error':
147
+ result.error = unescapedValue;
148
+ break;
149
+ case 'error_description':
150
+ result.errorDescription = unescapedValue;
151
+ break;
152
+ case 'error_uri':
153
+ result.errorUri = unescapedValue;
154
+ break;
155
+ case 'scope':
156
+ result.scope = unescapedValue;
157
+ break;
158
+ }
159
+ }
160
+ return result;
161
+ }
162
+ /**
163
+ * Escape special characters for quoted-string per RFC 7230
164
+ */
165
+ function escapeQuotedString(value) {
166
+ return value.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
167
+ }
168
+ /**
169
+ * Unescape quoted-string per RFC 7230
170
+ */
171
+ function unescapeQuotedString(value) {
172
+ return value.replace(/\\(.)/g, '$1');
173
+ }
174
+ /**
175
+ * Normalize a path segment (ensure leading slash, no trailing slash)
176
+ */
177
+ function normalizePathSegment(path) {
178
+ if (!path || path === '/')
179
+ return '';
180
+ const normalized = path.startsWith('/') ? path : `/${path}`;
181
+ return normalized.replace(/\/+$/, '');
182
+ }
183
+ //# sourceMappingURL=www-authenticate.utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"www-authenticate.utils.js","sourceRoot":"","sources":["../../../../src/auth/utils/www-authenticate.utils.ts"],"names":[],"mappings":"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","sourcesContent":["// auth/utils/www-authenticate.utils.ts\n\n/**\n * WWW-Authenticate Header Builder\n *\n * Implements RFC 9728 (OAuth 2.0 Protected Resource Metadata) and\n * RFC 6750 (Bearer Token Usage) compliant WWW-Authenticate headers.\n */\n\n/**\n * Error codes per RFC 6750 Section 3.1\n */\nexport type BearerErrorCode = 'invalid_request' | 'invalid_token' | 'insufficient_scope';\n\n/**\n * Options for building WWW-Authenticate header\n */\nexport interface WwwAuthenticateOptions {\n /**\n * The resource_metadata URL pointing to the PRM document\n * Per RFC 9728, this is the primary mechanism for resource discovery\n */\n resourceMetadataUrl?: string;\n\n /**\n * OAuth 2.0 realm (optional per RFC 6750)\n */\n realm?: string;\n\n /**\n * Required scopes for the resource (space-delimited)\n */\n scope?: string | string[];\n\n /**\n * Error code when authentication fails\n */\n error?: BearerErrorCode;\n\n /**\n * Human-readable error description\n */\n errorDescription?: string;\n\n /**\n * Error URI pointing to additional information\n */\n errorUri?: string;\n}\n\n/**\n * Build a WWW-Authenticate header for Bearer authentication\n *\n * @param options - Header options\n * @returns The formatted WWW-Authenticate header value\n *\n * @example\n * ```typescript\n * // Basic protected resource metadata header\n * buildWwwAuthenticate({\n * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',\n * });\n * // => 'Bearer resource_metadata=\"https://api.example.com/.well-known/oauth-protected-resource\"'\n *\n * // With error information\n * buildWwwAuthenticate({\n * resourceMetadataUrl: 'https://api.example.com/.well-known/oauth-protected-resource',\n * error: 'insufficient_scope',\n * scope: ['read', 'write'],\n * errorDescription: 'Additional permissions required',\n * });\n * // => 'Bearer resource_metadata=\"...\", error=\"insufficient_scope\", scope=\"read write\", error_description=\"...\"'\n * ```\n */\nexport function buildWwwAuthenticate(options: WwwAuthenticateOptions = {}): string {\n const parts: string[] = ['Bearer'];\n const params: string[] = [];\n\n // Resource metadata URL (RFC 9728)\n if (options.resourceMetadataUrl) {\n params.push(`resource_metadata=\"${escapeQuotedString(options.resourceMetadataUrl)}\"`);\n }\n\n // Realm (RFC 6750)\n if (options.realm) {\n params.push(`realm=\"${escapeQuotedString(options.realm)}\"`);\n }\n\n // Error code (RFC 6750)\n if (options.error) {\n params.push(`error=\"${options.error}\"`);\n }\n\n // Error description (RFC 6750)\n if (options.errorDescription) {\n params.push(`error_description=\"${escapeQuotedString(options.errorDescription)}\"`);\n }\n\n // Error URI (RFC 6750)\n if (options.errorUri) {\n params.push(`error_uri=\"${escapeQuotedString(options.errorUri)}\"`);\n }\n\n // Scope (RFC 6750) - space-delimited\n if (options.scope) {\n const scopeValue = Array.isArray(options.scope) ? options.scope.join(' ') : options.scope;\n params.push(`scope=\"${escapeQuotedString(scopeValue)}\"`);\n }\n\n if (params.length > 0) {\n parts.push(params.join(', '));\n }\n\n return parts.join(' ');\n}\n\n/**\n * Build the Protected Resource Metadata URL for a given base URL and path\n *\n * @param baseUrl - The server base URL\n * @param entryPath - The entry path prefix\n * @param routeBase - The route base path\n * @returns The full PRM URL\n */\nexport function buildPrmUrl(baseUrl: string, entryPath: string, routeBase: string): string {\n const normalizedEntry = normalizePathSegment(entryPath);\n const normalizedRoute = normalizePathSegment(routeBase);\n return `${baseUrl}/.well-known/oauth-protected-resource${normalizedEntry}${normalizedRoute}`;\n}\n\n/**\n * Build WWW-Authenticate header for unauthorized requests (no token)\n */\nexport function buildUnauthorizedHeader(prmUrl: string): string {\n return buildWwwAuthenticate({\n resourceMetadataUrl: prmUrl,\n });\n}\n\n/**\n * Build WWW-Authenticate header for invalid token errors\n */\nexport function buildInvalidTokenHeader(prmUrl: string, description?: string): string {\n return buildWwwAuthenticate({\n resourceMetadataUrl: prmUrl,\n error: 'invalid_token',\n errorDescription: description ?? 'The access token is invalid or expired',\n });\n}\n\n/**\n * Build WWW-Authenticate header for insufficient scope errors\n */\nexport function buildInsufficientScopeHeader(prmUrl: string, requiredScopes: string[], description?: string): string {\n return buildWwwAuthenticate({\n resourceMetadataUrl: prmUrl,\n error: 'insufficient_scope',\n scope: requiredScopes,\n errorDescription: description ?? 'The request requires higher privileges',\n });\n}\n\n/**\n * Build WWW-Authenticate header for invalid request errors\n */\nexport function buildInvalidRequestHeader(prmUrl: string, description?: string): string {\n return buildWwwAuthenticate({\n resourceMetadataUrl: prmUrl,\n error: 'invalid_request',\n errorDescription: description ?? 'The request is missing required parameters',\n });\n}\n\n/**\n * Parse a WWW-Authenticate header value\n *\n * @param header - The WWW-Authenticate header value\n * @returns Parsed header options\n */\nexport function parseWwwAuthenticate(header: string): WwwAuthenticateOptions {\n const result: WwwAuthenticateOptions = {};\n\n // Check for Bearer scheme\n if (!header.toLowerCase().startsWith('bearer')) {\n return result;\n }\n\n // Extract parameters\n const paramString = header.substring(6).trim();\n const paramRegex = /(\\w+)=\"([^\"\\\\]*(?:\\\\.[^\"\\\\]*)*)\"/g;\n let match: RegExpExecArray | null;\n\n while ((match = paramRegex.exec(paramString)) !== null) {\n const [, key, value] = match;\n const unescapedValue = unescapeQuotedString(value);\n\n switch (key.toLowerCase()) {\n case 'resource_metadata':\n result.resourceMetadataUrl = unescapedValue;\n break;\n case 'realm':\n result.realm = unescapedValue;\n break;\n case 'error':\n result.error = unescapedValue as BearerErrorCode;\n break;\n case 'error_description':\n result.errorDescription = unescapedValue;\n break;\n case 'error_uri':\n result.errorUri = unescapedValue;\n break;\n case 'scope':\n result.scope = unescapedValue;\n break;\n }\n }\n\n return result;\n}\n\n/**\n * Escape special characters for quoted-string per RFC 7230\n */\nfunction escapeQuotedString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"');\n}\n\n/**\n * Unescape quoted-string per RFC 7230\n */\nfunction unescapeQuotedString(value: string): string {\n return value.replace(/\\\\(.)/g, '$1');\n}\n\n/**\n * Normalize a path segment (ensure leading slash, no trailing slash)\n */\nfunction normalizePathSegment(path: string): string {\n if (!path || path === '/') return '';\n const normalized = path.startsWith('/') ? path : `/${path}`;\n return normalized.replace(/\\/+$/, '');\n}\n"]}