@redocly/reef 0.132.0-next.5 → 0.132.0-next.7

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 (126) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/dist/cli/telemetry/index.js +1 -1
  3. package/dist/client/App.js +1 -1
  4. package/dist/client/app/CircularProgress.js +8 -8
  5. package/dist/client/app/hooks/utils/match-banner-target.d.ts +23 -1
  6. package/dist/client/app/hooks/utils/match-banner-target.js +1 -1
  7. package/dist/client/mcp-tool-handlers-entry.d.ts +3 -0
  8. package/dist/client/mcp-tool-handlers-entry.js +1 -0
  9. package/dist/client/templates/asyncapi-docs/helpers.d.ts +1 -1
  10. package/dist/client/types/ai-search.d.ts +5 -3
  11. package/dist/constants/l10n/langs/ar.js +1 -1
  12. package/dist/constants/l10n/langs/de.js +1 -1
  13. package/dist/constants/l10n/langs/en.js +1 -1
  14. package/dist/constants/l10n/langs/es.js +1 -1
  15. package/dist/constants/l10n/langs/fr.js +1 -1
  16. package/dist/constants/l10n/langs/hi.js +1 -1
  17. package/dist/constants/l10n/langs/it.js +1 -1
  18. package/dist/constants/l10n/langs/ja.js +1 -1
  19. package/dist/constants/l10n/langs/ko.js +1 -1
  20. package/dist/constants/l10n/langs/pl.js +1 -1
  21. package/dist/constants/l10n/langs/pt-BR.js +1 -1
  22. package/dist/constants/l10n/langs/pt.js +1 -1
  23. package/dist/constants/l10n/langs/ru.js +1 -1
  24. package/dist/constants/l10n/langs/uk.js +1 -1
  25. package/dist/constants/l10n/langs/zh.js +1 -1
  26. package/dist/markdoc/nodes/fence/index.js +1 -1
  27. package/dist/markdoc/nodes/index.d.ts +1 -1
  28. package/dist/markdoc/nodes/index.js +1 -1
  29. package/dist/server/api-routes/run-api-routes-worker.js +1 -1
  30. package/dist/server/config/env-schema.d.ts +6 -3
  31. package/dist/server/config/env-schemas/api-urls.d.ts +3 -3
  32. package/dist/server/config/env-schemas/api-urls.js +1 -1
  33. package/dist/server/config/env-schemas/auth.d.ts +3 -0
  34. package/dist/server/config/env-schemas/auth.js +1 -1
  35. package/dist/server/esbuild/esbuild.js +3 -3
  36. package/dist/server/esbuild/plugins/codegen/index.d.ts +1 -0
  37. package/dist/server/esbuild/plugins/codegen/index.js +7 -3
  38. package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.d.ts +7 -0
  39. package/dist/server/esbuild/plugins/mcp-tool-handlers-resolver.js +1 -0
  40. package/dist/server/plugins/catalog-entities/plugin.js +1 -1
  41. package/dist/server/plugins/config-parser/index.js +1 -1
  42. package/dist/server/plugins/config-parser/loaders/content-slugs-loader.js +1 -1
  43. package/dist/server/plugins/default-theme/resolve-products-config.js +1 -1
  44. package/dist/server/plugins/dev-onboarding/api/adapter-factory.d.ts +10 -3
  45. package/dist/server/plugins/dev-onboarding/api/adapter-factory.js +1 -1
  46. package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.d.ts +5 -4
  47. package/dist/server/plugins/dev-onboarding/api/adapters/apigee/adapter.js +4 -4
  48. package/dist/server/plugins/dev-onboarding/api/adapters/gravitee/client.d.ts +3 -3
  49. package/dist/server/plugins/dev-onboarding/api/adapters/gravitee/client.js +1 -1
  50. package/dist/server/plugins/dev-onboarding/api/middlewares/integrations.d.ts +3 -2
  51. package/dist/server/plugins/dev-onboarding/api/middlewares/integrations.js +1 -1
  52. package/dist/server/plugins/dev-onboarding/api/routes/index.js +1 -1
  53. package/dist/server/plugins/dev-onboarding/api/types.d.ts +8 -0
  54. package/dist/server/plugins/dev-onboarding/template/components/ApiLogsActions.js +5 -5
  55. package/dist/server/plugins/dev-onboarding/template/components/DialogStyledComponents.js +1 -1
  56. package/dist/server/plugins/dev-onboarding/template/components/MultiSelect.js +1 -1
  57. package/dist/server/plugins/dev-onboarding/template/components/TextField.js +3 -3
  58. package/dist/server/plugins/enforce-login/index.js +1 -1
  59. package/dist/server/plugins/lifecycle.js +2 -2
  60. package/dist/server/plugins/markdown/attribute-resolvers/index.js +1 -1
  61. package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.d.ts +4 -0
  62. package/dist/server/plugins/markdown/attribute-resolvers/resolve-diagram-from-file.js +1 -0
  63. package/dist/server/plugins/markdown/attribute-resolvers/resolve-native-md-link.js +1 -1
  64. package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +1 -1
  65. package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.d.ts +16 -0
  66. package/dist/server/plugins/markdown/markdoc/plugins/render-diagrams.js +1 -0
  67. package/dist/server/plugins/markdown/runtime-transform.js +1 -1
  68. package/dist/server/plugins/markdown/search/to-markdown.js +24 -16
  69. package/dist/server/plugins/markdown/search/walk-sections.js +1 -1
  70. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.d.ts +7 -0
  71. package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -0
  72. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.d.ts +5 -9
  73. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoint-info.js +1 -1
  74. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.d.ts +5 -9
  75. package/dist/server/plugins/mcp/docs-mcp/tools/get-endpoints.js +1 -1
  76. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.d.ts +5 -9
  77. package/dist/server/plugins/mcp/docs-mcp/tools/get-full-api-description.js +1 -1
  78. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.d.ts +5 -9
  79. package/dist/server/plugins/mcp/docs-mcp/tools/get-security-schemes.js +1 -1
  80. package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.d.ts +4 -0
  81. package/dist/server/plugins/mcp/docs-mcp/tools/helpers/load-api-description.js +1 -0
  82. package/dist/server/plugins/mcp/docs-mcp/tools/index.d.ts +10 -7
  83. package/dist/server/plugins/mcp/docs-mcp/tools/index.js +1 -1
  84. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.d.ts +5 -9
  85. package/dist/server/plugins/mcp/docs-mcp/tools/list-apis.js +1 -1
  86. package/dist/server/plugins/mcp/docs-mcp/tools/search.d.ts +5 -10
  87. package/dist/server/plugins/mcp/docs-mcp/tools/search.js +3 -3
  88. package/dist/server/plugins/mcp/docs-mcp/tools/utils.d.ts +6 -3
  89. package/dist/server/plugins/mcp/docs-mcp/tools/utils.js +6 -6
  90. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.d.ts +5 -9
  91. package/dist/server/plugins/mcp/docs-mcp/tools/whoami.js +1 -1
  92. package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
  93. package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
  94. package/dist/server/plugins/mcp/index.js +1 -1
  95. package/dist/server/plugins/mcp/servers/docs-server.d.ts +13 -22
  96. package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
  97. package/dist/server/plugins/mcp/types.d.ts +24 -56
  98. package/dist/server/plugins/mcp/workers/execute-mcp-tool.d.ts +2 -2
  99. package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
  100. package/dist/server/plugins/openapi-docs/index.js +1 -1
  101. package/dist/server/plugins/openapi-docs/search-indexer.js +1 -1
  102. package/dist/server/store.d.ts +5 -2
  103. package/dist/server/store.js +1 -1
  104. package/dist/server/telemetry/index.js +1 -1
  105. package/dist/server/types/plugins/common.d.ts +15 -2
  106. package/dist/server/types/redirects.d.ts +6 -0
  107. package/dist/server/utils/rbac.js +1 -1
  108. package/dist/server/utils/redirects/find-redirect.d.ts +8 -31
  109. package/dist/server/utils/redirects/find-redirect.js +1 -1
  110. package/dist/server/utils/redirects/follow-redirect-chain.d.ts +9 -0
  111. package/dist/server/utils/redirects/follow-redirect-chain.js +1 -0
  112. package/dist/server/utils/redirects/validate-redirects.d.ts +8 -0
  113. package/dist/server/utils/redirects/validate-redirects.js +1 -0
  114. package/dist/server/web-server/routes/otel/otel.js +1 -1
  115. package/dist/server/workers/types.d.ts +2 -2
  116. package/dist/server/workers/worker-pool.js +1 -1
  117. package/dist/types/global-data.d.ts +7 -2
  118. package/package.json +10 -10
  119. package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.d.ts +0 -4
  120. package/dist/server/plugins/markdown/markdoc/plugins/render-mermaid.js +0 -1
  121. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.d.ts +0 -55
  122. package/dist/server/plugins/mcp/docs-mcp/tools/docs-mcp-tool.js +0 -1
  123. package/dist/server/plugins/mcp/handlers/mcp-request-handler.d.ts +0 -11
  124. package/dist/server/plugins/mcp/handlers/mcp-request-handler.js +0 -1
  125. package/dist/server/plugins/mcp/servers/base-server.d.ts +0 -17
  126. package/dist/server/plugins/mcp/servers/base-server.js +0 -1
@@ -1,10 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class GetEndpointsTool extends DocsMcpTool<'get-endpoints'> {
4
- readonly name = "get-endpoints";
5
- readonly description = "Get all endpoints for a specific API";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor();
8
- protected executeAction(args: ToolArgsMap['get-endpoints'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ 'get-endpoints': McpToolHandler;
4
+ };
5
+ export default _default;
10
6
  //# sourceMappingURL=get-endpoints.d.ts.map
@@ -1 +1 @@
1
- import{DocsMcpTool as r}from"./docs-mcp-tool.js";import{getEndpointsFromPaths as c}from"./utils.js";const p={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class u extends r{name="get-endpoints";description="Get all endpoints for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(p)}async executeAction(o,i){const{name:s}=o,t=await this.getApiDefinition(s,i);if(!t.success)return t.response;const{definition:e}=t,n=c(e);return n.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:e.info?.title||"",version:e.info?.version||"",servers:e.servers||[],endpoints:n},null,2)}]}}}export{u as GetEndpointsTool};
1
+ import{loadApiDescription as s}from"./helpers/load-api-description.js";import{getEndpointsFromPaths as p}from"./utils.js";const c=async(n,r)=>{const{name:o}=n;let t;try{t=await s(o,r)}catch(i){return{content:[{type:"text",text:i.message}],isError:!0}}const e=p(t);return e.length===0?{content:[{type:"text",text:"No endpoints found"}]}:{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",servers:t.servers||[],endpoints:e},null,2)}]}};var f={"get-endpoints":c};export{f as default};
@@ -1,10 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class GetFullApiDescriptionTool extends DocsMcpTool<'get-full-api-description'> {
4
- readonly name = "get-full-api-description";
5
- readonly description = "Get the complete OpenAPI description";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor();
8
- protected executeAction(args: ToolArgsMap['get-full-api-description'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ 'get-full-api-description': McpToolHandler;
4
+ };
5
+ export default _default;
10
6
  //# sourceMappingURL=get-full-api-description.d.ts.map
@@ -1 +1 @@
1
- import{DocsMcpTool as s}from"./docs-mcp-tool.js";const r={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class a extends s{name="get-full-api-description";description="Get the complete OpenAPI description";requiredContext=["outdir","accessInfo"];constructor(){super(r)}async executeAction(i,n){const{name:o}=i,e=await this.getApiDefinition(o,n);if(!e.success)return e.response;const{definition:t}=e;return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}}}export{a as GetFullApiDescriptionTool};
1
+ import{loadApiDescription as o}from"./helpers/load-api-description.js";const s=async(e,i)=>{const{name:n}=e;let t;try{t=await o(n,i)}catch(r){return{content:[{type:"text",text:r.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({api:t.info?.title||"",version:t.info?.version||"",definition:t},null,2)}]}};var c={"get-full-api-description":s};export{c as default};
@@ -1,10 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class GetSecuritySchemesTool extends DocsMcpTool<'get-security-schemes'> {
4
- readonly name = "get-security-schemes";
5
- readonly description = "Get the security schemes for a specific API";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor();
8
- protected executeAction(args: ToolArgsMap['get-security-schemes'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ 'get-security-schemes': McpToolHandler;
4
+ };
5
+ export default _default;
10
6
  //# sourceMappingURL=get-security-schemes.d.ts.map
@@ -1 +1 @@
1
- import{DocsMcpTool as c}from"./docs-mcp-tool.js";const o={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"API name",minLength:1}}};class p extends c{name="get-security-schemes";description="Get the security schemes for a specific API";requiredContext=["outdir","accessInfo"];constructor(){super(o)}async executeAction(s,i){const{name:n}=s,t=await this.getApiDefinition(n,i);if(!t.success)return t.response;const{definition:e}=t;return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}}}export{p as GetSecuritySchemesTool};
1
+ import{loadApiDescription as n}from"./helpers/load-api-description.js";const c=async(t,r)=>{const{name:s}=t;let e;try{e=await n(s,r)}catch(i){return{content:[{type:"text",text:i.message}],isError:!0}}return{content:[{type:"text",text:JSON.stringify({name:e.info?.title,version:e.info?.version,securitySchemes:e.components?.securitySchemes||[],security:e.security||[]},null,2)}]}};var u={"get-security-schemes":c};export{u as default};
@@ -0,0 +1,4 @@
1
+ import type { OpenAPIDefinition } from '@redocly/openapi-docs';
2
+ import type { McpToolContext } from '../../../types.js';
3
+ export declare function loadApiDescription(name: string, context: McpToolContext): Promise<OpenAPIDefinition>;
4
+ //# sourceMappingURL=load-api-description.d.ts.map
@@ -0,0 +1 @@
1
+ import{findApiDescriptionByName as c}from"../../utils.js";import{getApiDescriptionFromFs as t}from"../utils.js";async function f(r,i){const o=c(i.apiDescriptionsMap,r);if(!o)throw new Error(`No API found matching "${r}".`);const n=!!i?.config?.access?.requiresLogin,e=i?.config?.access?.rbac||{},s=await t({relativePath:o.relativePath||"",outdir:i.outdir||"",user:i.user,rbac:e,requiresLogin:n});if(!s)throw new Error(`No API found matching "${r}".`);return s}export{f as loadApiDescription};
@@ -1,8 +1,11 @@
1
- import type { ToolArgsMap } from '../../types.js';
2
- import type { DocsMcpTool, DocsMcpToolRegistrationOptions } from './docs-mcp-tool.js';
3
- export declare const docsTools: DocsMcpTool<keyof ToolArgsMap>[];
4
- export declare function registerDocsTools(options: DocsMcpToolRegistrationOptions): void;
5
- export declare function getDocsTool<T extends keyof ToolArgsMap>(name: T): DocsMcpTool<T> | undefined;
6
- export { DocsMcpTool } from './docs-mcp-tool.js';
7
- export type { DocsMcpToolRegistrationOptions } from './docs-mcp-tool.js';
1
+ declare const _default: {
2
+ whoami: import("../../types.js").McpToolHandler;
3
+ search: import("../../types.js").McpToolHandler;
4
+ 'get-full-api-description': import("../../types.js").McpToolHandler;
5
+ 'get-security-schemes': import("../../types.js").McpToolHandler;
6
+ 'get-endpoint-info': import("../../types.js").McpToolHandler;
7
+ 'get-endpoints': import("../../types.js").McpToolHandler;
8
+ 'list-apis': import("../../types.js").McpToolHandler;
9
+ };
10
+ export default _default;
8
11
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- import{GetEndpointInfoTool as t}from"./get-endpoint-info.js";import{GetEndpointsTool as n}from"./get-endpoints.js";import{GetFullApiDescriptionTool as i}from"./get-full-api-description.js";import{GetSecuritySchemesTool as m}from"./get-security-schemes.js";import{ListApisTool as s}from"./list-apis.js";import{SearchTool as c}from"./search.js";import{WhoAmITool as p}from"./whoami.js";import{shouldHandleMcpAuth as f}from"../../auth/auth-handlers.js";const e=[new s,new n,new t,new m,new i,new c,new p],l=e.reduce((o,r)=>(o[r.name]=r,o),{});function A(o){e.forEach(r=>{r.name==="whoami"&&!f(o.accessInfo.requiresLogin,o.accessInfo.rbac)||r.register(o)})}function D(o){return l[o]}import{DocsMcpTool as E}from"./docs-mcp-tool.js";export{E as DocsMcpTool,e as docsTools,D as getDocsTool,A as registerDocsTools};
1
+ import o from"./list-apis.js";import r from"./get-endpoints.js";import t from"./get-endpoint-info.js";import i from"./get-security-schemes.js";import m from"./get-full-api-description.js";import p from"./search.js";import e from"./whoami.js";var d={...o,...r,...t,...i,...m,...p,...e};export{d as default};
@@ -1,10 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class ListApisTool extends DocsMcpTool<'list-apis'> {
4
- readonly name = "list-apis";
5
- readonly description = "Lists available APIs with their context and purpose";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor();
8
- protected executeAction(args: ToolArgsMap['list-apis'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ 'list-apis': McpToolHandler;
4
+ };
5
+ export default _default;
10
6
  //# sourceMappingURL=list-apis.d.ts.map
@@ -1 +1 @@
1
- import{filterApiDescriptionsByName as u}from"../utils.js";import{DocsMcpTool as m}from"./docs-mcp-tool.js";const d={type:"object",additionalProperties:!1,required:[],properties:{filter:{type:"string",description:"API name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of APIs per page. Default is 300",minimum:1,default:300,nullable:!0}}};class y extends m{name="list-apis";description="Lists available APIs with their context and purpose";requiredContext=[];constructor(){super(d)}async executeAction(s,o){const{filter:i,page:n=1,limit:e=300}=s;let t=Object.values(o.apiDescriptionsMap);i&&(t=u(t,i));const r=(n-1)*e,a=r+e,l=Math.ceil(t.length/e),p=t.length;return t=t.slice(r,a),t.length===0?{content:[{type:"text",text:"No APIs available"}]}:{content:[{type:"text",text:JSON.stringify({items:t.map(({relativePath:b,...c})=>c),limit:e,total:p,page:n,totalPages:l})}]}}}export{y as ListApisTool};
1
+ import{filterApiDescriptionsByName as f}from"../utils.js";const x=async(a,l)=>{const{filter:i,page:n=1,limit:e=300}=a;let t=Object.values(l.apiDescriptionsMap);i&&(t=f(t,i));const s=(n-1)*e,o=s+e,r=Math.ceil(t.length/e),c=t.length;return t=t.slice(s,o),t.length===0?{content:[{type:"text",text:"No APIs available"}]}:{content:[{type:"text",text:JSON.stringify({items:t.map(({relativePath:g,...p})=>p),limit:e,total:c,page:n,totalPages:r})}]}};var m={"list-apis":x};export{m as default};
@@ -1,11 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type DocsMcpToolRegistrationOptions, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class SearchTool extends DocsMcpTool<'search'> {
4
- readonly name = "search";
5
- readonly description = "Search across the documentation to fetch relevant content for a given query";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor(products?: string[]);
8
- register(options: DocsMcpToolRegistrationOptions): void;
9
- protected executeAction(args: ToolArgsMap['search'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
10
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ search: McpToolHandler;
4
+ };
5
+ export default _default;
11
6
  //# sourceMappingURL=search.d.ts.map
@@ -1,6 +1,6 @@
1
- import{withPathPrefix as f}from"@redocly/theme/core/utils";import{ServerRoutes as y}from"../../../../../constants/common.js";import{DocsMcpTool as m}from"./docs-mcp-tool.js";class b extends m{name="search";description="Search across the documentation to fetch relevant content for a given query";requiredContext=["baseUrl","headers","products"];constructor(t){super(h(t))}register(t){this.schema=h(t.products),super.register(t)}async executeAction(t,r){const{query:p,product:l}=t;if(!r.baseUrl)throw new Error("Missing required context: baseUrl");const d=JSON.stringify({query:p,product:l});let n=`${r.baseUrl}${f(y.SEMANTIC_SEARCH)}`;n.startsWith("http://")&&(n=n.replace(/^http:\/\//,"https://"));const i=r.headers?.authorization,a=i?`authorization=${String(i).replace(/^Bearer /,"")}`:"";try{const c=await fetch(n,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...a?{Cookie:a}:{}},body:d});if(!c.ok)return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0};const o=await c.json();if(!o||o.length===0)return{content:[{type:"text",text:"No results found."}]};const u=o.map(s=>`### [${s.title}](${new URL(s.url,r.baseUrl).toString()})
1
+ import{withPathPrefix as l}from"@redocly/theme/core/utils";import{ServerRoutes as h}from"../../../../../constants/common.js";const d=async(c,t)=>{const{query:a,product:u}=c,p=JSON.stringify({query:a,product:u});let e=`${t.baseUrl}${l(h.SEMANTIC_SEARCH)}`;e.startsWith("http://")&&(e=e.replace(/^http:\/\//,"https://"));const o=t.user.idpAccessToken?`authorization=${String(t.user.idpAccessToken).replace(/^Bearer /,"")}`:"";try{const s=await fetch(e,{method:"POST",credentials:"include",headers:{"Content-Type":"application/json",...o?{Cookie:o}:{}},body:p});if(!s.ok)return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0};const r=await s.json();if(!r||r.length===0)return{content:[{type:"text",text:"No results found."}]};const i=r.map(n=>`### [${n.title}](${new URL(n.url,t.baseUrl).toString()})
2
2
 
3
- ${s.content}
3
+ ${n.content}
4
4
  `).join(`
5
5
 
6
- `).trim();return{content:[{type:"text",text:u.length?u:"No results found."}]}}catch{return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0}}}}function h(e){const t=e&&e.length>0;return{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1},...t?{product:{type:"string",description:"Optional product name to filter search results by specific product.",enum:e,nullable:!0}}:{}}}}export{b as SearchTool};
6
+ `).trim();return{content:[{type:"text",text:i.length?i:"No results found."}]}}catch{return{content:[{type:"text",text:"Error retrieving search results."}],isError:!0}}};var m={search:d};export{m as default};
@@ -1,6 +1,7 @@
1
1
  import type { OpenAPIDefinition, OpenAPIOperation } from '@redocly/openapi-docs';
2
2
  import type { SearchItemData } from '@redocly/theme/core/types';
3
- import type { AccessInfo, McpEndpoint } from '../../types';
3
+ import type { ApiFunctionsUser, RbacConfig } from '@redocly/config';
4
+ import type { McpEndpoint } from '../../types';
4
5
  export declare function isMcpEndpoint(value: unknown): value is McpEndpoint;
5
6
  type EndpointInfo = Pick<OpenAPIOperation, 'summary' | 'description' | 'security'> & {
6
7
  method: string;
@@ -8,10 +9,12 @@ type EndpointInfo = Pick<OpenAPIOperation, 'summary' | 'description' | 'security
8
9
  };
9
10
  export declare function getEndpointsFromPaths(def: OpenAPIDefinition): EndpointInfo[];
10
11
  export declare function processDocuments(documents: Record<string, SearchItemData[]>, outdir: string): string;
11
- export declare function getApiDescriptionFromFs({ relativePath, outdir, accessInfo: { isAuthenticated, email, teams, rbac, requiresLogin }, }: {
12
+ export declare function getApiDescriptionFromFs({ relativePath, outdir, user, rbac, requiresLogin, }: {
12
13
  relativePath: string;
13
14
  outdir: string;
14
- accessInfo: AccessInfo;
15
+ user: ApiFunctionsUser;
16
+ rbac?: RbacConfig;
17
+ requiresLogin?: boolean;
15
18
  }): Promise<OpenAPIDefinition | undefined>;
16
19
  export {};
17
20
  //# sourceMappingURL=utils.d.ts.map
@@ -1,11 +1,11 @@
1
- import y from"node:fs";import u from"node:path";import{existsSync as j}from"node:fs";import{readFile as A}from"node:fs/promises";import{replaceFileExtension as O}from"../../../../plugins/openapi-docs/store-definition-bundles";import{PUBLIC_API_DEFINITIONS_FOLDER as b}from"../../../../constants/common";import{filterDataByAccessDeep as g}from"../../../../utils/rbac";import{checkEndpointAndDeleteXMcp as E}from"../../utils/xmcp-utils.js";import{MAX_DOCUMENTS_PER_CATEGORY as F}from"../../constants.js";function N(e){return typeof e=="object"&&e!==null&&"responses"in e&&typeof e.responses=="object"}function T(e){const{paths:i={}}=e,s=[];for(const[c,r]of Object.entries(i)){const p=!E(r,"docs");for(const[a,t]of Object.entries(r))p||!E(t,"docs")||s.push({path:c,method:a.toUpperCase(),summary:t.summary,description:t.description,security:t.security})}return s}function R(e,i){return Object.entries(e).map(([c,r])=>{if(!r||r.length===0)return"";const p=r.slice(0,F).map(a=>{const{document:t,highlight:m}=a,d=m?.title||(Array.isArray(t.title)?t.title[0]:t.title);let o=`Document: ${t.title}`;o+=`### [${d}](${t.url})
1
+ import y from"node:fs";import d from"node:path";import{existsSync as D}from"node:fs";import{readFile as j}from"node:fs/promises";import{replaceFileExtension as O}from"../../../../plugins/openapi-docs/store-definition-bundles";import{PUBLIC_API_DEFINITIONS_FOLDER as b}from"../../../../constants/common";import{filterDataByAccessDeep as g}from"../../../../utils/rbac";import{checkEndpointAndDeleteXMcp as A}from"../../utils/xmcp-utils.js";import{MAX_DOCUMENTS_PER_CATEGORY as F}from"../../constants.js";function N(e){return typeof e=="object"&&e!==null&&"responses"in e&&typeof e.responses=="object"}function T(e){const{paths:s={}}=e,o=[];for(const[c,i]of Object.entries(s)){const r=!A(i,"docs");for(const[p,t]of Object.entries(i))r||!A(t,"docs")||o.push({path:c,method:p.toUpperCase(),summary:t.summary,description:t.description,security:t.security})}return o}function R(e,s){return Object.entries(e).map(([c,i])=>{if(!i||i.length===0)return"";const r=i.slice(0,F).map(p=>{const{document:t,highlight:f}=p,h=f?.title||(Array.isArray(t.title)?t.title[0]:t.title);let a=`Document: ${t.title}`;a+=`### [${h}](${t.url})
2
2
 
3
- `;let f;if(t.url)try{let n=t.url.startsWith("/")?t.url.slice(1):t.url;const l=n.indexOf("#");l!==-1&&(n=n.substring(0,l));const h=u.extname(n);h&&(n=n.slice(0,-h.length));let D=n+".md";const x=u.join(i,D);y.existsSync(x)&&(f=y.readFileSync(x,"utf8"))}catch{}return f||(f=m?.text||(Array.isArray(t.text)?t.text[0]:t.text)),o+=f,t.facets&&(o+=`
3
+ `;let m;if(t.url)try{let n=t.url.startsWith("/")?t.url.slice(1):t.url;const l=n.indexOf("#");l!==-1&&(n=n.substring(0,l));const u=d.extname(n);u&&(n=n.slice(0,-u.length));let E=n+".md";const x=d.join(s,E);y.existsSync(x)&&(m=y.readFileSync(x,"utf8"))}catch{}return m||(m=f?.text||(Array.isArray(t.text)?t.text[0]:t.text)),a+=m,t.facets&&(a+=`
4
4
 
5
5
  **Categories:**
6
- `,Object.entries(t.facets).forEach(([n,l])=>{o+=`- ${n}: ${l}
7
- `})),o});return`## ${c}
6
+ `,Object.entries(t.facets).forEach(([n,l])=>{a+=`- ${n}: ${l}
7
+ `})),a});return`## ${c}
8
8
 
9
- ${p}`}).join(`
9
+ ${r}`}).join(`
10
10
 
11
- `).trim()}async function U({relativePath:e,outdir:i,accessInfo:{isAuthenticated:s,email:c,teams:r,rbac:p={},requiresLogin:a=!1}}){const t=u.join(i||"",b,O(e,".json"));if(!j(t))return;const d=await A(t,"utf-8"),o=JSON.parse(d);return g(o,{isAuthenticated:s,email:c,teams:r},p,a)}export{U as getApiDescriptionFromFs,T as getEndpointsFromPaths,N as isMcpEndpoint,R as processDocuments};
11
+ `).trim()}async function U({relativePath:e,outdir:s,user:o,rbac:c={},requiresLogin:i=!1}){const r=d.join(s||"",b,O(e,".json"));if(!D(r))return;const t=await j(r,"utf-8"),f=JSON.parse(t);return g(f,{isAuthenticated:o?.isAuthenticated,email:o?.email,teams:o?.teams},c,i)}export{U as getApiDescriptionFromFs,T as getEndpointsFromPaths,N as isMcpEndpoint,R as processDocuments};
@@ -1,10 +1,6 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse, ToolArgsMap } from '../../types.js';
2
- import { DocsMcpTool, type ContextKey } from './docs-mcp-tool.js';
3
- export declare class WhoAmITool extends DocsMcpTool<'whoami'> {
4
- readonly name = "whoami";
5
- readonly description = "Get information about the currently authenticated user";
6
- readonly requiredContext: readonly ContextKey[];
7
- constructor();
8
- protected executeAction(_args: ToolArgsMap['whoami'], context: McpToolWorkerParams['context']): Promise<McpToolWorkerResponse>;
9
- }
1
+ import type { McpToolHandler } from '../../types.js';
2
+ declare const _default: {
3
+ whoami: McpToolHandler;
4
+ };
5
+ export default _default;
10
6
  //# sourceMappingURL=whoami.d.ts.map
@@ -1 +1 @@
1
- import{getUserInfoFromHeaders as r}from"../../utils/jwt.js";import{DocsMcpTool as o}from"./docs-mcp-tool.js";const n={type:"object",required:[],additionalProperties:!1,properties:{}};class u extends o{name="whoami";description="Get information about the currently authenticated user";requiredContext=["headers"];constructor(){super(n)}async executeAction(s,t){const e=r(t.headers||{});return e?{content:[{type:"text",text:JSON.stringify({email:e.email,name:e.name,subject:e.sub,clientId:e.client_id,scope:e.scope,issuedAt:e.iat?new Date(e.iat*1e3).toISOString():void 0,expiresAt:e.exp?new Date(e.exp*1e3).toISOString():void 0})}],isError:!1}:{content:[{type:"text",text:JSON.stringify({error:"Not authenticated",message:"No valid authentication token found. Please authenticate first."})}],isError:!0}}}export{u as WhoAmITool};
1
+ const s=async(i,e)=>e.user?.isAuthenticated?{content:[{type:"text",text:JSON.stringify({email:e.user.email,name:e.user.claims?.name,subject:e.user.claims?.sub,clientId:e.user.claims?.client_id,scope:e.user.claims?.scope,issuedAt:e.user.claims?.iat?new Date(Number(e.user.claims.iat)*1e3).toISOString():void 0,expiresAt:e.user.claims?.exp?new Date(Number(e.user.claims.exp)*1e3).toISOString():void 0})}],isError:!1}:{content:[{type:"text",text:JSON.stringify({error:"Not authenticated",message:"No valid authentication token found. Please authenticate first."})}],isError:!0};var r={whoami:s};export{r as default};
@@ -1 +1 @@
1
- import{createMcpRequestHandler as y}from"./mcp-request-handler.js";import{createDocsMcpServer as A}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as S}from"../utils.js";import{createInternalServerError as I}from"./errors.js";import{McpServerType as f}from"../constants.js";import{telemetry as d}from"../../../telemetry/index.js";import{constructInvalidTokenResponse as L,constructUnauthorizedResponse as R,handleMcpAuth as w,shouldHandleMcpAuth as T}from"../auth/auth-handlers.js";async function U(r,s,t,n){try{d.initialize();const e=s,a=e?.props?.config?.apiDescriptionsMap||{},i=e?.props?.outdir||"",c=e?.props?.config?.mcpDocsServerName||"Docs MCP server",l=new URL(n.url).origin,{user:o,config:{access:p,mcp:g={}}}=r,m=p?.rbac||{},u=p?.requiresLogin||!1,v=S(a,o,m,u),M=g.docs?.name||c,D=r.config.products?Object.values(r.config.products).map(b=>b?.name):[],h={rbac:m,email:o?.email,teams:o?.teams,isAuthenticated:!!o?.isAuthenticated,requiresLogin:u};return await A({name:M,baseUrl:l,headers:t,apiDescriptionsMap:v,outdir:i,accessInfo:h,products:D})}catch(e){throw d.sendMcpErrorMessage([{object:"mcp_server",server_type:f.Docs,message:e?.message||"",stack:e?.stack||""}]),I(e?.message||"Internal server error mcp docs")}}const k=y({createServerInstance:U,serverType:f.Docs}),H=async(r,s,t)=>{const n=!!s?.config?.access?.requiresLogin,e=s?.config?.access?.rbac;if(T(n,e)){const{isAuthenticated:a,isTokenValid:i,currentUser:c}=await w(r,s);if(!a)return R(new URL(r.url).origin);if(!i)return L();c&&(s.user=c)}return k(r,s,t)};var B=H;export{B as default};
1
+ import{toFetchResponse as R,toReqRes as w}from"fetch-to-node";import{createDocsMcpServer as y}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as C}from"../utils.js";import{createMethodNotAllowedError as D,withErrorHandling as v}from"./errors.js";import{McpServerType as A}from"../constants.js";import{constructInvalidTokenResponse as S,constructUnauthorizedResponse as T,handleMcpAuth as U,shouldHandleMcpAuth as b}from"../auth/auth-handlers.js";const L=async(o,e,p)=>{const t=!!e?.config?.access?.requiresLogin,a=e?.config?.access?.rbac||{};if(b(t,a)){const{isAuthenticated:s,isTokenValid:i,currentUser:n}=await U(o,e);if(!s)return T(new URL(o.url).origin);if(!i)return S();n&&(e.user=n)}let r;const d=async()=>{r&&(await r.cleanup(),r=void 0)};return await v(async()=>{if(o.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using that URL: ${o.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(o.method!=="POST")return D();const s=p,i=s?.props?.config?.apiDescriptionsMap||{},n=s?.props?.config?.mcpDocsServerName||"Docs MCP server",{config:{mcp:u={}}}=e,l=C(i,e.user,a,t),f=e.config.products?Object.values(e.config.products).map(M=>M?.name):[],m=u.docs?.name||n;r=await y({name:m,tools:s?.props?.tools||[],context:{...e,outdir:e.outdir||"",baseUrl:e.baseUrl||new URL(o.url).origin,apiDescriptionsMap:l,products:f}});const g=await o.json(),{req:h,res:c}=w(o);return await r.transport.handleRequest(h,c,g),R(c)},A.Docs,d)};var O=L;export{O as default};
@@ -1 +1 @@
1
- import{withPathPrefix as d}from"@redocly/theme/core/utils";import{importApiRoutesHandler as f}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as D}from"../../../persistence/kv/services/kv-service.js";import{envConfig as o}from"../../../config/env-config.js";async function y(a,s,t){const e=s.get("auth"),i=await t.resolveRouteStaticData(a)||{},r=d(a.slug),{requestHandlers:c}=await f(t.serverOutDir),p=c[a.requestHandlerId],m=(await p()).default,u=async()=>await D.getInstance({baseDbDir:t.serverOutDir,sqldRemoteDatabaseUrl:o.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:o.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),l=h({honoCtx:s,ctx:{user:{teams:e.teams,email:e.claims.email,claims:e.claims,idpAccessToken:e.idpAccessToken,idpId:e.claims.idpId,isAuthenticated:e.isAuthenticated},config:t.config},telemetry:A,getKv:u}),n=await m(s.req.raw,l,{...i,props:{...i.props,routeSlug:r,outdir:t.outdir}});return n instanceof Response?n:typeof n=="string"?new Response(n,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}export{y as handleMcpRequest};
1
+ import{withPathPrefix as d}from"@redocly/theme/core/utils";import{importApiRoutesHandler as f}from"../../../api-routes/import-api-routes-handlers.js";import{enhanceContext as h}from"../../../api-routes/helpers/enhance-context.js";import{telemetry as A}from"../../../telemetry/index.js";import{KvService as D}from"../../../persistence/kv/services/kv-service.js";import{envConfig as s}from"../../../config/env-config.js";async function v(i,a,e){const t=a.get("auth"),r=await e.resolveRouteStaticData(i)||{},o=d(i.slug),{requestHandlers:c}=await f(e.serverOutDir),p=c[i.requestHandlerId],u=(await p()).default,l=async()=>await D.getInstance({baseDbDir:e.serverOutDir,sqldRemoteDatabaseUrl:s.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:s.SQLD_REMOTE_DATABASE_AUTH_TOKEN}),m=h({honoCtx:a,ctx:{user:{teams:t.teams,email:t.claims.email,claims:t.claims,idpAccessToken:t.idpAccessToken,idpId:t.claims.idpId,isAuthenticated:t.isAuthenticated},config:e.config,outdir:e.outdir,baseUrl:new URL(a.req.url).origin},telemetry:A,getKv:l}),n=await u(a.req.raw,m,{...r,props:{...r.props,routeSlug:o,outdir:e.outdir}});return n instanceof Response?n:typeof n=="string"?new Response(n,{headers:{"Content-Type":"text/plain"}}):new Response(JSON.stringify(n),{headers:{"Content-Type":"application/json"}})}export{v as handleMcpRequest};
@@ -1 +1 @@
1
- import{fileURLToPath as g}from"node:url";import{dirname as u,join as D}from"node:path";import{logger as a}from"../../tools/notifiers/logger.js";import{reporter as h}from"../../tools/notifiers/reporter.js";import{filterIgnoredApiDescriptions as v,getCleanedUpApiDescriptions as C,isMcpInRedirects as y}from"./utils.js";import{telemetryTraceStep as P}from"../../../cli/telemetry/helpers/trace-step.js";const p="mcp-docs-server-handler",M=u(g(import.meta.url));async function R(){let o=!1;return{id:"mcp",async processContent(e,i){o||await P("build.plugin.mcp",async n=>{const s=await e.loadOpenApiDefinitions(i),d=await i.getConfig(),{mcp:r,redirects:f}=d;if(n?.setAttribute("config",JSON.stringify(r||{})),!(r?.hide||r?.docs?.hide)&&(y(f)&&await h.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),!r?.docs?.hide)){a.info("Configuring MCP servers...");const m=D(M,"./handlers/docs-mcp-handler.js"),l=C(v(s,r?.docs?.ignore||[])),c=new Map;for(const t of l)c.set(t.definition.info?.title?.toLowerCase()||"",{name:t.definition.info?.title||"",description:t.definition.info?.description||"",version:t.definition.info?.version||"",servers:t.definition.servers||[],relativePath:t.relativePath});await S({actions:e,handlerPath:m,apiDescriptionsMap:Object.fromEntries(c),mcpConfig:r}),o=!0}})},async afterRoutesCreated(e,i){const n=await i.getConfig(),{mcp:s}=n;e.setGlobalData({mcpData:{docs:{enabled:!s?.hide&&!s?.docs?.hide,name:s?.docs?.name}}})}}}var I=R;async function S({actions:o,handlerPath:e,apiDescriptionsMap:i,mcpConfig:n}){o.createRequestHandler(p,e),o.addApiRoute({slug:"/mcp",requestHandlerId:p,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:i,mcpDocsServerName:n?.docs?.name||"Docs MCP Server"}}})}),a.info("Registered Docs MCP Server endpoint at /mcp")}export{p as MCP_DOCS_SERVER_HANDLER_ID,I as default,R as mcpServerPlugin};
1
+ import{fileURLToPath as M}from"node:url";import{dirname as P,join as p}from"node:path";import{logger as d}from"../../tools/notifiers/logger.js";import{reporter as y}from"../../tools/notifiers/reporter.js";import{isDefined as S}from"../../../utils/guards/is-defined.js";import{filterIgnoredApiDescriptions as b,getCleanedUpApiDescriptions as R,isMcpInRedirects as w}from"./utils.js";import{getDefaultToolSchemas as O}from"./docs-mcp/tool-schemas.js";import{telemetryTraceStep as A}from"../../../cli/telemetry/helpers/trace-step.js";const f="mcp-docs-server-handler",m=P(M(import.meta.url));async function T(){let i=!1;return{id:"mcp",async processContent(r,o){i||await A("build.plugin.mcp",async c=>{const t=await r.loadOpenApiDefinitions(o),n=await o.getConfig(),{mcp:s,redirects:l}=n;if(c?.setAttribute("config",JSON.stringify(s||{})),!(s?.hide||s?.docs?.hide)&&(w(l)&&await y.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),!s?.docs?.hide)){d.info("Configuring MCP servers...");const u=p(m,"./handlers/docs-mcp-handler.js"),g=R(b(t,s?.docs?.ignore||[])),a=new Map;for(const e of g)a.set(e.definition.info?.title?.toLowerCase()||"",{name:e.definition.info?.title||"",description:e.definition.info?.description||"",version:e.definition.info?.version||"",servers:e.definition.servers||[],relativePath:e.relativePath});const D=Object.values(n.products||{}).map(e=>e?.name).filter(S),h=!!n?.access?.requiresLogin,v=n?.access?.rbac||{},C=O({products:D,requiresLogin:h,rbac:v});r.addMcpTools(p(m,"./docs-mcp/tools/index.js"),C),await j({actions:r,handlerPath:u,apiDescriptionsMap:Object.fromEntries(a),mcpConfig:s}),i=!0}})},async afterRoutesCreated(r,o){const c=await o.getConfig(),{mcp:t}=c;r.setGlobalData({mcpData:{docs:{enabled:!t?.hide&&!t?.docs?.hide,name:t?.docs?.name}}})}}}var U=T;async function j({actions:i,handlerPath:r,apiDescriptionsMap:o,mcpConfig:c}){i.createRequestHandler(f,r),i.addApiRoute({slug:"/mcp",requestHandlerId:f,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:o,mcpDocsServerName:c?.docs?.name||"Docs MCP Server"},serverOutDir:i.serverOutDir,tools:i.getMcpTools().map(({importPath:t,...n})=>n)}})}),d.info("Registered Docs MCP Server endpoint at /mcp")}export{f as MCP_DOCS_SERVER_HANDLER_ID,U as default,T as mcpServerPlugin};
@@ -1,24 +1,15 @@
1
- import type { AccessInfo, ApiDescriptionInfo, DocsServerDependencies, McpServerType } from '../types.js';
2
- import { BaseMcpServer } from './base-server.js';
3
- export declare class DocsMcpServer extends BaseMcpServer {
4
- private readonly dependencies;
5
- constructor(dependencies: DocsServerDependencies & {
6
- baseUrl: string;
7
- headers: Record<string, string | string[] | undefined>;
8
- outdir: string;
9
- accessInfo: AccessInfo;
10
- products?: string[];
11
- });
12
- protected registerTools(): void;
13
- protected getServerType(): McpServerType;
14
- }
15
- export declare function createDocsMcpServer({ name, baseUrl, headers, apiDescriptionsMap, outdir, accessInfo, products, }: {
1
+ import { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
2
+ import { StreamableHTTPServerTransport } from '@redocly/mcp-typescript-sdk/server/streamableHttp.js';
3
+ import type { McpToolSchema } from '../../../types';
4
+ import type { McpToolContext } from '../types.js';
5
+ export type DocsMcpServerInstance = {
6
+ server: McpServer;
7
+ transport: StreamableHTTPServerTransport;
8
+ cleanup: () => Promise<void>;
9
+ };
10
+ export declare function createDocsMcpServer({ name, tools, context, }: {
16
11
  name: string;
17
- baseUrl: string;
18
- headers: Record<string, string | string[] | undefined>;
19
- apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
20
- outdir: string;
21
- accessInfo: AccessInfo;
22
- products: string[];
23
- }): Promise<import("../types.js").McpServerInstance>;
12
+ tools: McpToolSchema[];
13
+ context: McpToolContext;
14
+ }): Promise<DocsMcpServerInstance>;
24
15
  //# sourceMappingURL=docs-server.d.ts.map
@@ -1 +1 @@
1
- import{BaseMcpServer as o}from"./base-server.js";import{registerDocsTools as p}from"../docs-mcp/tools/index.js";import{McpServerType as a}from"../constants.js";class d extends o{dependencies;constructor(e){super({name:e.name,version:new Date().toISOString().slice(0,10)}),this.dependencies=e}registerTools(){p({server:this.server,apiDescriptionsMap:this.dependencies.apiDescriptionsMap,baseUrl:this.dependencies.baseUrl,outdir:this.dependencies.outdir,headers:this.dependencies.headers,accessInfo:this.dependencies.accessInfo,products:this.dependencies.products})}getServerType(){return a.Docs}}async function S({name:s,baseUrl:e,headers:r,apiDescriptionsMap:i,outdir:t,accessInfo:n,products:c}){return await new d({name:s,baseUrl:e,headers:r,apiDescriptionsMap:i,outdir:t,accessInfo:n,products:c}).initialize()}export{d as DocsMcpServer,S as createDocsMcpServer};
1
+ import{McpServer as p}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as l}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as m}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as f,MCP_TOOL_WORKER_KEY as d}from"../../../workers/mcp-tool-worker-pool.js";async function v({name:e,tools:a,context:n}){const o=new p({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}}}),s=new l({sessionIdGenerator:void 0});for(const r of a){const t=async(i,c)=>{m.info(`MCP tool called: ${r.name}`);const u={toolName:r.name,args:i,context:g(n),extra:I(c)};return await f.exec(d,[u],{timeout:6e4})};o.tool(r.name,r.description,r.schema,t)}return await o.connect(s),{server:o,transport:s,cleanup:async()=>{s.close()}}}function I(e){return{sessionId:e.sessionId,authInfo:e.authInfo,requestId:e.requestId,requestInfo:e.requestInfo,_meta:e._meta}}function g(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,products:e.products}}export{v as createDocsMcpServer};
@@ -1,20 +1,13 @@
1
1
  import type { OpenAPIPath } from '@redocly/openapi-docs/src/types';
2
- import type { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
3
- import type { StreamableHTTPServerTransport } from '@redocly/mcp-typescript-sdk/server/streamableHttp.js';
4
- import type { CallToolResult } from '@redocly/mcp-typescript-sdk/types.js';
2
+ import type { ApiFunctionsContext, ApiFunctionsContextMethods, PageStaticData } from '@redocly/config';
3
+ import type { CallToolResult, RequestId, RequestInfo, RequestMeta } from '@redocly/mcp-typescript-sdk/types.js';
4
+ import type { AuthInfo } from '@redocly/mcp-typescript-sdk/server/types.js';
5
5
  import type { OpenAPIServer } from '@redocly/openapi-docs/lib/types/open-api.js';
6
6
  import type { McpErrorCodes, McpServerType } from './constants';
7
- import type { RbacConfig, PageStaticData } from '@redocly/config';
7
+ import type { McpToolSchema } from '../../types';
8
8
  type ObjectValues<T> = T[keyof T];
9
9
  export type McpServerType = ObjectValues<typeof McpServerType>;
10
10
  export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
11
- export type AccessInfo = {
12
- isAuthenticated: boolean;
13
- email?: string;
14
- teams?: string[];
15
- rbac: RbacConfig;
16
- requiresLogin: boolean;
17
- };
18
11
  export type ApiDescriptionInfo = {
19
12
  name: string;
20
13
  relativePath: string;
@@ -29,6 +22,8 @@ export type McpDocsStaticDataPropsConfig = {
29
22
  export type McpDocsStaticData = PageStaticData & {
30
23
  props: {
31
24
  config: McpDocsStaticDataPropsConfig;
25
+ serverOutDir?: string;
26
+ tools?: McpToolSchema[];
32
27
  };
33
28
  };
34
29
  export type McpPath = {
@@ -43,11 +38,6 @@ export type McpEndpoint = {
43
38
  'x-mcp'?: XMcpConfig;
44
39
  [key: string]: any;
45
40
  };
46
- export type McpServerInstance = {
47
- readonly server: McpServer;
48
- readonly transport: StreamableHTTPServerTransport;
49
- cleanup(): Promise<void>;
50
- };
51
41
  export type McpPluginConfig = {
52
42
  readonly hide: boolean;
53
43
  readonly docs: {
@@ -71,51 +61,29 @@ export type McpUserInfo = {
71
61
  exp?: number;
72
62
  [key: string]: any;
73
63
  };
74
- export type ToolArgsMap = {
75
- 'list-apis': {
76
- filter?: string;
77
- page?: number;
78
- limit?: number;
79
- };
80
- 'get-endpoints': {
81
- name: string;
82
- };
83
- 'get-endpoint-info': {
84
- name: string;
85
- path: string;
86
- method: string;
87
- };
88
- 'get-security-schemes': {
89
- name: string;
90
- };
91
- 'get-full-api-description': {
92
- name: string;
93
- };
94
- search: {
95
- query: string;
96
- product?: string;
97
- };
98
- whoami: Record<string, never>;
99
- };
100
- export type McpToolWorkerParams = {
101
- [K in keyof ToolArgsMap]: {
102
- toolName: K;
103
- args: ToolArgsMap[K];
104
- context: {
105
- apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
106
- outdir?: string;
107
- accessInfo?: AccessInfo;
108
- baseUrl?: string;
109
- headers?: Record<string, string | string[] | undefined>;
110
- products?: string[];
111
- };
112
- };
113
- }[keyof ToolArgsMap];
114
64
  export type SemanticSearchResult = {
115
65
  title: string;
116
66
  url: string;
117
67
  content: string;
118
68
  };
119
69
  export type McpToolWorkerResponse = CallToolResult;
70
+ export type McpToolExtra = {
71
+ sessionId?: string;
72
+ authInfo?: AuthInfo;
73
+ requestId: RequestId;
74
+ requestInfo?: RequestInfo;
75
+ _meta?: RequestMeta;
76
+ };
77
+ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | keyof ApiFunctionsContextMethods> & {
78
+ apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
79
+ products?: string[];
80
+ };
81
+ export type McpToolHandler<TArgs extends Record<string, unknown> = Record<string, unknown>> = (args: TArgs, context: McpToolContext, extra: McpToolExtra) => Promise<McpToolWorkerResponse>;
82
+ export type McpToolExecutionParams = {
83
+ toolName: string;
84
+ args: Record<string, unknown>;
85
+ context: McpToolContext;
86
+ extra: McpToolExtra;
87
+ };
120
88
  export {};
121
89
  //# sourceMappingURL=types.d.ts.map
@@ -1,3 +1,3 @@
1
- import type { McpToolWorkerParams, McpToolWorkerResponse } from '../types.js';
2
- export declare function executeMcpTool(params: McpToolWorkerParams): Promise<McpToolWorkerResponse>;
1
+ import type { McpToolExecutionParams, McpToolWorkerResponse } from '../types.js';
2
+ export declare function executeMcpTool(params: McpToolExecutionParams): Promise<McpToolWorkerResponse>;
3
3
  //# sourceMappingURL=execute-mcp-tool.d.ts.map
@@ -1 +1 @@
1
- import{getDocsTool as c}from"../docs-mcp/tools/index.js";async function l(e){const{toolName:o,args:n,context:r}=e,t=c(o);if(!t)throw new Error(`Unknown tool: ${o}`);return await t.execute(n,r)}export{l as executeMcpTool};
1
+ import{telemetry as s}from"../../../telemetry/index.js";import{mcpToolHandlers as p}from"../../../../client/mcp-tool-handlers-entry.js";async function w(o){s.initialize();const{toolName:e,args:c,context:a,extra:l}=o;try{const r=p[e];if(!r)throw new Error(`Unknown MCP tool: ${e}`);const{default:i}=await r(),n=i[e];if(!n)throw new Error(`MCP tool module does not export a handler for "${e}". Expected \`export default { '${e}': handler }\`.`);const t=await n(c,a,l);if(!f(t))throw new Error(`MCP tool "${e}" returned an invalid result.`);return t.isError?s.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:e,message:`${t.content.map(({text:d})=>d).join(" ")}`,stack:""}]):s.sendMcpToolCalledMessage([{object:"mcp_server",server_type:"docs",tool:e}]),t}catch(r){throw s.sendMcpErrorMessage([{object:"mcp_server",server_type:"docs",tool:e,message:r instanceof Error?r.message:String(r),stack:r instanceof Error&&r.stack||""}]),r}}function f(o){return!o||typeof o!="object"?!1:Array.isArray(o.content)}export{w as executeMcpTool};
@@ -1 +1 @@
1
- import{simplifyAstStructure as ee}from"@redocly/openapi-docs";import{REDOCLY_TEAMS_RBAC as D}from"@redocly/config";import{OPENAPI_DOCS_TEMPLATE_ID as $,PUBLIC_RBAC_SCOPE_ITEM as j}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as te,PUBLIC_API_DEFINITIONS_FOLDER as oe}from"../../constants/common.js";import{OPENAPI_CUSTOM_FIELDS_SERVER_PROPS_GETTER_ID as ae,OPENAPI_SHARED_DATA_PREFIX as U}from"../../constants/plugins/openapi-docs.js";import{envConfig as V}from"../../config/env-config.js";import{isRbacScopeItems as re}from"../../utils/rbac/is-rbac-scope-items.js";import{getRouteSlugsForPath as se}from"../utils.js";import{searchResolver as ne}from"./search/search-resolver.js";import{convertOpenAPIDocs2Sidebar as ie,shouldAddRoute as pe}from"./utils.js";import{getTemplatePath as T}from"./get-template-path.js";import{storeDefinitionBundles as ce}from"./store-definition-bundles.js";import{definitionLoader as de,definitionsLoader as le}from"./load-definition.js";import{getAiDocumentsStore as ue}from"./search/get-ai-search-documents.js";import{fromCurrentDir as me}from"../../utils/paths.js";import{telemetryTraceStep as fe}from"../../../cli/telemetry/helpers/trace-step.js";const w="openapi-spec-download";async function Te(){let M=[],R={},L=new Set;return{id:"openapi",requiredEntitlements:["openapi"],loaders:{"load-oas-docs":le,"load-oas":de},processContent:async(e,i)=>{await fe("build.plugin.openapi_docs",async u=>{e.createRequestHandler(w,me(import.meta.url,"./spec-download.api.js")),e.addApiRoute({slug:oe+"/*",requestHandlerId:w,httpMethod:"all",[D]:j,getStaticData:async()=>({props:{}})}),e.addApiRoute({slug:te+"/*",requestHandlerId:w,httpMethod:"all",[D]:j,getStaticData:async()=>({props:{}})});const A=e.createTemplate($,T("../../../client/templates/openapi-docs/template.js")),a=e.registerServerPropsGetter($,T("./get-server-props.js")),r=e.registerServerPropsGetter(ae,T("./get-server-props-custom-fields.js")),p=await i.getConfig();u?.setAttribute("config",JSON.stringify(p.openapi||{}));const h=p.rules?.["custom-fields-schema"];R={};const m=await e.loadOpenApiDefinitions(i);M=m.map(({markdocChunks:c,relativePath:f,customOutputRelativeFile:s,isVirtual:n,realRelativePath:d})=>({chunks:c,relativePath:f,realRelativePath:d,isVirtual:s!=null||n})),ce(m,e.outdir);const S={};for(const c of m||[]){const{definition:f,config:s,relativePath:n,customOutputRelativeFile:d,contentItems:_,flatItems:k,parser:E,options:B,rawOptions:q,hash:J}=c,N=d||n,o=[],x={},{definition:Q}=E||{},{info:l}=Q||{},v=l?.["x-metadata"],C=!!s.openapi?.excludeFromSearch||!!s.theme?.openapi?.excludeFromSearch||!!p.openapi?.excludeFromSearch||!!p.theme?.openapi?.excludeFromSearch,G={title:l?.title,description:l?.description,summary:l?.summary,...s.metadata,...v},g={untagged:[],tagged:new Map};for(const t of k){const{id:O,href:I,operationDefinition:b}=t;if(b){const{tags:P}=b;if(P)for(const F of P)g.tagged.has(F)||g.tagged.set(F,[]),g.tagged.get(F)?.push(t);else g.untagged.push(t);V.isDevelopMode&&(x[`#${b.pointer}`]=t.href)}if(!pe({item:t}))continue;const y=t,Y=y.type==="section"&&!!y.infoDefinition,z=I.split("#")[0]+"/",K=t?.operationDefinition?.[D],Z=re(s.access?.rbac)?s.access.rbac:void 0;o.push({excludeFromSearch:C,slugSuffix:z,fsPath:N,metadata:{subType:"openapi-operation"},httpVerb:t?.httpVerb||"",path:n,templateId:A,[D]:K||Z,getAiDocumentsStore:ue({parser:E,options:B,info:l,tagOperations:g,openapiContentItem:y,metadata:G,relativePath:n,getSearchFacets:e.getSearchFacets,includeInLLMsTxt:Y,excludeFromSearch:C}),getStaticData:async P=>({props:{dynamicMarkdocComponents:["openapi"],baseSlug:P.baseSlug,seo:t["x-metadata"]?.seo||{title:t.name,description:t.description},itemId:O,disableAutoScroll:!0}})})}o[0]={...o[0],metadata:{type:"openapi",...G},hasClientRoutes:!0,getSidebar:(t,O)=>{const I=[];return ie({contentItems:_,sidebarItems:I,routeSlug:t.slug,navItem:O}),I},getNavText:()=>l?.title,getSearchDocuments:ne(E,B,k,e.getSearchFacets,e.setSearchFacets,C)},v?.apiId&&(S[v.apiId]={slug:o[0]?.slug||""});const W=o[0];o[0]=o[o.length-1],o[o.length-1]=W;for(const t of o)e.addRoute({...t,serverPropsGetterIds:h?[a,r]:[a]});const X=V.isDevelopMode?n:void 0,H=`${U}${n}`;R[H]={fsPath:N,definition:f,options:q,sourcePath:X,routesMapping:x,hash:J};for(const t of o)e.addRoute({...t,sharedData:[{id:H,key:"openAPIDocsStore"}],serverPropsGetterIds:h?[a,r]:[a]})}e.setGlobalData({apiProducts:S})})},afterRoutesCreated:async(e,i)=>{const u=new Set;for(const{chunks:a,relativePath:r,isVirtual:p,realRelativePath:h}of M){const m=se(e.getAllRoutes(),r),S=(await i.cache.load(h,"load-oas")).compoundHash;await i.cache.load(r,{loader:async function(){for(const{node:f,markdown:s,key:n,relativePath:d}of a){const{ast:_}=await e.parseMarkdoc({input:{content:s,relativePath:d,isVirtual:p},context:i,deps:{sharedDataIds:[`${U}${d}`],routeSlugs:m}});f[`x-parsed-md-${n}`]={result:ee(_)}}},name:"openapi-markdoc-inline-parser"},[S]);for(const{pointer:c}of a)u.add(c)}const A=L.difference(u);for(const a of A)i.cache.delete(a);L=u;for(const[a,r]of Object.entries(R))await e.createSharedData(a,{...r,baseSlug:e.getRouteByFsPath(r.fsPath)?.baseSlug},r.hash)}}}export{Te as openAPIDocsPlugin};
1
+ import{simplifyAstStructure as te}from"@redocly/openapi-docs";import{REDOCLY_ROUTE_RBAC as E,REDOCLY_TEAMS_RBAC as P}from"@redocly/config";import{OPENAPI_DOCS_TEMPLATE_ID as U,PUBLIC_RBAC_SCOPE_ITEM as V}from"../../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as oe,PUBLIC_API_DEFINITIONS_FOLDER as ae}from"../../constants/common.js";import{OPENAPI_CUSTOM_FIELDS_SERVER_PROPS_GETTER_ID as re,OPENAPI_SHARED_DATA_PREFIX as $}from"../../constants/plugins/openapi-docs.js";import{envConfig as q}from"../../config/env-config.js";import{isRbacScopeItems as se}from"../../utils/rbac/is-rbac-scope-items.js";import{getRouteSlugsForPath as ie}from"../utils.js";import{searchResolver as ne}from"./search/search-resolver.js";import{convertOpenAPIDocs2Sidebar as pe,shouldAddRoute as ce}from"./utils.js";import{getTemplatePath as M}from"./get-template-path.js";import{storeDefinitionBundles as de}from"./store-definition-bundles.js";import{definitionLoader as le,definitionsLoader as ue}from"./load-definition.js";import{getAiDocumentsStore as fe}from"./search/get-ai-search-documents.js";import{fromCurrentDir as me}from"../../utils/paths.js";import{telemetryTraceStep as ge}from"../../../cli/telemetry/helpers/trace-step.js";import{getApiConfigByPath as he}from"../get-api-config.js";const B="openapi-spec-download";async function Me(){let k=[],_={},N=new Set,f={};return{id:"openapi",requiredEntitlements:["openapi"],loaders:{"load-oas-docs":ue,"load-oas":le},processContent:async(e,c)=>{await ge("build.plugin.openapi_docs",async m=>{e.createRequestHandler(B,me(import.meta.url,"./spec-download.api.js")),e.addApiRoute({slug:ae+"/*",requestHandlerId:B,httpMethod:"all",[P]:V,getStaticData:async()=>({props:{}})}),e.addApiRoute({slug:oe+"/*",requestHandlerId:B,httpMethod:"all",[P]:V,getStaticData:async()=>({props:{}})});const C=e.createTemplate(U,M("../../../client/templates/openapi-docs/template.js")),o=e.registerServerPropsGetter(U,M("./get-server-props.js")),a=e.registerServerPropsGetter(re,M("./get-server-props-custom-fields.js")),s=await c.getConfig();m?.setAttribute("config",JSON.stringify(s.openapi||{}));const d=s.rules?.["custom-fields-schema"];_={},f={};const g=await e.loadOpenApiDefinitions(c);k=g.map(({markdocChunks:p,relativePath:l,customOutputRelativeFile:i,isVirtual:n,realRelativePath:h})=>({chunks:p,relativePath:l,realRelativePath:h,isVirtual:i!=null||n})),de(g,e.outdir);for(const p of g||[]){const{definition:l,config:i,relativePath:n,customOutputRelativeFile:h,contentItems:I,flatItems:D,parser:v,options:x,rawOptions:Y,hash:J}=p,O=h||n,r=[],G={},{definition:Q}=v||{},{info:u}=Q||{},b=u?.["x-metadata"],y=!!i.openapi?.excludeFromSearch||!!i.theme?.openapi?.excludeFromSearch||!!s.openapi?.excludeFromSearch||!!s.theme?.openapi?.excludeFromSearch,j={title:u?.title,description:u?.description,summary:u?.summary,...i.metadata,...b},S={untagged:[],tagged:new Map};for(const t of D){const{id:F,href:R,operationDefinition:T}=t;if(T){const{tags:A}=T;if(A)for(const L of A)S.tagged.has(L)||S.tagged.set(L,[]),S.tagged.get(L)?.push(t);else S.untagged.push(t);q.isDevelopMode&&(G[`#${T.pointer}`]=t.href)}if(!ce({item:t}))continue;const w=t,z=w.type==="section"&&!!w.infoDefinition,K=R.split("#")[0]+"/",Z=t?.operationDefinition?.[P],ee=se(i.access?.rbac)?i.access.rbac:void 0;r.push({excludeFromSearch:y,slugSuffix:K,fsPath:O,metadata:{subType:"openapi-operation"},httpVerb:t?.httpVerb||"",path:n,templateId:C,[P]:Z||ee,getAiDocumentsStore:fe({parser:v,options:x,info:u,tagOperations:S,openapiContentItem:w,metadata:j,relativePath:n,getSearchFacets:e.getSearchFacets,includeInLLMsTxt:z,excludeFromSearch:y}),getStaticData:async A=>({props:{dynamicMarkdocComponents:["openapi"],baseSlug:A.baseSlug,seo:t["x-metadata"]?.seo||{title:t.name,description:t.description},itemId:F,disableAutoScroll:!0}})})}if(r[0]={...r[0],metadata:{type:"openapi",...j},hasClientRoutes:!0,getSidebar:(t,F)=>{const R=[];return pe({contentItems:I,sidebarItems:R,routeSlug:t.slug,navItem:F}),R},getNavText:()=>u?.title,getSearchDocuments:ne(v,x,D,e.getSearchFacets,e.setSearchFacets,y)},b?.apiId&&!p.isVirtual){const t=he(p.config.apis,p.realRelativePath);f[b.apiId]={[P]:t.rbac,[E]:{fsPath:O}}}const W=r[0];r[0]=r[r.length-1],r[r.length-1]=W;for(const t of r)e.addRoute({...t,serverPropsGetterIds:d?[o,a]:[o]});const X=q.isDevelopMode?n:void 0,H=`${$}${n}`;_[H]={fsPath:O,definition:l,options:Y,sourcePath:X,routesMapping:G,hash:J};for(const t of r)e.addRoute({...t,sharedData:[{id:H,key:"openAPIDocsStore"}],serverPropsGetterIds:d?[o,a]:[o]})}})},afterRoutesCreated:async(e,c)=>{const m=new Set;for(const{chunks:o,relativePath:a,isVirtual:s,realRelativePath:d}of k){const g=ie(e.getAllRoutes(),a),p=(await c.cache.load(d,"load-oas")).compoundHash;await c.cache.load(a,{loader:async function(){for(const{node:i,markdown:n,key:h,relativePath:I}of o){const{ast:D}=await e.parseMarkdoc({input:{content:n,relativePath:I,isVirtual:s},context:c,deps:{sharedDataIds:[`${$}${I}`],routeSlugs:g}});i[`x-parsed-md-${h}`]={result:te(D)}}},name:"openapi-markdoc-inline-parser"},[p]);for(const{pointer:l}of o)m.add(l)}const C=N.difference(m);for(const o of C)c.cache.delete(o);N=m;for(const[o,a]of Object.entries(_))await e.createSharedData(o,{...a,baseSlug:e.getRouteByFsPath(a.fsPath)?.baseSlug},a.hash);Object.entries(f).forEach(([o,a])=>{const s=a[E]?.fsPath;if(!s)return;const d=e.getRouteByFsPath(s)?.baseSlug;f[o]={...a,[E]:{...a[E],slug:d},slug:d}}),e.setGlobalData({apiProducts:f})}}}export{Me as openAPIDocsPlugin};
@@ -1 +1 @@
1
- import*as y from"@redocly/openapi-docs";import{REDOCLY_TEAMS_RBAC as d}from"@redocly/config";import{combineUrls as u}from"@redocly/theme/core/utils";import{SEARCH_DOCUMENT_METADATA_KEY as x}from"../../constants/plugins/search.js";import{removeMarkdownLinks as c,stripFormatting as a}from"./utils.js";import{normalizeFrontmatterKeywords as k}from"../helpers/normalize-frontmatter-keywords.js";const h=y.default||y;class q{#n=[];#r;#s;#e;#i;constructor(e,t,n){this.#r=e,this.#s=t,this.#e=n}addItem(e){const{result:t}=k(e.keywords||e.operationDefinition?.keywords);t?.excludes&&e.type==="section"&&e.id===""&&(this.#i=t.excludes);try{let n;switch(e.type){case"tag":n=this.#c(e);break;case"operation":const o=this.getOperation(e);n=this.#d(o,e[d]);break;case"section":n=this.#p(e);break;case"rsrc":case"prompt":case"tool":n=this.#o(e);break}if(!n)return;const s=[...new Set([...t?.excludes?t.excludes:[],...this.#i?this.#i:[]])];return(t||s.length)&&(n[x]={curated:!0,...t,excludes:s}),this.#n.push(n),n}catch(n){console.error("Cannot add item to search indexer",n.message)}}addInfo(e,t){const n=this.#e,s={id:n,url:n,text:a(c(e.description||"")),title:a(`${e.title} (${e.version})`),metadata:t};return this.#n.push(s),s}#o(e){const t=u(this.#e,e.href);return{id:t,url:t,text:a(c(e.description||"")),title:e.name}}getResult(){return this.#n}getOperation(e){return h.getOperation(this.#r,e.operationDefinition,e.parent,{...this.#s,internal_skipSamples:!0},e.href)}#a(e){return[...e.path||[],e.name.toString()].join(".")+e.description+e.place}#d(e,t){if(e.type!=="operation")return;let n={};for(let i of e.parameters){if(i[d])continue;const r=i.schema?.example||i.example,p={name:i.name,description:a(c(i.description)),place:i.in+" parameters",mediaType:void 0,type:i.schema?.type.toString()||"unknown",deepLink:h.generateDeepLink(i),[d]:i[d],required:i.required,example:r?JSON.stringify(r):void 0,enum:i.schema?.enum?.length?i.schema.enum:void 0};n[this.#a(p)]=p}const s=new Set;this.#t(n,e.requestBody?.content?.mediaTypes[0]?.schema,e.requestBody?.content?.mediaTypes[0]?.name,"request fields",!1,[],s);for(let i of e.responses){const r=`response ${i.code} fields`;this.#t(n,i.content?.mediaTypes[0]?.schema,i.content?.mediaTypes[0]?.name,r,!0,[],s)}let o=u(this.#e,e.href);return{id:o,url:o,title:a(e.name),text:a(c(e.description||"")),httpMethod:e.httpVerb,httpPath:e.path,deprecated:e.deprecated,isAdditionalOperation:e.isAdditionalOperation,security:e.security.map(i=>i.schemes.map(r=>r.id)).flat().filter(Boolean),parameters:Object.values(n),badges:e.badges.length?e.badges:void 0,[d]:t}}#t(e,t,n,s,o,l=[],i=new Set){if(!(!t||t.isCircular)){if(t.pointer){if(i.has(t.pointer))return;i.add(t.pointer)}if(t?.fields)for(let r of t.fields){if(t[d]||r.kind==="additionalProperties"||r.schema?.readOnly&&!o||r.schema?.writeOnly&&o)continue;const p=r.schema?.example||r.example,m=r.schema?.enum,f={name:r.name,description:a(r.description),place:s,mediaType:n,path:l,deepLink:h.generateDeepLink(r),type:r.schema?.type.toString()||"unknown",required:r.required||t.schema.required?.includes(r.name)||!1,example:p?JSON.stringify(p):void 0,enum:m?.length?m:void 0},g=this.#a(f);e[g]==null&&(e[g]=f,this.#t(e,r.schema,n,s,o,l.concat([r.name]),i))}t?.items&&this.#t(e,t.items,n,s,o,l,i)}}#c(e){const t=u(this.#e,e.href);return{id:t,url:t,text:a(c(e.description||"")),title:a(e.name)}}#p(e){const t=u(this.#e,e.href);return{id:t,url:t,text:a(c(e.description||"")),title:a(e.name)}}}export{q as SearchIndexer};
1
+ import*as y from"@redocly/openapi-docs";import{REDOCLY_TEAMS_RBAC as c}from"@redocly/config";import{combineUrls as l}from"@redocly/theme/core/utils";import{SEARCH_DOCUMENT_METADATA_KEY as k}from"../../constants/plugins/search.js";import{removeMarkdownLinks as p,stripFormatting as a}from"./utils.js";import{normalizeFrontmatterKeywords as O}from"../helpers/normalize-frontmatter-keywords.js";const h=y.default||y;class q{#n=[];#s;#r;#e;#i;constructor(e,t,n){this.#s=e,this.#r=t,this.#e=n}addItem(e){const{result:t}=O(e.keywords||e.operationDefinition?.keywords);t?.excludes&&e.type==="section"&&e.id===""&&(this.#i=t.excludes);try{let n;switch(e.type){case"tag":n=this.#c(e);break;case"operation":const d=this.getOperation(e);n=this.#d(d,e[c]);break;case"section":n=this.#p(e);break;case"rsrc":case"prompt":case"tool":n=this.#o(e);break}if(!n)return;const s=[...new Set([...t?.excludes?t.excludes:[],...this.#i?this.#i:[]])];return(t||s.length)&&(n[k]={curated:!0,...t,excludes:s}),this.#n.push(n),n}catch(n){console.error("Cannot add item to search indexer",n.message)}}addInfo(e,t){const n=this.#e,s={id:n,url:n,text:a(p(e.description||"")),title:a(`${e.title} (${e.version})`),metadata:t};return this.#n.push(s),s}#o(e){const t=l(this.#e,e.href);return{id:t,url:t,text:a(p(e.description||"")),title:e.name}}getResult(){return this.#n}getOperation(e){return h.getOperation(this.#s,e.operationDefinition,e.parent,{...this.#r,internal_skipSamples:!0},e.href)}#a(e){return[...e.path||[],e.name.toString()].join(".")+e.description+e.place}#d(e,t){if(e.type!=="operation")return;let n={};for(let r of e.parameters){if(r[c])continue;const o=r.schema?.example||r.example,i={name:r.name,description:a(p(r.description)),place:r.in+" parameters",mediaType:void 0,type:r.schema?.type.toString()||"unknown",deepLink:h.generateDeepLink(r),[c]:r[c],required:r.required,example:o?JSON.stringify(o):void 0,enum:r.schema?.enum?.length?r.schema.enum:void 0};n[this.#a(i)]=i}const s=new Set;this.#t(n,e.requestBody?.content?.mediaTypes[0]?.schema,e.requestBody?.content?.mediaTypes[0]?.name,"request fields",!1,[],s);for(let r of e.responses){const o=`response ${r.code} fields`;this.#t(n,r.content?.mediaTypes[0]?.schema,r.content?.mediaTypes[0]?.name,o,!0,[],s)}let d=l(this.#e,e.href);return{id:d,url:d,title:a(e.name),text:a(p(e.description||"")),httpMethod:e.httpVerb,httpPath:e.path,deprecated:e.deprecated,isAdditionalOperation:e.isAdditionalOperation,security:e.security.map(r=>r.schemes.map(o=>o.id)).flat().filter(Boolean),parameters:Object.values(n),badges:e.badges.length?e.badges:void 0,[c]:t}}#t(e,t,n,s,d,u=[],r=new Set,o=0){if(!(!t||t.isCircular)){if(t.pointer){if(r.has(t.pointer))return;r.add(t.pointer)}if(!(o>this.#r.generatedSamplesMaxDepth)){if(t?.fields)for(let i of t.fields){if(t[c]||i.kind==="additionalProperties"||i.schema?.readOnly&&!d||i.schema?.writeOnly&&d)continue;const m=i.schema?.example||i.example,f=i.schema?.enum,g={name:i.name,description:a(i.description),place:s,mediaType:n,path:u,deepLink:h.generateDeepLink(i),type:i.schema?.type.toString()||"unknown",required:i.required||t.schema.required?.includes(i.name)||!1,example:m?JSON.stringify(m):void 0,enum:f?.length?f:void 0},x=this.#a(g);e[x]==null&&(e[x]=g,this.#t(e,i.schema,n,s,d,u.concat([i.name]),r,o+1))}t?.items&&this.#t(e,t.items,n,s,d,u,r,o+1)}}}#c(e){const t=l(this.#e,e.href);return{id:t,url:t,text:a(p(e.description||"")),title:a(e.name)}}#p(e){const t=l(this.#e,e.href);return{id:t,url:t,text:a(p(e.description||"")),title:a(e.name)}}}export{q as SearchIndexer};
@@ -1,7 +1,7 @@
1
1
  import type { Node } from '@markdoc/markdoc';
2
2
  import type { JSX } from 'react';
3
3
  import type { CommonError, GlobalData } from '../types/index.js';
4
- import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, WildcardRedirectsTree } from './types';
4
+ import type { MiddlewareDetails, PageRouteInit, PageRouteDetails, RouteDetails, LifecycleContext, ApiRoute, ParseMarkdocOpts, WildcardRedirectsTree, RedirectOptions, McpToolRegistration, McpToolSchema } from './types';
5
5
  import type { RedoclyConfig, RedirectConfig, CompilationError, PageStaticData } from '@redocly/config';
6
6
  import type { SearchFacet } from '@redocly/theme/core/types';
7
7
  import type { BundledDefinition as OpenApiBundledDefinition } from './plugins/openapi-docs/load-definition.js';
@@ -55,6 +55,7 @@ export declare class Store {
55
55
  templates: Map<string, string>;
56
56
  browserPlugins: Set<string>;
57
57
  apiRoutesRequestHandlers: Map<string, string>;
58
+ mcpToolHandlers: Map<string, McpToolRegistration>;
58
59
  serverPropsGetters: Map<string, string>;
59
60
  pagePropsGetters: Map<string, string>;
60
61
  listeners: Map<string, Set<(...args: any[]) => void>>;
@@ -140,7 +141,7 @@ export declare class Store {
140
141
  getConfig: () => RedoclyConfig;
141
142
  getGlobalConfig: <T = unknown>(key: string) => T;
142
143
  getSearchFacets: () => Map<string, SearchFacet>;
143
- addRedirect: (from: string, to: RedirectConfig) => void;
144
+ addRedirect: (from: string, to: RedirectConfig, options?: RedirectOptions) => void;
144
145
  getRedirect: (from: string) => WithRequired<RedirectConfig, "to"> | null;
145
146
  createSharedData: (id: string, data: unknown, hash?: string) => Promise<string>;
146
147
  addRouteSharedData: (routeSlug: string, dataKey: string, dataId: string) => void;
@@ -149,6 +150,8 @@ export declare class Store {
149
150
  addRoute: (route: PageRouteInit) => void;
150
151
  addRouteSharedDataToAllLocales: (slug: string, dataKey: string, dataId: string) => void;
151
152
  addApiRoute: (route: ApiRoute) => void;
153
+ addMcpTools: (importPath: string, tools: McpToolSchema[]) => void;
154
+ getMcpTools: () => McpToolRegistration[];
152
155
  addMiddleware: (middleware: MiddlewareDetails) => void;
153
156
  getRouteByFsPath: (relativePath: string) => PageRouteDetails | undefined;
154
157
  getRouteBySlug: (slug: string, opts?: {