@redocly/realm 0.138.0-next.1 → 0.138.0-next.2

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 (83) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/client/app/Sidebar/Sidebar.js +1 -1
  3. package/dist/client/app/l10n/L10nContext.d.ts +10 -0
  4. package/dist/client/app/l10n/L10nContext.js +1 -0
  5. package/dist/client/app/l10n/hooks/useL10n.js +1 -1
  6. package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
  7. package/dist/client/app/l10n/hooks/useTranslationKeys.d.ts +2 -0
  8. package/dist/client/app/l10n/hooks/useTranslationKeys.js +1 -1
  9. package/dist/client/app/l10n/ssrL10n.d.ts +4 -0
  10. package/dist/client/app/l10n/ssrL10n.js +1 -0
  11. package/dist/client/server-entry.d.ts +2 -1
  12. package/dist/client/server-entry.js +1 -1
  13. package/dist/constants/l10n/langs/ar.js +1 -1
  14. package/dist/constants/l10n/langs/de.js +1 -1
  15. package/dist/constants/l10n/langs/en.js +1 -1
  16. package/dist/constants/l10n/langs/es.js +1 -1
  17. package/dist/constants/l10n/langs/fr.js +1 -1
  18. package/dist/constants/l10n/langs/hi.js +1 -1
  19. package/dist/constants/l10n/langs/it.js +1 -1
  20. package/dist/constants/l10n/langs/ja.js +1 -1
  21. package/dist/constants/l10n/langs/ko.js +1 -1
  22. package/dist/constants/l10n/langs/pl.js +1 -1
  23. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  24. package/dist/constants/l10n/langs/pt.js +1 -1
  25. package/dist/constants/l10n/langs/ru.js +1 -1
  26. package/dist/constants/l10n/langs/uk.js +1 -1
  27. package/dist/constants/l10n/langs/zh.js +1 -1
  28. package/dist/server/constants/common.d.ts +2 -0
  29. package/dist/server/constants/common.js +1 -1
  30. package/dist/server/constants/plugins/search.js +1 -1
  31. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +1 -1
  32. package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -1
  33. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +5 -1
  34. package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +7 -1
  35. package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
  36. package/dist/server/plugins/config-parser/index.js +1 -1
  37. package/dist/server/plugins/config-parser/loaders/versions-config-loader.js +1 -1
  38. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.d.ts +10 -0
  39. package/dist/server/plugins/mcp/auth/assistant-anonymous-token.js +1 -0
  40. package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +5 -3
  41. package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
  42. package/dist/server/plugins/mcp/codemode/build-tool-type-declarations.js +4 -4
  43. package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +0 -1
  44. package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -2
  45. package/dist/server/plugins/mcp/codemode/capabilities/utils.js +4 -4
  46. package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +2 -2
  47. package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +0 -2
  48. package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
  49. package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
  50. package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
  51. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
  52. package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.js +1 -1
  53. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.d.ts +2 -0
  54. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.js +1 -1
  55. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.d.ts +6 -0
  56. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.js +1 -1
  57. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
  58. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +2 -0
  59. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
  60. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +5 -0
  61. package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
  62. package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.d.ts +20 -14
  63. package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
  64. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  65. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  66. package/dist/server/plugins/mcp/servers/mcp-server.js +3 -3
  67. package/dist/server/plugins/mcp/utils/disabled-tools.d.ts +3 -0
  68. package/dist/server/plugins/mcp/utils/disabled-tools.js +1 -0
  69. package/dist/server/plugins/mcp/utils/tool-registration.d.ts +2 -1
  70. package/dist/server/plugins/mcp/utils/tool-registration.js +1 -1
  71. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  72. package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
  73. package/dist/server/ssr/render.js +1 -1
  74. package/dist/server/types/plugins/search.d.ts +1 -1
  75. package/dist/server/utils/rbac-expand.js +1 -1
  76. package/dist/server/utils/rbac.js +1 -1
  77. package/dist/server/utils/search/highlight-text-for-search.d.ts +1 -0
  78. package/dist/server/utils/search/highlight-text-for-search.js +1 -1
  79. package/dist/server/utils/search/text-match.d.ts +6 -0
  80. package/dist/server/utils/search/text-match.js +1 -0
  81. package/dist/server/web-server/routes/ask-ai.js +1 -1
  82. package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
  83. package/package.json +3 -3
@@ -1,20 +1,26 @@
1
- import type { OpenAPISchema, OpenAPIParameter, OpenAPIResponse, OpenAPIRequestBody, Referenced, OpenAPIDefinition } from '@redocly/api-docs';
2
- export declare function resolveRef<T>(ref: string, def?: OpenAPIDefinition): T | undefined;
3
- type ResolveSchemaRefsParams = {
4
- schema: Referenced<OpenAPISchema> | undefined;
5
- definition: OpenAPIDefinition;
6
- visitedRefs?: Set<string>;
7
- maxDepth?: number;
8
- currentDepth?: number;
1
+ import type { OpenAPIParameter, Referenced, OpenAPIDefinition } from '@redocly/api-docs';
2
+ import type { McpEndpoint } from '../../types.js';
3
+ type JsonValue = string | number | boolean | null | JsonValue[] | {
4
+ [key: string]: JsonValue;
5
+ };
6
+ type JsonObject = {
7
+ [key: string]: JsonValue;
9
8
  };
10
- export declare function resolveSchemaRefs({ schema, definition, visitedRefs, maxDepth, currentDepth, }: ResolveSchemaRefsParams): OpenAPISchema | undefined;
11
- type ResolveParametersParams = {
9
+ export type ResolvedOperation = {
10
+ operation: JsonObject;
11
+ components?: Record<string, JsonObject>;
12
+ };
13
+ export declare function resolveRef<T>(ref: string, def?: OpenAPIDefinition): T | undefined;
14
+ type ResolveOperationParams = {
15
+ operation: McpEndpoint;
12
16
  pathParams: Referenced<OpenAPIParameter>[];
13
- opParams: Referenced<OpenAPIParameter>[];
14
17
  definition: OpenAPIDefinition;
15
18
  };
16
- export declare function resolveParameters({ pathParams, opParams, definition, }: ResolveParametersParams): OpenAPIParameter[];
17
- export declare function resolveRequestBody(requestBody: Referenced<OpenAPIRequestBody> | undefined, definition: OpenAPIDefinition): OpenAPIRequestBody | undefined;
18
- export declare function resolveResponses(responses: Record<string, Referenced<OpenAPIResponse>>, definition: OpenAPIDefinition): Record<string, OpenAPIResponse>;
19
+ export declare function resolveOperation({ operation, pathParams, definition, }: ResolveOperationParams): ResolvedOperation;
20
+ /**
21
+ * The operation with every `$ref` it follows inlined, or undefined when the followed targets pass
22
+ * `maxBytes` or the inliner cannot read the operation.
23
+ */
24
+ export declare function inlineOperation({ operation, pathParams, definition }: ResolveOperationParams, maxBytes: number): ResolvedOperation | undefined;
19
25
  export {};
20
26
  //# sourceMappingURL=resolve-refs.d.ts.map
@@ -1 +1 @@
1
- function $(e,o){if(!o||!e?.startsWith("#/"))return;const n=e.slice(2).split("/");let t=o;for(const r of n)if(typeof t=="object"&&t!==null&&r in t)t=t[r];else return;return t}function m(e,o){const n=Object.fromEntries(Object.entries(e).filter(([t,r])=>t!=="$ref"&&r!==void 0));return{...o,...n}}function l({schema:e,definition:o,visitedRefs:n=new Set,maxDepth:t=50,currentDepth:r=0}){if(!e)return;if(r>=t)return{type:"object",description:`Maximum resolution depth exceeded (${t})`};if("$ref"in e&&e.$ref){if(n.has(e.$ref))return{type:"object",description:`Circular reference detected: ${e.$ref}`,"x-circular-ref":e.$ref};const f=new Set(n);f.add(e.$ref);const i=$(e.$ref,o);if(!i)return{type:"object",description:`Could not resolve reference: ${e.$ref}`,"x-unresolved-ref":e.$ref};const u=l({schema:i,definition:o,visitedRefs:f,maxDepth:t,currentDepth:r+1});return u&&m(e,u)}const s={...e};if(s.properties){const f={};for(const[i,u]of Object.entries(s.properties)){const d=l({schema:u,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:r+1});f[i]=d||u}s.properties=f}if(s.items&&typeof s.items=="object")if(Array.isArray(s.items))s.items=s.items.map(f=>l({schema:f,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:r+1})||f);else{const f=l({schema:s.items,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:r+1});f&&(s.items=f)}return["allOf","anyOf","oneOf"].forEach(f=>{const i=s[f];Array.isArray(i)&&(s[f]=i.reduce((u,d)=>{const p=l({schema:d,definition:o,visitedRefs:new Set(n),maxDepth:t,currentDepth:r+1});return p&&u.push(p),u},[]))}),s}function a({pathParams:e,opParams:o,definition:n}){return[...e,...o].reduce((t,r)=>{if(!r)return t;if("$ref"in r&&r.$ref){const s=$(r.$ref,n);if(!s)return t;const c=m(r,s);return t.push({...c,schema:"schema"in c&&c.schema?l({schema:c.schema,definition:n}):void 0}),t}return t.push({...r,schema:"schema"in r&&r.schema?l({schema:r.schema,definition:n}):void 0}),t},[])}function v(e,o){const n={...e};if(e.example!==void 0&&(n.example=e.example),!e.examples)return n;const t={};for(const[r,s]of Object.entries(e.examples))if("$ref"in s){const c=$(s.$ref,o);c&&(t[r]=c)}else t[r]=s;return n.examples=t,n}function h(e,o){if(!e)return;const n="$ref"in e&&e.$ref?$(e.$ref,o):e;if(!n)return;const t=m(e,n),r={...t};if("content"in t&&t.content){const s={};for(const[c,f]of Object.entries(t.content))s[c]={...v(f,o),schema:f.schema?l({schema:f.schema,definition:o}):void 0};r.content=s}return r}function b(e,o){return Object.entries(e).reduce((n,[t,r])=>{const s="$ref"in r&&r.$ref?$(r.$ref,o):r;if(!s)return n;const c=m(r,s),f={...c};if("content"in c&&c.content){const i={};for(const[u,d]of Object.entries(c.content))i[u]={...v(d,o),schema:d.schema?l({schema:d.schema,definition:o}):void 0};f.content=i}return n[t]=f,n},{})}export{a as resolveParameters,$ as resolveRef,h as resolveRequestBody,b as resolveResponses,l as resolveSchemaRefs};
1
+ const S=/^#\/components\/([^/]+)\/([^/]+)(\/.*)?$/;function w(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function d(e,s){if(!s||!e?.startsWith("#/"))return;const n=e.slice(2).split("/").map(w);let t=s;for(const r of n)if(typeof t=="object"&&t!==null&&r in t)t=t[r];else return;return t}function h(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function O(e,s){const n={},t=new Set,r=new Set,o=[e];for(;o.length>0;){const c=o.pop();if(!(c===null||typeof c!="object")){if(h(c)&&typeof c.$ref=="string"&&!t.has(c.$ref)){t.add(c.$ref);const[,i,f]=S.exec(c.$ref)??[],u=f&&w(f);if(i&&u&&!r.has(`${i}/${u}`)){const l=d(`#/components/${i}/${f}`,s);l!==void 0&&(r.add(`${i}/${u}`),(n[i]??={})[u]=l,o.push(l))}}for(const i of Object.values(c))o.push(i)}}return Object.keys(n).length>0?n:void 0}function R(e,s){const n=h(e)&&typeof e.$ref=="string"?d(e.$ref,s)??e:e,{name:t,in:r}=h(n)?n:{};return typeof t=="string"&&typeof r=="string"?`${r}:${t}`:JSON.stringify(e)}function g(e,s,n){const t=new Map;for(const r of[...e,...s])r&&t.set(R(r,n),r);return[...t.values()]}function C({operation:e,pathParams:s,definition:n}){const t={...e,parameters:g(s,e.parameters??[],n)};return{operation:t,components:O(t,n)}}class E extends Error{}function j(e,s){if(e.remainingBytes-=s,e.remainingBytes<0)throw new E}function $(e,s){return j(e,JSON.stringify(s).length),s}function m(e,s,n){const t=d(e,s);if(t===void 0)return;const r=n.bytesByRef.get(e)??JSON.stringify(t).length;return n.bytesByRef.set(e,r),j(n,r),t}function y(e,s,n){const t=$(n,Object.fromEntries(Object.entries(e).filter(([r,o])=>r!=="$ref"&&o!==void 0)));return{...s,...t}}function a({schema:e,definition:s,budget:n,visitedRefs:t=new Set,maxDepth:r=50,currentDepth:o=0}){if(!e)return;if(o>=r)return $(n,{type:"object",description:`Maximum resolution depth exceeded (${r})`});if("$ref"in e&&e.$ref){if(t.has(e.$ref))return $(n,{type:"object",description:`Circular reference detected: ${e.$ref}`,"x-circular-ref":e.$ref});const f=new Set(t);f.add(e.$ref);const u=m(e.$ref,s,n);if(!u)return $(n,{type:"object",description:`Could not resolve reference: ${e.$ref}`,"x-unresolved-ref":e.$ref});const l=a({schema:u,definition:s,budget:n,visitedRefs:f,maxDepth:r,currentDepth:o+1});return l&&y(e,l,n)}const c={...e};if(c.properties){const f={};for(const[u,l]of Object.entries(c.properties)){const p=a({schema:l,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});f[u]=p||l}c.properties=f}if(c.items&&typeof c.items=="object")if(Array.isArray(c.items))c.items=c.items.map(f=>a({schema:f,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1})||f);else{const f=a({schema:c.items,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});f&&(c.items=f)}return["allOf","anyOf","oneOf"].forEach(f=>{const u=c[f];Array.isArray(u)&&(c[f]=u.reduce((l,p)=>{const v=a({schema:p,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});return v&&l.push(v),l},[]))}),c}function P({pathParams:e,opParams:s,definition:n,budget:t}){return[...e,...s].reduce((r,o)=>{if(!o)return r;if("$ref"in o&&o.$ref){const c=m(o.$ref,n,t);if(!c)return r;const i=y(o,c,t);return r.push({...i,schema:"schema"in i&&i.schema?a({schema:i.schema,definition:n,budget:t}):void 0}),r}return r.push({...o,schema:"schema"in o&&o.schema?a({schema:o.schema,definition:n,budget:t}):void 0}),r},[])}function x(e,s,n){const t={...e};if(e.example!==void 0&&(t.example=e.example),!e.examples)return t;const r={};for(const[o,c]of Object.entries(e.examples))if("$ref"in c){const i=m(c.$ref,s,n);i&&(r[o]=i)}else r[o]=c;return t.examples=r,t}function A(e,s,n){if(!e)return;const t="$ref"in e&&e.$ref?m(e.$ref,s,n):e;if(!t)return;const r=y(e,t,n),o={...r};if("content"in r&&r.content){const c={};for(const[i,f]of Object.entries(r.content))c[i]={...x(f,s,n),schema:f.schema?a({schema:f.schema,definition:s,budget:n}):void 0};o.content=c}return o}function B(e,s,n){return Object.entries(e).reduce((t,[r,o])=>{const c="$ref"in o&&o.$ref?m(o.$ref,s,n):o;if(!c)return t;const i=y(o,c,n),f={...i};if("content"in i&&i.content){const u={};for(const[l,p]of Object.entries(i.content))u[l]={...x(p,s,n),schema:p.schema?a({schema:p.schema,definition:s,budget:n}):void 0};f.content=u}return t[r]=f,t},{})}function N({operation:e,pathParams:s,definition:n},t){const r={remainingBytes:t,bytesByRef:new Map};try{const o={...e,parameters:P({pathParams:s,opParams:e.parameters||[],definition:n,budget:r}),requestBody:A(e.requestBody,n,r),responses:B(e.responses,n,r)};return{operation:o,components:O(o,n)}}catch{return}}export{N as inlineOperation,C as resolveOperation,d as resolveRef};
@@ -1 +1 @@
1
- import{logger as f}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,DEFAULT_ANONYMOUS_VISITOR_TEAM as k,RbacFeatures as B}from"../../../../constants/common.js";import{isObject as L}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as H}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as V}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as $}from"@modelcontextprotocol/server";import{createDocsMcpServer as j}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as G,filterGraphqlDescriptionsByRbac as J}from"../utils.js";import{McpClientInputError as K,createMethodNotAllowedError as Y,withErrorHandling as z}from"./errors.js";import{constructForbiddenResponse as W,constructInvalidTokenResponse as X,constructUnauthorizedResponse as Q,handleMcpAuth as Z}from"../auth/auth-handlers.js";import{shouldHandleMcpAuth as q}from"../../../utils/rbac/should-handle-mcp-auth.js";import{canAnonymousAccessMcpFeature as x}from"../../../utils/rbac/can-anonymous-access-mcp-feature.js";import{extractTokenFromAuthHeader as ee}from"../utils/jwt.js";import{resolveMcpClient as re}from"../utils/mcp-client.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as oe,SSE_KEEPALIVE_INTERVAL_MS as se}from"../constants.js";import{withPathPrefix as ne}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as ie}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as te}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as ce}from"../../../constants/rbac.js";const h="X-Redocly-AI-Metadata";function ae(r){if(r)try{const e=JSON.parse(r);if(L(e))return e;f.warn(`Ignoring ${h} header: not a JSON object.`)}catch{f.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={...ce,email:"",idpAccessToken:void 0,idpId:void 0};else if(q(n,i)){const{isAuthenticated:d,isTokenValid:l,currentUser:a,accessToken:m}=await Z(r,e);if(!d){const c=g(r),u=e.config.mcp?.docs?.publicEndpoint&&x(i,n)?`${c}${ne(ie)}`:void 0;return l===!1?X(c):Q(c,u)}a&&(e.user=a),p=m}else E&&(p=ee(E||"")??void 0);const I={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[k],claims:e.user?.claims??{}};return te(B.MCP,I,i,n)?await z(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 Y();const l=s?.props?.config?.apiDescriptionsMap||{},a=s?.props?.config?.graphqlDescriptions||[],m=s?.props?.config?.mcpDocsServerName||oe,{config:{mcp:c={}}}=e,u=G(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=H(s?.props?.skills||[],e.user,i,n).map(o=>({slug:o.slug,name:o.name,description:o.description,content:o.content,uri:V(_,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:u,graphqlDescriptions:y,products:U,metadata:C,mcpMode:A,elicitationEnabled:d,gatewayFetchBudgetPerExec:T,searchIgnoredRoutes:S,clientIp:N(r),...re(r)}},P=await j({...O,getKv:e.getKv});return await $(async()=>P,{keepAliveMs:se,onerror:o=>f.warn(`MCP handler: ${o.message}`)}).fetch(r,M!==void 0?{parsedBody:M}:void 0)},A):W()};async function de(r){try{return await r.json()}catch(e){throw new K(e instanceof Error?e.message:String(e),{cause:e})}}var Ne=pe;export{Ne as default};
1
+ import{logger as g}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as F}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as h,getInternalOrigin as N}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as v,DEFAULT_ANONYMOUS_VISITOR_TEAM as B,RbacFeatures as L}from"../../../../constants/common.js";import{isObject as H}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as V}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as $}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as j}from"@modelcontextprotocol/server";import{createDocsMcpServer as G}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as J,filterGraphqlDescriptionsByRbac as K}from"../utils.js";import{McpClientInputError as Y,createMethodNotAllowedError as z,withErrorHandling as W}from"./errors.js";import{constructForbiddenResponse as X,constructInvalidTokenResponse as Q,constructUnauthorizedResponse as Z,handleMcpAuth as q}from"../auth/auth-handlers.js";import{isAssistantAnonymousToken as x}from"../auth/assistant-anonymous-token.js";import{shouldHandleMcpAuth as ee}from"../../../utils/rbac/should-handle-mcp-auth.js";import{canAnonymousAccessMcpFeature as re}from"../../../utils/rbac/can-anonymous-access-mcp-feature.js";import{extractTokenFromAuthHeader as oe}from"../utils/jwt.js";import{resolveMcpClient as se}from"../utils/mcp-client.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as ne,SSE_KEEPALIVE_INTERVAL_MS as ie}from"../constants.js";import{withPathPrefix as te}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as ce}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as ae}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as pe}from"../../../constants/rbac.js";const A="X-Redocly-AI-Metadata";function de(r){if(r)try{const e=JSON.parse(r);if(H(e))return e;g.warn(`Ignoring ${A} header: not a JSON object.`)}catch{g.warn(`Ignoring ${A} header: invalid JSON.`)}}function b(){return{...pe,email:"",idpAccessToken:void 0,idpId:void 0}}const le=async(r,e,c)=>{const i=!!e?.config?.access?.requiresLogin,t=e?.config?.access?.rbac||{},M=c?.props?.config?.mcpMode??"tools",y=c?.props?.config?.gatewayFetchBudgetPerExec??v.budgetPerExec,S=c?.props?.config?.searchIgnoredRoutes??[],s=c,I=!!s?.props?.config?.isPublicEndpoint;let u;const E=r.headers.get("Authorization");if(I)e.user=b();else if(ee(i,t)){const{isAuthenticated:n,isTokenValid:p,isFirstPartyAnonymous:m,currentUser:d,accessToken:f}=await q(r,e);if(m)e.user=b();else if(n)d&&(e.user=d),u=f;else{const a=h(r),l=e.config.mcp?.docs?.publicEndpoint&&re(t,i)?`${a}${te(ce)}`:void 0;return p===!1?Q(a,l):Z(a,l)}}else if(E){const n=oe(E)??void 0;u=(n?await x(n):!1)?void 0:n}const U={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[B],claims:e.user?.claims??{}};return ae(L.MCP,U,t,i)?await W(async()=>{const n=c?.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 z();const p=s?.props?.config?.apiDescriptionsMap||{},m=s?.props?.config?.graphqlDescriptions||[],d=s?.props?.config?.mcpDocsServerName||ne,{config:{mcp:f={}}}=e,a=J(p,e.user,t,i),l=K(m,e.user,t,i),w=e.config.products?Object.values(e.config.products).map(o=>o?.name):[],C=f.docs?.name||d,R=de(r.headers.get(A)),_=s?.props?.tools||[],D=s?.props?.skillsBaseUrl||h(r),O=V(s?.props?.skills||[],e.user,t,i).map(o=>({slug:o.slug,name:o.name,description:o.description,content:o.content,uri:$(D,o.slug)})),T=await ue(r),P={name:C,tools:_,skills:O,context:{...e,accessToken:u,outdir:e.outdir||"",baseUrl:e.baseUrl||h(r),internalBaseUrl:N(r),apiDescriptionsMap:a,graphqlDescriptions:l,products:w,metadata:R,mcpMode:M,elicitationEnabled:n,gatewayFetchBudgetPerExec:y,searchIgnoredRoutes:S,clientIp:F(r),...se(r)}},k=await G({...P,getKv:e.getKv});return await j(async()=>k,{keepAliveMs:ie,onerror:o=>g.warn(`MCP handler: ${o.message}`)}).fetch(r,T!==void 0?{parsedBody:T}:void 0)},M):X()};async function ue(r){try{return await r.json()}catch(e){throw new Y(e instanceof Error?e.message:String(e),{cause:e})}}var ve=le;export{ve as default};
@@ -1 +1 @@
1
- import{logger as g}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as M,MCP_TOOL_IS_AVAILABLE_KEY as v}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as k}from"../constants.js";import{isAnonymousSessionToolAvailable as C}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as L,manageApiCredentials as y,manageApiCredentialsSchema as x}from"../codemode/tools/manage-credentials.js";import{EXECUTE_TOOL_SCHEMA as h}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as D,CODE_MODE_TOOL_NAMES as w,FETCH_TOOL_NAME as N}from"../codemode/constants.js";import{buildCodeModeInstructions as H,buildExecuteDescription as I}from"../codemode/prompts.js";import{toToolListEntries as U}from"../codemode/build-tool-list.js";import{composeExecuteAnnotations as F,getActiveCapabilities as P}from"../codemode/capabilities/index.js";import{describeToolsSchema as R,describeTools as z}from"../codemode/tools/describe-tools.js";import{availableSandboxTools as W}from"../utils/available-sandbox-tools.js";import{toRegisterToolConfig as A}from"../utils/tool-registration.js";import{createMcpServer as X,createToolDispatch as Y,extractSerializableContext as $}from"./mcp-server.js";function S(s,t){const o=t.schema;if(C(s))return o;const{sessionHandle:f,...p}=o.properties;return{...o,properties:p}}function j(s){return Object.fromEntries(s.map(t=>[t.name,t.schema]))}async function se({name:s,tools:t,context:o,skills:f=[],getKv:p}){const n=$(o),r=o.mcpMode==="code",c=r?P(o):[],T=c.some(e=>e.id===N),m=r?await W(t.filter(e=>!w.has(e.name)),n):[],b=U(m,c),O=r&&L(o),l=X(s,r?H(T,b):void 0),E={getClientCapabilities:()=>l.server.getClientCapabilities(),getKv:p},d=Y(r?{...n,sandboxToolSchemas:j(m)}:n,E),u=async e=>{try{return await M.exec(v,[{toolName:e,context:n}],{timeout:1e4})}catch(i){return g.error(`Failed to check MCP tool availability for "${e}": ${i instanceof Error?i.message:String(i)}`),!1}};if(r){const e=[{tool:{...h,description:I(T,b),schema:S(o,h),annotations:F(c)},callback:d(D)},{tool:R(m,c),callback:z(m,u,c,o)}],i=t.find(a=>a.name===k);if(i&&C(o)&&e.push({tool:i,callback:d(i.name)}),O){const a=x(o);e.push({tool:{...a,schema:S(o,a)},callback:y(n,E)})}for(const{tool:a,callback:_}of e)l.registerTool(a.name,A(a),_)}else await Promise.all(t.map(async e=>{const i=l.registerTool(e.name,A(e),d(e.name));await u(e.name)||i.disable()}));for(const e of f)l.registerResource(e.slug,e.uri,{title:e.name,description:e.description,mimeType:"text/markdown"},async()=>({contents:[{uri:e.uri,mimeType:"text/markdown",text:e.content}]}));return l}export{se as createDocsMcpServer};
1
+ import{logger as v}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as L,MCP_TOOL_IS_AVAILABLE_KEY as k}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as C,MANAGE_API_CREDENTIALS_TOOL_NAME as y}from"../constants.js";import{isAnonymousSessionToolAvailable as D}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as N,manageApiCredentials as x,manageApiCredentialsSchema as w}from"../codemode/tools/manage-credentials.js";import{EXECUTE_TOOL_SCHEMA as _}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as I,CODE_MODE_TOOL_NAMES as H,FETCH_TOOL_NAME as P}from"../codemode/constants.js";import{buildCodeModeInstructions as R,buildExecuteDescription as U}from"../codemode/prompts.js";import{toToolListEntries as F}from"../codemode/build-tool-list.js";import{composeExecuteAnnotations as z,getActiveCapabilities as B}from"../codemode/capabilities/index.js";import{describeToolsSchema as W,describeTools as X}from"../codemode/tools/describe-tools.js";import{availableSandboxTools as Y}from"../utils/available-sandbox-tools.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{toRegisterToolConfig as h}from"../utils/tool-registration.js";import{createMcpServer as $,createToolDispatch as j,extractSerializableContext as G}from"./mcp-server.js";function O(r,t){const o=t.schema;if(r)return o;const{sessionHandle:T,...p}=o.properties;return{...o,properties:p}}function K(r){return Object.fromEntries(r.map(t=>[t.name,t.schema]))}async function me({name:r,tools:t,context:o,skills:T=[],getKv:p}){const n=G(o),s=o.mcpMode==="code",l=s?B(o):[],b=l.some(e=>e.id===P),c=s?await Y(t.filter(e=>!H.has(e.name)),n):[],E=F(c,l),d=D(o)&&!S(C,o.metadata),g=s&&N(o)&&!S(y,o.metadata),m=$(r,s?R(b,E):void 0),u={getClientCapabilities:()=>m.server.getClientCapabilities(),getKv:p},f=j(s?{...n,sandboxToolSchemas:K(c)}:n,u),A=async e=>{try{return await L.exec(k,[{toolName:e,context:n}],{timeout:1e4})}catch(i){return v.error(`Failed to check MCP tool availability for "${e}": ${i instanceof Error?i.message:String(i)}`),!1}};if(s){const e=[{tool:{..._,description:U(b,E),schema:O(d,_),annotations:z(c,l)},callback:f(I)},{tool:W(c,l),callback:X(c,A,l,o)}],i=t.find(a=>a.name===C);if(i&&d&&e.push({tool:i,callback:f(i.name)}),g){const a=w(o);e.push({tool:{...a,schema:O(d,a)},callback:x(n,u)})}for(const{tool:a,callback:M}of e)m.registerTool(a.name,h(a),M)}else await Promise.all(t.map(async e=>{const i=m.registerTool(e.name,h({...e,outputSchema:void 0}),f(e.name));await A(e.name)||i.disable()}));for(const e of T)m.registerResource(e.slug,e.uri,{title:e.name,description:e.description,mimeType:"text/markdown"},async()=>({contents:[{uri:e.uri,mimeType:"text/markdown",text:e.content}]}));return m}export{me as createDocsMcpServer};
@@ -1,5 +1,5 @@
1
- import{McpServer as _}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as j,MCP_TOOL_WORKER_KEY as D}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as F}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as K,stripAuthRequiredMeta as y,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{buildCredentialsToolHint as L,buildSchemeChoiceHint as H,buildUpstreamCredentialFallback as T,buildUpstreamCredentialInputRequired as P,dedupeElicitation as $,isCredentialElicitationDeclined as B,isStatelessRequest as x,schemeLabelOf as N,supportsUrlElicitation as v}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as q,resolveUpstreamApiAuth as G,schemeChoicesOf as V}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as W,resolveSecretSubject as Y}from"../gateway-mcp/subject.js";const J=6e4;function pe(e,t){return new _({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function de(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,c=x(s.mcpReq),a=i?Y(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const p=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await F.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let u;const l=async()=>{u=await p();const m={toolName:r,args:n,context:{...e,upstreamSecrets:u},extra:re(s)};return await j.exec(D,[m],{timeout:J})};let d=await l();const f=K(d);if(f.length>0&&i&&!o)return y({...d,content:[{type:"text",text:W}],isError:!0});if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${c?"2026-07-28":"2025"} clientElicitation=${Q(t)}`);const m=await t.getKv(),h=await X(e,f),w=f.map(O=>Z(O,h)),E=z(u),g=c?await ee(e,s,w,o,m,E,h,t):await te(e,w,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":d=await l();break;case"prependText":d={...d,content:[{type:"text",text:g.text},...d.content],isError:!0};break;case"none":break}}return y(d)}}function Q(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function X(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await G(e,n));return r}function Z(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??q};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function z(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function R(e,t){return e.status===401&&!t.has(b(e))}function M(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?N(r.schemes,n):void 0}function A(e,t){const r=t.get(e.api);return!r||!e.schemes?.length?[]:V(r,e.schemes)}function I(e,t){return A(e,t).length>1}function k(e,t){return e.map(r=>L(r,M(r,t))).join(`
1
+ import{McpServer as j}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as D,MCP_TOOL_WORKER_KEY as F}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as K}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as L,stripAuthRequiredMeta as y,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{buildCredentialsToolHint as H,buildSchemeChoiceHint as P,buildUpstreamCredentialFallback as T,buildUpstreamCredentialInputRequired as $,dedupeElicitation as B,isCredentialElicitationDeclined as x,isStatelessRequest as N,schemeLabelOf as v,supportsUrlElicitation as G}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as q,resolveUpstreamApiAuth as V,schemeChoicesOf as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as Y,resolveSecretSubject as J}from"../gateway-mcp/subject.js";const Q=6e4;function pe(e,t){return new j({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function me(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,c=N(s.mcpReq),a=i?J(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const d=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await K.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let u;const l=async()=>{u=await d();const m={toolName:r,args:n,context:{...e,upstreamSecrets:u},extra:ne(s)};return await D.exec(F,[m],{timeout:Q})};let p=await l();const f=L(p);if(f.length>0&&i&&!o)return y(R(p,[{type:"text",text:Y}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${c?"2026-07-28":"2025"} clientElicitation=${X(t)}`);const m=await t.getKv(),h=await Z(e,f),k=f.map(O=>z(O,h)),E=ee(u),g=c?await te(e,s,k,o,m,E,h,t):await re(e,k,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await l();break;case"prependText":p=R(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return y(p)}}function R(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function X(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function Z(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await V(e,n));return r}function z(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??q};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function ee(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function M(e,t){return e.status===401&&!t.has(b(e))}function C(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?v(r.schemes,n):void 0}function A(e,t){const r=t.get(e.api);return!r||!e.schemes?.length?[]:W(r,e.schemes)}function I(e,t){return A(e,t).length>1}function w(e,t){return e.map(r=>H(r,C(r,t))).join(`
2
2
 
3
- `)}function C(e,t,r){const n=e.map(s=>H(s,A(s,r)));return t.length>0&&n.push(k(t,r)),n.join(`
3
+ `)}function U(e,t,r){const n=e.map(s=>P(s,A(s,r)));return t.length>0&&n.push(w(t,r)),n.join(`
4
4
 
5
- `)}function U(e,t,r,n,s){const[i,...c]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??q,p=M(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...p?{schemeLabel:p}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:c.map(u=>u.name)}}}async function ee(e,t,r,n,s,i,c,a){if(B(t.mcpReq.inputResponses))return{kind:"none"};const o=r.filter(l=>R(l,i));if(o.length===0)return{kind:"prependText",text:k(r,c)};const p=o.filter(l=>I(l,c));if(p.length>0){const l=r.filter(d=>!p.includes(d));return{kind:"prependText",text:C(p,l,c)}}const u=U(e,o,n,s,c);return v(a?.getClientCapabilities())?{kind:"inputRequired",result:await P(u)}:{kind:"prependText",text:await T(u)}}async function te(e,t,r,n,s,i){const c=t.filter(u=>R(u,s));if(c.length===0)return{kind:"prependText",text:k(t,i)};const a=c.filter(u=>I(u,i));if(a.length>0){const u=t.filter(l=>!a.includes(l));return{kind:"prependText",text:C(a,u,i)}}const o=U(e,c,r,n,i);return{kind:"prependText",text:await $(`${r}:${b(c[0])}`,()=>T(o))}}function re(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function me(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{pe as createMcpServer,de as createToolDispatch,me as extractSerializableContext};
5
+ `)}function _(e,t,r,n,s){const[i,...c]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??q,d=C(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...d?{schemeLabel:d}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:c.map(u=>u.name)}}}async function te(e,t,r,n,s,i,c,a){if(x(t.mcpReq.inputResponses))return{kind:"none"};const o=r.filter(l=>M(l,i));if(o.length===0)return{kind:"prependText",text:w(r,c)};const d=o.filter(l=>I(l,c));if(d.length>0){const l=r.filter(p=>!d.includes(p));return{kind:"prependText",text:U(d,l,c)}}const u=_(e,o,n,s,c);return G(a?.getClientCapabilities())?{kind:"inputRequired",result:await $(u)}:{kind:"prependText",text:await T(u)}}async function re(e,t,r,n,s,i){const c=t.filter(u=>M(u,s));if(c.length===0)return{kind:"prependText",text:w(t,i)};const a=c.filter(u=>I(u,i));if(a.length>0){const u=t.filter(l=>!a.includes(l));return{kind:"prependText",text:U(a,u,i)}}const o=_(e,c,r,n,i);return{kind:"prependText",text:await B(`${r}:${b(c[0])}`,()=>T(o))}}function ne(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function fe(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{pe as createMcpServer,me as createToolDispatch,fe as extractSerializableContext};
@@ -0,0 +1,3 @@
1
+ import type { McpToolContext } from '../types.js';
2
+ export declare function isToolDisabledByCaller(toolName: string, metadata: McpToolContext['metadata']): boolean;
3
+ //# sourceMappingURL=disabled-tools.d.ts.map
@@ -0,0 +1 @@
1
+ function r(o,s){const l=s?.disabledTools;return Array.isArray(l)&&l.includes(o)}export{r as isToolDisabledByCaller};
@@ -1,11 +1,12 @@
1
1
  import type { McpToolSchema } from '../../../types';
2
2
  import type { ToolArgs } from '../types.js';
3
3
  export declare function normalizeToolDisplayName(tool: McpToolSchema): McpToolSchema;
4
- /** The `registerTool` config for a tool schema, with its input schema compiled for validation. */
4
+ /** The `registerTool` config for a tool schema, with its input and output schemas compiled for validation. */
5
5
  export declare function toRegisterToolConfig(tool: McpToolSchema): {
6
6
  title: string | undefined;
7
7
  description: string;
8
8
  inputSchema: import("@modelcontextprotocol/server").StandardSchemaWithJSON<ToolArgs, ToolArgs>;
9
+ outputSchema?: import("@modelcontextprotocol/server").StandardSchemaWithJSON<unknown, unknown> | undefined;
9
10
  annotations: {
10
11
  title?: string | undefined;
11
12
  readOnlyHint?: boolean | undefined;
@@ -1 +1 @@
1
- import{fromJsonSchema as a}from"@modelcontextprotocol/server";import{mcpJsonSchemaValidator as r}from"./json-schema-validator.js";function m(t){const n=t.title??t.annotations?.title;return n?{...t,title:n,annotations:{...t.annotations,title:n}}:t}function p(t){const{title:n,description:o,schema:i,annotations:e}=m(t);return{title:n,description:o,inputSchema:a(i,r),annotations:e}}export{m as normalizeToolDisplayName,p as toRegisterToolConfig};
1
+ import{fromJsonSchema as i}from"@modelcontextprotocol/server";import{mcpJsonSchemaValidator as e}from"./json-schema-validator.js";function c(t){const n=t.title??t.annotations?.title;return n?{...t,title:n,annotations:{...t.annotations,title:n}}:t}function u(t){const{title:n,description:a,schema:r,outputSchema:o,annotations:m}=c(t);return{title:n,description:a,inputSchema:i(r,e),...o?{outputSchema:i(o,e)}:{},annotations:m}}export{c as normalizeToolDisplayName,u as toRegisterToolConfig};
@@ -1 +1 @@
1
- import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as _,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{importMcpToolHandlers as b}from"./import-mcp-tool-handlers.js";function A(t){return t.content.map(e=>e.type==="text"?e.text:"")}async function D(t){h.initialize();const{toolName:e,args:o,extra:s}=t,r=E(t.context),n=r?.mcpMode??"tools",a={client:r?.client,clientVersion:r?.clientVersion},d=performance.now();try{const i=await M(e);if(!i)throw new Error(`MCP tool "${e}" is not registered or its module does not export a handler for "${e}". Expected \`export default { '${e}': handler }\` or a single tool definition with \`description\` and \`execute\` as the default export.`);const C=typeof i=="function"?i:i.execute,l=P(e,await C(o,r,s),n),m=Math.round(performance.now()-d),{errorClass:y}=l;delete l.errorClass;const f=l.isError?y??(e===w?"sandbox_error":"tool_error"):void 0,v=e===w&&y==="tool_error",x=A(l),T=x.join("");return g({tool:e,mode:n,serverType:c.Docs,args:o,result:T,errorClass:f,...a}),f?v||u({tool:e,message:x.join(" "),mode:n,serverType:c.Docs,durationMs:m,errorClass:f,...a}):_({tool:e,mode:n,serverType:c.Docs,durationMs:m,outputLength:T.length,...a}),l}catch(i){throw g({tool:e,mode:n,serverType:c.Docs,args:o,errorClass:"server_error",...a}),u({tool:e,message:i instanceof Error?i.message:String(i),mode:n,serverType:c.Docs,durationMs:Math.round(performance.now()-d),stack:i instanceof Error&&i.stack||"",errorClass:"server_error",...a}),i}}function S(t){return"execute"in t&&typeof t.execute=="function"&&"description"in t&&typeof t.description=="string"}async function M(t){const e=(await b())[t];if(!e)return;const{default:o}=await e();return O(o,t)}function O(t,e){return S(t)?t:t[e]}function P(t,e,o){if(L(e))return e;if(typeof e=="string")return{content:[{type:"text",text:e}]};let s;try{s=JSON.stringify(e)}catch(n){throw new Error(`MCP tool "${t}" returned a value that cannot be serialized to JSON: `+(n instanceof Error?n.message:String(n)))}if(s===void 0)throw new Error(`MCP tool "${t}" returned an invalid result.`);const r=o==="code"?JSON.parse(s):void 0;return p(r)?{content:[{type:"text",text:s}],structuredContent:r}:{content:[{type:"text",text:s}]}}const k=new Set(["text","image","audio","resource","resource_link"]);function L(t){if(!p(t))return!1;const{content:e}=t;return Array.isArray(e)&&e.every(o=>p(o)&&k.has(o.type))}async function j(t){h.initialize();const{toolName:e}=t;if(N(e,t.context.metadata))return!1;const o=E(t.context),s=performance.now();try{const r=await M(e);return r?typeof r=="object"&&typeof r.isAvailable=="function"?await r.isAvailable(o):!0:!1}catch(r){throw u({tool:e,message:"Failed to check if MCP tool is available: "+(r instanceof Error?r.message:String(r)),mode:o?.mcpMode??"tools",serverType:c.Docs,durationMs:Math.round(performance.now()-s),stack:r instanceof Error&&r.stack||"",errorClass:"server_error",client:o?.client,clientVersion:o?.clientVersion}),r}}function N(t,e){const o=e?.disabledTools;return Array.isArray(o)&&o.includes(t)}async function F(t){const{toolNames:e,context:o}=t,s=await Promise.all(e.map(r=>j({toolName:r,context:o}).catch(()=>!1)));return Object.fromEntries(e.map((r,n)=>[r,s[n]]))}export{D as executeMcpTool,j as isMcpToolAvailable,F as mcpToolAvailability,O as resolveToolHandler};
1
+ import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as _,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{importMcpToolHandlers as b}from"./import-mcp-tool-handlers.js";function A(e){return e.content.map(t=>t.type==="text"?t.text:"")}async function F(e){h.initialize();const{toolName:t,args:o,extra:s}=e,r=E(e.context),n=r?.mcpMode??"tools",a={client:r?.client,clientVersion:r?.clientVersion},d=performance.now();try{const i=await M(t);if(!i)throw new Error(`MCP tool "${t}" is not registered or its module does not export a handler for "${t}". Expected \`export default { '${t}': handler }\` or a single tool definition with \`description\` and \`execute\` as the default export.`);const C=typeof i=="function"?i:i.execute,l=k(t,await C(o,r,s),n),m=Math.round(performance.now()-d),{errorClass:y}=l;delete l.errorClass;const f=l.isError?y??(t===w?"sandbox_error":"tool_error"):void 0,v=t===w&&y==="tool_error",x=A(l),T=x.join("");return g({tool:t,mode:n,serverType:c.Docs,args:o,result:T,errorClass:f,...a}),f?v||u({tool:t,message:x.join(" "),mode:n,serverType:c.Docs,durationMs:m,errorClass:f,...a}):_({tool:t,mode:n,serverType:c.Docs,durationMs:m,outputLength:T.length,...a}),l}catch(i){throw g({tool:t,mode:n,serverType:c.Docs,args:o,errorClass:"server_error",...a}),u({tool:t,message:i instanceof Error?i.message:String(i),mode:n,serverType:c.Docs,durationMs:Math.round(performance.now()-d),stack:i instanceof Error&&i.stack||"",errorClass:"server_error",...a}),i}}function O(e){return"execute"in e&&typeof e.execute=="function"&&"description"in e&&typeof e.description=="string"}async function M(e){const t=(await b())[e];if(!t)return;const{default:o}=await t();return P(o,e)}function P(e,t){return O(e)?e:e[t]}function k(e,t,o){if(j(t))return t;if(typeof t=="string")return{content:[{type:"text",text:t}]};let s;try{s=JSON.stringify(t)}catch(n){throw new Error(`MCP tool "${e}" returned a value that cannot be serialized to JSON: `+(n instanceof Error?n.message:String(n)))}if(s===void 0)throw new Error(`MCP tool "${e}" returned an invalid result.`);const r=o==="code"?JSON.parse(s):void 0;return p(r)?{content:[{type:"text",text:s}],structuredContent:r}:{content:[{type:"text",text:s}]}}const L=new Set(["text","image","audio","resource","resource_link"]);function j(e){if(!p(e))return!1;const{content:t}=e;return Array.isArray(t)&&t.every(o=>p(o)&&L.has(o.type))}async function N(e){h.initialize();const{toolName:t}=e;if(S(t,e.context.metadata))return!1;const o=E(e.context),s=performance.now();try{const r=await M(t);return r?typeof r=="object"&&typeof r.isAvailable=="function"?await r.isAvailable(o):!0:!1}catch(r){throw u({tool:t,message:"Failed to check if MCP tool is available: "+(r instanceof Error?r.message:String(r)),mode:o?.mcpMode??"tools",serverType:c.Docs,durationMs:Math.round(performance.now()-s),stack:r instanceof Error&&r.stack||"",errorClass:"server_error",client:o?.client,clientVersion:o?.clientVersion}),r}}async function U(e){const{toolNames:t,context:o}=e,s=await Promise.all(t.map(r=>N({toolName:r,context:o}).catch(()=>!1)));return Object.fromEntries(t.map((r,n)=>[r,s[n]]))}export{F as executeMcpTool,N as isMcpToolAvailable,U as mcpToolAvailability,P as resolveToolHandler};
@@ -1 +1 @@
1
- import L from"flexsearch";import{REDOCLY_TEAMS_RBAC as A}from"@redocly/config";import{DISABLE_DEEP_LINK_IF_FIELDS_EXIST as R,SEARCH_LIMIT as D}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as b}from"../../../../telemetry/helpers/trace-step.js";import{highlightTextForSearch as u}from"../../../../utils/search/highlight-text-for-search.js";function v(S){const{name:e,description:t,place:r,path:o,deepLink:s}=S,i=s?.indexOf("#")??-1;return{name:e,description:t,place:r,...o&&{path:o},...s&&{deepLink:i>=0?s.slice(i+1):s}}}class C{#e;#t=new Map;#s=1;id;constructor(e,t){this.id=e,this.#e=new L.Document(t)}get documents(){return this.#t.entries()}get documentsCount(){return this.#s}clearDocuments(){this.#t.clear()}async export(e){await this.#e.export(e)}async import(e){const{documents:t,index:r}=e;this.#t.clear();for(const[o,s]of t)this.#t.set(o,s);for(const[o,s]of Object.entries(r))await this.#e.import(o,s)}add(e){const t={...e,tags:e.tags??[],[A]:e[A],...e.parameters&&{parameters:e.parameters.map(v)}};this.#t.set(this.#s,t),this.#e.add(this.#s,t),this.#s++}async search(e){return await b("com.redocly.search.performed",async t=>{t?.setAttribute("id","searchQueryId"),t?.setAttribute("object","searchQuery"),t?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:r,offset:o,auth:s,product:i,versions:n}=e,c=[],l=s.teams,p={limit:D,offset:o};let h=new Map,m=await this.#e.searchAsync(r,{...p,tag:l});if(i){const a=await this.#e.searchAsync(r,{...p,tag:i});m=this.#a(m,a),t?.setAttribute("product",i)}if(n&&n.length){const a=await this.#e.searchAsync(r,{...p,tag:n});m=this.#a(m,a),t?.setAttribute("versions",n.join(","))}for(const a of m)for(const d of a.result){const f=h.get(d)?.fields||[];h.set(d,{fields:a.field?[...f,a.field]:[...f]})}const x=this.#r(r),g=[];for(const[a,d]of h.entries()){const f=this.#t.get(a);f&&!this.#h(f,n)&&g.push({document:f,fields:d.fields,score:this.#l(x,f)})}const I=g.filter(a=>a.score>=x.length),y=I.length?I:g;y.sort((a,d)=>d.score-a.score);for(const a of y.slice(0,D))c.push({document:this.#n(a.document,r,a.fields),highlight:this.#c(a.document,r,a.fields)});return{documents:{[this.id]:c},facets:{},hasCoveringHit:I.length>0}})}#n(e,t,r){return this.#f(e,t,r)}#c(e,t,r){const o={};let s=!1;for(const i of r)if(i==="path")o.path=e.path?e.path.map(n=>u(t,n)):[];else if(i.includes("parameters")){if(!s){const n=i.split(":")[1],c=this.#o(t,n,e.parameters);c&&(o.parameters=[{name:u(t,c.name),description:u(t,c.description),place:u(t,c.place),path:c.path?c.path.map(l=>u(t,l)):[]}],s=!0)}}else o[i]=u(t,e[i]);return o}#r(e){return[...new Set(e.toLowerCase().split(/\s+/g).filter(Boolean))]}#i(e,t){const r=t.toLowerCase().replace(/\s+/g," "),o=e.filter(i=>r.includes(i)).length;let s=0;for(let i=1;i<e.length;i++)r.includes(`${e[i-1]} ${e[i]}`)&&s++;return o+s/e.length}#l(e,t){let r=0;const o=s=>{if(s==null)return;const i=this.#i(e,String(s));i>r&&(r=i)};o(t.title),o(t.text),o(t.httpPath),o(t.path?.join(" "));for(const s of t.parameters??[])o([s.name,s.description,s.place].filter(Boolean).join(" "));return r}#o(e,t,r){const o=this.#r(e);let s,i=0;for(const n of r??[]){const c=n[t],l=(Array.isArray(c)?c:[c]).filter(h=>h!=null).map(h=>String(h)).join(" "),p=this.#i(o,l);p>i&&(i=p,s=n)}return s}#a(e,t){const r=[];for(const o of e){const s=[];for(const i of t)for(const n of o.result){const c=i.result.find(l=>l===n);c&&s.push(c)}s.length&&r.push({result:s,field:o.field})}return r}#h(e,t){return!!(t&&t.length&&e.isDefaultVersion&&e.versionFolderId&&e.version&&t.some(r=>r.includes(e.versionFolderId??""))&&!t.some(r=>r.includes(e.version??"")))}#f(e,t,r){for(const s of R)if(r.some(i=>i===s))return e;let o;for(const s of r)if(s.includes("parameters")){const i=s.split(":")[1],n=this.#o(t,i,e.parameters);if(n){o=n.deepLink;break}}return o?{...e,url:`${e.url}#${o}`}:e}}export{C as FlexSearchIndex};
1
+ import _ from"flexsearch";import{REDOCLY_TEAMS_RBAC as L}from"@redocly/config";import{DISABLE_DEEP_LINK_IF_FIELDS_EXIST as b,SEARCH_LIMIT as R}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as j}from"../../../../telemetry/helpers/trace-step.js";import{highlightTextForSearch as m,markMatchedValue as D}from"../../../../utils/search/highlight-text-for-search.js";import{MIN_QUERY_WORD_LENGTH as M,containsQueryWord as S,matchableQueryWords as C}from"../../../../utils/search/text-match.js";function k(I){const{name:e,description:t,place:r,path:i,deepLink:s,example:n,enum:a}=I,o=s?.indexOf("#")??-1;return{name:e,description:t,place:r,...i&&{path:i},...s&&{deepLink:o>=0?s.slice(o+1):s},example:n,enum:a}}class T{#t;#e=new Map;#s=1;id;constructor(e,t){this.id=e,this.#t=new _.Document(t)}get documents(){return this.#e.entries()}get documentsCount(){return this.#s}clearDocuments(){this.#e.clear()}async export(e){await this.#t.export(e)}async import(e){const{documents:t,index:r}=e;this.#e.clear();for(const[i,s]of t)this.#e.set(i,s);for(const[i,s]of Object.entries(r))await this.#t.import(i,s)}add(e){const t={...e,tags:e.tags??[],[L]:e[L],...e.parameters&&{parameters:e.parameters.map(k)}};this.#e.set(this.#s,t),this.#t.add(this.#s,t),this.#s++}async search(e){return await j("com.redocly.search.performed",async t=>{t?.setAttribute("id","searchQueryId"),t?.setAttribute("object","searchQuery"),t?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:r,offset:i,auth:s,product:n,versions:a}=e,o=[],l=s.teams,p={limit:R,offset:i},c=this.#r(r);if(!c.length&&r.trim())return{documents:{[this.id]:[]},facets:{},hasCoveringHit:!1};let d=new Map,g=await this.#t.searchAsync(r,{...p,tag:l});if(n){const h=await this.#t.searchAsync(r,{...p,tag:n});g=this.#a(g,h),t?.setAttribute("product",n)}if(a&&a.length){const h=await this.#t.searchAsync(r,{...p,tag:a});g=this.#a(g,h),t?.setAttribute("versions",a.join(","))}for(const h of g)for(const u of h.result){const f=d.get(u)?.fields||[];d.set(u,{fields:h.field?[...f,h.field]:[...f]})}!i&&c.length&&!d.size&&(d=this.#l(c,l,n,a));const x=[];for(const[h,u]of d.entries()){const f=this.#e.get(h);f&&!this.#d(f,a)&&x.push({document:f,fields:u.fields,score:this.#m(c,f)})}const y=x.filter(h=>h.score>=c.length),A=y.length?y:x;A.sort((h,u)=>u.score-h.score);for(const h of A.slice(0,R))o.push({document:this.#o(h.document,r,h.fields),highlight:this.#h(h.document,r,h.fields)});return{documents:{[this.id]:o},facets:{},hasCoveringHit:y.length>0}})}#o(e,t,r){return this.#g(e,t,r)}#h(e,t,r){const i={};let s=!1;for(const n of r)if(n==="path")i.path=e.path?e.path.map(a=>m(t,a)):[];else if(n.includes("parameters")){if(!s){const a=n.split(":")[1],o=this.#n(t,a,e.parameters);o&&(i.parameters=[{name:m(t,o.name),description:m(t,o.description),place:m(t,o.place),path:o.path?o.path.map(l=>m(t,l)):[],...this.#c(t,o)}],s=!0)}}else n!=="httpMethod"&&(i[n]=m(t,e[n]));return i}#c(e,t){return{enum:D(e,(t.enum??[]).join(", ")),example:D(e,t.example??"")}}#r(e){return C(e)}#l(e,t,r,i){const s=new Map;if(!e.length)return s;for(const[n,a]of this.#e)this.#p(a,t,r,i)&&this.#f(e,a)&&s.set(n,{fields:this.#u(e,a)});return s}#f(e,t){const r=i=>{if(i==null)return!1;const s=(Array.isArray(i)?i.join(" "):String(i)).toLowerCase();return!!s&&e.every(n=>S(s,n))};return r(t.title)||r(t.text)||r(t.httpPath)||r(t.path)?!0:(t.parameters??[]).some(i=>r(i.name)||r(i.description)||r(i.example)||r(i.enum))}#p(e,t,r,i){const s=new Set(e.tags??[]);return!(t.length&&!t.some(n=>s.has(n))||r&&!s.has(r)||i&&i.length&&!i.some(n=>s.has(n)))}#u(e,t){const r=s=>{if(s==null)return!1;const n=(Array.isArray(s)?s.join(" "):String(s)).toLowerCase();return e.some(a=>S(n,a))},i=[];r(t.title)&&i.push("title"),r(t.text)&&i.push("text"),r(t.path)&&i.push("path"),t.httpMethod&&e.some(s=>s.length>=M&&t.httpMethod?.toLowerCase().startsWith(s))&&i.push("httpMethod"),r(t.httpPath)&&i.push("httpPath");for(const s of["name","description","path","example","enum"])t.parameters?.some(n=>r(n[s]))&&i.push(`parameters[]:${s}`);return i}#i(e,t){const r=t.toLowerCase().replace(/\s+/g," "),i=e.filter(n=>S(r,n)).length;let s=0;for(let n=1;n<e.length;n++)r.includes(`${e[n-1]} ${e[n]}`)&&s++;return i+s/e.length}#m(e,t){let r=0;const i=s=>{if(s==null)return;const n=this.#i(e,String(s));n>r&&(r=n)};if(i(t.title),i(t.text),i(t.httpPath),i(t.path?.join(" ")),t.httpMethod){const s=t.httpMethod.toLowerCase(),n=e.filter(a=>a.length>=M&&s.startsWith(a)).length;n>r&&(r=n)}for(const s of t.parameters??[])i([s.name,s.description,s.place,s.example,s.enum?.join(" ")].filter(Boolean).join(" "));return r}#n(e,t,r){const i=this.#r(e);let s,n=0;for(const a of r??[]){const o=a[t],l=(Array.isArray(o)?o:[o]).filter(c=>c!=null).map(c=>String(c)).join(" "),p=this.#i(i,l);p>n&&(n=p,s=a)}return s}#a(e,t){const r=[];for(const i of e){const s=[];for(const n of t)for(const a of i.result){const o=n.result.find(l=>l===a);o&&s.push(o)}s.length&&r.push({result:s,field:i.field})}return r}#d(e,t){return!!(t&&t.length&&e.isDefaultVersion&&e.versionFolderId&&e.version&&t.some(r=>r.includes(e.versionFolderId??""))&&!t.some(r=>r.includes(e.version??"")))}#g(e,t,r){for(const s of b)if(r.some(n=>n===s))return e;let i;for(const s of r)if(s.includes("parameters")){const n=s.split(":")[1],a=this.#n(t,n,e.parameters);if(a){i=a.deepLink;break}}return i?{...e,url:`${e.url}#${i}`}:e}}export{T as FlexSearchIndex};
@@ -1 +1 @@
1
- import{pathToFileURL as z}from"url";import{HelmetProvider as G}from"@dr.pogodin/react-helmet";import{renderToString as l}from"react-dom/server";import{StaticRouterProvider as J,createStaticHandler as K,createStaticRouter as Q}from"react-router";import r from"react";import{readFile as V}from"fs/promises";import{join as W}from"path";import{withPathPrefix as m,getLocaleFromPathname as X,withoutPathPrefix as Y,removeTrailingSlash as Z,getSafeClassName as tt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as et}from"../../utils/path/slash.js";import{reporter as rt}from"../tools/notifiers/reporter.js";import{envConfig as p}from"../config/env-config.js";import{slug as ot}from"../../utils/slugger.js";import{shouldForwardProp as st}from"../../utils/should-forward-prop.js";import{htmlTemplate as nt}from"./template.js";import{detectColorSchemaScript as at,generatePreloadPageData as it,generatePreloadSharedData as ct}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as lt}from"./get-sitemap-link-tag.js";let g="";async function mt(t){return p.isRuntimeMode?await import("../../client/server-entry.js"):await import(z(`${et(t)}/server-entry.js`)+"?"+new Date)}async function Lt(t){if(!p.isRuntimeMode){const e=rt.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:u,App:R,routes:w,ServerStyleSheet:E,StyleSheetManager:C,ErrorDetails:P,initL10n:D}=await mt(t.serverOutDir),{page:h,store:{globalData:S,hasSitemap:y},sharedData:v,ssrHref:b}=t,d=S?.l10n,i=X(Y(h.slug),d?.defaultLocale,d?.locales),f=t.page.request?.url||"http://localhost/";await u.prepare({...h,slug:Z(new URL(f).pathname)},v,S,i),await D(i);const c=new E,{query:M,dataRoutes:x}=K([{Component:R,path:m("*"),children:w}]),s=await M(new Request(f));if(s instanceof Response)throw s;const B=Q(x,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=l(r.createElement(G,{context:e},r.createElement(C,{sheet:c.instance,shouldForwardProp:st},r.createElement(J,{router:B,context:s})))),L=y?lt():"",a=e.helmet,j=a?.title.toString()||"",k=t.store.globalData?.logo?.favicon,o=t.store.config,_=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${m("/app-data.json")}" />`,F=it(t.page.slug),H=ct(t.page.sharedDataIds),U=at(o),A=t.page.product?.name?tt(`product-${ot(t.page.product.name)}`):"",N=t.store.ssr.headTags.join(""),$=t.store.ssr.postBodyTags.join(""),I=t.store.ssr.preBodyTags.join(""),O=`<link rel="stylesheet" href="${m(T)}/browser-entry.css" />`;!p.isDevelopMode&&!g&&(g=`<style>${await V(W(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const q={bodyHtml:n,linkTags:o.linkTags+c.getStyleTags()+(a?.link.toString()||""),title:j,favicon:k,headScriptTags:L+U+o.headScriptTags+N+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[_,F,...H],postBodyScriptTags:o.postBodyScriptTags+$,preBodyScriptTags:o.preBodyScriptTags||""+I,lang:i,productClass:A,runtimeCss:g||O};return{html:nt(q),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:l(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{c.seal(),u.clear()}}function jt(t){return l(r.createElement(r.Fragment,null,...t))}export{Lt as render,jt as renderComponents};
1
+ import{pathToFileURL as J}from"url";import{HelmetProvider as K}from"@dr.pogodin/react-helmet";import{renderToString as m}from"react-dom/server";import{StaticRouterProvider as Q,createStaticHandler as V,createStaticRouter as W}from"react-router";import r from"react";import{readFile as X}from"fs/promises";import{join as Y}from"path";import{withPathPrefix as p,getLocaleFromPathname as Z,withoutPathPrefix as tt,removeTrailingSlash as et,getSafeClassName as rt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as ot}from"../../utils/path/slash.js";import{reporter as st}from"../tools/notifiers/reporter.js";import{envConfig as g}from"../config/env-config.js";import{slug as nt}from"../../utils/slugger.js";import{shouldForwardProp as at}from"../../utils/should-forward-prop.js";import{htmlTemplate as it}from"./template.js";import{detectColorSchemaScript as ct,generatePreloadPageData as lt,generatePreloadSharedData as mt}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as pt}from"./get-sitemap-link-tag.js";let u="";async function gt(t){return g.isRuntimeMode?await import("../../client/server-entry.js"):await import(J(`${ot(t)}/server-entry.js`)+"?"+new Date)}async function kt(t){if(!g.isRuntimeMode){const e=st.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:h,App:C,routes:R,ServerStyleSheet:w,StyleSheetManager:E,ErrorDetails:P,L10nContext:D,createSsrL10nContext:y}=await gt(t.serverOutDir),{page:S,store:{globalData:d,hasSitemap:v},sharedData:x,ssrHref:b}=t,i=d?.l10n,c=Z(tt(S.slug),i?.defaultLocale,i?.locales),f=t.page.request?.url||"http://localhost/";await h.prepare({...S,slug:et(new URL(f).pathname)},x,d,c);const L=await y(i,c),l=new w,{query:M,dataRoutes:B}=V([{Component:C,path:p("*"),children:R}]),s=await M(new Request(f));if(s instanceof Response)throw s;const j=W(B,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=m(r.createElement(D.Provider,{value:L},r.createElement(K,{context:e},r.createElement(E,{sheet:l.instance,shouldForwardProp:at},r.createElement(Q,{router:j,context:s}))))),k=v?pt():"",a=e.helmet,_=a?.title.toString()||"",F=t.store.globalData?.logo?.favicon,o=t.store.config,H=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${p("/app-data.json")}" />`,U=lt(t.page.slug),A=mt(t.page.sharedDataIds),N=ct(o),$=t.page.product?.name?rt(`product-${nt(t.page.product.name)}`):"",I=t.store.ssr.headTags.join(""),O=t.store.ssr.postBodyTags.join(""),q=t.store.ssr.preBodyTags.join(""),z=`<link rel="stylesheet" href="${p(T)}/browser-entry.css" />`;!g.isDevelopMode&&!u&&(u=`<style>${await X(Y(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const G={bodyHtml:n,linkTags:o.linkTags+l.getStyleTags()+(a?.link.toString()||""),title:_,favicon:F,headScriptTags:k+N+o.headScriptTags+I+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[H,U,...A],postBodyScriptTags:o.postBodyScriptTags+O,preBodyScriptTags:o.preBodyScriptTags||""+q,lang:c,productClass:$,runtimeCss:u||z};return{html:it(G),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:m(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{l.seal(),h.clear()}}function _t(t){return m(r.createElement(r.Fragment,null,...t))}export{kt as render,_t as renderComponents};
@@ -87,7 +87,7 @@ export type SearchDocument = {
87
87
  [SEARCH_DOCUMENT_METADATA_KEY]?: SearchDocumentMetadata;
88
88
  };
89
89
  /** Parameter fields kept in the FlexSearch index and its export; the rest never leaves the build. */
90
- export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink'>;
90
+ export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink' | 'example' | 'enum'>;
91
91
  export type IndexedSearchDocument = Omit<SearchDocument, 'parameters'> & {
92
92
  parameters?: IndexedParameter[];
93
93
  };
@@ -1 +1 @@
1
- import{getHigherRole as c}from"./rbac.js";function d(e,r){if(!e)return;if(!p(e))return e;const t={reunite:{},content:f(e)},n=i(e,r);for(const o of n)t.reunite[o.teamName]=o.projectRole,t.content={...t.content,...Object.fromEntries((e.teamFolders||[]).flatMap(a=>{const l={...e.teamFoldersBaseRoles||{authenticated:"READ"},[o.teamName]:o.projectRole,"redocly.owners":"ADMIN"},m=a.replaceAll("{teamPathSegment}",o.teamPathSegment),s=m+"/**";return[[m,l],[s,l]]}))};return{reunite:{...e.reunite,...t.reunite},content:{...P(e.content||{},t.content)}}}function p(e){return!!(e.teamNamePatterns&&e.teamFolders)}function u(e,r){for(const t of e.teamNamePatterns||[]){if(!t.includes("{teamPathSegment}")&&!t.includes("{projectRole}"))continue;const n="^"+t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)").replace("{projectRole}","(?<projectRole>admin|maintain|triage|write|read|none)")+"$",a=new RegExp(n,"i").exec(r)?.groups;if(a?.projectRole||a?.teamPathSegment)return{teamName:r,projectRole:a.projectRole?.toUpperCase(),teamPathSegment:a.teamPathSegment?.toLowerCase()}}return null}function g(e,r){for(const t of e?.teamFolders||[]){if(!t.includes("{teamPathSegment}"))continue;const n=`^${t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)")}($|/)`,o=new RegExp(n,"i");for(const a of r){const l=o.exec(a)?.groups;if(l?.teamPathSegment)return{teamPathSegment:l.teamPathSegment.toLowerCase()}}}return null}function i(e,r){const t=r.map(o=>u(e,o));let n=null;for(const o of t)o?.projectRole&&!o.teamPathSegment&&(n=n?c(n,o.projectRole):o.projectRole);return t.map(o=>!o?.teamPathSegment||!o.projectRole&&!n?null:{...o,projectRole:o?.projectRole??n}).filter(Boolean)}function f(e){const r={};if(e.teamFoldersBaseRoles)for(const t of e.teamFolders){const n=t.replaceAll("{teamPathSegment}","**");r[n]=e.teamFoldersBaseRoles}return r}function P(e,r){const t={...e};for(const[n,o]of Object.entries(r))t[n]?t[n]={...t[n],...o}:t[n]=o;return t}export{p as canExpandConfig,d as expandRbacConfig,f as getTeamFolderDefaults,g as parseTeamFoldersTemplate,u as parseTeamNameTemplate,i as parseTeams};
1
+ import{getHigherRole as c}from"./rbac.js";function d(e,r){if(!e)return;if(!p(e))return e;const t={reunite:{},content:f(e)},n=i(e,r);for(const o of n)t.reunite[o.teamName]=o.projectRole,t.content={...t.content,...Object.fromEntries((e.teamFolders||[]).flatMap(a=>{const l={...e.teamFoldersBaseRoles||{authenticated:"READ"},[o.teamName]:o.projectRole,"redocly.owners":"ADMIN"},m=a.replaceAll("{teamPathSegment}",o.teamPathSegment),s=m+"/**";return[[m,l],[s,l]]}))};return{...e,reunite:{...e.reunite,...t.reunite},content:{...P(e.content||{},t.content)}}}function p(e){return!!(e.teamNamePatterns&&e.teamFolders)}function u(e,r){for(const t of e.teamNamePatterns||[]){if(!t.includes("{teamPathSegment}")&&!t.includes("{projectRole}"))continue;const n="^"+t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)").replace("{projectRole}","(?<projectRole>admin|maintain|triage|write|read|none)")+"$",a=new RegExp(n,"i").exec(r)?.groups;if(a?.projectRole||a?.teamPathSegment)return{teamName:r,projectRole:a.projectRole?.toUpperCase(),teamPathSegment:a.teamPathSegment?.toLowerCase()}}return null}function g(e,r){for(const t of e?.teamFolders||[]){if(!t.includes("{teamPathSegment}"))continue;const n=`^${t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)")}($|/)`,o=new RegExp(n,"i");for(const a of r){const l=o.exec(a)?.groups;if(l?.teamPathSegment)return{teamPathSegment:l.teamPathSegment.toLowerCase()}}}return null}function i(e,r){const t=r.map(o=>u(e,o));let n=null;for(const o of t)o?.projectRole&&!o.teamPathSegment&&(n=n?c(n,o.projectRole):o.projectRole);return t.map(o=>!o?.teamPathSegment||!o.projectRole&&!n?null:{...o,projectRole:o?.projectRole??n}).filter(Boolean)}function f(e){const r={};if(e.teamFoldersBaseRoles)for(const t of e.teamFolders){const n=t.replaceAll("{teamPathSegment}","**");r[n]=e.teamFoldersBaseRoles}return r}function P(e,r){const t={...e};for(const[n,o]of Object.entries(r))t[n]?t[n]={...t[n],...o}:t[n]=o;return t}export{p as canExpandConfig,d as expandRbacConfig,f as getTeamFolderDefaults,g as parseTeamFoldersTemplate,u as parseTeamNameTemplate,i as parseTeams};
@@ -1 +1 @@
1
- import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as g,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as w}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as B}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as S,PUBLIC_RBAC_SCOPE_ITEM as y,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as L}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as C,PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_ASSETS_FOLDER as M}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as U}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as b}from"../constants/rbac.js";import{removeTrailingSlash as W}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const I=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]);function Ct(t,e){const r=I.indexOf(t.toUpperCase()),n=I.indexOf(e.toUpperCase());return r>n?t:e}const E={};function T(t,e){if(!t?.content)return y;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return y;const s=a=>{const d=`slug:${a}`,p=E[d]??P(a);E[d]=p;const _=`fsPath:${a}`,D=E[_]??P($(a));return E[_]=D,!!(n&&p(n))||!!(o&&D(o))};if(ot(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[L]||y;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return y;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function F(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function jt(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?F(o,e.teams):!0}function It(t,e){return O(t,b,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&Object.values(B).some(c=>{const i=c.split(":")[0].replace(/\/$/,"");return t.slug===i||t.slug?.startsWith(c)})||(t.slug===k||t.slug===w||t.slug===U)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[g]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:F(s,e?.teams||[],e?.email)}function Ft(t,e,r,n){if(!t.startsWith(j)&&!t.startsWith(C))return!0;const o=t.replace(new RegExp(`^${j}/`),"").replace(new RegExp(`^${C}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function Nt(t,e,r,n,o){if(!t.startsWith(M))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function kt(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==S):f=[S],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function N(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=N(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===g||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=N(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&rt(i)&&nt(i)}return o?void 0:s}return t}function wt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Bt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===L?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Mt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function rt(t){return m(t)&&Object.keys(t).length>0}function nt(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function ot(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const st=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},Ut=async t=>{if(t){if(Object.keys(t).length===0)return{};if(st(t))return ct(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},ct=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=W(n);r[o]=e.content[n]}e.content=r}return e};function bt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return it(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function it(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{I as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Bt as applyL10nToRbacConfig,Nt as canAccessAsset,jt as canAccessFeature,O as canAccessResource,Ft as canDownloadApiDefinition,it as expandTeamsForRead,x as extractTeamsFromScopeItems,N as filterDataByAccessDeep,kt as getAuthDetailsFromCookies,Ct as getHigherRole,bt as getRbacTeamsListForResource,T as getScopeItemsForResource,F as hasScopeAccess,st as isRbacConfigValid,It as isResourcePubliclyAccessible,ct as normalizeRbacConfig,Ut as parseRbacConfig,wt as parseTeamClaimToArray,Mt as resolveDirectoryHashes};
1
+ import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as L,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as U,PUBLIC_MCP_ROUTE as k}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as M}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as g,PUBLIC_RBAC_SCOPE_ITEM as E,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as C}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as B}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as b}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as W}from"../constants/rbac.js";import{removeTrailingSlash as _}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const F=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]),rt=new Set(Object.values(M).map(t=>_(t.split(":")[0])));function jt(t,e){const r=F.indexOf(t.toUpperCase()),n=F.indexOf(e.toUpperCase());return r>n?t:e}const y={};function T(t,e){if(!t?.content)return E;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return E;const s=a=>{const d=`slug:${a}`,p=y[d]??P(a);y[d]=p;const S=`fsPath:${a}`,D=y[S]??P($(a));return y[S]=D,!!(n&&p(n))||!!(o&&D(o))};if(st(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[C]||E;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return E;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function N(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function It(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?N(o,e.teams):!0}function Ft(t,e){return O(t,W,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&rt.has(_(t.slug))||(t.slug===U||t.slug===k||t.slug===b)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[L]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:N(s,e?.teams||[],e?.email)}function Nt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const o=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function wt(t,e,r,n,o){if(!t.startsWith(B))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function Ut(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==g):f=[g],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function w(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=w(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===L||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=w(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&nt(i)&&ot(i)}return o?void 0:s}return t}function kt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Mt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===C?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Bt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function nt(t){return m(t)&&Object.keys(t).length>0}function ot(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function st(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const ct=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},bt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(ct(t))return it(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},it=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=_(n);r[o]=e.content[n]}e.content=r}return e};function Wt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return at(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function at(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{F as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Mt as applyL10nToRbacConfig,wt as canAccessAsset,It as canAccessFeature,O as canAccessResource,Nt as canDownloadApiDefinition,at as expandTeamsForRead,x as extractTeamsFromScopeItems,w as filterDataByAccessDeep,Ut as getAuthDetailsFromCookies,jt as getHigherRole,Wt as getRbacTeamsListForResource,T as getScopeItemsForResource,N as hasScopeAccess,ct as isRbacConfigValid,Ft as isResourcePubliclyAccessible,it as normalizeRbacConfig,bt as parseRbacConfig,kt as parseTeamClaimToArray,Bt as resolveDirectoryHashes};
@@ -1,2 +1,3 @@
1
1
  export declare function highlightTextForSearch(query: string, text: string): string;
2
+ export declare function markMatchedValue(query: string, value: string): string | undefined;
2
3
  //# sourceMappingURL=highlight-text-for-search.d.ts.map
@@ -1 +1 @@
1
- import{HIGHLIGHTED_TEXT_MAX_LENGTH as l}from"../../constants/plugins/search.js";const h=i=>i.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function m(i,n){if(!n)return"";const o=[...new Set(i.split(/\s+/g).filter(Boolean))].sort((t,e)=>e.length-t.length);if(!o.length)return n;const a=new RegExp(`(^|\\s)(${o.map(h).join("|")})`,"gi");let s=n,g="",c="";if(n.length>l){const t=a.exec(n);a.lastIndex=0;const e=Math.max(0,(t?.index??0)-l/2),r=Math.min(n.length,e+l);s=n.substring(e,r),g=e>0?"...":"",c=r<n.length?"...":""}return g+s.replace(a,(t,e,r)=>`${e}<mark>${r}</mark>`)+c}export{m as highlightTextForSearch};
1
+ import{HIGHLIGHTED_TEXT_MAX_LENGTH as f}from"../../constants/plugins/search.js";import{MIN_INFIX_MATCH_LENGTH as h,MIN_QUERY_WORD_LENGTH as g,isWordChar as c,matchableQueryWords as m}from"./text-match.js";function w(t,e){if(!e)return"";const r=p(t);if(!r.length)return e;const n=f+t.length;if(e.length<=n)return u(r,e);const o=M(l(r,e),n)??{start:0,end:0},{start:s,end:d}=_(e,o,n),a=u(r,e.slice(s,d));return`${s>0?"...":""}${a}${d<e.length?"...":""}`}function I(t,e){if(!e)return;const r=w(t,e);return r.includes("<mark>")?r:void 0}function p(t){return m(t).sort((e,r)=>r.length-e.length)}function l(t,e){const r=e.toLowerCase(),n=[];for(const o of t)for(let s=r.indexOf(o);s!==-1;s=r.indexOf(o,s+1)){const d=!c(r[s-1]);if(!d&&o.length<h||o.length<g&&c(r[s+o.length]))continue;let a=s+o.length;if(d)for(;c(r[a]);)a++;n.push({start:s,end:a,word:o})}return n.sort((o,s)=>o.start-s.start||o.end-s.end)}function M(t,e){let r;for(let n=0;n<t.length;n++){const o=new Set;let s=t[n].end;for(let a=n;a<t.length&&t[a].end-t[n].start<=e;a++)o.has(t[a].word)||(o.add(t[a].word),s=t[a].end);const d=s-t[n].start;(!r||o.size>r.count||o.size===r.count&&d<r.end-r.start)&&(r={start:t[n].start,end:s,count:o.size})}return r&&{start:r.start,end:r.end}}function _(t,e,r){const n=Math.max(r,e.end-e.start),o=n-(e.end-e.start),s=Math.min(t.length,Math.max(0,Math.floor(e.start-o/2))+n),d=Math.max(0,s-n);return{start:H(t,d,e.start),end:T(t,s,e.end)}}function H(t,e,r){let n=e;if(n>0&&!i(t[n-1]))for(;n<r&&!i(t[n]);)n++;for(;n<r&&i(t[n]);)n++;return n}function T(t,e,r){let n=e;if(n<t.length&&!i(t[n]))for(;n>r&&!i(t[n]);)n--;for(;n>r&&i(t[n-1]);)n--;return n}function i(t){return t!==void 0&&/\s/.test(t)}function u(t,e){const r=l(t,e);if(!r.length)return e;const n=[];for(const d of r){const a=n[n.length-1];a&&(d.start<=a.end||!e.slice(a.end,d.start).trim())?a.end=Math.max(a.end,d.end):n.push({start:d.start,end:d.end})}let o="",s=0;for(const d of n)o+=`${e.slice(s,d.start)}<mark>${e.slice(d.start,d.end)}</mark>`,s=d.end;return o+e.slice(s)}export{w as highlightTextForSearch,I as markMatchedValue};
@@ -0,0 +1,6 @@
1
+ export declare const MIN_QUERY_WORD_LENGTH = 2;
2
+ export declare const MIN_INFIX_MATCH_LENGTH = 3;
3
+ export declare function isWordChar(char: string | undefined): boolean;
4
+ export declare function matchableQueryWords(query: string): string[];
5
+ export declare function containsQueryWord(lowered: string, word: string): boolean;
6
+ //# sourceMappingURL=text-match.d.ts.map
@@ -0,0 +1 @@
1
+ const i=2,o=3,r=/[\p{L}\p{N}_-]/u;function _(t){return t!==void 0&&r.test(t)}function s(t){const n=[...new Set(t.toLowerCase().split(/\s+/g).filter(Boolean))];return n.some(e=>e.length>=2)?n:[]}function u(t,n){if(n.length>=3)return t.includes(n);for(let e=t.indexOf(n);e!==-1;e=t.indexOf(n,e+1))if(!_(t[e-1])&&(n.length>=2||!_(t[e+n.length])))return!0;return!1}export{o as MIN_INFIX_MATCH_LENGTH,i as MIN_QUERY_WORD_LENGTH,u as containsQueryWord,_ as isWordChar,s as matchableQueryWords};
@@ -1 +1 @@
1
- import{RbacFeatures as d}from"../../../constants/common.js";import{ASK_AI_API_URL as h,AI_ASSISTANT_ESCALATIONS_API_URL as p,AI_ASSISTANT_FEEDBACK_API_URL as f}from"../../constants/common.js";import{fetchWithClient as l}from"../../utils/fetch-with-client.js";import{canAccessFeature as S}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as T}from"../utils.js";import{isAiSearchEnabled as I}from"../../plugins/search/utils.js";function _(e,t){const n=t.getConfig();return I(n)?S(d.AI_SEARCH,e.get("auth"),n.access?.rbac,n.access?.requiresLogin)?null:T(e):e.newResponse(null,403,{})}function g(e){const t=e.get("auth"),n={"Content-Type":"application/json"},r=[];t.claims?.authCookie&&r.push(`authorization=${t.claims.authCookie}`),t.idpAccessToken&&r.push(`accessToken=${t.idpAccessToken}`),r.length>0&&(n.Cookie=r.join("; "));const i=e.req.header("Authorization");i&&(n.Authorization=i);const s=e.req.header(u);return s&&(n[u]=s),n}const m="x-redocly-ai-assistant-origin",u="x-redocly-ai-assistant-identity",A="x-redocly-ai-assistant-identity-status";function y(e){const t=e.req.header("Origin");if(t)return t;const n=e.req.header("Referer");if(n)try{return new URL(n).origin}catch{}return new URL(e.req.url).origin}function a({store:e,apiUrl:t,successContentType:n="application/json"}){return async r=>{if(!t)return r.newResponse(null,404);const i=_(r,e);if(i)return i;const s=g(r);s[m]=y(r);const o=await l(t,{method:"POST",body:JSON.stringify(await r.req.json()),headers:s}),c=o.headers.get(A);return r.newResponse(o.body,o.status,{"Content-Type":o.ok?n:"application/json",...c?{[A]:c}:{}})}}function U(e){return a({store:e,apiUrl:h,successContentType:"text/event-stream"})}function b(e){return a({store:e,apiUrl:p})}function q(e){return a({store:e,apiUrl:f})}export{A as AI_ASSISTANT_IDENTITY_STATUS_HEADER,b as aiAssistantEscalationsHandler,q as aiAssistantFeedbackHandler,U as askAiHandler};
1
+ import{RbacFeatures as d}from"../../../constants/common.js";import{ASK_AI_API_URL as h,AI_ASSISTANT_ESCALATIONS_API_URL as l,AI_ASSISTANT_FEEDBACK_API_URL as T}from"../../constants/common.js";import{fetchWithClient as S}from"../../utils/fetch-with-client.js";import{canAccessFeature as m}from"../../utils/rbac.js";import{handleUnauthorizedApiRequest as I}from"../utils.js";import{isAiSearchEnabled as _}from"../../plugins/search/utils.js";import{createAssistantAnonymousToken as y}from"../../plugins/mcp/auth/assistant-anonymous-token.js";import{isMcpContentProtected as g}from"../../plugins/mcp/auth/auth-handlers.js";function E(e,i){const t=i.getConfig();return _(t)?m(d.AI_SEARCH,e.get("auth"),t.access?.rbac,t.access?.requiresLogin)?null:I(e):e.newResponse(null,403,{})}async function R(e,{mintsAnonymousMcpToken:i}){const t=e.get("auth"),r={"Content-Type":"application/json"},n=[];t.claims?.authCookie&&n.push(`authorization=${t.claims.authCookie}`),t.idpAccessToken&&n.push(`accessToken=${t.idpAccessToken}`),n.length>0&&(r.Cookie=n.join("; "));const s=e.req.header(p);s&&(r[p]=s);const a=e.req.header("Authorization");if(a)r.Authorization=a;else if(i&&n.length===0&&!s){const o=await y();o&&(r.Authorization=`Bearer ${o}`)}return r}const k="x-redocly-ai-assistant-origin",p="x-redocly-ai-assistant-identity",f="x-redocly-ai-assistant-identity-status";function C(e){const i=e.req.header("Origin");if(i)return i;const t=e.req.header("Referer");if(t)try{return new URL(t).origin}catch{}return new URL(e.req.url).origin}function u({store:e,apiUrl:i,successContentType:t="application/json",reachesMcp:r=!1}){return async n=>{if(!i)return n.newResponse(null,404);const s=E(n,e);if(s)return s;const a=r&&g(e),o=await R(n,{mintsAnonymousMcpToken:a});o[k]=C(n);const c=await S(i,{method:"POST",body:JSON.stringify(await n.req.json()),headers:o}),A=c.headers.get(f);return n.newResponse(c.body,c.status,{"Content-Type":c.ok?t:"application/json",...A?{[f]:A}:{}})}}function D(e){return u({store:e,apiUrl:h,successContentType:"text/event-stream",reachesMcp:!0})}function O(e){return u({store:e,apiUrl:l})}function P(e){return u({store:e,apiUrl:T})}export{f as AI_ASSISTANT_IDENTITY_STATUS_HEADER,O as aiAssistantEscalationsHandler,P as aiAssistantFeedbackHandler,D as askAiHandler};
@@ -1 +1 @@
1
- import{combineUrls as b,withPathPrefix as u}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as S,MCP_PROTOCOL_VERSION as T}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as g}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as v}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as M,FETCH_TOOL_NAME as O}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as R}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as L}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{normalizeToolDisplayName as y}from"../../../plugins/mcp/utils/tool-registration.js";import{buildCodeModeInstructions as D,buildExecuteDescription as I}from"../../../plugins/mcp/codemode/prompts.js";import{toToolListEntries as P}from"../../../plugins/mcp/codemode/build-tool-list.js";import{composeExecuteAnnotations as U}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as V}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as H}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as x}from"../../../utils/rbac/should-handle-mcp-auth.js";import{resolvePublicBaseUrl as N}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as w}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as j}from"./constants.js";const k="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",q="1.0";function ne(r){const s=v(),C=new Date().toISOString().slice(0,10);return async m=>await w("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(),a=o.mcp?.docs?.name||S,n=r.getMcpTools().filter(t=>!M.has(t.name)&&!t.hasAvailabilityGate),i=H(o.mcp)?[...V]:[],l=i.some(t=>t.id===O),d=P(n,i),c=(s?[{...R,description:I(l,d),annotations:U(i)},L(n,i)]:n).map(y).map(({name:t,title:f,description:h,schema:_,annotations:A})=>({name:t,title:f,description:h,inputSchema:_,annotations:A})),E=o.skills?.hide===!0?[]:r.getSkills(),p={$schema:k,version:q,protocolVersion:T,serverInfo:{name:a,title:a,version:C},description:o.seo?.description,documentationUrl:b(N(r,m),u("/")),transport:{type:"streamable-http",endpoint:u(g.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...E.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:x(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:j}:void 0,instructions:s?D(l,d):void 0,tools:c.length>0?c:["dynamic"]};return e?.setAttribute("mode",s?"code":"tools"),e?.setAttribute("toolsCount",c.length),e?.setAttribute("authRequired",p.authentication!==void 0),m.json(p,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{ne as mcpServerCardHandler};
1
+ import{combineUrls as b,withPathPrefix as u}from"@redocly/theme/core/utils";import{DEFAULT_DOCS_MCP_SERVER_NAME as S,MCP_PROTOCOL_VERSION as T}from"../../../plugins/mcp/constants.js";import{RESERVED_ROUTES as g}from"../../../plugins/get-reserved-routes.js";import{isMcpCodeModeEnabled as v}from"../../../plugins/mcp/utils/mode.js";import{CODE_MODE_TOOL_NAMES as M,FETCH_TOOL_NAME as O}from"../../../plugins/mcp/codemode/constants.js";import{EXECUTE_TOOL_SCHEMA as R}from"../../../plugins/mcp/codemode/tools/execute-schema.js";import{describeToolsSchema as L}from"../../../plugins/mcp/codemode/tools/describe-tools.js";import{normalizeToolDisplayName as y}from"../../../plugins/mcp/utils/tool-registration.js";import{buildCodeModeInstructions as D,buildExecuteDescription as I}from"../../../plugins/mcp/codemode/prompts.js";import{toToolListEntries as P}from"../../../plugins/mcp/codemode/build-tool-list.js";import{composeExecuteAnnotations as U}from"../../../plugins/mcp/codemode/capabilities/index.js";import{ALL_CAPABILITIES as V}from"../../../plugins/mcp/codemode/capabilities/registry.js";import{isGatewayCapabilityEnabled as H}from"../../../plugins/mcp/gateway-mcp/eligibility.js";import{shouldHandleMcpAuth as x}from"../../../utils/rbac/should-handle-mcp-auth.js";import{resolvePublicBaseUrl as N}from"../../../web-server/utils/resolve-public-base-url.js";import{telemetryTraceStep as w}from"../../../telemetry/helpers/trace-step.js";import{MCP_AUTH_SCHEMES as j}from"./constants.js";const k="https://static.modelcontextprotocol.io/schemas/mcp-server-card/v1.json",q="1.0";function ne(r){const n=v(),C=new Date().toISOString().slice(0,10);return async m=>await w("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(),a=o.mcp?.docs?.name||S,i=r.getMcpTools().filter(t=>!M.has(t.name)&&!t.hasAvailabilityGate),s=H(o.mcp)?[...V]:[],l=s.some(t=>t.id===O),d=P(i,s),c=(n?[{...R,description:I(l,d),annotations:U(i,s)},L(i,s)]:i).map(y).map(({name:t,title:f,description:h,schema:_,annotations:A})=>({name:t,title:f,description:h,inputSchema:_,annotations:A})),E=o.skills?.hide===!0?[]:r.getSkills(),p={$schema:k,version:q,protocolVersion:T,serverInfo:{name:a,title:a,version:C},description:o.seo?.description,documentationUrl:b(N(r,m),u("/")),transport:{type:"streamable-http",endpoint:u(g.mcp)},capabilities:{logging:{},tools:{listChanged:!0},...E.length>0?{resources:{listChanged:!0},completions:{}}:{}},authentication:x(!!o.access?.requiresLogin,o.access?.rbac)?{required:!0,schemes:j}:void 0,instructions:n?D(l,d):void 0,tools:c.length>0?c:["dynamic"]};return e?.setAttribute("mode",n?"code":"tools"),e?.setAttribute("toolsCount",c.length),e?.setAttribute("authRequired",p.authentication!==void 0),m.json(p,200,{"Access-Control-Allow-Origin":"*","Cache-Control":"public, max-age=3600"})})}export{ne as mcpServerCardHandler};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@redocly/realm",
3
- "version": "0.138.0-next.1",
3
+ "version": "0.138.0-next.2",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {
@@ -33,13 +33,13 @@
33
33
  "@opentelemetry/sdk-trace-web": "2.8.0",
34
34
  "@opentelemetry/semantic-conventions": "1.40.0",
35
35
  "@redocly/ajv": "8.18.0",
36
- "@redocly/api-docs": "0.3.0-next.1",
36
+ "@redocly/api-docs": "0.3.0-next.2",
37
37
  "@redocly/config": "0.57.0",
38
38
  "@redocly/openapi-core": "2.53.0",
39
39
  "@redocly/portal-legacy-ui": "0.19.0",
40
40
  "@redocly/portal-plugin-mock-server": "0.22.0",
41
41
  "@redocly/realm-asyncapi-sdk": "0.16.0-next.0",
42
- "@redocly/theme": "0.70.0-next.1",
42
+ "@redocly/theme": "0.70.0-next.2",
43
43
  "@shikijs/transformers": "3.21.0",
44
44
  "@tanstack/react-query": "5.62.3",
45
45
  "@tanstack/react-table": "8.21.3",