@redocly/reef 0.137.0-next.0 → 0.137.0-next.10

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 (355) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/dist/api-schemas/otel-traces.d.ts +1359 -0
  3. package/dist/api-schemas/otel-traces.js +1 -0
  4. package/dist/cli/stats/collectors/asyncapi/index.d.ts +3 -0
  5. package/dist/cli/stats/collectors/asyncapi/index.js +1 -0
  6. package/dist/cli/stats/collectors/extension-sampling.d.ts +44 -0
  7. package/dist/cli/stats/collectors/extension-sampling.js +1 -0
  8. package/dist/cli/stats/collectors/openapi/index.js +1 -1
  9. package/dist/cli/stats/collectors/page-slugs/index.d.ts +9 -0
  10. package/dist/cli/stats/collectors/page-slugs/index.js +1 -0
  11. package/dist/cli/stats/collectors/prepare-stats-walk.d.ts +10 -0
  12. package/dist/cli/stats/collectors/prepare-stats-walk.js +1 -0
  13. package/dist/cli/stats/collectors/run-stats-collector.d.ts +24 -0
  14. package/dist/cli/stats/collectors/run-stats-collector.js +1 -0
  15. package/dist/cli/stats/index.js +1 -1
  16. package/dist/client/app/hooks/useMcpData.d.ts +1 -0
  17. package/dist/client/app/hooks/useMcpData.js +1 -1
  18. package/dist/client/app/markdoc/custom-components/openapi/json-schema.js +1 -1
  19. package/dist/client/app/markdoc/custom-components/openapi/openapi-code-sample.js +1 -1
  20. package/dist/client/app/markdoc/custom-components/openapi/openapi-example.js +1 -1
  21. package/dist/client/app/markdoc/custom-components/openapi/openapi-response-sample.js +1 -1
  22. package/dist/client/app/markdoc/custom-components/openapi/replay-openapi.js +1 -1
  23. package/dist/client/app/markdoc/custom-components/openapi/use-markdown-adapter.d.ts +45 -0
  24. package/dist/client/app/markdoc/custom-components/openapi/use-markdown-adapter.js +1 -0
  25. package/dist/client/app/utils/loadAndNavigate.js +1 -1
  26. package/dist/client/providers/hooks.js +1 -1
  27. package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
  28. package/dist/client/templates/api-docs/helpers.d.ts +4 -1
  29. package/dist/client/templates/api-docs/helpers.js +5 -1
  30. package/dist/client/templates/api-docs/template.js +8 -3
  31. package/dist/client/utils/catalog/get-next-page-param.d.ts +1 -1
  32. package/dist/client/utils/catalog/get-next-page-param.js +1 -1
  33. package/dist/compiled/svgo/svgo-node.js +32 -32
  34. package/dist/constants/l10n/langs/ar.js +1 -1
  35. package/dist/constants/l10n/langs/de.js +1 -1
  36. package/dist/constants/l10n/langs/en.js +1 -1
  37. package/dist/constants/l10n/langs/es.js +1 -1
  38. package/dist/constants/l10n/langs/fr.js +1 -1
  39. package/dist/constants/l10n/langs/hi.js +1 -1
  40. package/dist/constants/l10n/langs/it.js +1 -1
  41. package/dist/constants/l10n/langs/ja.js +1 -1
  42. package/dist/constants/l10n/langs/ko.js +1 -1
  43. package/dist/constants/l10n/langs/pl.js +1 -1
  44. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  45. package/dist/constants/l10n/langs/pt.js +1 -1
  46. package/dist/constants/l10n/langs/ru.js +1 -1
  47. package/dist/constants/l10n/langs/uk.js +1 -1
  48. package/dist/constants/l10n/langs/zh.js +1 -1
  49. package/dist/server/config/env-config.d.ts +6 -0
  50. package/dist/server/config/env-schema.d.ts +15 -0
  51. package/dist/server/config/env-schemas/feature-flags.d.ts +9 -1
  52. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  53. package/dist/server/config/env-schemas/search.d.ts +3 -0
  54. package/dist/server/config/env-schemas/search.js +1 -1
  55. package/dist/server/constants/common.d.ts +1 -0
  56. package/dist/server/constants/common.js +1 -1
  57. package/dist/server/constants/mcp.d.ts +5 -0
  58. package/dist/server/constants/mcp.js +1 -0
  59. package/dist/server/constants/plugins/search.d.ts +0 -2
  60. package/dist/server/constants/plugins/search.js +1 -1
  61. package/dist/server/constants/rbac.d.ts +3 -0
  62. package/dist/server/constants/rbac.js +1 -0
  63. package/dist/server/esbuild/esbuild.js +3 -3
  64. package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -1
  65. package/dist/server/plugins/api-docs/options.js +1 -1
  66. package/dist/server/plugins/api-docs/search/create-indexer.d.ts +5 -0
  67. package/dist/server/plugins/api-docs/search/create-indexer.js +1 -0
  68. package/dist/server/plugins/api-docs/search/get-ai-search-documents.js +28 -28
  69. package/dist/server/plugins/api-docs/search/search-resolver.js +1 -1
  70. package/dist/server/plugins/{openapi-docs/is-openapi-doc.d.ts → api-docs/utils/is-api-doc.d.ts} +4 -2
  71. package/dist/server/plugins/api-docs/utils/is-api-doc.js +1 -0
  72. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.d.ts +1 -1
  73. package/dist/server/plugins/arazzo-docs/arazzo-doc-loader.js +1 -1
  74. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.d.ts +5 -0
  75. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
  76. package/dist/server/plugins/entitlements/index.js +1 -1
  77. package/dist/server/plugins/l10n/index.js +1 -1
  78. package/dist/server/plugins/lifecycle.js +2 -2
  79. package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
  80. package/dist/server/plugins/markdown/attribute-resolvers/resolve-open-api-ref.js +1 -1
  81. package/dist/server/plugins/markdown/html/html-jsx-attribute-mapping.js +1 -1
  82. package/dist/server/plugins/markdown/utils/sanitize-malformed-md-content.js +2 -2
  83. package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +1 -2
  84. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  85. package/dist/server/plugins/mcp/auth/token-audience-telemetry.d.ts +7 -0
  86. package/dist/server/plugins/mcp/auth/token-audience-telemetry.js +1 -0
  87. package/dist/server/plugins/mcp/auth/token-audience.d.ts +6 -0
  88. package/dist/server/plugins/mcp/auth/token-audience.js +1 -0
  89. package/dist/server/plugins/mcp/codemode/capabilities/fetch/index.js +4 -4
  90. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +3 -1
  91. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -1
  92. package/dist/server/plugins/mcp/codemode/invoke-tool.js +1 -1
  93. package/dist/server/plugins/mcp/codemode/prompts.js +1 -1
  94. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.d.ts +1 -1
  95. package/dist/server/plugins/mcp/codemode/sandbox/polyfills/fetch-shim.js +9 -3
  96. package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +1 -1
  97. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +1 -1
  98. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
  99. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  100. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.d.ts +1 -0
  101. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  102. package/dist/server/plugins/mcp/codemode/types.d.ts +1 -0
  103. package/dist/server/plugins/mcp/constants.d.ts +1 -1
  104. package/dist/server/plugins/mcp/constants.js +1 -1
  105. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.d.ts +13 -0
  106. package/dist/server/plugins/mcp/custom-tools/extract-tool-definition.js +1 -0
  107. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.d.ts +6 -0
  108. package/dist/server/plugins/mcp/custom-tools/scan-custom-tools.js +1 -0
  109. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.d.ts +3 -0
  110. package/dist/server/plugins/mcp/custom-tools/validate-tool-definition.js +1 -0
  111. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +2 -0
  112. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  113. package/dist/server/plugins/mcp/docs-mcp/tools/core/search.js +2 -2
  114. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoints.js +1 -1
  115. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/list-apis.js +1 -1
  116. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  117. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.d.ts +10 -0
  118. package/dist/server/plugins/mcp/gateway-mcp/callable-apis.js +1 -0
  119. package/dist/server/plugins/mcp/gateway-mcp/credential-validation.d.ts +4 -0
  120. package/dist/server/plugins/mcp/gateway-mcp/credential-validation.js +1 -0
  121. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +15 -5
  122. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -3
  123. package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
  124. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.d.ts +2 -1
  125. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-audit.js +1 -1
  126. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +10 -1
  127. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
  128. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.d.ts +7 -0
  129. package/dist/server/plugins/mcp/gateway-mcp/fetch/upstream-detail.js +1 -0
  130. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +2 -10
  131. package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
  132. package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +16 -4
  133. package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -1
  134. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +26 -1
  135. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +2 -1
  136. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +12 -0
  137. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -1
  138. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  139. package/dist/server/plugins/mcp/handlers/errors.d.ts +7 -2
  140. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  141. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  142. package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -124
  143. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.d.ts +12 -0
  144. package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +225 -0
  145. package/dist/server/plugins/mcp/index.d.ts +0 -2
  146. package/dist/server/plugins/mcp/index.js +1 -1
  147. package/dist/server/plugins/mcp/servers/docs-server.d.ts +2 -2
  148. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  149. package/dist/server/plugins/mcp/servers/mcp-server.d.ts +2 -11
  150. package/dist/server/plugins/mcp/servers/mcp-server.js +4 -2
  151. package/dist/server/plugins/mcp/types.d.ts +32 -5
  152. package/dist/server/plugins/mcp/utils/available-sandbox-tools.d.ts +4 -0
  153. package/dist/server/plugins/mcp/utils/available-sandbox-tools.js +1 -0
  154. package/dist/server/plugins/mcp/utils/find-gated-tool-names.d.ts +12 -0
  155. package/dist/server/plugins/mcp/utils/find-gated-tool-names.js +1 -0
  156. package/dist/server/plugins/mcp/utils/mcp-client.d.ts +13 -0
  157. package/dist/server/plugins/mcp/utils/mcp-client.js +1 -0
  158. package/dist/server/plugins/mcp/utils/tool-registration.d.ts +17 -0
  159. package/dist/server/plugins/mcp/utils/tool-registration.js +1 -0
  160. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +6 -1
  161. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  162. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.d.ts +5 -0
  163. package/dist/server/plugins/mcp/workers/import-mcp-tool-handlers.js +1 -0
  164. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +6 -11
  165. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  166. package/dist/server/plugins/mcp/workers/tool-file-system.d.ts +6 -0
  167. package/dist/server/plugins/mcp/workers/tool-file-system.js +1 -0
  168. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.d.ts +4 -2
  169. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +1 -3
  170. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  171. package/dist/server/plugins/search/engines/flexsearch/search-index.d.ts +8 -4
  172. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  173. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  174. package/dist/server/plugins/search/index.js +1 -1
  175. package/dist/server/plugins/search/llmstxt/build-page-llms-txt-md.d.ts +4 -0
  176. package/dist/server/plugins/search/llmstxt/build-page-llms-txt-md.js +3 -0
  177. package/dist/server/plugins/search/llmstxt/create-llms-txt-generator.d.ts +4 -0
  178. package/dist/server/plugins/search/llmstxt/create-llms-txt-generator.js +1 -0
  179. package/dist/server/plugins/search/llmstxt/get-llms-txt-exclude-matcher.d.ts +4 -0
  180. package/dist/server/plugins/search/llmstxt/get-llms-txt-exclude-matcher.js +1 -0
  181. package/dist/server/plugins/search/llmstxt/index.d.ts +2 -2
  182. package/dist/server/plugins/search/llmstxt/is-included-in-llms-txt.d.ts +6 -0
  183. package/dist/server/plugins/search/llmstxt/is-included-in-llms-txt.js +1 -0
  184. package/dist/server/plugins/search/utils.d.ts +2 -1
  185. package/dist/server/plugins/search/utils.js +2 -2
  186. package/dist/server/sandbox/constants/sandbox.d.ts +4 -1
  187. package/dist/server/sandbox/constants/sandbox.js +1 -1
  188. package/dist/server/sandbox/sandbox.js +2 -2
  189. package/dist/server/sandbox/utils/returns-from-top-level.d.ts +4 -0
  190. package/dist/server/sandbox/utils/returns-from-top-level.js +1 -0
  191. package/dist/server/store.d.ts +2 -0
  192. package/dist/server/store.js +1 -1
  193. package/dist/server/types/plugins/common.d.ts +5 -0
  194. package/dist/server/types/plugins/search.d.ts +7 -2
  195. package/dist/server/types/web-server.d.ts +8 -0
  196. package/dist/server/utils/envs/get-api-route-allowed-env-variables.js +1 -1
  197. package/dist/server/utils/get-route-ai-documents-store.d.ts +5 -0
  198. package/dist/server/utils/get-route-ai-documents-store.js +1 -0
  199. package/dist/server/utils/get-route-static-data.d.ts +4 -0
  200. package/dist/server/utils/get-route-static-data.js +1 -0
  201. package/dist/server/utils/llmstxt/agent-feedback-llms-footer.js +1 -1
  202. package/dist/server/utils/llmstxt/resolve-llms-txt-md.d.ts +10 -0
  203. package/dist/server/utils/llmstxt/resolve-llms-txt-md.js +1 -0
  204. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.d.ts +3 -0
  205. package/dist/server/utils/rbac/can-anonymous-access-mcp-feature.js +1 -0
  206. package/dist/server/utils/rbac/should-handle-mcp-auth.d.ts +2 -0
  207. package/dist/server/utils/rbac/should-handle-mcp-auth.js +1 -0
  208. package/dist/server/utils/rbac.js +1 -1
  209. package/dist/server/utils/search/highlight-text-for-search.js +1 -1
  210. package/dist/server/web-server/auth.d.ts +13 -2
  211. package/dist/server/web-server/auth.js +3 -3
  212. package/dist/server/web-server/dev-server.js +1 -1
  213. package/dist/server/web-server/handle-api-route-request.js +1 -1
  214. package/dist/server/web-server/middleware/ensureSearchData.js +1 -1
  215. package/dist/server/web-server/routes/ask-ai.d.ts +1 -0
  216. package/dist/server/web-server/routes/ask-ai.js +1 -1
  217. package/dist/server/web-server/routes/auth.js +1 -1
  218. package/dist/server/web-server/routes/dynamic-route.d.ts +2 -1
  219. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  220. package/dist/server/web-server/routes/error.js +1 -1
  221. package/dist/server/web-server/routes/helpers/resolve-ui-locales-for-idp-login.js +1 -1
  222. package/dist/server/web-server/routes/index.d.ts +2 -1
  223. package/dist/server/web-server/routes/index.js +1 -1
  224. package/dist/server/web-server/routes/llms-txt.d.ts +4 -0
  225. package/dist/server/web-server/routes/llms-txt.js +1 -0
  226. package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
  227. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  228. package/dist/server/web-server/routes/otel/otel.js +1 -1
  229. package/dist/server/web-server/routes/page-data.js +1 -1
  230. package/dist/server/web-server/routes/resolve-route.js +1 -1
  231. package/dist/server/web-server/utils/get-request-origin.d.ts +2 -0
  232. package/dist/server/web-server/utils/get-request-origin.js +1 -1
  233. package/dist/server/web-server/utils/prepare-list-response.d.ts +2 -4
  234. package/dist/server/web-server/utils/prepare-list-response.js +1 -1
  235. package/dist/server/web-server/utils.d.ts +1 -1
  236. package/dist/server/web-server/utils.js +1 -1
  237. package/dist/server/workers/mcp-tool-worker-pool.d.ts +1 -0
  238. package/dist/server/workers/mcp-tool-worker-pool.js +1 -1
  239. package/dist/server/workers/mcp-tool-worker.js +1 -1
  240. package/dist/server/workers/types.d.ts +9 -2
  241. package/dist/server/workers/worker-pool.d.ts +1 -0
  242. package/dist/server/workers/worker-pool.js +1 -1
  243. package/dist/types/global-data.d.ts +1 -0
  244. package/dist/utils/guards/is-plain-object.d.ts +19 -0
  245. package/dist/utils/guards/is-plain-object.js +1 -0
  246. package/package.json +12 -15
  247. package/dist/client/templates/asyncapi-docs/helpers.d.ts +0 -12
  248. package/dist/client/templates/asyncapi-docs/helpers.js +0 -1
  249. package/dist/client/templates/asyncapi-docs/template.d.ts +0 -15
  250. package/dist/client/templates/asyncapi-docs/template.js +0 -9
  251. package/dist/client/templates/openapi-docs/helpers.d.ts +0 -18
  252. package/dist/client/templates/openapi-docs/helpers.js +0 -5
  253. package/dist/client/templates/openapi-docs/template.d.ts +0 -6
  254. package/dist/client/templates/openapi-docs/template.js +0 -14
  255. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.d.ts +0 -9
  256. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-check.js +0 -1
  257. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.d.ts +0 -2
  258. package/dist/server/esbuild/plugins/api-docs-module-replacer/empty-overlay.js +0 -1
  259. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.d.ts +0 -6
  260. package/dist/server/esbuild/plugins/api-docs-module-replacer/index.js +0 -1
  261. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.d.ts +0 -8
  262. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-check.js +0 -1
  263. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.d.ts +0 -2
  264. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-overlay.js +0 -1
  265. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.d.ts +0 -5
  266. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/empty-use-license-key.js +0 -1
  267. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.d.ts +0 -6
  268. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/index.js +0 -1
  269. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.d.ts +0 -3
  270. package/dist/server/esbuild/plugins/openapi-docs-module-replacer/loadAndBundleSpec.mock.js +0 -1
  271. package/dist/server/plugins/api-docs/search/search-indexer.d.ts +0 -9
  272. package/dist/server/plugins/api-docs/search/search-indexer.js +0 -1
  273. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.d.ts +0 -18
  274. package/dist/server/plugins/asyncapi-docs/asyncapi-doc-loader.js +0 -5
  275. package/dist/server/plugins/asyncapi-docs/get-server-props.d.ts +0 -4
  276. package/dist/server/plugins/asyncapi-docs/get-server-props.js +0 -1
  277. package/dist/server/plugins/asyncapi-docs/get-template-path.d.ts +0 -2
  278. package/dist/server/plugins/asyncapi-docs/get-template-path.js +0 -1
  279. package/dist/server/plugins/asyncapi-docs/index.d.ts +0 -3
  280. package/dist/server/plugins/asyncapi-docs/index.js +0 -1
  281. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.d.ts +0 -3
  282. package/dist/server/plugins/asyncapi-docs/is-asyncapi-doc.js +0 -1
  283. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.d.ts +0 -9
  284. package/dist/server/plugins/asyncapi-docs/search/get-ai-search-documents.js +0 -56
  285. package/dist/server/plugins/asyncapi-docs/search/schema-processor.d.ts +0 -8
  286. package/dist/server/plugins/asyncapi-docs/search/schema-processor.js +0 -1
  287. package/dist/server/plugins/asyncapi-docs/search/search-facets.d.ts +0 -8
  288. package/dist/server/plugins/asyncapi-docs/search/search-facets.js +0 -1
  289. package/dist/server/plugins/asyncapi-docs/search/search-resolver.d.ts +0 -5
  290. package/dist/server/plugins/asyncapi-docs/search/search-resolver.js +0 -1
  291. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.d.ts +0 -4
  292. package/dist/server/plugins/asyncapi-docs/store-definition-bundles.js +0 -1
  293. package/dist/server/plugins/graphql-docs/constants.d.ts +0 -2
  294. package/dist/server/plugins/graphql-docs/constants.js +0 -1
  295. package/dist/server/plugins/graphql-docs/get-template-path.d.ts +0 -2
  296. package/dist/server/plugins/graphql-docs/get-template-path.js +0 -1
  297. package/dist/server/plugins/graphql-docs/graphql-doc-loader.d.ts +0 -17
  298. package/dist/server/plugins/graphql-docs/graphql-doc-loader.js +0 -1
  299. package/dist/server/plugins/graphql-docs/index.d.ts +0 -4
  300. package/dist/server/plugins/graphql-docs/index.js +0 -1
  301. package/dist/server/plugins/graphql-docs/is-graphql-doc.d.ts +0 -2
  302. package/dist/server/plugins/graphql-docs/is-graphql-doc.js +0 -1
  303. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.d.ts +0 -17
  304. package/dist/server/plugins/graphql-docs/search/ai/get-ai-search-document.js +0 -4
  305. package/dist/server/plugins/graphql-docs/search/ai/utils.d.ts +0 -14
  306. package/dist/server/plugins/graphql-docs/search/ai/utils.js +0 -36
  307. package/dist/server/plugins/graphql-docs/search/search-facets.d.ts +0 -8
  308. package/dist/server/plugins/graphql-docs/search/search-facets.js +0 -1
  309. package/dist/server/plugins/graphql-docs/search/search-resolver.d.ts +0 -5
  310. package/dist/server/plugins/graphql-docs/search/search-resolver.js +0 -1
  311. package/dist/server/plugins/graphql-docs/spec-download.api.d.ts +0 -3
  312. package/dist/server/plugins/graphql-docs/spec-download.api.js +0 -1
  313. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.d.ts +0 -5
  314. package/dist/server/plugins/graphql-docs/template/GraphQLDocs.js +0 -4
  315. package/dist/server/plugins/graphql-docs/types.d.ts +0 -40
  316. package/dist/server/plugins/graphql-docs/types.js +0 -0
  317. package/dist/server/plugins/openapi-docs/ai-search-indexer.d.ts +0 -14
  318. package/dist/server/plugins/openapi-docs/ai-search-indexer.js +0 -1
  319. package/dist/server/plugins/openapi-docs/decorators.d.ts +0 -25
  320. package/dist/server/plugins/openapi-docs/decorators.js +0 -1
  321. package/dist/server/plugins/openapi-docs/format-bundle-error.d.ts +0 -6
  322. package/dist/server/plugins/openapi-docs/format-bundle-error.js +0 -5
  323. package/dist/server/plugins/openapi-docs/get-server-props.d.ts +0 -4
  324. package/dist/server/plugins/openapi-docs/get-server-props.js +0 -1
  325. package/dist/server/plugins/openapi-docs/get-template-path.d.ts +0 -2
  326. package/dist/server/plugins/openapi-docs/get-template-path.js +0 -1
  327. package/dist/server/plugins/openapi-docs/index.d.ts +0 -3
  328. package/dist/server/plugins/openapi-docs/index.js +0 -1
  329. package/dist/server/plugins/openapi-docs/is-openapi-doc.js +0 -1
  330. package/dist/server/plugins/openapi-docs/load-definition.d.ts +0 -31
  331. package/dist/server/plugins/openapi-docs/load-definition.js +0 -3
  332. package/dist/server/plugins/openapi-docs/openapi-search-builder.d.ts +0 -24
  333. package/dist/server/plugins/openapi-docs/openapi-search-builder.js +0 -1
  334. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.d.ts +0 -18
  335. package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +0 -94
  336. package/dist/server/plugins/openapi-docs/search/search-facets.d.ts +0 -11
  337. package/dist/server/plugins/openapi-docs/search/search-facets.js +0 -1
  338. package/dist/server/plugins/openapi-docs/search/search-resolver.d.ts +0 -5
  339. package/dist/server/plugins/openapi-docs/search/search-resolver.js +0 -1
  340. package/dist/server/plugins/openapi-docs/search-indexer.d.ts +0 -17
  341. package/dist/server/plugins/openapi-docs/search-indexer.js +0 -1
  342. package/dist/server/plugins/openapi-docs/spec-download.api.d.ts +0 -4
  343. package/dist/server/plugins/openapi-docs/spec-download.api.js +0 -1
  344. package/dist/server/plugins/openapi-docs/store-definition-bundles.d.ts +0 -4
  345. package/dist/server/plugins/openapi-docs/store-definition-bundles.js +0 -1
  346. package/dist/server/plugins/openapi-docs/types.d.ts +0 -17
  347. package/dist/server/plugins/openapi-docs/types.js +0 -0
  348. package/dist/server/plugins/openapi-docs/utils.d.ts +0 -25
  349. package/dist/server/plugins/openapi-docs/utils.js +0 -1
  350. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.d.ts +0 -0
  351. /package/dist/client/templates/{openapi-docs → api-docs}/mock-server-config.js +0 -0
  352. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.d.ts +0 -0
  353. /package/dist/{server/plugins → markdoc}/helpers/parse-partials.js +0 -0
  354. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.d.ts +0 -0
  355. /package/dist/server/plugins/{openapi-docs → api-docs/utils}/ast-utils.js +0 -0
@@ -1,11 +1,13 @@
1
1
  import type { InputRequiredResult } from '@modelcontextprotocol/server';
2
2
  import type { UpstreamAuthRequiredEvent } from './upstream-auth.js';
3
- import type { UpstreamAuthScheme } from './upstream-auth-scheme.js';
3
+ import type { SchemeChoice, UpstreamApiAuth, UpstreamAuthScheme } from './upstream-auth-scheme.js';
4
4
  import type { KvService } from '@redocly/config';
5
5
  export declare const CREDENTIALS_INPUT_REQUEST_KEY = "credentials";
6
6
  export type CredentialTarget = {
7
7
  api: string;
8
8
  name: string;
9
+ scheme: string;
10
+ schemeLabel?: string;
9
11
  };
10
12
  /**
11
13
  * Why the prompt is being raised. `authFailure` is the automatic path behind an upstream 401;
@@ -14,6 +16,7 @@ export type CredentialTarget = {
14
16
  export type CredentialElicitationReason = {
15
17
  kind: 'authFailure';
16
18
  status: number;
19
+ detail?: string;
17
20
  otherApiNames?: string[];
18
21
  } | {
19
22
  kind: 'requested';
@@ -23,12 +26,13 @@ type CredentialElicitationRequest = {
23
26
  baseUrl: string;
24
27
  target: CredentialTarget;
25
28
  auth: UpstreamAuthScheme;
29
+ apiAuth?: UpstreamApiAuth;
26
30
  kv: KvService;
27
31
  hasExistingSecret: boolean;
28
32
  reason: CredentialElicitationReason;
29
33
  };
30
34
  export declare function isCredentialElicitationDeclined(inputResponses: Record<string, unknown> | undefined): boolean;
31
- export declare function targetOf(event: UpstreamAuthRequiredEvent): CredentialTarget;
35
+ export declare function schemeLabelOf(schemes: Record<string, unknown>, scheme: string): string | undefined;
32
36
  /**
33
37
  * The 2026-07-28-era credentials prompt: the tool call returns an input-required result the
34
38
  * client fulfils and retries, with no push `elicitation/create` and no session behind it.
@@ -40,9 +44,15 @@ export declare function buildUpstreamCredentialInputRequired(request: Credential
40
44
  export declare function buildUpstreamCredentialFallback(request: CredentialElicitationRequest): Promise<string>;
41
45
  /**
42
46
  * Text for an authorization failure we deliberately do NOT prompt for: a stored secret the
43
- * upstream rejected, or a 403/407 that is more likely a permissions problem than a missing key.
44
- * Minting another link here is what produced the credentials-link loop.
47
+ * upstream rejected, a 401 that never carried a stored credential, or a 403/407 that is more
48
+ * likely a permissions problem than a missing key.
45
49
  */
46
- export declare function buildCredentialsToolHint(event: UpstreamAuthRequiredEvent): string;
50
+ export declare function buildCredentialsToolHint(event: UpstreamAuthRequiredEvent, schemeLabel?: string): string;
51
+ /**
52
+ * Text for an operation that accepts several security schemes and has no stored credential for
53
+ * any of them. Picking one here is what sent an API key as a session cookie, so the model is told
54
+ * to ask the user which credential they hold and pass it back as `scheme`.
55
+ */
56
+ export declare function buildSchemeChoiceHint(event: UpstreamAuthRequiredEvent, choices: readonly SchemeChoice[]): string;
47
57
  export {};
48
58
  //# sourceMappingURL=elicitation.d.ts.map
@@ -1,3 +1,5 @@
1
- import{inputRequired as c,inputResponse as f}from"@modelcontextprotocol/server";import{MANAGE_API_CREDENTIALS_TOOL_NAME as T}from"../constants.js";import{secretStore as $,ELICITATION_TTL_MS as A}from"./secret-store.js";import{ANONYMOUS_SUBJECT_PREFIX as l}from"./subject.js";const h="credentials";function C(e){const t=f(e,h);return t.kind==="elicit"&&(t.action==="decline"||t.action==="cancel")}function _(e){return{api:e.api,name:e.name}}async function b(e){const{url:t}=await d(e);return c({inputRequests:{[h]:c.elicitUrl({message:P(e.target.name,e.hasExistingSecret),url:t})}})}async function O(e){const{url:t}=await d(e);return y(e,t,I(e.subject))}function R(e){return[e.status===401?`The stored credentials for "${e.name}" were rejected (HTTP 401).`:`The "${e.name}" API rejected the request with HTTP ${e.status}.`,"",`Do not retry the same call. Call \`${T}\` with api: "${e.api}" to get a link the user has to open in a browser to replace or remove the stored credentials, then retry once they confirm they saved them.`].join(`
2
- `)}async function d({kv:e,subject:t,baseUrl:n,target:i,auth:a,hasExistingSecret:o}){const r=await $.createElicitation(e,{subject:t,api:i.api,name:i.name,auth:a,hasExistingSecret:o});return{token:r,url:g(n,r)}}function I(e){return e.startsWith(l)?e.slice(l.length):void 0}function P(e,t){const n=`The link works for ${u()} minutes.`;return t?`Open this page in a browser to replace or remove the stored credentials for the "${e}" API. They go straight to the API and never enter the chat. ${n}`:`The "${e}" API needs credentials. Open this page in a browser to paste them - they go straight to the API and never enter the chat. ${n}`}function u(){return Math.round(A/6e4)}function g(e,t){if(!e)return`/mcp/credentials?token=${t}`;try{const n=new URL("/mcp/credentials",e);return n.searchParams.set("token",t),n.toString()}catch{return`${e}/mcp/credentials?token=${t}`}}function y({target:e,reason:t,hasExistingSecret:n},i,a){const r=[`**Stop and show the user this link. They have to open it in a browser to ${n?`replace or remove the stored credentials for the "${e.name}" API`:`add credentials for the "${e.name}" API`} - nothing continues until they do.**`,"",i,"",`The link is valid ${u()} minutes and opens a form on this site. Credentials go straight to the API from there: never ask for them in the conversation and never pass them as a tool argument.`,"",t.kind==="authFailure"?`The upstream API "${e.name}" returned ${t.status} and needs credentials.`:n?`Credentials are already stored for the "${e.name}" API; the link lets the user replace or remove them.`:`The "${e.name}" API needs credentials.`,a?`Once the user confirms they saved them, call this tool again with sessionHandle: "${a}" - the credentials are stored against that handle, applied server-side, and never appear in the conversation.`:"Once the user confirms they saved them, call this tool again - the credentials are applied server-side and never appear in the conversation."],s=t.kind==="authFailure"?t.otherApiNames??[]:[];if(s.length>0){const p=s.map(m=>`"${m}"`).join(", ");r.push("",`The remaining APIs (${p}) will prompt for credentials on subsequent calls.`)}return r.join(`
3
- `)}export{h as CREDENTIALS_INPUT_REQUEST_KEY,R as buildCredentialsToolHint,O as buildUpstreamCredentialFallback,b as buildUpstreamCredentialInputRequired,C as isCredentialElicitationDeclined,_ as targetOf};
1
+ import{inputRequired as h,inputResponse as w}from"@modelcontextprotocol/server";import{MANAGE_API_CREDENTIALS_TOOL_NAME as l}from"../constants.js";import{secretStore as d,ELICITATION_TTL_MS as y}from"./secret-store.js";import{operationsForScheme as I,orderedSchemesOf as A}from"./upstream-auth-scheme.js";import{ANONYMOUS_SUBJECT_PREFIX as u}from"./subject.js";const m="credentials";function R(e){const t=w(e,m);return t.kind==="elicit"&&(t.action==="decline"||t.action==="cancel")}function x(e,t){return Object.keys(e).length>1?t:void 0}async function F(e){const{url:t}=await f(e);return h({inputRequests:{[m]:h.elicitUrl({message:b(e),url:t})}})}async function L(e){const{url:t}=await f(e);return C(e,t,P(e.subject))}function U(e,t){const r=p(e);if(e.status===401&&!e.sentScheme){const[a,o]=e.callerHeader?[`Your code set the "${e.callerHeader}" header itself, so the stored credential was not sent.`,"Remove that header from the request and retry. Do not replace the stored credentials."]:["No stored credential was sent with this request, so this result says nothing about the stored credentials.","Do not replace them. Check whether this operation needs a different kind of credential or a different route."];return[`The "${e.name}" API returned ${r}. ${a}`,"",o].join(`
2
+ `)}const n=e.status===401?`The "${e.name}" API rejected the stored ${t?`"${t}" `:""}credential (${r}).`:`The "${e.name}" API rejected the request with ${r}.`,i=t?`api: "${e.api}" and scheme: "${t}"`:`api: "${e.api}"`;return[n,"",`Do not retry the same call. Call \`${l}\` with ${i} to get a link the user has to open in a browser to replace or remove the stored credentials, then retry once they confirm they saved them.`].join(`
3
+ `)}function p({status:e,detail:t}){return t?`HTTP ${e}: ${t}`:`HTTP ${e}`}function H(e,t){const r=t.map(({name:n,label:i,description:a})=>`- ${n} \u2014 ${i}${a?`: ${a}`:""}`);return[`The "${e.name}" API rejected the request with ${p(e)} and this operation accepts more than one kind of credential:`,"",...r,"","Ask the user which one of these they have, and wait for the answer. Never guess and never reuse a value meant for another kind.",`Then call \`${l}\` with api: "${e.api}" and scheme set to the name they picked to get a link where they enter it.`].join(`
4
+ `)}async function f({kv:e,subject:t,baseUrl:r,target:n,auth:i,apiAuth:a,hasExistingSecret:o}){const s=a?await k(e,t,n.api,a):[],c=await d.createElicitation(e,{subject:t,api:n.api,name:n.name,scheme:n.scheme,...n.schemeLabel?{schemeLabel:n.schemeLabel}:{},auth:i,hasExistingSecret:o,...s.length>1?{schemes:s}:{}});return{token:c,url:E(r,c)}}async function k(e,t,r,n){const a=(await d.getSecretsForSubject(e,t))[r]??{};return A(n.schemes).map(o=>{const s=I(n,o),c=n.descriptions?.[o];return{name:o,...c?{label:c}:{},auth:n.schemes[o],hasExistingSecret:!!a[o],...s.length>0?{operations:s}:{}}})}function P(e){return e.startsWith(u)?e.slice(u.length):void 0}function b({target:e,hasExistingSecret:t,reason:r}){const n=`The link works for ${$()} minutes.`,i=S(e),a=r.kind==="authFailure"&&r.detail?` The API answered: ${r.detail}.`:"";return t?`Open this page in a browser to replace or remove the stored credentials for ${i}. They go straight to the API and never enter the chat. ${n}`:`${g(i)} needs credentials.${a} Open this page in a browser to paste them - they go straight to the API and never enter the chat. ${n}`}function S({name:e,schemeLabel:t}){return t?`the "${t}" scheme of the "${e}" API`:`the "${e}" API`}function g(e){return e.charAt(0).toUpperCase()+e.slice(1)}function $(){return Math.round(y/6e4)}function E(e,t){if(!e)return`/mcp/credentials?token=${t}`;try{const r=new URL("/mcp/credentials",e);return r.searchParams.set("token",t),r.toString()}catch{return`${e}/mcp/credentials?token=${t}`}}function C({target:e,reason:t,hasExistingSecret:r},n,i){const o=[`**Stop and show the user this link. They have to open it in a browser to ${r?`replace or remove the stored credentials for the "${e.name}" API`:`add credentials for the "${e.name}" API`} - nothing continues until they do.**`,"",n,"",`The link is valid ${$()} minutes and opens a form on this site. Credentials go straight to the API from there: never ask for them in the conversation and never pass them as a tool argument.`,"",t.kind==="authFailure"?`The upstream API "${e.name}" returned ${t.status}${t.detail?` (${t.detail})`:""} and needs credentials.`:r?`Credentials are already stored for the "${e.name}" API; the link lets the user replace or remove them.`:`The "${e.name}" API needs credentials.`,...e.schemeLabel?[`The operation authenticates with its "${e.schemeLabel}" security scheme.`]:[],i?`Once the user confirms they saved them, call this tool again with sessionHandle: "${i}" - the credentials are stored against that handle, applied server-side, and never appear in the conversation.`:"Once the user confirms they saved them, call this tool again - the credentials are applied server-side and never appear in the conversation."],s=t.kind==="authFailure"?t.otherApiNames??[]:[];if(s.length>0){const c=s.map(T=>`"${T}"`).join(", ");o.push("",`The remaining APIs (${c}) will prompt for credentials on subsequent calls.`)}return o.join(`
5
+ `)}export{m as CREDENTIALS_INPUT_REQUEST_KEY,U as buildCredentialsToolHint,H as buildSchemeChoiceHint,L as buildUpstreamCredentialFallback,F as buildUpstreamCredentialInputRequired,R as isCredentialElicitationDeclined,x as schemeLabelOf};
@@ -1 +1 @@
1
- import{join as e}from"node:path";import{PUBLIC_API_DEFINITIONS_FOLDER as s}from"../../../constants/common.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as a}from"../../../../constants/common.js";import{canDownloadApiDefinition as n}from"../../../utils/rbac.js";import{MCP_PROTOCOL_VERSION as p}from"../constants.js";import{isApiIncludedInDocsMcp as c}from"../utils.js";import{isMcpGatewayEnabled as l}from"../utils/mode.js";import{isDefinitionHidden as m,hasGatewayConfig as f}from"../utils/xmcp-utils.js";function u(o){return l()&&!o?.hide&&!o?.docs?.hide}function d(o,i,r){return m(o,"gateway")?!1:n(e(s,i),r,!1,{isAuthenticated:!1,teams:[a]})||f(o)}function D(o,i,r,t){return u(t)&&!o?.["x-mcp"]?.servers?.length&&d(o?.info,i,r)&&c(i,o,t)}function M(o){return{protocolVersion:p,capabilities:{tools:{}},servers:[{url:o}],tools:[],resources:[],prompts:[]}}export{M as buildGatewayXMcp,u as isGatewayCapabilityEnabled,d as isGatewayEligible,D as shouldAdvertiseGatewayXMcp};
1
+ import{join as e}from"node:path";import{PUBLIC_API_DEFINITIONS_FOLDER as s}from"../../../constants/common.js";import{ANONYMOUS_AUTH_DETAILS as n}from"../../../constants/rbac.js";import{canDownloadApiDefinition as a}from"../../../utils/rbac.js";import{MCP_PROTOCOL_VERSION as p}from"../constants.js";import{isApiIncludedInDocsMcp as c}from"../utils.js";import{isMcpGatewayEnabled as l}from"../utils/mode.js";import{isDefinitionHidden as m,hasGatewayConfig as f}from"../utils/xmcp-utils.js";function u(o){return l()&&!o?.hide&&!o?.docs?.hide}function d(o,r,i){return m(o,"gateway")?!1:a(e(s,r),i,!1,n)||f(o)}function _(o,r,i,t){return u(t)&&!o?.["x-mcp"]?.servers?.length&&d(o?.info,r,i)&&c(r,o,t)}function G(o){return{protocolVersion:p,capabilities:{tools:{}},servers:[{url:o}],tools:[],resources:[],prompts:[]}}export{G as buildGatewayXMcp,u as isGatewayCapabilityEnabled,d as isGatewayEligible,_ as shouldAdvertiseGatewayXMcp};
@@ -9,6 +9,7 @@ type GatewayFetchAuditRecord = {
9
9
  path?: string;
10
10
  api?: string;
11
11
  status?: number;
12
+ injectedScheme?: string;
12
13
  requestHeaders?: Record<string, string>;
13
14
  requestBody?: string;
14
15
  responseHeaders?: Record<string, string>;
@@ -19,6 +20,6 @@ type GatewayFetchAuditRecord = {
19
20
  * telemetry event verbatim so a Grafana row joins onto this line; `url_sha256` identifies the
20
21
  * request itself, since the telemetry event's `path` is deliberately normalized.
21
22
  */
22
- export declare function logGatewayFetchAudit({ rawUrl, method, host, outcome, durationMs, injectedSecretValues, path, api, status, requestHeaders, requestBody, responseHeaders, responseBody, }: GatewayFetchAuditRecord): void;
23
+ export declare function logGatewayFetchAudit({ rawUrl, method, host, outcome, durationMs, injectedSecretValues, path, api, status, injectedScheme, requestHeaders, requestBody, responseHeaders, responseBody, }: GatewayFetchAuditRecord): void;
23
24
  export {};
24
25
  //# sourceMappingURL=fetch-audit.d.ts.map
@@ -1 +1 @@
1
- import{auditHeaderNames as u,auditInput as g,auditOutputDigest as c,auditSha256 as b,auditUrl as l,logAuditRecord as y}from"../../audit/audit-log.js";function D({rawUrl:e,method:n,host:i,outcome:r,durationMs:o,injectedSecretValues:t,path:_,api:h,status:f,requestHeaders:p,requestBody:d,responseHeaders:m,responseBody:a}){const s=a===void 0?void 0:c(a);y("Record gateway fetch",{url_sha256:b(e),host:i,method:n,path:_,api:h,outcome:r,status:f,duration_ms:o,url:l(e,t),request_header_names:u(p),request_body:d===void 0?void 0:g(d,t),response_header_names:u(m),response_sha256:s?.sha256,response_bytes:s?.bytes})}export{D as logGatewayFetchAudit};
1
+ import{auditHeaderNames as n,auditInput as g,auditOutputDigest as b,auditSha256 as l,auditUrl as y,logAuditRecord as A}from"../../audit/audit-log.js";function R({rawUrl:e,method:u,host:i,outcome:r,durationMs:o,injectedSecretValues:t,path:_,api:h,status:f,injectedScheme:m,requestHeaders:p,requestBody:d,responseHeaders:c,responseBody:s}){const a=s===void 0?void 0:b(s);A("Record gateway fetch",{url_sha256:l(e),host:i,method:u,path:_,api:h,outcome:r,status:f,injected_scheme:m,duration_ms:o,url:y(e,t),request_header_names:n(p),request_body:d===void 0?void 0:g(d,t),response_header_names:n(c),response_sha256:a?.sha256,response_bytes:a?.bytes})}export{R as logGatewayFetchAudit};
@@ -3,11 +3,20 @@ import type { SandboxFetch } from '../../codemode/types.js';
3
3
  import type { UpstreamAuthRequiredEvent } from '../upstream-auth.js';
4
4
  import type { StoredSecret } from '../secret-store.js';
5
5
  export declare function getDefaultAgent(): Agent;
6
+ export type FetchBridgeRoute = {
7
+ pattern: RegExp;
8
+ method: string;
9
+ schemes: readonly string[];
10
+ };
6
11
  export type FetchBridgeApi = {
7
12
  slug: string;
8
13
  name: string;
9
14
  matchers: readonly RegExp[];
10
- secret?: StoredSecret;
15
+ secrets?: Readonly<Record<string, StoredSecret>>;
16
+ defaultScheme?: string;
17
+ routes?: readonly FetchBridgeRoute[];
18
+ credentialHeaders?: readonly string[];
19
+ schemePriority?: readonly string[];
11
20
  };
12
21
  type FetchBridgeOptions = {
13
22
  allowedHosts: readonly RegExp[];
@@ -1 +1 @@
1
- import{Agent as W}from"undici";import{envConfig as I}from"../../../../config/env-config.js";import{logger as R}from"../../../../tools/notifiers/logger.js";import{assertUrlAllowed as B}from"./ssrf-guard.js";import{createSsrfSafeLookup as J}from"./ssrf-safe-lookup.js";import{SsrfBlockedError as C}from"./ssrf-blocklist.js";import{GatewayFetchBlockedError as $,GatewayFetchSystemError as K,GatewayFetchUserError as U}from"./fetch-errors.js";import{redactHeaders as x,redactSecretsFromString as V}from"./redact.js";import{normalizeFetchPath as X}from"./normalize-path.js";import{reportGatewayFetch as G}from"./fetch-telemetry.js";import{logGatewayFetchAudit as O}from"./fetch-audit.js";const N="x-forwarded-for",Y=3e4,z=1024*1024,Q=new Set([401,403,407]);let M;function Z(){if(!M){const t=I.isDevelopMode;t&&R.warn("Gateway MCP SSRF guard: loopback upstreams are ALLOWED (develop mode only, never in runtime)."),M=new W({connect:{lookup:J({allowLoopback:t})}})}return M}function be({allowedHosts:t,apis:e=[],authorization:o,onAuthRequired:s,fetchImpl:i=fetch,dispatcher:u=Z(),timeoutMs:d=Y,maxResponseBytes:h=z,maxFetchesPerExec:f,clientIp:m}){const k=[...t,...e.flatMap(r=>r.matchers)],L=[o,...e.map(r=>r.secret?.value)].filter(r=>!!r),v=e.map(r=>r.secret?.header).filter(r=>!!r);let H=0;return async r=>{const w=r.method??"GET",A=Date.now();let _,g,b,S={},T,D;try{if(f!==void 0){const l=Math.max(0,f);if(H+=1,H>l)throw new U(`Outbound fetch budget exceeded (max ${l} fetches per execute); split the work across calls`)}const n=B(r.url,k);_=n.hostname,g=X(n.pathname);const E=e.filter(l=>l.matchers.some(P=>P.test(n.hostname))),c=E.length===1?E[0]:void 0;b=c?.slug,S=se(r.headers,c?.secret,o,m);const p=new AbortController;D=setTimeout(()=>p.abort(),d);const a=await i(n,{method:w,headers:S,body:r.body,redirect:"manual",signal:p.signal,dispatcher:u});T=a.status,Q.has(a.status)&&c&&s&&s({api:c.slug,name:c.name,status:a.status});const F=await ae(a,h);let y=ce(a.headers);if(re(a.status)){y=x(y,v);const{location:l}=y;l&&!oe(l,n,k)&&delete y.location}return G({host:n.hostname,method:w,outcome:"success",durationMs:Date.now()-A,path:g,api:b,status:a.status,bytes:Buffer.byteLength(F,"utf8")}),O({rawUrl:n.href,method:w,host:n.hostname,outcome:"success",durationMs:Date.now()-A,injectedSecretValues:L,path:g,api:b,status:a.status,requestHeaders:S,requestBody:r.body,responseHeaders:y,responseBody:F}),{status:a.status,statusText:a.statusText,ok:a.ok,headers:y,bodyText:F}}catch(n){const{outcome:E,userSafe:c}=ee(n),p=_??(c instanceof $?c.host:void 0)??te(r.url)??"invalid-url";throw G({host:p,method:w,outcome:E,durationMs:Date.now()-A,path:g,api:b,status:T}),O({rawUrl:r.url,method:w,host:p,outcome:E,durationMs:Date.now()-A,injectedSecretValues:L,path:g,api:b,status:T,requestHeaders:S,requestBody:r.body}),c||(R.error(`Gateway MCP fetch failed [${w} ${p}]: ${V(ne(n),L)} headers=${JSON.stringify(x(S,v))}`),new K("Upstream fetch failed due to an internal error"))}finally{D!==void 0&&clearTimeout(D)}}}function q(t){let e=t;for(let o=0;o<5&&e instanceof Error;o++){if(e instanceof U||e instanceof C)return e;e=e.cause}}function ee(t){const e=q(t);return{outcome:e instanceof $||e instanceof C?"blocked":e?"user_error":"system_error",userSafe:e}}function te(t){try{return new URL(t).hostname||void 0}catch{return}}function re(t){return t>=300&&t<400}function oe(t,e,o){try{return!!B(new URL(t,e).href,o)}catch{return!1}}function ne(t){if(!(t instanceof Error))return String(t);const e=t.cause;return e instanceof Error?`${t.message}: ${e.message}`:t.message}async function ae(t,e){const o=Number(t.headers.get("content-length"));if(Number.isFinite(o)&&o>e)throw j(e,o);if(!t.body)return"";const s=t.body.getReader(),i=new TextDecoder;let u=0,d="";try{for(;;){const{done:h,value:f}=await s.read();if(h)break;if(u+=f.byteLength,u>e)throw j(e,u);d+=i.decode(f,{stream:!0})}return d+i.decode()}finally{await s.cancel().catch(()=>{})}}function j(t,e){return new U(`Response is too large (over ${t} bytes, got ${e}); request less data`)}function se(t,e,o,s){const i={},u=new Set;for(const[h,f]of Object.entries(t??{})){const m=h.toLowerCase();m==="host"||m==="content-length"||m!==N&&(u.add(m),i[h]=f)}s&&(i[N]=s);const d=e??(o?{header:"Authorization",value:o}:void 0);return d&&!u.has(d.header.toLowerCase())&&(i[d.header]=d.value),i}function ce(t){const e={};return t.forEach((o,s)=>{e[s.toLowerCase()]=o}),e}export{be as buildFetchBridge,Z as getDefaultAgent,ae as readCappedBody};
1
+ import{Agent as Q}from"undici";import{envConfig as Z}from"../../../../config/env-config.js";import{logger as N}from"../../../../tools/notifiers/logger.js";import{assertUrlAllowed as I}from"./ssrf-guard.js";import{createSsrfSafeLookup as q}from"./ssrf-safe-lookup.js";import{SsrfBlockedError as W}from"./ssrf-blocklist.js";import{GatewayFetchBlockedError as R,GatewayFetchSystemError as ee,GatewayFetchUserError as g}from"./fetch-errors.js";import{redactHeaders as J,redactSecretsFromString as te}from"./redact.js";import{extractUpstreamDetail as re}from"./upstream-detail.js";import{normalizeFetchPath as ne}from"./normalize-path.js";import{reportGatewayFetch as K}from"./fetch-telemetry.js";import{logGatewayFetchAudit as V}from"./fetch-audit.js";const X="x-forwarded-for",oe=3e4,se=1024*1024,ae=new Set([401,403,407]);let C;function ce(){if(!C){const e=Z.isDevelopMode;e&&N.warn("Gateway MCP SSRF guard: loopback upstreams are ALLOWED (develop mode only, never in runtime)."),C=new Q({connect:{lookup:q({allowLoopback:e})}})}return C}function _e({allowedHosts:e,apis:t=[],authorization:r,onAuthRequired:n,fetchImpl:c=fetch,dispatcher:a=ce(),timeoutMs:h=oe,maxResponseBytes:l=se,maxFetchesPerExec:w,clientIp:k}){const f=[...e,...t.flatMap(o=>o.matchers)],$=[...new Set(t.map(o=>o.name).filter(Boolean))].join(", "),m=t.flatMap(o=>Object.values(o.secrets??{})),D=[r,...m.map(o=>o.value)].filter(o=>!!o),x=m.map(o=>o.header);let O=0;return async o=>{const y=o.method??"GET",T=Date.now();let B,b,A,E={},H,_,j;try{if(w!==void 0){const u=Math.max(0,w);if(O+=1,O>u)throw new g(`Outbound fetch budget exceeded (max ${u} fetches per execute); split the work across calls`)}const d=le(o.url,f,$);B=d.hostname,b=ne(d.pathname);const v=t.filter(u=>u.matchers.some(z=>z.test(d.hostname))),s=v.length===1?v[0]:void 0;A=s?.slug;const S=pe(o.securityScheme,s),F=S?[S]:s?ye(s,d.pathname,y):void 0,L=s&&F?Se(s,F):void 0,P=L?s?.secrets?.[L]:void 0,M=be({callerHeaders:o.headers,secret:P,authorization:r,clientIp:k,credentialHeaders:s?.credentialHeaders});E=M.headers,H=P&&!M.callerHeader?L:void 0;const G=new AbortController;j=setTimeout(()=>G.abort(),h);const i=await c(d,{method:y,headers:E,body:o.body,redirect:"manual",signal:G.signal,dispatcher:a});_=i.status;let U="";try{U=await we(i,l)}finally{if(ae.has(i.status)&&s&&n){const u=re(U,i.headers.get("content-type"),D);n({api:s.slug,name:s.name,status:i.status,...L?{scheme:L}:{},...F?.length?{schemes:[...F]}:{},...H?{sentScheme:H}:{},...M.callerHeader?{callerHeader:M.callerHeader}:{},...u?{detail:u}:{}})}}let p=Ae(i.headers);if(fe(i.status)){p=J(p,x);const{location:u}=p;u&&!he(u,d,f)&&delete p.location}return K({host:d.hostname,method:y,outcome:"success",durationMs:Date.now()-T,path:b,api:A,status:i.status,bytes:Buffer.byteLength(U,"utf8")}),V({rawUrl:d.href,method:y,host:d.hostname,outcome:"success",durationMs:Date.now()-T,injectedSecretValues:D,path:b,api:A,status:i.status,injectedScheme:H,requestHeaders:E,requestBody:o.body,responseHeaders:p,responseBody:U}),{status:i.status,statusText:i.statusText,ok:i.ok,headers:p,bodyText:U}}catch(d){const{outcome:v,userSafe:s}=ie(d),S=B??(s instanceof R?s.host:void 0)??ue(o.url)??"invalid-url";throw K({host:S,method:y,outcome:v,durationMs:Date.now()-T,path:b,api:A,status:_}),V({rawUrl:o.url,method:y,host:S,outcome:v,durationMs:Date.now()-T,injectedSecretValues:D,path:b,api:A,status:_,injectedScheme:H,requestHeaders:E,requestBody:o.body}),s||(N.error(`Gateway MCP fetch failed [${y} ${S}]: ${te(me(d),D)} headers=${JSON.stringify(J(E,x))}`),new ee("Upstream fetch failed due to an internal error"))}finally{j!==void 0&&clearTimeout(j)}}}function de(e){let t=e;for(let r=0;r<5&&t instanceof Error;r++){if(t instanceof g||t instanceof W)return t;t=t.cause}}function ie(e){const t=de(e);return{outcome:t instanceof R||t instanceof W?"blocked":t?"user_error":"system_error",userSafe:t}}function le(e,t,r){try{return I(e,t)}catch(n){throw n instanceof R&&r?new R(`${n.message}. \`fetch\` reaches only the documented hosts of the callable APIs (${r}); other documented APIs can be read through the tools but not called.`,n.host):n}}function ue(e){try{return new URL(e).hostname||void 0}catch{return}}function fe(e){return e>=300&&e<400}function he(e,t,r){try{return!!I(new URL(e,t).href,r)}catch{return!1}}function me(e){if(!(e instanceof Error))return String(e);const t=e.cause;return t instanceof Error?`${e.message}: ${t.message}`:e.message}async function we(e,t){const r=Number(e.headers.get("content-length"));if(Number.isFinite(r)&&r>t)throw Y(t,r);if(!e.body)return"";const n=e.body.getReader(),c=new TextDecoder;let a=0,h="";try{for(;;){const{done:l,value:w}=await n.read();if(l)break;if(a+=w.byteLength,a>t)throw Y(t,a);h+=c.decode(w,{stream:!0})}return h+c.decode()}finally{await n.cancel().catch(()=>{})}}function Y(e,t){return new g(`Response is too large (over ${e} bytes, got ${t}); request less data`)}function ye(e,t,r){const n=e.routes?.find(c=>c.method===r&&c.pattern.test(t));return n?n.schemes:ge(e)}function Se(e,t){const r=t.filter(n=>e.secrets?.[n]);return r.length===0?t[0]:r.reduce((n,c)=>{const a=e.secrets?.[n]?.savedAt??0;return(e.secrets?.[c]?.savedAt??0)>a?c:n})}function pe(e,t){if(e==null)return;if(typeof e!="string")throw new g("securityScheme must be a security scheme name (a string)");if(!t)throw new g("securityScheme cannot be applied: the URL host does not identify exactly one callable API");const r=t.schemePriority??[];if(r.length>0&&!r.includes(e))throw new g(`Unknown securityScheme "${e}" for ${t.name}; valid values: ${r.join(", ")}`);return e}function ge(e){const t=Object.keys(e.secrets??{});if(t.length===0)return e.defaultScheme?[e.defaultScheme]:[];const r=(e.schemePriority??[]).filter(n=>t.includes(n));return[...r,...t.filter(n=>!r.includes(n))]}function be({callerHeaders:e,secret:t,authorization:r,clientIp:n,credentialHeaders:c}){const a={},h=new Set,l=t??(r?{header:"Authorization",value:r}:void 0),w=l?new Set((c??[]).map(f=>f.toLowerCase()).filter(f=>f!==l.header.toLowerCase())):new Set;for(const[f,$]of Object.entries(e??{})){const m=f.toLowerCase();m==="host"||m==="content-length"||m!==X&&(w.has(m)||(h.add(m),a[f]=$))}if(n&&(a[X]=n),!l)return{headers:a};const k=l.header.toLowerCase();return h.has(k)?{headers:a,callerHeader:k}:(a[l.header]=l.value,{headers:a})}function Ae(e){const t={};return e.forEach((r,n)=>{t[n.toLowerCase()]=r}),t}export{_e as buildFetchBridge,ce as getDefaultAgent,we as readCappedBody};
@@ -0,0 +1,7 @@
1
+ /**
2
+ * The upstream's own explanation of an auth failure: `title` and `detail` of a `problem+json`
3
+ * body, a `message`/`error` string of a plain JSON body, or a short text body. Whitespace is
4
+ * collapsed, injected secrets are redacted, and the result is capped so it fits in a hint.
5
+ */
6
+ export declare function extractUpstreamDetail(bodyText: string, contentType: string | null, injectedSecretValues: readonly string[]): string | undefined;
7
+ //# sourceMappingURL=upstream-detail.d.ts.map
@@ -0,0 +1 @@
1
+ import{redactSecretsFromString as c}from"./redact.js";const o=200;function l(t,e,r){const i=f(e)?u(t):t;if(!i)return;const n=c(i.replace(/\s+/g," ").trim(),r);if(n)return n.length>o?`${n.slice(0,o-1)}\u2026`:n}function f(t){return/[/+]json\b/i.test(t??"")}function u(t){let e;try{e=JSON.parse(t)}catch{return}if(typeof e!="object"||e===null||Array.isArray(e))return;const r=[e.title,e.detail].filter(s);return r.length>0?r.join(": "):[e.message,e.error].find(s)}function s(t){return typeof t=="string"&&t.trim()!==""}export{l as extractUpstreamDetail};
@@ -1,13 +1,5 @@
1
- import type { ApiDescriptionInfo, McpToolContext } from '../types.js';
1
+ import type { McpToolContext } from '../types.js';
2
2
  import type { SandboxFetch } from '../codemode/types.js';
3
3
  import type { UpstreamAuthRequiredEvent } from './upstream-auth.js';
4
- export declare function getCallableApis(context: McpToolContext): ApiDescriptionInfo[];
5
- /**
6
- * Fetch capability at request/worker time is derived purely from the build-time stamps:
7
- * `fetchEligible` is stamped per API by the lifecycle plugin under `isGatewayCapabilityEnabled`
8
- * (entitlement + hide checks), and the map arriving here is already RBAC-filtered.
9
- * No EntitlementsProvider read — this code runs in graphs where the provider is uninitialized.
10
- */
11
- export declare function isFetchCapable(context: McpToolContext): boolean;
12
- export declare function buildExecuteHostFetch(context: McpToolContext, onAuthRequired?: (event: UpstreamAuthRequiredEvent) => void): SandboxFetch;
4
+ export declare function buildExecuteHostFetch(context: McpToolContext, onAuthRequired?: (event: UpstreamAuthRequiredEvent) => void): Promise<SandboxFetch>;
13
5
  //# sourceMappingURL=fetch-capability.d.ts.map
@@ -1 +1 @@
1
- import{buildAllowedHostMatchers as a}from"./fetch/allowed-hosts.js";import{buildFetchBridge as s}from"./fetch/fetch-bridge.js";function i(e){return Object.values(e.apiDescriptionsMap??{}).filter(r=>r.fetchEligible)}function u(e){return i(e).length>0}function n(e,r){const l=i(e).map(t=>({slug:t.relativePath,name:t.name,matchers:a(t.servers??[]),secret:e.upstreamSecrets?.[t.relativePath]}));return s({allowedHosts:a([]),apis:l,authorization:e.upstreamAuthorization,onAuthRequired:r,maxFetchesPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp})}export{n as buildExecuteHostFetch,i as getCallableApis,u as isFetchCapable};
1
+ import{getCallableApis as l}from"./callable-apis.js";import{buildAllowedHostMatchers as a}from"./fetch/allowed-hosts.js";import{buildFetchBridge as m}from"./fetch/fetch-bridge.js";import{credentialHeadersOf as o,orderedSchemesOf as c,resolveUpstreamApiAuth as h}from"./upstream-auth-scheme.js";async function f(e,s){const i=await Promise.all(l(e).map(async r=>{const t=await h(e,r.relativePath);return{slug:r.relativePath,name:r.name,matchers:a(r.servers??[]),secrets:e.upstreamSecrets?.[r.relativePath],defaultScheme:t.defaultScheme,routes:t.routes,credentialHeaders:o(t.schemes),schemePriority:c(t.schemes)}}));return m({allowedHosts:a([]),apis:i,authorization:e.upstreamAuthorization,onAuthRequired:s,maxFetchesPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp})}export{f as buildExecuteHostFetch};
@@ -4,20 +4,32 @@ export declare const ELICITATION_TTL_MS: number;
4
4
  export type StoredSecret = {
5
5
  header: string;
6
6
  value: string;
7
+ savedAt?: number;
8
+ };
9
+ export type UpstreamSecrets = Record<string, Record<string, StoredSecret>>;
10
+ export type ElicitationScheme = {
11
+ name: string;
12
+ label?: string;
13
+ auth: UpstreamAuthScheme;
14
+ hasExistingSecret: boolean;
15
+ operations?: string[];
7
16
  };
8
17
  export type ElicitationTarget = {
9
18
  subject: string;
10
19
  api: string;
11
20
  name: string;
21
+ scheme: string;
22
+ schemeLabel?: string;
12
23
  auth: UpstreamAuthScheme;
13
24
  hasExistingSecret?: boolean;
25
+ schemes?: ElicitationScheme[];
14
26
  };
15
27
  export declare class SecretStore {
16
28
  #private;
17
- setSecret(kv: KvService, subject: string, api: string, secret: StoredSecret): Promise<void>;
18
- getSecretsForSubject(kv: KvService, subject: string): Promise<Record<string, StoredSecret>>;
19
- hasSecret(kv: KvService, subject: string, api: string): Promise<boolean>;
20
- deleteSecret(kv: KvService, subject: string, api: string): Promise<void>;
29
+ setSecret(kv: KvService, subject: string, api: string, scheme: string, secret: StoredSecret): Promise<void>;
30
+ getSecretsForSubject(kv: KvService, subject: string): Promise<UpstreamSecrets>;
31
+ hasSecret(kv: KvService, subject: string, api: string, scheme: string): Promise<boolean>;
32
+ deleteSecret(kv: KvService, subject: string, api: string, scheme: string): Promise<void>;
21
33
  deleteSubject(kv: KvService, subject: string): Promise<void>;
22
34
  createElicitation(kv: KvService, target: ElicitationTarget): Promise<string>;
23
35
  peekElicitation(kv: KvService, token: string): Promise<ElicitationTarget | undefined>;
@@ -1 +1 @@
1
- import{createCipheriv as o,createDecipheriv as f,createHash as u,hkdfSync as a,randomBytes as h,randomUUID as l}from"node:crypto";import{JWT_SECRET_KEY as c}from"../../../constants/common.js";import{secretTtlSeconds as m}from"./subject.js";const p=900*1e3,d="mcp-upstream-secrets",y="mcp-elicitation",S="mcp-elicitation";class g{async setSecret(t,e,r,n){const i={api:r,...this.#c(this.#a(e),n,r)};await t.set(this.#t(e,r),i,{ttlInSeconds:m(e)})}async getSecretsForSubject(t,e){const r=this.#a(e),{items:n}=await t.list({prefix:this.#n(e)}),i={};for(const s of n)if(s.value)try{i[s.value.api]=this.#i(r,s.value,s.value.api)}catch{continue}return i}async hasSecret(t,e,r){return!!await t.get(this.#t(e,r))}async deleteSecret(t,e,r){await t.delete(this.#t(e,r))}async deleteSubject(t,e){const{items:r}=await t.list({prefix:this.#n(e)}),n=r.flatMap(i=>i.value?[this.#t(e,i.value.api)]:[]);n.length!==0&&await t.transaction(async i=>{for(const s of n)await i.delete(s)})}async createElicitation(t,e){const r=l();return await t.set(this.#e(r),this.#c(this.#r(),e),{ttlInSeconds:p/1e3}),r}async peekElicitation(t,e){const r=await t.get(this.#e(e));if(r)try{return this.#i(this.#r(),r)}catch{return}}async consumeElicitation(t,e){const r=this.#e(e),n=await t.transaction(async i=>{const s=await i.get(r);return s&&await i.delete(r),s});if(n)try{return this.#i(this.#r(),n)}catch{return}}#n(t){return["mcp","secret",this.#s(t)]}#t(t,e){return["mcp","secret",this.#s(t),e]}#e(t){return["mcp","elicitation",t]}#s(t){return u("sha256").update(t).digest("hex")}#a(t){return Buffer.from(a("sha256",c,t,d,32))}#r(){return Buffer.from(a("sha256",c,S,y,32))}#c(t,e,r){const n=h(12),i=o("aes-256-gcm",t,n);r&&i.setAAD(Buffer.from(r,"utf8"));const s=Buffer.concat([i.update(JSON.stringify(e),"utf8"),i.final()]);return{iv:n.toString("base64"),tag:i.getAuthTag().toString("base64"),data:s.toString("base64")}}#i(t,e,r){const n=f("aes-256-gcm",t,Buffer.from(e.iv,"base64"));r&&n.setAAD(Buffer.from(r,"utf8")),n.setAuthTag(Buffer.from(e.tag,"base64"));const i=Buffer.concat([n.update(Buffer.from(e.data,"base64")),n.final()]).toString("utf8");return JSON.parse(i)}}const B=new g;export{p as ELICITATION_TTL_MS,g as SecretStore,B as secretStore};
1
+ import{createCipheriv as h,createDecipheriv as m,createHash as d,hkdfSync as o,randomBytes as l,randomUUID as p}from"node:crypto";import{JWT_SECRET_KEY as f}from"../../../constants/common.js";import{assertHeaderSafe as y}from"./credential-validation.js";import{secretTtlSeconds as S}from"./subject.js";const g=900*1e3,I="mcp-upstream-secrets",T="mcp-elicitation",w="mcp-elicitation";class A{async setSecret(t,e,r,s,i){y(i.header,i.value);const n={...i,savedAt:Date.now()},a={api:r,scheme:s,...this.#o(this.#c(e),n,this.#n(r,s))};await t.set(this.#t(e,r,s),a,{ttlInSeconds:S(e)})}async getSecretsForSubject(t,e){const r=this.#c(e),{items:s}=await t.list({prefix:this.#i(e)}),i={};for(const n of s){if(!n.value?.scheme)continue;const{api:a,scheme:c}=n.value;try{const u=this.#s(r,n.value,this.#n(a,c));i[a]={...i[a],[c]:u}}catch{continue}}return i}async hasSecret(t,e,r,s){return!!await t.get(this.#t(e,r,s))}async deleteSecret(t,e,r,s){await t.delete(this.#t(e,r,s))}async deleteSubject(t,e){const{items:r}=await t.list({prefix:this.#i(e)}),s=r.flatMap(i=>i.value?[i.key]:[]);s.length!==0&&await t.transaction(async i=>{for(const n of s)await i.delete(n)})}async createElicitation(t,e){const r=p();return await t.set(this.#e(r),this.#o(this.#r(),e),{ttlInSeconds:g/1e3}),r}async peekElicitation(t,e){const r=await t.get(this.#e(e));if(r)try{return this.#s(this.#r(),r)}catch{return}}async consumeElicitation(t,e){const r=this.#e(e),s=await t.transaction(async i=>{const n=await i.get(r);return n&&await i.delete(r),n});if(s)try{return this.#s(this.#r(),s)}catch{return}}#i(t){return["mcp","secret",this.#a(t)]}#t(t,e,r){return["mcp","secret",this.#a(t),e,r]}#n(t,e){return`${t}\0${e}`}#e(t){return["mcp","elicitation",t]}#a(t){return d("sha256").update(t).digest("hex")}#c(t){return Buffer.from(o("sha256",f,t,I,32))}#r(){return Buffer.from(o("sha256",f,w,T,32))}#o(t,e,r){const s=l(12),i=h("aes-256-gcm",t,s);r&&i.setAAD(Buffer.from(r,"utf8"));const n=Buffer.concat([i.update(JSON.stringify(e),"utf8"),i.final()]);return{iv:s.toString("base64"),tag:i.getAuthTag().toString("base64"),data:n.toString("base64")}}#s(t,e,r){const s=m("aes-256-gcm",t,Buffer.from(e.iv,"base64"));r&&s.setAAD(Buffer.from(r,"utf8")),s.setAuthTag(Buffer.from(e.tag,"base64"));const i=Buffer.concat([s.update(Buffer.from(e.data,"base64")),s.final()]).toString("utf8");return JSON.parse(i)}}const N=new A;export{g as ELICITATION_TTL_MS,A as SecretStore,N as secretStore};
@@ -7,12 +7,37 @@ export type UpstreamAuthScheme = {
7
7
  } | {
8
8
  kind: 'apiKey';
9
9
  header: string;
10
+ } | {
11
+ kind: 'cookie';
12
+ name: string;
10
13
  } | {
11
14
  kind: 'oauth2ClientCredentials';
12
15
  tokenUrl: string;
13
16
  scopes: string[];
14
17
  };
18
+ export type UpstreamAuthRoute = {
19
+ pattern: RegExp;
20
+ path: string;
21
+ method: string;
22
+ schemes: string[];
23
+ };
24
+ export type UpstreamApiAuth = {
25
+ schemes: Record<string, UpstreamAuthScheme>;
26
+ defaultScheme: string;
27
+ routes: UpstreamAuthRoute[];
28
+ descriptions?: Record<string, string>;
29
+ };
30
+ export type SchemeChoice = {
31
+ name: string;
32
+ label: string;
33
+ description?: string;
34
+ };
15
35
  type SecuritySchemeLoader = typeof getApiDescriptionFromFs;
16
- export declare function resolveUpstreamAuthScheme(context: McpToolContext, apiRelativePath: string, loadDescription?: SecuritySchemeLoader): Promise<UpstreamAuthScheme>;
36
+ export declare const DEFAULT_SCHEME_NAME = "default";
37
+ export declare function resolveUpstreamApiAuth(context: McpToolContext, apiRelativePath: string, loadDescription?: SecuritySchemeLoader): Promise<UpstreamApiAuth>;
38
+ export declare function schemeChoicesOf(auth: UpstreamApiAuth, names: readonly string[]): SchemeChoice[];
39
+ export declare function credentialHeadersOf(schemes: Record<string, UpstreamAuthScheme>): string[];
40
+ export declare function orderedSchemesOf(schemes: Record<string, UpstreamAuthScheme>): string[];
41
+ export declare function operationsForScheme(auth: UpstreamApiAuth, scheme: string): string[];
17
42
  export {};
18
43
  //# sourceMappingURL=upstream-auth-scheme.d.ts.map
@@ -1 +1,2 @@
1
- import{getApiDescriptionFromFs as o}from"../docs-mcp/tools/openapi/utils.js";const c={kind:"raw"};async function u(i,r,n=o){const s=Object.values(i.apiDescriptionsMap??{}).find(t=>t.relativePath===r);if(!s)return c;try{const t=await n({relativePath:s.relativePath,outdir:i.outdir||"",user:i.user,rbac:i.config?.access?.rbac||{},requiresLogin:!!i.config?.access?.requiresLogin});return a(t)}catch{return c}}function a(i){const r=Object.values(i?.components?.securitySchemes??{}).filter(l),n=r.find(e=>e.type==="oauth2"&&e.flows?.clientCredentials);if(n?.flows.clientCredentials){const e=n.flows.clientCredentials;return{kind:"oauth2ClientCredentials",tokenUrl:e.tokenUrl,scopes:Object.keys(e.scopes??{})}}if(r.find(e=>e.type==="http"&&e.scheme==="bearer"||e.type==="oauth2"))return{kind:"bearer"};const t=r.find(e=>e.type==="apiKey"&&e.in==="header");return t?{kind:"apiKey",header:t.name||"X-Api-Key"}:c}function l(i){return typeof i=="object"&&i!==null&&"type"in i}export{u as resolveUpstreamAuthScheme};
1
+ import{getApiDescriptionFromFs as O}from"../docs-mcp/tools/openapi/utils.js";import{OPERATION_METHODS as S}from"../docs-mcp/tools/openapi/constants.js";const A=120,l="default",g={kind:"raw"},h=["oauth2ClientCredentials","bearer","apiKey","cookie","raw"],w=new Set(S),C=/\{[^}]*\}/g;function c(){return{schemes:{[l]:g},defaultScheme:l,routes:[]}}async function L(e,t,n=O){const r=Object.values(e.apiDescriptionsMap??{}).find(i=>i.relativePath===t);if(!r)return c();try{const i=await n({relativePath:r.relativePath,outdir:e.outdir||"",user:e.user,rbac:e.config?.access?.rbac||{},requiresLogin:!!e.config?.access?.requiresLogin});return i?E(i,r.servers??[]):c()}catch{return c()}}function E(e,t){const n=$(e),r=Object.keys(n);if(r.length===0)return c();const i=m(e.security,n)[0]??a(r,n)[0],o=x(e,r);return{schemes:n,defaultScheme:i,routes:v(e,n,t),...Object.keys(o).length>0?{descriptions:o}:{}}}function N(e,t){return t.flatMap(n=>{const r=e.schemes[n];if(!r)return[];const i=e.descriptions?.[n];return[{name:n,label:j(r),...i?{description:i}:{}}]})}function U(e){return[...new Set(Object.values(e).map(P))]}function q(e){return a(Object.keys(e),e)}function z(e,t){const n=new Set;for(const r of e.routes)r.schemes.includes(t)&&n.add(`${r.method} ${r.path}`);return[...n]}function P(e){return e.kind==="apiKey"?e.header:e.kind==="cookie"?"Cookie":"Authorization"}function j(e){switch(e.kind){case"bearer":return"API key or bearer token";case"cookie":return`browser session cookie (${e.name})`;case"apiKey":return`API key in the ${e.header} header`;case"oauth2ClientCredentials":return"OAuth2 client credentials";default:return"Authorization header value"}}function x(e,t){const n={};for(const r of t){const i=e.components?.securitySchemes?.[r],o=k(i)?i.description:void 0;if(typeof o!="string")continue;const s=o.split(`
2
+ `)[0].trim();s&&(n[r]=s.slice(0,A))}return n}function $(e){const t={};for(const[n,r]of Object.entries(e.components?.securitySchemes??{})){if(!k(r))continue;const i=T(r);i&&(t[n]=i)}return t}function T(e){if(e.type==="oauth2"){const t=e.flows?.clientCredentials;return t?{kind:"oauth2ClientCredentials",tokenUrl:t.tokenUrl,scopes:Object.keys(t.scopes??{})}:{kind:"bearer"}}if(e.type==="http"&&e.scheme==="bearer")return{kind:"bearer"};if(e.type==="apiKey"&&e.in==="header")return{kind:"apiKey",header:e.name||"X-Api-Key"};if(e.type==="apiKey"&&e.in==="cookie"&&e.name)return{kind:"cookie",name:e.name}}function a(e,t){return[...e].sort((n,r)=>h.indexOf(t[n].kind)-h.indexOf(t[r].kind)||e.indexOf(n)-e.indexOf(r))}function m(e,t){const n=[];for(const r of e??[])for(const i of Object.keys(r))t[i]&&!n.includes(i)&&n.push(i);return n}function v(e,t,n){const r=I(n),i=[];for(const[o,s]of Object.entries(e.paths??{})){if(!s||typeof s!="object")continue;const f=H(r,o);if(f)for(const[p,b]of Object.entries(s)){if(!w.has(p.toLowerCase()))continue;const u=b?.security??e.security;if(u===void 0)continue;const d=m(u,t);d.length===0&&u.length>0||i.push({pattern:f,path:o,method:p.toUpperCase(),schemes:a(d,t)})}}return i}function H(e,t){if(t.startsWith("/"))return new RegExp(`^${e}${y(t)}/?$`)}function y(e){return e.split(C).map(_).join("[^/]+").replace(/\/+$/,"")}function I(e){const t=[...new Set(e.map(n=>R(n.url)).filter(Boolean).map(y))];return t.length>0?`(?:${t.join("|")})?`:""}function R(e){if(!e)return"";const t=e.replace(/^[a-z][a-z0-9+.-]*:\/\//i,""),n=t.indexOf("/");return n===-1?"":t.slice(n).split(/[?#]/)[0].replace(/\/+$/,"")}function _(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function k(e){return typeof e=="object"&&e!==null&&"type"in e}export{l as DEFAULT_SCHEME_NAME,U as credentialHeadersOf,z as operationsForScheme,q as orderedSchemesOf,L as resolveUpstreamApiAuth,N as schemeChoicesOf};
@@ -4,7 +4,19 @@ export type UpstreamAuthRequiredEvent = {
4
4
  api: string;
5
5
  name: string;
6
6
  status: number;
7
+ scheme?: string;
8
+ schemes?: string[];
9
+ /** Scheme whose stored credential the bridge actually sent; absent when nothing was injected. */
10
+ sentScheme?: string;
11
+ /** Lower-cased credential header the sandbox code set itself, which suppressed the injection. */
12
+ callerHeader?: string;
13
+ /** The upstream's own explanation of the failure, taken from the response body. */
14
+ detail?: string;
7
15
  };
16
+ export declare function upstreamAuthKey(event: {
17
+ api: string;
18
+ scheme?: string;
19
+ }): string;
8
20
  export declare function withAuthRequiredMeta(result: CallToolResult, events: UpstreamAuthRequiredEvent[]): CallToolResult;
9
21
  export declare function readAuthRequiredMeta(result: CallToolResult): UpstreamAuthRequiredEvent[];
10
22
  export declare function stripAuthRequiredMeta(result: CallToolResult): CallToolResult;
@@ -1 +1 @@
1
- const i="com.redocly/upstream-auth-required";function u(t,n){const e=new Map;for(const a of n){const o=e.get(a.api);(!o||o.status!==401&&a.status===401)&&e.set(a.api,a)}const r=[...e.values()];return r.length===0?t:{...t,_meta:{...t._meta,[i]:r}}}function p(t){const n=t._meta?.[i];return Array.isArray(n)?n.filter(e=>typeof e?.api=="string"&&typeof e?.name=="string"&&typeof e?.status=="number"):[]}function s(t){if(!t._meta||!(i in t._meta))return t;const{[i]:n,...e}=t._meta,r={...t};return Object.keys(e).length>0?r._meta=e:delete r._meta,r}export{i as UPSTREAM_AUTH_REQUIRED_META,p as readAuthRequiredMeta,s as stripAuthRequiredMeta,u as withAuthRequiredMeta};
1
+ const i="com.redocly/upstream-auth-required";function m(e){return`${e.api}\0${e.scheme??""}`}function h(e,n){const t=new Map;for(const o of n){const s=m(o),a=t.get(s);(!a||u(o)>u(a))&&t.set(s,o)}const r=[...t.values()];return r.length===0?e:{...e,_meta:{...e._meta,[i]:r}}}function u(e){return e.status!==401?0:e.sentScheme?2:1}function y(e){const n=e._meta?.[i];return Array.isArray(n)?n.filter(t=>typeof t?.api=="string"&&typeof t?.name=="string"&&typeof t?.status=="number").map(t=>{const r=Array.isArray(t.schemes)?t.schemes.filter(f=>typeof f=="string"):[],{schemes:o,sentScheme:s,callerHeader:a,detail:c,...p}=t;return{...p,...r.length>0?{schemes:r}:{},...typeof s=="string"?{sentScheme:s}:{},...typeof a=="string"?{callerHeader:a}:{},...typeof c=="string"?{detail:c}:{}}}):[]}function d(e){if(!e._meta||!(i in e._meta))return e;const{[i]:n,...t}=e._meta,r={...e};return Object.keys(t).length>0?r._meta=t:delete r._meta,r}export{i as UPSTREAM_AUTH_REQUIRED_META,y as readAuthRequiredMeta,d as stripAuthRequiredMeta,m as upstreamAuthKey,h as withAuthRequiredMeta};
@@ -1 +1 @@
1
- import{logger as A}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as v}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as f}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as N}from"../../../../constants/common.js";import{isObject as _}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as k}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as B}from"../../../utils/skills/get-skill-url.js";import{createDocsMcpServer as P}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as H,filterGraphqlDescriptionsByRbac as L}from"../utils.js";import{createMethodNotAllowedError as j,withErrorHandling as V}from"./errors.js";import{constructForbiddenResponse as G,constructInvalidTokenResponse as J,constructUnauthorizedResponse as $,handleMcpAuth as z,shouldHandleMcpAuth as K}from"../auth/auth-handlers.js";import{extractTokenFromAuthHeader as Y}from"../utils/jwt.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as W}from"../constants.js";import{canAccessFeature as X}from"../../../utils/rbac.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as Q,RbacFeatures as Z}from"../../../../constants/common.js";const m="X-Redocly-AI-Metadata";function q(r){if(r)try{const e=JSON.parse(r);if(_(e))return e;A.warn(`Ignoring ${m} header: not a JSON object.`)}catch{A.warn(`Ignoring ${m} header: invalid JSON.`)}}const x=async(r,e,o)=>{const t=!!e?.config?.access?.requiresLogin,i=e?.config?.access?.rbac||{},g=o?.props?.config?.mcpMode??"tools",M=o?.props?.config?.gatewayFetchBudgetPerExec??N.budgetPerExec,E=o?.props?.config?.searchIgnoredRoutes??[];let d;const h=r.headers.get("Authorization");if(K(t,i)){const{isAuthenticated:l,isTokenValid:s,currentUser:a,accessToken:u}=await z(r,e);if(!l){const p=f(r);return s===!1?J(p):$(p)}a&&(e.user=a),d=u}else h&&(d=Y(h||"")??void 0);const T={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[Q],claims:e.user?.claims??{}};if(!X(Z.MCP,T,i,t))return G();let c;return await V(async()=>{const l=o?.props?.config?.elicitationEnabled??!1;if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return j();const s=o,a=s?.props?.config?.apiDescriptionsMap||{},u=s?.props?.config?.graphqlDescriptions||[],p=s?.props?.config?.mcpDocsServerName||W,{config:{mcp:b={}}}=e,D=H(a,e.user,i,t),R=L(u,e.user,i,t),S=e.config.products?Object.values(e.config.products).map(n=>n?.name):[],y=b.docs?.name||p,w=q(r.headers.get(m)),C=s?.props?.tools||[],I=s?.props?.skillsBaseUrl||f(r),O=k(s?.props?.skills||[],e.user,i,t).map(n=>({slug:n.slug,name:n.name,description:n.description,content:n.content,uri:B(I,n.slug)})),U=await r.json(),F={name:y,tools:C,skills:O,context:{...e,accessToken:d,outdir:e.outdir||"",baseUrl:e.baseUrl||f(r),apiDescriptionsMap:D,graphqlDescriptions:R,products:S,metadata:w,mcpMode:g,elicitationEnabled:l,gatewayFetchBudgetPerExec:M,searchIgnoredRoutes:E,clientIp:v(r)}};return c=await P({...F,getKv:e.getKv}),await ee(r,c,U)},async()=>{c&&(await c.cleanup(),c=void 0)},g)};async function ee(r,e,o){return e.transport.handleRequest(r,o!==void 0?{parsedBody:o}:void 0)}var Ae=x;export{Ae as default};
1
+ import{logger as u}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as N}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as g,getInternalOrigin as F}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as v}from"../../../../constants/common.js";import{isObject as k}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as B}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as L}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as H}from"@modelcontextprotocol/server";import{createDocsMcpServer as V}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as $,filterGraphqlDescriptionsByRbac as j}from"../utils.js";import{McpClientInputError as G,createMethodNotAllowedError as J,withErrorHandling as K}from"./errors.js";import{constructForbiddenResponse as Y,constructInvalidTokenResponse as z,constructUnauthorizedResponse as W,handleMcpAuth as X}from"../auth/auth-handlers.js";import{shouldHandleMcpAuth as Q}from"../../../utils/rbac/should-handle-mcp-auth.js";import{canAnonymousAccessMcpFeature as Z}from"../../../utils/rbac/can-anonymous-access-mcp-feature.js";import{extractTokenFromAuthHeader as q}from"../utils/jwt.js";import{resolveMcpClient as x}from"../utils/mcp-client.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as ee,SSE_KEEPALIVE_INTERVAL_MS as re}from"../constants.js";import{withPathPrefix as oe}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as se}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as ne}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as ie}from"../../../constants/rbac.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as te,RbacFeatures as ce}from"../../../../constants/common.js";const h="X-Redocly-AI-Metadata";function ae(r){if(r)try{const e=JSON.parse(r);if(k(e))return e;u.warn(`Ignoring ${h} header: not a JSON object.`)}catch{u.warn(`Ignoring ${h} header: invalid JSON.`)}}const pe=async(r,e,t)=>{const n=!!e?.config?.access?.requiresLogin,i=e?.config?.access?.rbac||{},A=t?.props?.config?.mcpMode??"tools",T=t?.props?.config?.gatewayFetchBudgetPerExec??v.budgetPerExec,S=t?.props?.config?.searchIgnoredRoutes??[],s=t,b=!!s?.props?.config?.isPublicEndpoint;let p;const E=r.headers.get("Authorization");if(b)e.user={...ie,email:"",idpAccessToken:void 0,idpId:void 0};else if(Q(n,i)){const{isAuthenticated:d,isTokenValid:l,currentUser:a,accessToken:m}=await X(r,e);if(!d){const c=g(r),f=e.config.mcp?.docs?.publicEndpoint&&Z(i,n)?`${c}${oe(se)}`:void 0;return l===!1?z(c):W(c,f)}a&&(e.user=a),p=m}else E&&(p=q(E||"")??void 0);const I={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[te],claims:e.user?.claims??{}};return ne(ce.MCP,I,i,n)?await K(async()=>{const d=t?.props?.config?.elicitationEnabled??!1;if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return J();const l=s?.props?.config?.apiDescriptionsMap||{},a=s?.props?.config?.graphqlDescriptions||[],m=s?.props?.config?.mcpDocsServerName||ee,{config:{mcp:c={}}}=e,f=$(l,e.user,i,n),y=j(a,e.user,i,n),U=e.config.products?Object.values(e.config.products).map(o=>o?.name):[],w=c.docs?.name||m,C=ae(r.headers.get(h)),R=s?.props?.tools||[],_=s?.props?.skillsBaseUrl||g(r),D=B(s?.props?.skills||[],e.user,i,n).map(o=>({slug:o.slug,name:o.name,description:o.description,content:o.content,uri:L(_,o.slug)})),M=await de(r),O={name:w,tools:R,skills:D,context:{...e,accessToken:p,outdir:e.outdir||"",baseUrl:e.baseUrl||g(r),internalBaseUrl:F(r),apiDescriptionsMap:f,graphqlDescriptions:y,products:U,metadata:C,mcpMode:A,elicitationEnabled:d,gatewayFetchBudgetPerExec:T,searchIgnoredRoutes:S,clientIp:N(r),...x(r)}},P=await V({...O,getKv:e.getKv});return await H(async()=>P,{keepAliveMs:re,onerror:o=>u.warn(`MCP handler: ${o.message}`)}).fetch(r,M!==void 0?{parsedBody:M}:void 0)},A):Y()};async function de(r){try{return await r.json()}catch(e){throw new G(e instanceof Error?e.message:String(e),{cause:e})}}var Fe=pe;export{Fe as default};
@@ -12,9 +12,14 @@ export declare class McpError extends Error {
12
12
  constructor(code: McpErrorCodeTypes, message: string, data?: unknown, requestId?: string | number | null);
13
13
  createErrorResponse(): Response;
14
14
  }
15
+ export declare class McpClientInputError extends Error {
16
+ constructor(message: string, options?: {
17
+ cause?: unknown;
18
+ });
19
+ }
15
20
  export declare function createMethodNotAllowedError(requestId?: string | number | null): Response;
16
- export declare function createInternalServerError(error: Error | string, requestId?: string | number | null, mode?: McpMode): Response;
21
+ export declare function createInternalServerError(error: Error | string, requestId?: string | number | null): Response;
17
22
  export declare function createInvalidRequestError(message?: string, requestId?: string | number | null): Response;
18
23
  export declare function createInvalidParamsError(message?: string, requestId?: string | number | null): Response;
19
- export declare function withErrorHandling<T>(operation: () => Promise<T>, cleanup?: () => Promise<void>, mode?: McpMode): Promise<T | Response>;
24
+ export declare function withErrorHandling<T>(operation: () => Promise<T>, mode?: McpMode): Promise<T | Response>;
20
25
  //# sourceMappingURL=errors.d.ts.map
@@ -1 +1 @@
1
- import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as s,McpServerType as d}from"../constants.js";import{serverAttributes as i}from"../utils/telemetry-attributes.js";class n extends Error{code;data;requestId;constructor(e,t,o,a){super(t),this.name="McpError",this.code=e,this.data=o,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=u(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}function u(r){switch(r){case s.InvalidRequest:case s.InvalidParams:return 400;case s.MethodNotFound:return 404;case s.ServerError:return 405;case s.InternalError:default:return 500}}function h(r){return new n(s.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function p(r,e,t="tools"){const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;return c.sendMcpErrorMessage([{...i(d.Docs),message:o,stack:a||"",error_class:"server_error",mode:t}]),new n(s.InternalError,"Internal server error mcp",o,e).createErrorResponse()}function v(r="Invalid request",e){return new n(s.InvalidRequest,r,void 0,e).createErrorResponse()}function I(r="Invalid parameters",e){return new n(s.InvalidParams,r,void 0,e).createErrorResponse()}async function g(r,e,t="tools"){try{return await r()}catch(o){return c.sendMcpErrorMessage([{...i(d.Docs),message:o?.message||"",stack:o?.stack||"",error_class:"server_error",mode:t}]),e&&e(),p(o,void 0,t)}}export{n as McpError,p as createInternalServerError,I as createInvalidParamsError,v as createInvalidRequestError,h as createMethodNotAllowedError,g as withErrorHandling};
1
+ import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as o,McpServerType as i}from"../constants.js";import{serverAttributes as d}from"../utils/telemetry-attributes.js";class s extends Error{code;data;requestId;constructor(e,t,n,a){super(t),this.name="McpError",this.code=e,this.data=n,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=p(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}class u extends Error{constructor(e,t){super(e,t),this.name="McpClientInputError"}}function p(r){switch(r){case o.InvalidRequest:case o.InvalidParams:return 400;case o.MethodNotFound:return 404;case o.ServerError:return 405;case o.InternalError:default:return 500}}function I(r){return new s(o.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function l(r,e){const t=r instanceof Error?r.message:String(r);return new s(o.InternalError,"Internal server error mcp",t,e).createErrorResponse()}function f(r="Invalid request",e){return new s(o.InvalidRequest,r,void 0,e).createErrorResponse()}function v(r="Invalid parameters",e){return new s(o.InvalidParams,r,void 0,e).createErrorResponse()}async function M(r,e="tools"){try{return await r()}catch(t){return c.sendMcpErrorMessage([{...d(i.Docs),message:t?.message||"",stack:t?.stack||"",error_class:t instanceof u?"client_error":"server_error",mode:e}]),l(t)}}export{u as McpClientInputError,s as McpError,l as createInternalServerError,v as createInvalidParamsError,f as createInvalidRequestError,I as createMethodNotAllowedError,M as withErrorHandling};
@@ -1 +1 @@
1
- import{withPathPrefix as g}from"@redocly/theme/core/utils";import{importApiRoutesHandler as D}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as E}from"../../../persistence/kv/services/kv-service.js";import{envConfig as l}from"../../../config/env-config.js";import{acceptsHtml as R}from"../../../utils/ai-agent-detection.js";import{handleErrorPageRender as T}from"../../../web-server/utils.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as _}from"../constants.js";import{MCP_DOCS_SERVER_HANDLER_ID as w}from"../index.js";import{resolvePublicBaseUrl as S}from"../../../web-server/utils/resolve-public-base-url.js";import{getForwardedOrigin as q}from"../../../web-server/utils/get-request-origin.js";import{applyEdgeRateLimit as O}from"../gateway-mcp/rate-limit/apply-edge-rate-limit.js";async function K(a,t,e){const n=t.req.raw;if(a.requestHandlerId===w&&n.method==="GET"&&R(n.headers.get("accept"))&&e.globalData.mcpData?.docs?.enabled)return T(t,e,{slug:a.slug},405,_);const r=t.get("auth"),o=await O(n,e);if(o)return o;const s=await e.resolveRouteStaticData(a)||{},m=g(a.slug),{requestHandlers:p}=await D(e.serverOutDir),c=p[a.requestHandlerId],d=(await c()).default,u=async()=>await E.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:l.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:l.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),f=h({honoCtx:t,ctx:{user:{teams:r.teams,email:r.claims.email,claims:r.claims,idpAccessToken:r.idpAccessToken,idpId:r.claims.idpId,isAuthenticated:r.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:q(t.req.raw)},telemetry:A,getKv:u}),i=await d(t.req.raw,f,{...s,props:{...s.props,routeSlug:m,outdir:e.outdir,skills:e.config.skills?.hide===!0?[]:e.getSkills(),skillsBaseUrl:S(e,t)}});return i instanceof Response?i:typeof i=="string"?new Response(i,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}})}export{K as handleMcpRequest};
1
+ import{withPathPrefix as g}from"@redocly/theme/core/utils";import{importApiRoutesHandler as D}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as E}from"../../../persistence/kv/services/kv-service.js";import{envConfig as l}from"../../../config/env-config.js";import{acceptsHtml as R}from"../../../utils/ai-agent-detection.js";import{handleErrorPageRender as T}from"../../../web-server/utils.js";import{MCP_DOCS_SERVER_HANDLER_ID as _,MCP_NOT_ALLOWED_TEMPLATE_ID as w}from"../../../constants/mcp.js";import{resolvePublicBaseUrl as S}from"../../../web-server/utils/resolve-public-base-url.js";import{getForwardedOrigin as q}from"../../../web-server/utils/get-request-origin.js";import{applyEdgeRateLimit as O}from"../gateway-mcp/rate-limit/apply-edge-rate-limit.js";async function N(a,t,e){const n=t.req.raw;if(a.requestHandlerId===_&&n.method==="GET"&&R(n.headers.get("accept"))&&e.globalData.mcpData?.docs?.enabled)return T(t,e,{slug:a.slug},405,w);const r=t.get("auth"),s=await O(n,e);if(s)return s;const o=await e.resolveRouteStaticData(a)||{},m=g(a.slug),{requestHandlers:c}=await D(e.serverOutDir),p=c[a.requestHandlerId],d=(await p()).default,u=async()=>await E.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:l.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:l.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),f=h({honoCtx:t,ctx:{user:{teams:r.teams,email:r.claims.email,claims:r.claims,idpAccessToken:r.idpAccessToken,idpId:r.claims.idpId,isAuthenticated:r.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:q(t.req.raw)},telemetry:A,getKv:u}),i=await d(t.req.raw,f,{...o,props:{...o.props,routeSlug:m,outdir:e.outdir,skills:e.config.skills?.hide===!0?[]:e.getSkills(),skillsBaseUrl:S(e,t)}});return i instanceof Response?i:typeof i=="string"?new Response(i,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(i),{headers:{"Content-Type":"application/json"}})}export{N as handleMcpRequest};