@redocly/realm 0.136.0-next.7 → 0.136.0-next.9

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 (72) hide show
  1. package/CHANGELOG.md +42 -0
  2. package/dist/server/api-routes/helpers/enhance-context.js +1 -1
  3. package/dist/server/api-routes/run-api-routes-worker.js +1 -1
  4. package/dist/server/config/env-config.d.ts +0 -2
  5. package/dist/server/config/env-schema.d.ts +0 -5
  6. package/dist/server/config/env-schemas/feature-flags.d.ts +0 -4
  7. package/dist/server/config/env-schemas/feature-flags.js +1 -1
  8. package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.js +1 -1
  9. package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +1 -1
  10. package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -1
  11. package/dist/server/plugins/mcp/codemode/code-audit.d.ts +12 -0
  12. package/dist/server/plugins/mcp/codemode/code-audit.js +1 -0
  13. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +11 -0
  14. package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -0
  15. package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +2 -3
  16. package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +1 -1
  17. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  18. package/dist/server/plugins/mcp/constants.d.ts +1 -1
  19. package/dist/server/plugins/mcp/constants.js +1 -1
  20. package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +19 -18
  21. package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +2 -2
  22. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
  23. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.d.ts +2 -1
  24. package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.js +1 -1
  25. package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.d.ts +6 -0
  26. package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.js +1 -0
  27. package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +1 -1
  28. package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.d.ts +8 -0
  29. package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.js +1 -0
  30. package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +1 -1
  31. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  32. package/dist/server/plugins/mcp/handlers/errors.js +1 -1
  33. package/dist/server/plugins/mcp/servers/docs-server.d.ts +2 -3
  34. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  35. package/dist/server/plugins/mcp/servers/mcp-server.d.ts +10 -14
  36. package/dist/server/plugins/mcp/servers/mcp-server.js +1 -1
  37. package/dist/server/plugins/mcp/types.d.ts +6 -6
  38. package/dist/server/plugins/mcp/utils/json-schema-validator.d.ts +9 -0
  39. package/dist/server/plugins/mcp/utils/json-schema-validator.js +1 -0
  40. package/dist/server/plugins/mcp/utils/mode.js +1 -1
  41. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  42. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +9 -1
  43. package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
  44. package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +2 -2
  45. package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
  46. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  47. package/dist/server/plugins/search/engines/typesense/index.js +1 -1
  48. package/dist/server/tools/notifiers/logger.js +1 -1
  49. package/dist/server/tools/notifiers/reporter.js +6 -6
  50. package/dist/server/types/plugins/common.d.ts +1 -1
  51. package/dist/server/web-server/auth.js +3 -3
  52. package/dist/server/web-server/middleware/telemetry-middleware.js +1 -1
  53. package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
  54. package/dist/server/web-server/routes/catalog/bff-catalog-revisions.js +1 -1
  55. package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
  56. package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
  57. package/dist/server/web-server/routes/catalog/catalog.js +1 -1
  58. package/dist/server/web-server/routes/dynamic-route.js +1 -1
  59. package/dist/server/web-server/routes/mcp-routes/a2a.js +1 -1
  60. package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
  61. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  62. package/dist/server/web-server/routes/page-data.js +1 -1
  63. package/dist/server/web-server/routes/search.js +1 -1
  64. package/dist/server/web-server/routes/skills/skill-markdown.js +1 -1
  65. package/dist/server/web-server/routes/skills/skills-index.js +1 -1
  66. package/dist/utils/url/parse-preview-url.d.ts +22 -0
  67. package/dist/utils/url/parse-preview-url.js +1 -0
  68. package/package.json +9 -10
  69. package/dist/server/plugins/mcp/handlers/sse-keepalive.d.ts +0 -15
  70. package/dist/server/plugins/mcp/handlers/sse-keepalive.js +0 -3
  71. package/dist/server/plugins/mcp/servers/session-manager.d.ts +0 -15
  72. package/dist/server/plugins/mcp/servers/session-manager.js +0 -1
@@ -1 +1 @@
1
- import m from"path";import{REDOCLY_ROUTE_RBAC as U,REDOCLY_TEAMS_RBAC as b}from"@redocly/config";import{withoutPathPrefix as j,withPathPrefix as V}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as M,CACHE_CONTROL_PUBLIC_HTML as W,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as Z,X_REDOCLY_CACHE_CONTROL_HEADER as J,X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML as K}from"../../constants/common.js";import{removeTrailingSlash as Q}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as x}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as ee}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as te}from"../../config/env-config.js";import{sanitizePath as ne}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as oe}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as re}from"../../../utils/path/is-path-in-folder.js";import{getLlmsTxtMdPathBySlug as ae}from"../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{removeLeadingSlash as D}from"../../../utils/url/remove-leading-slash.js";import{processRedirects as ie}from"./helpers/process-redirects.js";import{renderPage as se,getServerProps as ce}from"../../ssr/index.js";import{canAccessAsset as le,canAccessResource as H}from"../../utils/rbac.js";import{handleErrorPageRender as q,handleUnauthorized as v,handleUnauthorizedAsset as B}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as me,MIME_TYPES as ue}from"../mime-types.js";import{fileExistsAsync as F}from"../../utils/index.js";import{isAiAgentRequest as de}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as ge}from"../utils/legacy-openapi-redirects.js";import{getContentTypeHeaderValue as fe}from"../utils/content-type.js";import{telemetry as pe}from"../../../cli/telemetry/index.js";import{telemetry as he}from"../../telemetry/index.js";function Xe(e,z,Y){return async n=>{const R=n.get("logger"),a=n.req,i=new URL(a.url),r=j(ne(decodeURIComponent(i.pathname))),A=m.parse(r).ext===".md",E=de({accept:a.header("accept"),signatureAgent:a.header("signature-agent"),signature:a.header("signature"),signatureInput:a.header("signature-input"),userAgent:a.header("user-agent")}),l=oe(r),o=(a.method==="GET"||a.method==="HEAD")&&!A?e.getRouteBySlug(l,{followRedirect:!1})||x(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(r===t.slug||r.startsWith(t.slug+"/"))):void 0,L=e.getRedirect(l);if(L){const t=ie({redirect:L,reqUrlSearch:i.search});return he.sendRedirectMessage([{object:"redirect",from:l,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const f=te.isProductionEnv?301:302;if(o?.metadata?.type==="openapi"){const t=ge(i.pathname);if(t)return R.info("Legacy OpenAPI docs redirect from "+i.pathname),n.newResponse(null,f,{Location:encodeURI(t)});if(i.pathname.match(/[A-Z]/))return R.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,f,{Location:encodeURI(i.pathname.toLowerCase())})}if(r.endsWith("/")&&r!=="/"){const t=ee(new URL(l||"/",n.req.url).pathname);return n.newResponse(null,f,{Location:encodeURI(V((t==="/"?"/":Q(t))+i.search))})}const u=o&&E?ae(o.slug):void 0,_=u?await F(m.resolve(e.outdir,D(u))):!1,{isAuthenticated:d,teams:p,claims:{email:h}}=n.get("auth");if(o&&!H(o,{isAuthenticated:d,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return d?q(n,e,{slug:o.slug,[b]:o[b],[U]:o[U]},403):v(n,e,o.slug);if(o&&(!E||!_)){const t=await z(o),c=await ce(o,n,t,e),{html:X,statusCode:y,error:k}=await se(o,c,n,e,pe),O=e.config.access?.rbac,I=!e.config.access?.requiresLogin&&(!O||!Object.keys(O).length),S=y>=400||!!k||!!e.compilationErrors?.length,$=I&&!S;let g;return S?g=M:I?g=W:g="private",n.html(X,y,{"Cache-Control":g,...$&&{[J]:K}})}const w=u&&_?u:r,G=D(w),s=m.resolve(e.outdir,G);if(!re(s,e.outdir))return B(n);if(A){const t=r==="index.html.md"?"/":r.replace(/\.md$/,""),c=e.getRouteBySlug(t,{followRedirect:!1});if(c&&!H(c,{isAuthenticated:d,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return v(n,e,r)}const P=e.getGlobalConfig("access");if(!le(w,P?.rbac||{},P?.requiresLogin||!1,e.getGlobalConfig("directoryPaths"),{isAuthenticated:d,email:h,teams:p}))return B(n);const T=ue[m.extname(s)]||"text/plain",C=s.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||s.match(/runtime\/chunks\/.*/)?Z:me[T],N=C?{"Cache-Control":`public, max-age=${C}, immutable`,Expires:new Date(Date.now()+C*1e3).toUTCString()}:{"Cache-Control":M};if(await F(s)){const t=a.query("download")!=null,c=await Y(s);return n.newResponse(c,200,{"Content-Type":fe(T),"Access-Control-Allow-Origin":"*",...N,...t&&{"Content-Disposition":`attachment; filename="${m.basename(s)}"`}})}else return q(n,e,{slug:l},404)}}export{Xe as dynamicRouteHandler};
1
+ import m from"path";import{REDOCLY_ROUTE_RBAC as M,REDOCLY_TEAMS_RBAC as S}from"@redocly/config";import{combineUrls as V,withoutPathPrefix as W,withPathPrefix as Z}from"@redocly/theme/core/utils";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as D,CACHE_CONTROL_PUBLIC_HTML as J,DEFAULT_IMMUTABLE_CACHE_MAX_AGE as K,X_REDOCLY_CACHE_CONTROL_HEADER as Q,X_REDOCLY_CACHE_CONTROL_PUBLIC_HTML as x}from"../../constants/common.js";import{removeTrailingSlash as ee}from"../../../utils/url/remove-trailing-slash.js";import{findInIterable as te}from"../../../utils/collection/find-in-iterable.js";import{sanitizeRedirectPathname as ne}from"../../../utils/url/sanitize-redirect-pathname.js";import{envConfig as re}from"../../config/env-config.js";import{sanitizePath as oe}from"../../../utils/path/sanitize-path.js";import{normalizeRouteSlug as ie}from"../../../utils/path/normalize-route-slug.js";import{isPathInFolder as ae}from"../../../utils/path/is-path-in-folder.js";import{getLlmsTxtMdPathBySlug as se}from"../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{removeLeadingSlash as H}from"../../../utils/url/remove-leading-slash.js";import{processRedirects as ce}from"./helpers/process-redirects.js";import{renderPage as le,getServerProps as me}from"../../ssr/index.js";import{canAccessAsset as ue,canAccessResource as q}from"../../utils/rbac.js";import{handleErrorPageRender as v,handleUnauthorized as B,handleUnauthorizedAsset as F}from"../utils.js";import{DEFAULT_MAX_AGE_FOR_MIME_TYPE as de,MIME_TYPES as ge}from"../mime-types.js";import{fileExistsAsync as z}from"../../utils/index.js";import{isAiAgentRequest as fe}from"../../utils/ai-agent-detection.js";import{getRedirectRoute as pe}from"../utils/legacy-openapi-redirects.js";import{getContentTypeHeaderValue as he}from"../utils/content-type.js";import{telemetry as Re}from"../../../cli/telemetry/index.js";import{telemetry as Ce}from"../../telemetry/index.js";function ke(e,Y,G){return async n=>{const A=n.get("logger"),i=n.req,a=new URL(i.url),o=W(oe(decodeURIComponent(a.pathname))),E=m.parse(o).ext===".md",L=fe({accept:i.header("accept"),signatureAgent:i.header("signature-agent"),signature:i.header("signature"),signatureInput:i.header("signature-input"),userAgent:i.header("user-agent")}),s=ie(o),r=(i.method==="GET"||i.method==="HEAD")&&!E?e.getRouteBySlug(s,{followRedirect:!1})||te(e.routesBySlug?.values(),t=>t.hasClientRoutes&&(o===t.slug||o.startsWith(t.slug+"/"))):void 0,_=e.getRedirect(s);if(_){const t=ce({redirect:_,reqUrlSearch:a.search});return Ce.sendRedirectMessage([{id:s,object:"redirect",uri:`urn:redocly:realm:api:redirect:${s}`,from:s,templateId:t.type.toString()}]),n.newResponse(null,t.type,{Location:t.location})}const f=re.isProductionEnv?301:302;if(r?.metadata?.type==="openapi"){const t=pe(a.pathname);if(t)return A.info("Legacy OpenAPI docs redirect from "+a.pathname),n.newResponse(null,f,{Location:encodeURI(t)});if(a.pathname.match(/[A-Z]/))return A.warn("Redirect to lowercase route to avoid 404 error"),n.newResponse(null,f,{Location:encodeURI(a.pathname.toLowerCase())})}if(o.endsWith("/")&&o!=="/"){const t=ne(new URL(s||"/",n.req.url).pathname);return n.newResponse(null,f,{Location:encodeURI(Z((t==="/"?"/":ee(t))+a.search))})}const u=r&&L?se(r.slug):void 0,w=u?await z(m.resolve(e.outdir,H(u))):!1,{isAuthenticated:d,teams:p,claims:{email:h}}=n.get("auth");if(r&&!q(r,{isAuthenticated:d,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return d?v(n,e,{slug:r.slug,[S]:r[S],[M]:r[M]},403):B(n,e,r.slug);if(r&&(!L||!w)){const t=await Y(r),C=await me(r,n,t,e),{html:$,statusCode:U,error:k}=await le(r,C,n,e,Re),b=e.config.access?.rbac,O=!e.config.access?.requiresLogin&&(!b||!Object.keys(b).length),I=U>=400||!!k||!!e.compilationErrors?.length,j=O&&!I;let g;return I?g=D:O?g=J:g="private",n.html($,U,{"Cache-Control":g,...j&&{[Q]:x}})}const P=u&&w?u:o,N=H(P),c=m.resolve(e.outdir,N);if(!ae(c,e.outdir))return F(n);let l;if(E){const t=o==="/index.html.md"?"/":o.replace(/\.md$/,"");if(l=e.getRouteBySlug(t,{followRedirect:!1}),l&&!q(l,{isAuthenticated:d,email:h,teams:p},e.config.access?.rbac,e.config.access?.requiresLogin))return B(n,e,o)}const T=e.getGlobalConfig("access");if(!ue(P,T?.rbac||{},T?.requiresLogin||!1,e.getGlobalConfig("directoryPaths"),{isAuthenticated:d,email:h,teams:p}))return F(n);const y=ge[m.extname(c)]||"text/plain",R=c.match(/assets\/.*\.[a-f0-9]{8,}\..+/)||c.match(/runtime\/chunks\/.*/)?K:de[y],X=R?{"Cache-Control":`public, max-age=${R}, immutable`,Expires:new Date(Date.now()+R*1e3).toUTCString()}:{"Cache-Control":D};if(await z(c)){const t=i.query("download")!=null,C=await G(c);return n.newResponse(C,200,{"Content-Type":he(y),"Access-Control-Allow-Origin":"*",...X,...l&&{"X-Robots-Tag":"noindex, follow",...e.config.seo?.siteUrl&&{Link:`<${V(e.config.seo.siteUrl,l.slug)}>; rel="canonical"`}},...t&&{"Content-Disposition":`attachment; filename="${m.basename(c)}"`}})}else return v(n,e,{slug:s},404)}}export{ke as dynamicRouteHandler};
@@ -1 +1 @@
1
- import{withPathPrefix as t}from"@redocly/theme/core/utils";import{MCP_SERVER_CARD_SLUG as n}from"../../../../constants/common.js";import{telemetryTraceStep as a}from"../../../telemetry/helpers/trace-step.js";import{SKILLS_INDEX_SLUG as l}from"../skills/constants.js";function p(i){return async s=>await a("a2a",async o=>{const r=i.config.skills?.hide!==!0,e=[`<${t(n)}>; rel="mcp-server-card"`];return r&&e.push(`<${t(l)}>; rel="agent-skills"`),o?.setAttribute("skillsAdvertised",r),s.json({error:{code:"405",message:"Method not allowed"}},405,{Link:e.join(", ")})})}export{p as a2aHandler};
1
+ import{withPathPrefix as i}from"@redocly/theme/core/utils";import{MCP_SERVER_CARD_SLUG as a}from"../../../../constants/common.js";import{telemetryTraceStep as l}from"../../../telemetry/helpers/trace-step.js";import{SKILLS_INDEX_SLUG as n}from"../skills/constants.js";function f(s){return async o=>await l("com.redocly.a2a.requested",async e=>{const r=s.config.skills?.hide!==!0,t=[`<${i(a)}>; rel="mcp-server-card"`];return r&&t.push(`<${i(n)}>; rel="agent-skills"`),e?.setAttribute("skillsAdvertised",r),e?.setAttribute("object","a2a"),e?.setAttribute("id","a2aId"),e?.setAttribute("uri","urn:redocly:realm:api:a2a:a2aId"),o.json({error:{code:"405",message:"Method not allowed"}},405,{Link:t.join(", ")})})}export{f as a2aHandler};
@@ -1 +1 @@
1
- import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as u}from"../../../constants/common.js";import{telemetryTraceStep as m}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as g}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as f}from"../../../web-server/utils/resolve-public-base-url.js";import{shouldHandleMcpAuth as A}from"../../../plugins/mcp/auth/auth-handlers.js";import{buildAgentCard as d}from"./utils/build-agent-card.js";function _(e){return async i=>await m("agent_card",async t=>{if(e.config.skills?.hide===!0)return i.newResponse(null,404);const{isAuthenticated:o,teams:c,claims:{email:a}}=i.get("auth"),r=e.config.access?.rbac||{},s=!!e.config.access?.requiresLogin,n=g(e.getSkills(),{isAuthenticated:o,teams:c,email:a},r,s),l=A(s,r);return t?.setAttribute("skillsCount",n.length),t?.setAttribute("mcpAuthRequired",l),i.json(d({seo:e.getGlobalConfig("seo"),baseUrl:f(e,i),skills:n,mcpAuthRequired:l}),200,{"Cache-Control":u,"Access-Control-Allow-Origin":"*"})})}export{_ as agentCardHandler};
1
+ import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as c}from"../../../constants/common.js";import{telemetryTraceStep as d}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as g}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as m}from"../../../web-server/utils/resolve-public-base-url.js";import{shouldHandleMcpAuth as A}from"../../../plugins/mcp/auth/auth-handlers.js";import{buildAgentCard as C}from"./utils/build-agent-card.js";function y(e){return async r=>await d("com.redocly.agentCard.served",async t=>{if(t?.setAttribute("id","agentCardId"),t?.setAttribute("object","agentCard"),t?.setAttribute("uri","urn:redocly:realm:api:agentCard:agentCardId"),e.config.skills?.hide===!0)return r.newResponse(null,404);const{isAuthenticated:l,teams:a,claims:{email:u}}=r.get("auth"),i=e.config.access?.rbac||{},n=!!e.config.access?.requiresLogin,s=g(e.getSkills(),{isAuthenticated:l,teams:a,email:u},i,n),o=A(n,i);return t?.setAttribute("skillsCount",s.length),t?.setAttribute("mcpAuthRequired",o),r.json(C({seo:e.getGlobalConfig("seo"),baseUrl:m(e,r),skills:s,mcpAuthRequired:o}),200,{"Cache-Control":c,"Access-Control-Allow-Origin":"*"})})}export{y as agentCardHandler};
@@ -1 +1 @@
1
- import{LATEST_PROTOCOL_VERSION as f}from"@redocly/mcp-typescript-sdk/types.js";import{withPathPrefix as h}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as S}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as O}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as T}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as A,DESCRIBE_TOOLS_TOOL_NAME as R,FETCH_TOOL_NAME as g}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as M}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as b}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{buildCodeModeInstructions as L,buildExecuteDescription as v,DESCRIBE_TOOLS_DESCRIPTION as D}from"../../../plugins/mcp/codemode/prompts.js";import{composeExecuteAnnotations as I}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as P}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as V}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as y}from"../../../plugins/mcp/auth/auth-handlers.js";import{resolvePublicBaseUrl as H}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as N}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as U}from"./constants.js";const x="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",w="1.0";function to(t){const r=T(),E=new Date().toISOString().slice(0,10);return async c=>await N("mcp_server_card",async s=>{const o=t.getConfig(),m=o.mcp?.docs?.name||S,a=t.getMcpTools().filter(e=>!A.has(e.name)),i=V(o.mcp)?[...P]:[],l=i.some(e=>e.id===g),n=(r?[{...M,description:v(l),annotations:I(i)},{name:R,description:D,schema:b(a,i)}]:a).map(({name:e,description:C,schema:_,annotations:p})=>({name:e,description:C,inputSchema:_,...p?{annotations:p}:{}})),u=o.skills?.hide===!0?[]:t.getSkills(),d={$schema:x,version:w,protocolVersion:f,serverInfo:{name:m,title:m,version:E},description:o.seo?.description,documentationUrl:H(t,c),transport:{type:"streamable-http",endpoint:h(O.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...u.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:y(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:U}:void 0,instructions:r?L(l):void 0,tools:n.length>0?n:["dynamic"]};return s?.setAttribute("mode",r?"code":"tools"),s?.setAttribute("toolsCount",n.length),s?.setAttribute("authRequired",d.authentication!==void 0),c.json(d,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{to as mcpServerCardHandler};
1
+ import{withPathPrefix as S}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as h,MCP_PROTOCOL_VERSION as f}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as O}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as A}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as T,DESCRIBE_TOOLS_TOOL_NAME as b,FETCH_TOOL_NAME as M}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as R}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as g}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{buildCodeModeInstructions as v,buildExecuteDescription as I,DESCRIBE_TOOLS_DESCRIPTION as L}from"../../../plugins/mcp/codemode/prompts.js";import{composeExecuteAnnotations as D}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as P}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as y}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as V}from"../../../plugins/mcp/auth/auth-handlers.js";import{resolvePublicBaseUrl as H}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as N}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as U}from"./constants.js";const x="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",w="1.0";function oe(r){const i=A(),u=new Date().toISOString().slice(0,10);return async c=>await N("com.redocly.mcpServerCard.served",async e=>{e?.setAttribute("id","mcpServerCardId"),e?.setAttribute("object","mcpServerCard"),e?.setAttribute("uri","urn:redocly:realm:api:mcpServerCard:mcpServerCardId");const o=r.getConfig(),m=o.mcp?.docs?.name||h,a=r.getMcpTools().filter(t=>!T.has(t.name)),s=y(o.mcp)?[...P]:[],d=s.some(t=>t.id===M),n=(i?[{...R,description:I(d),annotations:D(s)},{name:b,description:L,schema:g(a,s)}]:a).map(({name:t,description:E,schema:_,annotations:p})=>({name:t,description:E,inputSchema:_,...p?{annotations:p}:{}})),C=o.skills?.hide===!0?[]:r.getSkills(),l={$schema:x,version:w,protocolVersion:f,serverInfo:{name:m,title:m,version:u},description:o.seo?.description,documentationUrl:H(r,c),transport:{type:"streamable-http",endpoint:S(O.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...C.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:V(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:U}:void 0,instructions:i?v(d):void 0,tools:n.length>0?n:["dynamic"]};return e?.setAttribute("mode",i?"code":"tools"),e?.setAttribute("toolsCount",n.length),e?.setAttribute("authRequired",l.authentication!==void 0),c.json(l,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{oe as mcpServerCardHandler};
@@ -1 +1 @@
1
- import{ServerRoutes as w}from"../../../constants/api.js";import{DEV_LOGIN_SLUG as U}from"../../../constants/common.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as r,DEFAULT_TITLE as $}from"../../constants/common.js";import{findInIterable as F}from"../../../utils/collection/find-in-iterable.js";import{removeTrailingSlash as N}from"../../../utils/url/remove-trailing-slash.js";import{envConfig as b}from"../../config/env-config.js";import{canAccessResource as q,filterDataByAccessDeep as T,isResourcePubliclyAccessible as B}from"../../utils/rbac.js";import{getServerProps as H}from"../../ssr/index.js";import{readSharedData as M}from"../../utils/index.js";import{getRedirectLoginUrl as G}from"../utils/get-redirect-login-url.js";import{processRedirects as V}from"./helpers/process-redirects.js";import{removeErrorDetails as W}from"../utils/remove-error-details.js";import{telemetry as k}from"../../telemetry/index.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as K}from"../../plugins/mcp/constants.js";function ie(e,n){return async(t,g)=>{const m=t.get("logger"),{req:p}=t,{pathname:d}=new URL(p.url),{seo:f,ssoDirect:h}=e.getConfig(),i=f?.title||$;if(e?.compilationErrors?.length&&b.isDevelopMode)return t.json({templateId:"compilation-error",props:{compilationErrors:e?.compilationErrors},sharedDataIds:{}},500,{"Cache-Control":r});const u=d.match(/page-data(.*)data.json$/);if(!u)return g();const c=decodeURI(u[1]),s=c==="/index/"?"/":N(c),o=e.getRouteBySlug(s,{followRedirect:!1})||F(e.routesBySlug.values(),a=>a.hasClientRoutes&&c.startsWith(a.slug+"/"));if(c===w.OIDC_CALLBACK+"/")return t.json({templateId:"403OIDC",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}}},200,{"Cache-Control":r});const{isAuthenticated:C,teams:D,claims:{name:j,picture:A,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},l={isAuthenticated:C,name:j,picture:A,email:I,teams:D};if(s==="/mcp"&&e.globalData.mcpData?.docs?.enabled)return t.json({templateId:K,sharedDataIds:{},props:{},userData:l},405,{"Cache-Control":r});const L=e.getRedirect(s);if(L){const a=V({redirect:L}).location;return k.sendRedirectMessage([{object:"redirect",from:s,templateId:"404"}]),t.json({templateId:"404",redirectTo:a,sharedDataIds:{},props:{}},301,{"Cache-Control":r})}if(!o){const a=e.getRouteBySlug(s,{followRedirect:!0});return m.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:a?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l},404,{"Cache-Control":r})}if(m.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.access?.rbac,e.config.access?.requiresLogin)&&o.slug!==U){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:l},403,{"Cache-Control":r});const a=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l,...a?{redirectTo:G(e,o.slug)}:{}},a?401:404,{"Cache-Control":r})}const S=T(o.versions,R,e.config.access?.rbac,e.config.access?.requiresLogin),_=e.routesSharedData.get(o.slug)||{},v=await n(o),P=await H(o,t,v,e),{sharedDataIds:O,...E}=P,y={templateId:o.templateId,versions:S,sharedDataIds:{..._,...O||{}},props:b.isProductionEnv?W(E):E,slug:o.slug,userData:l,isPublic:B(o,e.config)};return t.json(y,200,{"Cache-Control":r})}}function ce(e){return async(n,t)=>{const g=n.get("logger"),{req:m}=n,{pathname:p}=new URL(m.url),d=p.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await M(f,e.outdir),{isAuthenticated:i,teams:u,claims:{email:c}}=n.get("auth"),s=T(h,{isAuthenticated:i,email:c,teams:u},e.config.access?.rbac,e.config.access?.requiresLogin);return s?n.json(s,200,{"Cache-Control":r}):(g.error(`Shared data not found: ${p}`),n.text("Not Found",404,{"Cache-Control":r}))}}export{ie as pageDataHandler,ce as sharedPageDataHandler};
1
+ import{ServerRoutes as $}from"../../../constants/api.js";import{DEV_LOGIN_SLUG as w}from"../../../constants/common.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as a,DEFAULT_TITLE as U}from"../../constants/common.js";import{findInIterable as F}from"../../../utils/collection/find-in-iterable.js";import{removeTrailingSlash as N}from"../../../utils/url/remove-trailing-slash.js";import{envConfig as b}from"../../config/env-config.js";import{canAccessResource as q,filterDataByAccessDeep as T,isResourcePubliclyAccessible as B}from"../../utils/rbac.js";import{getServerProps as H}from"../../ssr/index.js";import{readSharedData as M}from"../../utils/index.js";import{getRedirectLoginUrl as G}from"../utils/get-redirect-login-url.js";import{processRedirects as V}from"./helpers/process-redirects.js";import{removeErrorDetails as W}from"../utils/remove-error-details.js";import{telemetry as k}from"../../telemetry/index.js";import{MCP_NOT_ALLOWED_TEMPLATE_ID as K}from"../../plugins/mcp/constants.js";function ie(e,n){return async(t,g)=>{const m=t.get("logger"),{req:p}=t,{pathname:d}=new URL(p.url),{seo:f,ssoDirect:h}=e.getConfig(),i=f?.title||U;if(e?.compilationErrors?.length&&b.isDevelopMode)return t.json({templateId:"compilation-error",props:{compilationErrors:e?.compilationErrors},sharedDataIds:{}},500,{"Cache-Control":a});const u=d.match(/page-data(.*)data.json$/);if(!u)return g();const c=decodeURI(u[1]),r=c==="/index/"?"/":N(c),o=e.getRouteBySlug(r,{followRedirect:!1})||F(e.routesBySlug.values(),s=>s.hasClientRoutes&&c.startsWith(s.slug+"/"));if(c===$.OIDC_CALLBACK+"/")return t.json({templateId:"403OIDC",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}}},200,{"Cache-Control":a});const{isAuthenticated:C,teams:D,claims:{name:j,picture:A,email:I}}=t.get("auth"),R={isAuthenticated:C,email:I,teams:D},l={isAuthenticated:C,name:j,picture:A,email:I,teams:D};if(r==="/mcp"&&e.globalData.mcpData?.docs?.enabled)return t.json({templateId:K,sharedDataIds:{},props:{},userData:l},405,{"Cache-Control":a});const L=e.getRedirect(r);if(L){const s=V({redirect:L}).location;return k.sendRedirectMessage([{id:r,object:"redirect",uri:`urn:redocly:realm:api:redirect:${r}`,from:r,templateId:"404"}]),t.json({templateId:"404",redirectTo:s,sharedDataIds:{},props:{}},301,{"Cache-Control":a})}if(!o){const s=e.getRouteBySlug(r,{followRedirect:!0});return m.error(`Page not found: ${d}`),t.json({templateId:"404",redirectTo:s?.slug,sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l},404,{"Cache-Control":a})}if(m.verbose(`Page viewed: ${o.slug}`),!q(o,R,e.config.access?.rbac,e.config.access?.requiresLogin)&&o.slug!==w){if(C)return t.json({templateId:"403",sharedDataIds:{},props:{seo:{title:`${i} - Forbidden`}},userData:l},403,{"Cache-Control":a});const s=Object.keys(h||{}).length>0;return t.json({templateId:"404",sharedDataIds:{},props:{seo:{title:`${i} - Not Found`}},userData:l,...s?{redirectTo:G(e,o.slug)}:{}},s?401:404,{"Cache-Control":a})}const S=T(o.versions,R,e.config.access?.rbac,e.config.access?.requiresLogin),_=e.routesSharedData.get(o.slug)||{},v=await n(o),P=await H(o,t,v,e),{sharedDataIds:y,...E}=P,O={templateId:o.templateId,versions:S,sharedDataIds:{..._,...y||{}},props:b.isProductionEnv?W(E):E,slug:o.slug,userData:l,isPublic:B(o,e.config)};return t.json(O,200,{"Cache-Control":a})}}function ce(e){return async(n,t)=>{const g=n.get("logger"),{req:m}=n,{pathname:p}=new URL(m.url),d=p.match(/\/page-data\/shared\/(.*)\.json/);if(!d)return t();const f=decodeURIComponent(d[1]),h=await M(f,e.outdir),{isAuthenticated:i,teams:u,claims:{email:c}}=n.get("auth"),r=T(h,{isAuthenticated:i,email:c,teams:u},e.config.access?.rbac,e.config.access?.requiresLogin);return r?n.json(r,200,{"Cache-Control":a}):(g.error(`Shared data not found: ${p}`),n.text("Not Found",404,{"Cache-Control":a}))}}export{ie as pageDataHandler,ce as sharedPageDataHandler};
@@ -1 +1 @@
1
- import{telemetryTraceStep as C}from"../../telemetry/helpers/trace-step.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as T}from"../../constants/common.js";import{expandTeamsForRead as E}from"../../utils/rbac.js";function F(e){return async t=>(t.header("Cache-Control",T),await C("search",async s=>{const i=t.get("logger"),a=t.get("auth"),A=i.startTiming(),o=e.getConfig().access?.requiresLogin&&!a.isAuthenticated,u=t.req.valid("json");s?.setAttribute("engine",e?.searchEngine?.type),s?.setAttribute("query",u.query||""),s?.setAttribute("user",a.claims.email??"anonymous"),s?.setAttribute("noAccess",o);const g=e.getSearchFacets(),r=o?{}:e.searchEngine?await e.searchEngine.search(u,{...a,teams:E(e.config.access?.rbac,a.teams)},g):{};let l=0;if(Object.keys(r).length){const f=r.documents;for(const[c,n]of Object.entries(f))l+=n.length}return i.infoTime(A,`Search with query "${u.query||""}". Total results: ${l}`),s?.setAttribute("resultsCount",l),t.json(r)}))}function j(e){return async t=>(t.header("Cache-Control",T),await C("search.facets",async s=>{const i=t.get("logger"),a=t.get("auth"),m=e.getConfig().access?.requiresLogin&&!a.isAuthenticated,o=t.req.valid("json");s?.setAttribute("engine",e?.searchEngine?.type),s?.setAttribute("user",a.claims.email??"anonymous"),s?.setAttribute("noAccess",m);const u=i.startTiming(),g=e.getSearchFacets(),r=m?{}:e.searchEngine?await e.searchEngine.countFacets(o,a,g):{},l=!!o.field;let f=[];if(l){const c=o.field,n=c&&g.get(c);if(n){const h={...n};h.values=r?.[c]||[],f.push(h)}}else{const c=new Map;for(const[n,h]of g){const y=r?.[n],d={...h};d.values=y||h.values.map(b=>({value:b,count:0})),c.set(n,d)}f=Array.from(c,([,n])=>n)}return i.verboseTime(u,"Search facets"),t.json(f)}))}export{j as searchFacetsHandler,F as searchHandler};
1
+ import{telemetryTraceStep as b}from"../../telemetry/helpers/trace-step.js";import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as C}from"../../constants/common.js";import{expandTeamsForRead as E}from"../../utils/rbac.js";function v(t){return async s=>(s.header("Cache-Control",C),await b("com.redocly.search.performed",async e=>{e?.setAttribute("id","searchQueryId"),e?.setAttribute("object","searchQuery"),e?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const i=s.get("logger"),r=s.get("auth"),d=i.startTiming(),a=t.getConfig().access?.requiresLogin&&!r.isAuthenticated,u=s.req.valid("json");e?.setAttribute("engine",t?.searchEngine?.type),e?.setAttribute("query",u.query||""),e?.setAttribute("user",r.claims.email??"anonymous"),e?.setAttribute("noAccess",a);const l=t.getSearchFacets(),o=a?{}:t.searchEngine?await t.searchEngine.search(u,{...r,teams:E(t.config.access?.rbac,r.teams)},l):{};let h=0;if(Object.keys(o).length){const g=o.documents;for(const[c,n]of Object.entries(g))h+=n.length}return i.infoTime(d,`Search with query "${u.query||""}". Total results: ${h}`),e?.setAttribute("resultsCount",h),s.json(o)}))}function p(t){return async s=>(s.header("Cache-Control",C),await b("com.redocly.search.facets",async e=>{e?.setAttribute("id","searchFacetsId"),e?.setAttribute("object","searchFacets"),e?.setAttribute("uri","urn:redocly:realm:api:searchFacets:searchFacetsId");const i=s.get("logger"),r=s.get("auth"),m=t.getConfig().access?.requiresLogin&&!r.isAuthenticated,a=s.req.valid("json");e?.setAttribute("engine",t?.searchEngine?.type),e?.setAttribute("user",r.claims.email??"anonymous"),e?.setAttribute("noAccess",m);const u=i.startTiming(),l=t.getSearchFacets(),o=m?{}:t.searchEngine?await t.searchEngine.countFacets(a,r,l):{},h=!!a.field;let g=[];if(h){const c=a.field,n=c&&l.get(c);if(n){const f={...n};f.values=o?.[c]||[],g.push(f)}}else{const c=new Map;for(const[n,f]of l){const y=o?.[n],A={...f};A.values=y||f.values.map(T=>({value:T,count:0})),c.set(n,A)}g=Array.from(c,([,n])=>n)}return i.verboseTime(u,"Search facets"),s.json(g)}))}export{p as searchFacetsHandler,v as searchHandler};
@@ -1 +1 @@
1
- import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as c}from"../../../constants/common.js";import{telemetryTraceStep as a}from"../../../telemetry/helpers/trace-step.js";import{canAccessSkill as m}from"../../../utils/skills/can-access-skill.js";import{MIME_TYPES as u}from"../../mime-types.js";import{getContentTypeHeaderValue as p}from"../../utils/content-type.js";function _(n){return async e=>await a("agent_skill",async r=>{const t=e.req.param("slug")??"";if(r?.setAttribute("skill",t),n.config.skills?.hide===!0)return e.newResponse(null,404);const s=n.skills.get(t),{isAuthenticated:l,teams:i,claims:{email:o}}=e.get("auth");return s&&m(s,{isAuthenticated:l,teams:i,email:o},n.config.access?.rbac,n.config.access?.requiresLogin)?e.newResponse(s.content,200,{"Content-Type":p(u[".md"]),"Cache-Control":c,"Access-Control-Allow-Origin":"*"}):e.newResponse(null,404)})}export{_ as skillMarkdownHandler};
1
+ import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as c}from"../../../constants/common.js";import{telemetryTraceStep as a}from"../../../telemetry/helpers/trace-step.js";import{canAccessSkill as u}from"../../../utils/skills/can-access-skill.js";import{MIME_TYPES as m}from"../../mime-types.js";import{getContentTypeHeaderValue as g}from"../../utils/content-type.js";function y(n){return async e=>await a("com.redocly.agentSkill.served",async t=>{t?.setAttribute("object","agentSkill");const r=e.req.param("slug")??"";if(t?.setAttribute("id",r),t?.setAttribute("uri",`urn:redocly:realm:api:agentSkill:${r}`),t?.setAttribute("skill",r),n.config.skills?.hide===!0)return e.newResponse(null,404);const s=n.skills.get(r),{isAuthenticated:i,teams:l,claims:{email:o}}=e.get("auth");return s&&u(s,{isAuthenticated:i,teams:l,email:o},n.config.access?.rbac,n.config.access?.requiresLogin)?e.newResponse(s.content,200,{"Content-Type":g(m[".md"]),"Cache-Control":c,"Access-Control-Allow-Origin":"*"}):e.newResponse(null,404)})}export{y as skillMarkdownHandler};
@@ -1 +1 @@
1
- import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as o}from"../../../constants/common.js";import{telemetryTraceStep as c}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as a}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as u}from"../../utils/resolve-public-base-url.js";import{buildSkillsIndex as m}from"./build-skills-index.js";function b(e){return async i=>await c("agent_skills_index",async l=>{if(e.config.skills?.hide===!0)return l?.setAttribute("skillsCount",0),i.newResponse(null,404);const{isAuthenticated:t,teams:n,claims:{email:r}}=i.get("auth"),s=a(e.getSkills(),{isAuthenticated:t,teams:n,email:r},e.config.access?.rbac,e.config.access?.requiresLogin);return l?.setAttribute("skillsCount",s.length),i.json(m(s,u(e,i)),200,{"Cache-Control":o,"Access-Control-Allow-Origin":"*"})})}export{b as skillsIndexHandler};
1
+ import{CACHE_CONTROL_NO_STORE_HEADER_VALUE as o}from"../../../constants/common.js";import{telemetryTraceStep as u}from"../../../telemetry/helpers/trace-step.js";import{getAccessibleSkills as a}from"../../../utils/skills/get-accessible-skills.js";import{resolvePublicBaseUrl as c}from"../../utils/resolve-public-base-url.js";import{buildSkillsIndex as d}from"./build-skills-index.js";function f(e){return async l=>await u("com.redocly.agentSkillsIndex.served",async i=>{if(i?.setAttribute("id","agentSkillsIndexId"),i?.setAttribute("object","agentSkillsIndex"),i?.setAttribute("uri","urn:redocly:realm:api:agentSkillsIndex:agentSkillsIndexId"),e.config.skills?.hide===!0)return i?.setAttribute("skillsCount",0),l.newResponse(null,404);const{isAuthenticated:s,teams:n,claims:{email:r}}=l.get("auth"),t=a(e.getSkills(),{isAuthenticated:s,teams:n,email:r},e.config.access?.rbac,e.config.access?.requiresLogin);return i?.setAttribute("skillsCount",t.length),l.json(d(t,c(e,l)),200,{"Cache-Control":o,"Access-Control-Allow-Origin":"*"})})}export{f as skillsIndexHandler};
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Parses an absolute preview URL string. Accepts `https:` on any host, and `http:`
3
+ * only on `localhost` hosts, which is how previews are served in the local dev
4
+ * environment. Returns `null` on parse errors and for any other scheme/host pair.
5
+ *
6
+ * @param uri - Absolute URL string to parse.
7
+ * @returns A `URL` when the string is a valid preview URL; otherwise `null`.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * parsePreviewUrl('https://slug--branch.preview.redocly.app');
12
+ * // URL { href: 'https://slug--branch.preview.redocly.app/' }
13
+ *
14
+ * parsePreviewUrl('http://slug--branch.preview.localhost');
15
+ * // URL { href: 'http://slug--branch.preview.localhost/' }
16
+ *
17
+ * parsePreviewUrl('http://slug--branch.preview.redocly.app');
18
+ * // null
19
+ * ```
20
+ */
21
+ export declare function parsePreviewUrl(uri: string): URL | null;
22
+ //# sourceMappingURL=parse-preview-url.d.ts.map
@@ -0,0 +1 @@
1
+ import{parseHttpsUrl as n}from"./parse-https-url.js";function s(t){const o=n(t);if(o)return o;try{const r=new URL(t);return r.protocol==="http:"&&l(r.hostname)?r:null}catch{return null}}function l(t){return t==="localhost"||t.endsWith(".localhost")}export{s as parsePreviewUrl};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/realm",
3
- "version": "0.136.0-next.7",
3
+ "version": "0.136.0-next.9",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -21,6 +21,7 @@
21
21
  "@jitl/quickjs-singlefile-mjs-release-sync": "0.32.0",
22
22
  "@libsql/client": "0.17.3",
23
23
  "@markdoc/markdoc": "0.5.2",
24
+ "@modelcontextprotocol/server": "2.0.0",
24
25
  "@opentelemetry/api": "1.9.1",
25
26
  "@opentelemetry/context-zone": "2.0.1",
26
27
  "@opentelemetry/core": "2.8.0",
@@ -32,7 +33,6 @@
32
33
  "@opentelemetry/sdk-trace-web": "2.8.0",
33
34
  "@opentelemetry/semantic-conventions": "1.40.0",
34
35
  "@redocly/ajv": "8.18.0",
35
- "@redocly/mcp-typescript-sdk": "1.18.1",
36
36
  "@redocly/openapi-core": "2.43.1",
37
37
  "@shikijs/transformers": "3.21.0",
38
38
  "@tanstack/react-query": "5.62.3",
@@ -51,11 +51,10 @@
51
51
  "enquirer": "2.3.6",
52
52
  "esbuild": "0.28.1",
53
53
  "escape-carriage": "^1.3.1",
54
- "fetch-to-node": "^2.1.0",
55
54
  "fflate": "0.7.4",
56
55
  "flexsearch": "0.7.43",
57
56
  "graphql": "16.12.0",
58
- "hono": "4.12.27",
57
+ "hono": "4.12.34",
59
58
  "htmlparser2": "8.0.2",
60
59
  "i18next": "22.4.15",
61
60
  "is-glob": "4.0.3",
@@ -94,14 +93,14 @@
94
93
  "xpath": "0.0.34",
95
94
  "yaml-ast-parser": "0.0.43",
96
95
  "zod": "^3.25.76",
97
- "@redocly/api-docs": "0.1.0-next.0",
98
- "@redocly/asyncapi-docs": "1.13.0-next.7",
96
+ "@redocly/api-docs": "0.1.0-next.1",
97
+ "@redocly/asyncapi-docs": "1.13.0-next.8",
99
98
  "@redocly/config": "0.53.1",
100
- "@redocly/graphql-docs": "1.13.0-next.7",
101
- "@redocly/openapi-docs": "3.24.0-next.7",
99
+ "@redocly/graphql-docs": "1.13.0-next.8",
100
+ "@redocly/openapi-docs": "3.24.0-next.8",
102
101
  "@redocly/portal-legacy-ui": "0.18.0",
103
- "@redocly/portal-plugin-mock-server": "0.21.0-next.7",
104
- "@redocly/realm-asyncapi-sdk": "0.14.0-next.0",
102
+ "@redocly/portal-plugin-mock-server": "0.21.0-next.8",
103
+ "@redocly/realm-asyncapi-sdk": "0.14.0-next.2",
105
104
  "@redocly/theme": "0.68.0-next.5"
106
105
  },
107
106
  "peerDependencies": {
@@ -1,15 +0,0 @@
1
- import type { ServerResponse } from 'node:http';
2
- export type SseKeepalive = {
3
- stop: () => void;
4
- };
5
- /**
6
- * Wraps res.writeHead so that, the moment the transport starts an SSE response
7
- * (status 200 + Content-Type: text/event-stream), headers are flushed immediately
8
- * (so intermediary proxies like CloudFront receive them before their origin
9
- * response timeout) and SSE comment pings are written on an interval.
10
- *
11
- * Returns a handle whose stop() clears the timer; it also auto-stops on the
12
- * response's 'finish'/'close'/'error' events.
13
- */
14
- export declare function attachSseKeepalive(res: ServerResponse, intervalMs?: number): SseKeepalive;
15
- //# sourceMappingURL=sse-keepalive.d.ts.map
@@ -1,3 +0,0 @@
1
- import{SSE_KEEPALIVE_INTERVAL_MS as u}from"../constants.js";const s="text/event-stream",d=`: keepalive
2
-
3
- `;function p(t){const[a,r,o]=t;if(a!==200)return!1;const e=typeof r=="object"&&r!==null?r:o;if(!e||typeof e!="object")return!1;if(!Array.isArray(e)){for(const[n,i]of Object.entries(e))if(n.toLowerCase()==="content-type")return String(i).toLowerCase().includes(s);return!1}if(e.length&&Array.isArray(e[0]))return e.some(([n,i])=>String(n).toLowerCase()==="content-type"&&String(i).toLowerCase().includes(s));for(let n=0;n+1<e.length;n+=2)if(String(e[n]).toLowerCase()==="content-type"&&String(e[n+1]).toLowerCase().includes(s))return!0;return!1}function S(t,a=u){let r,o=!1;const e=()=>{o=!0,r&&(clearInterval(r),r=void 0)},n=()=>!t.writableEnded&&!t.destroyed,i=()=>{o||r||(r=setInterval(()=>{if(!n()){e();return}try{t.write(d)}catch{e()}},a),r.unref?.())};t.once("finish",e),t.once("close",e),t.once("error",e);const c=t.writeHead.bind(t);return t.writeHead=function(...f){t.writeHead=c;const l=c(...f);if(!o&&p(f)){try{t.flushHeaders()}catch{}i()}return l},{stop:e}}export{S as attachSseKeepalive};
@@ -1,15 +0,0 @@
1
- import type { McpServerInstance } from './mcp-server.js';
2
- type SessionManagerOptions = {
3
- maxSessions?: number;
4
- onEvict?: (sessionId: string) => void;
5
- };
6
- export declare class McpSessionManager {
7
- #private;
8
- constructor(options?: SessionManagerOptions);
9
- get(sessionId: string): McpServerInstance | undefined;
10
- set(sessionId: string, instance: McpServerInstance): void;
11
- close(sessionId: string): Promise<void>;
12
- }
13
- export declare const mcpSessionManager: McpSessionManager;
14
- export {};
15
- //# sourceMappingURL=session-manager.d.ts.map
@@ -1 +0,0 @@
1
- import{logger as i}from"../../../tools/notifiers/logger.js";const a=1800*1e3,c=60*1e3,o=500;class r{#t=new Map;#e;#s;constructor(t={}){this.#e=t.maxSessions??o,this.#s=t.onEvict??(()=>{}),setInterval(()=>{this.#i()},c).unref?.()}get(t){const e=this.#t.get(t);if(e)return e.lastAccess=Date.now(),this.#t.delete(t),this.#t.set(t,e),e.instance}set(t,e){const s=this.#t.get(t);if(this.#t.delete(t),this.#t.set(t,{instance:e,lastAccess:Date.now()}),s&&s.instance!==e&&this.#n(t,s.instance),this.#t.size>this.#e){const n=this.#t.keys().next().value;n!==void 0&&this.close(n)}}async close(t){const e=this.#t.get(t);e&&(this.#t.delete(t),this.#s(t),await this.#n(t,e.instance))}async#n(t,e){try{await e.cleanup()}catch(s){i.warn(`Failed to clean up MCP session ${t.slice(0,8)}\u2026: ${s instanceof Error?s.message:String(s)}`)}}async#i(){const t=Date.now()-a;for(const[e,s]of this.#t)s.lastAccess<=t&&await this.close(e)}}const f=new r;export{r as McpSessionManager,f as mcpSessionManager};