@redocly/redoc-reef 0.136.0-next.4 → 0.136.0-next.6
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.
- package/CHANGELOG.md +47 -0
- package/dist/client/ErrorBoundary.js +1 -1
- package/dist/client/app/Sidebar/helpers/hide-empty-separators.d.ts +13 -0
- package/dist/client/app/Sidebar/helpers/hide-empty-separators.js +1 -0
- package/dist/client/app/Sidebar/utils.js +1 -1
- package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
- package/dist/client/app/l10n/initL10n.js +1 -1
- package/dist/client/app/utils/same-resolved-route.d.ts +5 -0
- package/dist/client/app/utils/same-resolved-route.js +1 -0
- package/dist/client/providers/post-message/PostMessageProvider.js +1 -1
- package/dist/client/templates/openapi-docs/helpers.d.ts +1 -1
- package/dist/client/templates/openapi-docs/helpers.js +2 -2
- package/dist/constants/common.d.ts +13 -1
- package/dist/constants/common.js +1 -1
- package/dist/server/config/env-config.d.ts +2 -4
- package/dist/server/config/env-schema.d.ts +5 -10
- package/dist/server/config/env-schemas/feature-flags.d.ts +4 -8
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/constants/common.d.ts +2 -0
- package/dist/server/constants/common.js +1 -1
- package/dist/server/constants/entitlements.js +1 -1
- package/dist/server/plugins/config-parser/loaders/utils/read-and-validate-config.js +1 -1
- package/dist/server/plugins/markdown/search/create-render-tag-fn.d.ts +2 -1
- package/dist/server/plugins/markdown/search/create-render-tag-fn.js +1 -1
- package/dist/server/plugins/markdown/search/get-ai-search-documents.js +9 -9
- package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +1 -0
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +27 -0
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +2 -0
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.d.ts +4 -15
- package/dist/server/plugins/mcp/gateway-mcp/eligibility.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.d.ts +8 -8
- package/dist/server/plugins/mcp/gateway-mcp/fetch/allowed-hosts.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.d.ts +17 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-errors.d.ts +11 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-errors.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.d.ts +13 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.d.ts +4 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/redact.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-blocklist.d.ts +22 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-blocklist.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.d.ts +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-guard.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-safe-lookup.d.ts +13 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/ssrf-safe-lookup.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.d.ts +8 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch-capability.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.d.ts +3 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/edge-limiter.d.ts +16 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/edge-limiter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.d.ts +2 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/ip-key.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/limits.d.ts +7 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/limits.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/window-counter.d.ts +15 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/window-counter.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +24 -0
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.d.ts +18 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth-scheme.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +10 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.js +1 -0
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/errors.d.ts +3 -3
- package/dist/server/plugins/mcp/handlers/errors.js +1 -1
- package/dist/server/plugins/mcp/handlers/handle-mcp-request.js +1 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.d.ts +5 -0
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +101 -0
- package/dist/server/plugins/mcp/index.d.ts +1 -0
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.d.ts +5 -2
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.d.ts +13 -2
- package/dist/server/plugins/mcp/servers/mcp-server.js +1 -1
- package/dist/server/plugins/mcp/servers/session-manager.d.ts +15 -0
- package/dist/server/plugins/mcp/servers/session-manager.js +1 -0
- package/dist/server/plugins/mcp/types.d.ts +9 -12
- package/dist/server/plugins/mcp/utils/jwt.d.ts +0 -9
- package/dist/server/plugins/mcp/utils/jwt.js +1 -1
- package/dist/server/plugins/mcp/utils/mode.d.ts +12 -2
- package/dist/server/plugins/mcp/utils/mode.js +1 -1
- package/dist/server/plugins/mcp/utils/telemetry-attributes.d.ts +8 -0
- package/dist/server/plugins/mcp/utils/telemetry-attributes.js +1 -0
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
- package/dist/server/plugins/openapi-docs/search/get-ai-search-documents.js +16 -16
- package/dist/server/plugins/openapi-docs/utils.js +1 -1
- package/dist/server/plugins/sso/index.js +1 -1
- package/dist/server/sandbox/types.d.ts +3 -2
- package/dist/server/sandbox/utils/execution-budget.d.ts +4 -3
- package/dist/server/sandbox/utils/execution-budget.js +1 -1
- package/dist/server/types/plugins/markdown.d.ts +2 -2
- package/dist/server/utils/crypto/constants.d.ts +5 -0
- package/dist/server/utils/crypto/constants.js +1 -0
- package/dist/server/utils/crypto/decrypt-aes-gcm.d.ts +6 -0
- package/dist/server/utils/crypto/decrypt-aes-gcm.js +1 -0
- package/dist/server/utils/crypto/decrypt-claim-value.d.ts +6 -0
- package/dist/server/utils/crypto/decrypt-claim-value.js +1 -0
- package/dist/server/utils/crypto/derive-key.d.ts +5 -0
- package/dist/server/utils/crypto/derive-key.js +1 -0
- package/dist/server/utils/crypto/encrypt-aes-gcm.d.ts +6 -0
- package/dist/server/utils/crypto/encrypt-aes-gcm.js +1 -0
- package/dist/server/utils/crypto/encrypt-claim-value.d.ts +6 -0
- package/dist/server/utils/crypto/encrypt-claim-value.js +1 -0
- package/dist/server/utils/l10n/get-build-translate-context.d.ts +7 -0
- package/dist/server/utils/l10n/get-build-translate-context.js +1 -0
- package/dist/server/utils/rbac.d.ts +4 -0
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/web-server/auth.d.ts +33 -3
- package/dist/server/web-server/auth.js +3 -3
- package/dist/server/web-server/handle-api-route-request.js +1 -1
- package/dist/server/web-server/routes/api-routes/api-routes.js +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.d.ts +5 -2
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
- package/dist/server/workers/worker-pool.js +1 -1
- package/dist/types/entitlements.d.ts +6 -1
- package/dist/utils/l10n/build-i18n-config.d.ts +24 -0
- package/dist/utils/l10n/build-i18n-config.js +1 -0
- package/dist/utils/l10n/create-translate.d.ts +19 -0
- package/dist/utils/l10n/create-translate.js +1 -0
- package/package.json +11 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as
|
|
1
|
+
import{fileURLToPath as w}from"node:url";import{dirname as q,join as p}from"node:path";import{logger as f}from"../../tools/notifiers/logger.js";import{reporter as G}from"../../tools/notifiers/reporter.js";import{isDefined as N}from"../../../utils/guards/is-defined.js";import{buildGraphqlDescriptions as H,filterIgnoredApiDescriptions as E,getCleanedUpApiDescriptions as I,isMcpInRedirects as U}from"./utils.js";import{getMcpMode as j,isMcpElicitationEnabled as x}from"./utils/mode.js";import{getDefaultToolSchemas as F}from"./docs-mcp/tool-schemas.js";import{EXECUTE_TOOL_SCHEMA as B}from"./codemode/tools/execute-schema.js";import{isGatewayCapabilityEnabled as V,isGatewayEligible as J}from"./gateway-mcp/eligibility.js";import{resolveGatewayFetchLimits as W}from"./gateway-mcp/rate-limit/limits.js";import{telemetryTraceStep as X}from"../../../cli/telemetry/helpers/trace-step.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as M,MCP_NOT_ALLOWED_TEMPLATE_ID as k}from"./constants.js";const C="mcp-docs-server-handler",z="/mcp",P="mcp-credentials-handler",K="/mcp/credentials",d=q(w(import.meta.url));async function Q(){let o=!1;return{id:"mcp",async processContent(t,r){o||await X("build.plugin.mcp",async a=>{const n=await t.loadOpenApiDefinitions(r),l=await t.loadGraphqlDefinitions(r),s=await r.getConfig(),{mcp:i,redirects:c}=s;if(a?.setAttribute("config",JSON.stringify(i||{})),!(i?.hide||i?.docs?.hide)&&(U(c)&&await G.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),t.createTemplate(k,"@redocly/theme/layouts/McpNotAllowed"),!i?.docs?.hide)){f.info("Configuring MCP servers...");const m=p(d,"./handlers/docs-mcp-handler.js"),_=I(E(n,i?.docs?.ignore||[])),v=!!s?.access?.requiresLogin,g=s?.access?.rbac||{},y=V(i),u=new Map;for(const e of _){const O=e.definition.info?.title||"",L=e.definition.info?.version||"";u.set(e.relativePath,{name:O,description:e.definition.info?.description||"",version:L,servers:e.definition.servers||[],relativePath:e.relativePath,...y&&J(e.definition.info,e.relativePath,g)?{fetchEligible:!0}:{}})}const h=H(E(l,i?.docs?.ignore||[])),R=Object.values(s.products||{}).map(e=>e?.name).filter(N),S=s.l10n?.locales?.map(e=>e.code)??r.fs.localeFolders,b=F({products:R,locales:S,requiresLogin:v,rbac:g,hasGraphqlApis:h.length>0});t.addMcpTools(p(d,"./docs-mcp/tools/index.js"),b);const D=j(),A=x(),{budgetPerExec:T}=W();D==="code"&&t.addMcpTools(p(d,"./codemode/tools/execute.js"),[B]),await Y({actions:t,handlerPath:m,apiDescriptionsMap:Object.fromEntries(u),graphqlDescriptions:h,mcpConfig:i,mcpMode:D,elicitationEnabled:A,gatewayFetchBudgetPerExec:T}),o=!0}})},async afterRoutesCreated(t,r){const a=await r.getConfig(),{mcp:n}=a;t.setGlobalData({mcpData:{docs:{enabled:!n?.hide&&!n?.docs?.hide,name:n?.docs?.name||M}}})}}}var le=Q;async function Y({actions:o,handlerPath:t,apiDescriptionsMap:r,graphqlDescriptions:a,mcpConfig:n,mcpMode:l,elicitationEnabled:s,gatewayFetchBudgetPerExec:i}){if(o.createRequestHandler(C,t),o.addApiRoute({slug:z,requestHandlerId:C,httpMethod:"all",getStaticData:async()=>({props:{config:{apiDescriptionsMap:r,graphqlDescriptions:a,mcpDocsServerName:n?.docs?.name||M,mcpMode:l,elicitationEnabled:s,gatewayFetchBudgetPerExec:i},serverOutDir:o.serverOutDir,tools:o.getMcpTools().map(({importPath:c,...m})=>m)}})}),f.info("Registered Docs MCP Server endpoint at /mcp"),s){const c=p(d,"./handlers/mcp-credentials-handler.js");o.createRequestHandler(P,c),o.addApiRoute({slug:K,requestHandlerId:P,httpMethod:"all",getStaticData:async()=>({props:{}})}),f.info("Registered MCP credentials endpoint at /mcp/credentials")}}export{P as MCP_CREDENTIALS_HANDLER_ID,C as MCP_DOCS_SERVER_HANDLER_ID,le as default,Q as mcpServerPlugin};
|
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
import type { McpToolSchema } from '../../../types';
|
|
2
2
|
import type { McpToolContext, SkillMcpResource } from '../types.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
3
|
+
import type { KvService } from '@redocly/config';
|
|
4
|
+
import { type McpServerInstance, type McpSessionHooks } from './mcp-server.js';
|
|
5
|
+
export declare function createDocsMcpServer({ name, tools, context, sessionHooks, skills, getKv, }: {
|
|
5
6
|
name: string;
|
|
6
7
|
tools: McpToolSchema[];
|
|
7
8
|
context: McpToolContext;
|
|
9
|
+
sessionHooks?: McpSessionHooks;
|
|
8
10
|
skills?: SkillMcpResource[];
|
|
11
|
+
getKv: () => Promise<KvService>;
|
|
9
12
|
}): Promise<McpServerInstance>;
|
|
10
13
|
//# sourceMappingURL=docs-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as _}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as u,MCP_TOOL_IS_AVAILABLE_KEY as b}from"../../../workers/mcp-tool-worker-pool.js";import{EXECUTE_TOOL_SCHEMA as M}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as p,DESCRIBE_TOOLS_TOOL_NAME as S,CODE_MODE_TOOL_NAMES as A,FETCH_TOOL_NAME as h}from"../codemode/constants.js";import{buildCodeModeInstructions as L,buildExecuteDescription as g,DESCRIBE_TOOLS_DESCRIPTION as v}from"../codemode/prompts.js";import{composeExecuteAnnotations as x,getActiveCapabilities as D}from"../codemode/capabilities/index.js";import{describeToolsSchema as y,describeTools as I}from"../codemode/tools/describe-tools.js";import{connectMcpServer as k,createMcpServer as w,createToolDispatch as N,extractSerializableContext as P}from"./mcp-server.js";async function K({name:E,tools:n,context:o,sessionHooks:d,skills:T=[],getKv:f}){const a=o.mcpMode==="code",r=a?D(o):[],s=r.some(e=>e.id===h),{server:i,transport:C}=w(E,a?L(s):void 0,d),c=P(o),m=N(c,{getClientCapabilities:()=>i.server.getClientCapabilities(),getKv:f}),l=async e=>{try{return await u.exec(b,[{toolName:e,context:c}],{timeout:1e4})}catch(t){return _.error(`Failed to check MCP tool availability for "${e}": ${t instanceof Error?t.message:String(t)}`),!1}};if(a){const e=n.filter(t=>!A.has(t.name));i.tool(p,g(s),M.schema,x(r),m(p)),i.tool(S,v,y(e,r),I(e,l,r,o))}else await Promise.all(n.map(async e=>{const t=e.annotations||{title:e.name},O=i.tool(e.name,e.description,e.schema,t,m(e.name));await l(e.name)||O.disable()}));for(const e of T)i.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 k(i,C)}export{K as createDocsMcpServer};
|
|
@@ -2,17 +2,28 @@ import { McpServer } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
|
2
2
|
import { StreamableHTTPServerTransport } from '@redocly/mcp-typescript-sdk/server/streamableHttp.js';
|
|
3
3
|
import type { ToolCallback } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
4
4
|
import type { McpToolContext } from '../types.js';
|
|
5
|
+
import type { KvService } from '@redocly/config';
|
|
5
6
|
export type McpServerInstance = {
|
|
6
7
|
server: McpServer;
|
|
7
8
|
transport: StreamableHTTPServerTransport;
|
|
8
9
|
cleanup: () => Promise<void>;
|
|
9
10
|
};
|
|
10
|
-
export
|
|
11
|
+
export type McpSessionHooks = {
|
|
12
|
+
onInitialized: (sessionId: string) => void;
|
|
13
|
+
onClosed: (sessionId: string) => void;
|
|
14
|
+
};
|
|
15
|
+
export declare function createMcpServer(name: string, instructions?: string, sessionHooks?: McpSessionHooks): {
|
|
11
16
|
server: McpServer;
|
|
12
17
|
transport: StreamableHTTPServerTransport;
|
|
13
18
|
};
|
|
14
19
|
export declare function connectMcpServer(server: McpServer, transport: StreamableHTTPServerTransport): Promise<McpServerInstance>;
|
|
20
|
+
export type ToolDispatchDeps = {
|
|
21
|
+
getClientCapabilities: () => {
|
|
22
|
+
elicitation?: unknown;
|
|
23
|
+
} | undefined;
|
|
24
|
+
getKv: () => Promise<KvService>;
|
|
25
|
+
};
|
|
15
26
|
/** Build the tool callback that ships a tool call to the worker pool. */
|
|
16
|
-
export declare function createToolDispatch(serializableContext: McpToolContext): (toolName: string) => ToolCallback<Record<string, unknown>>;
|
|
27
|
+
export declare function createToolDispatch(serializableContext: McpToolContext, deps?: ToolDispatchDeps): (toolName: string) => ToolCallback<Record<string, unknown>>;
|
|
17
28
|
export declare function extractSerializableContext(context: McpToolContext): McpToolContext;
|
|
18
29
|
//# sourceMappingURL=mcp-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{randomUUID as w}from"node:crypto";import{McpServer as h}from"@redocly/mcp-typescript-sdk/server/mcp.js";import{StreamableHTTPServerTransport as E}from"@redocly/mcp-typescript-sdk/server/streamableHttp.js";import{logger as d}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as M,MCP_TOOL_WORKER_KEY as q}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as v}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as y,stripAuthRequiredMeta as T}from"../gateway-mcp/upstream-auth.js";import{runUpstreamCredentialElicitation as b}from"../gateway-mcp/elicitation.js";import{resolveUpstreamAuthScheme as U}from"../gateway-mcp/upstream-auth-scheme.js";const D=6e4,p=new Map;function O(e,t){const r=p.get(e);if(r)return r;const s=t().finally(()=>{p.delete(e)});return p.set(e,s),s}function z(e,t,r){const s=new h({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}}),i=new E(r?{sessionIdGenerator:()=>w(),onsessioninitialized:r.onInitialized,onsessionclosed:r.onClosed}:{sessionIdGenerator:void 0});return{server:s,transport:i}}async function G(e,t){return await e.connect(t),{server:e,transport:t,cleanup:async()=>{t.close()}}}function L(e,t){return r=>async(s,i)=>{d.info(`MCP tool called: ${r}`);const m=async()=>{if(!(!e.elicitationEnabled||!i.sessionId||!t?.getKv))try{const n=await t.getKv();return await v.getSecretsForSession(n,i.sessionId)}catch(n){d.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(n)}`);return}},l=async()=>{const n=await m(),c={toolName:r,args:s,context:{...e,upstreamSecrets:n},extra:_(i)};return await M.exec(q,[c],{timeout:D})};let a=await l();const o=y(a);if(o.length>0&&e.elicitationEnabled&&i.sessionId&&t?.getKv){const n=i.sessionId,c=await t.getKv(),f=await U(e,o[0].api),u=await O(`${n}:${o[0].api}`,()=>b({sendRequest:(g,I,S)=>i.sendRequest(g,I,S),clientSupportsElicitation:!!t?.getClientCapabilities()?.elicitation,sessionId:n,baseUrl:e.baseUrl??"",events:o,auth:f,kv:c}));u.status==="accepted"?a=await l():u.status==="fallback"&&(a={...a,content:[...a.content,{type:"text",text:u.text}]})}return T(a)}}function _(e){return{sessionId:e.sessionId,authInfo:e.authInfo,requestId:e.requestId,requestInfo:e.requestInfo,_meta:e._meta}}function W(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,upstreamSecrets:e.upstreamSecrets}}export{G as connectMcpServer,z as createMcpServer,L as createToolDispatch,W as extractSerializableContext};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { McpServerInstance } from './mcp-server.js';
|
|
2
|
+
type SessionManagerOptions = {
|
|
3
|
+
maxSessions?: number;
|
|
4
|
+
onEvict?: (sessionId: string) => void;
|
|
5
|
+
};
|
|
6
|
+
export declare class McpSessionManager {
|
|
7
|
+
#private;
|
|
8
|
+
constructor(options?: SessionManagerOptions);
|
|
9
|
+
get(sessionId: string): McpServerInstance | undefined;
|
|
10
|
+
set(sessionId: string, instance: McpServerInstance): void;
|
|
11
|
+
close(sessionId: string): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export declare const mcpSessionManager: McpSessionManager;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{logger as i}from"../../../tools/notifiers/logger.js";const a=1800*1e3,c=60*1e3,o=500;class r{#t=new Map;#e;#s;constructor(t={}){this.#e=t.maxSessions??o,this.#s=t.onEvict??(()=>{}),setInterval(()=>{this.#i()},c).unref?.()}get(t){const e=this.#t.get(t);if(e)return e.lastAccess=Date.now(),this.#t.delete(t),this.#t.set(t,e),e.instance}set(t,e){const s=this.#t.get(t);if(this.#t.delete(t),this.#t.set(t,{instance:e,lastAccess:Date.now()}),s&&s.instance!==e&&this.#n(t,s.instance),this.#t.size>this.#e){const n=this.#t.keys().next().value;n!==void 0&&this.close(n)}}async close(t){const e=this.#t.get(t);e&&(this.#t.delete(t),this.#s(t),await this.#n(t,e.instance))}async#n(t,e){try{await e.cleanup()}catch(s){i.warn(`Failed to clean up MCP session ${t.slice(0,8)}\u2026: ${s instanceof Error?s.message:String(s)}`)}}async#i(){const t=Date.now()-a;for(const[e,s]of this.#t)s.lastAccess<=t&&await this.close(e)}}const f=new r;export{r as McpSessionManager,f as mcpSessionManager};
|
|
@@ -6,6 +6,7 @@ import type { OpenAPIServer } from '@redocly/openapi-docs/lib/types/open-api.js'
|
|
|
6
6
|
import type { McpErrorCodes, McpServerType } from './constants';
|
|
7
7
|
import type { McpToolSchema } from '../../types';
|
|
8
8
|
import type { Skill } from '../../types/plugins/skills.js';
|
|
9
|
+
import type { StoredSecret } from './gateway-mcp/secret-store.js';
|
|
9
10
|
type ObjectValues<T> = T[keyof T];
|
|
10
11
|
export type McpServerType = ObjectValues<typeof McpServerType>;
|
|
11
12
|
export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
|
|
@@ -26,6 +27,9 @@ export type McpDocsStaticDataPropsConfig = {
|
|
|
26
27
|
mcpDocsServerName: string;
|
|
27
28
|
apiDescriptionsMap: Record<string, ApiDescriptionInfo>;
|
|
28
29
|
graphqlDescriptions: GraphqlDescriptionInfo[];
|
|
30
|
+
mcpMode: McpMode;
|
|
31
|
+
elicitationEnabled: boolean;
|
|
32
|
+
gatewayFetchBudgetPerExec: number;
|
|
29
33
|
};
|
|
30
34
|
export type McpDocsStaticData = PageStaticData & {
|
|
31
35
|
props: {
|
|
@@ -59,18 +63,6 @@ export type McpEndpoint = OpenAPIOperation & {
|
|
|
59
63
|
'x-mcp'?: XMcpConfig;
|
|
60
64
|
};
|
|
61
65
|
export type McpMode = 'tools' | 'code';
|
|
62
|
-
export type McpPluginConfig = {
|
|
63
|
-
readonly hide: boolean;
|
|
64
|
-
readonly docs: {
|
|
65
|
-
readonly hide: boolean;
|
|
66
|
-
readonly name: string;
|
|
67
|
-
readonly ignore: readonly string[];
|
|
68
|
-
};
|
|
69
|
-
readonly gateway?: {
|
|
70
|
-
readonly hide: boolean;
|
|
71
|
-
readonly allowedHosts?: readonly string[];
|
|
72
|
-
};
|
|
73
|
-
};
|
|
74
66
|
export type McpUserInfo = {
|
|
75
67
|
email?: string;
|
|
76
68
|
name?: string;
|
|
@@ -102,6 +94,11 @@ export type McpToolContext = Omit<ApiFunctionsContext, 'telemetry' | 'getKv' | k
|
|
|
102
94
|
accessToken?: string;
|
|
103
95
|
metadata?: Record<string, unknown>;
|
|
104
96
|
upstreamAuthorization?: string;
|
|
97
|
+
mcpMode?: McpMode;
|
|
98
|
+
elicitationEnabled?: boolean;
|
|
99
|
+
gatewayFetchBudgetPerExec?: number;
|
|
100
|
+
clientIp?: string;
|
|
101
|
+
upstreamSecrets?: Record<string, StoredSecret>;
|
|
105
102
|
};
|
|
106
103
|
export type McpToolHandler<TArgs extends Record<string, unknown> = Record<string, unknown>> = (args: TArgs, context: McpToolContext, extra: McpToolExtra) => Promise<McpToolWorkerResponse>;
|
|
107
104
|
export type McpToolIsAvailable = (context: McpToolContext) => boolean | Promise<boolean>;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
|
-
import type { McpUserInfo } from '../types';
|
|
2
1
|
/**
|
|
3
2
|
* Extract JWT token from Authorization header
|
|
4
3
|
*/
|
|
5
4
|
export declare function extractTokenFromAuthHeader(authHeader?: string | string[]): string | null;
|
|
6
|
-
/**
|
|
7
|
-
* Decode and validate JWT token to get user information
|
|
8
|
-
*/
|
|
9
|
-
export declare function getUserInfoFromToken(token: string): McpUserInfo | null;
|
|
10
|
-
/**
|
|
11
|
-
* Get user info from MCP request headers
|
|
12
|
-
*/
|
|
13
|
-
export declare function getUserInfoFromHeaders(headers: Record<string, string | string[] | undefined>): McpUserInfo | null;
|
|
14
5
|
//# sourceMappingURL=jwt.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
function n(r){if(!r)return null;const e=Array.isArray(r)?r[0]:r;return!e||!e.startsWith("Bearer ")?null:e.replace(/^Bearer /,"")}export{n as extractTokenFromAuthHeader};
|
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { McpMode } from '../types.js';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Codemode - `execute` sandbox and `describeTools`. Gated by the org-level `mcpMode`
|
|
4
|
+
* entitlement (GrowthBook `mcp-mode` flag → PLAN_GATES JWT).
|
|
5
|
+
*
|
|
6
|
+
* Read the VALUE, never `canAccessFeature('mcpMode')` — 'tools' is truthy.
|
|
7
|
+
* Only call these helpers where EntitlementsProvider is initialized: the build lifecycle
|
|
8
|
+
* and web-server routes. Request handlers and workers run in module graphs with an
|
|
9
|
+
* UNINITIALIZED provider copy — they must read the build-stamped `mcpMode` from static
|
|
10
|
+
* data / McpToolContext instead (see docs-mcp-handler / execute-mcp-tool).
|
|
11
|
+
*/
|
|
3
12
|
export declare function isMcpCodeModeEnabled(): boolean;
|
|
4
|
-
/** The gateway capability — a guarded `fetch` in the `execute` sandbox. Requires
|
|
13
|
+
/** The gateway capability — a guarded `fetch` in the `execute` sandbox. Requires code mode. */
|
|
5
14
|
export declare function isMcpGatewayEnabled(): boolean;
|
|
15
|
+
export declare function isMcpElicitationEnabled(): boolean;
|
|
6
16
|
export declare function getMcpMode(): McpMode;
|
|
7
17
|
//# sourceMappingURL=mode.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{EntitlementsProvider as e}from"../../../entitlements/entitlements-provider.js";import{envConfig as n}from"../../../config/env-config.js";function t(){return e.instance().entitlements?.mcpMode==="code"}function o(){return!!e.instance().canAccessFeature("mcpGateway")&&t()}function i(){return(n.REDOCLY_EXP_MCP_ELICITATION_ENABLED??!0)&&o()}function a(){return t()?"code":"tools"}export{a as getMcpMode,t as isMcpCodeModeEnabled,i as isMcpElicitationEnabled,o as isMcpGatewayEnabled};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { McpServerType } from '../types.js';
|
|
2
|
+
/** CloudEvent resource attributes shared by every `mcpServer` telemetry event. */
|
|
3
|
+
export declare function serverAttributes(serverType: McpServerType): {
|
|
4
|
+
id: "docs";
|
|
5
|
+
object: 'mcpServer';
|
|
6
|
+
uri: string;
|
|
7
|
+
};
|
|
8
|
+
//# sourceMappingURL=telemetry-attributes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function e(r){return{id:r,object:"mcpServer",uri:`urn:redocly:realm:mcp:server:${r}`}}export{e as serverAttributes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetry as d}from"../../../telemetry/index.js";import{mcpToolHandlers as w}from"../../../../client/mcp-tool-handlers-entry.js";import{
|
|
1
|
+
import{telemetry as d}from"../../../telemetry/index.js";import{mcpToolHandlers as w}from"../../../../client/mcp-tool-handlers-entry.js";import{McpServerType as f}from"../constants.js";import{reportMcpToolCalled as y,reportMcpToolError as u}from"./mcp-tool-telemetry.js";async function b(r){d.initialize();const{toolName:o,args:c,context:i,extra:t}=r,a=i?.mcpMode??"tools",n=performance.now();try{const e=w[o];if(!e)throw new Error(`Unknown MCP tool: ${o}`);const{default:h}=await e(),l=h[o];if(!l)throw new Error(`MCP tool module does not export a handler for "${o}". Expected \`export default { '${o}': handler }\`.`);const s=await(typeof l=="function"?l:l.execute)(c,i,t);if(!x(s))throw new Error(`MCP tool "${o}" returned an invalid result.`);const m=Math.round(performance.now()-n);if(s.isError)u({tool:o,message:s.content.map(({text:p})=>p).join(" "),mode:a,serverType:f.Docs,durationMs:m});else{const p=s.content.map(({text:M})=>M).join("").length;y({tool:o,mode:a,serverType:f.Docs,durationMs:m,outputLength:p})}return s}catch(e){throw u({tool:o,message:e instanceof Error?e.message:String(e),mode:a,serverType:f.Docs,durationMs:Math.round(performance.now()-n),stack:e instanceof Error&&e.stack||""}),e}}function x(r){return!r||typeof r!="object"?!1:Array.isArray(r.content)}async function k(r){d.initialize();const{toolName:o,context:c}=r,i=performance.now();try{const t=w[o];if(!t)return!1;const{default:a}=await t(),n=a[o];return n?typeof n=="object"&&typeof n.isAvailable=="function"?await n.isAvailable(c):!0:!1}catch(t){throw u({tool:o,message:"Failed to check if MCP tool is available: "+(t instanceof Error?t.message:String(t)),mode:c?.mcpMode??"tools",serverType:f.Docs,durationMs:Math.round(performance.now()-i),stack:t instanceof Error&&t.stack||""}),t}}export{b as executeMcpTool,k as isMcpToolAvailable};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetry as
|
|
1
|
+
import{telemetry as s}from"../../../telemetry/index.js";import{serverAttributes as l}from"../utils/telemetry-attributes.js";function u({tool:r,mode:o,serverType:e,durationMs:t,outputLength:p}){s.sendMcpToolCalledMessage([{...l(e),tool:r,mode:o,output_length:p,duration_ms:t}])}function a({tool:r,mode:o,serverType:e,durationMs:t,message:p,stack:n=""}){s.sendMcpErrorMessage([{...l(e),tool:r,message:p,stack:n,mode:o,duration_ms:t}])}export{u as reportMcpToolCalled,a as reportMcpToolError};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{REDOCLY_TEAMS_RBAC as
|
|
2
|
-
`;for(const[S,
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as x}from"@redocly/config";import{basename as C,join as _}from"node:path";import q from"@markdoc/markdoc";import{joinSectionContent as G}from"../../../plugins/markdown/search/join-section-content.js";import{toMarkdown as J}from"../../../plugins/markdown/search/to-markdown.js";import{AstToSearchNodeTransformer as B}from"../../../plugins/markdown/search/walk-sections.js";import{createRenderTagFn as z}from"../../../plugins/markdown/search/create-render-tag-fn.js";import{getBuildTranslateContext as v}from"../../../utils/l10n/get-build-translate-context.js";import{canDownloadApiDefinition as V,isResourcePubliclyAccessible as Y}from"../../../utils/rbac.js";import{PUBLIC_API_DEFINITIONS_FOLDER as H}from"../../../constants/common.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as I}from"../../../../constants/common.js";import{getLlmsTxtMdPathBySlug as K}from"../../../utils/llmstxt/get-llms-txt-md-path-by-slug.js";import{AiSearchIndexer as Q}from"../ai-search-indexer.js";import{getLocaleFromRelativePath as W}from"../../../fs/utils/get-locale-from-relative-path.js";import{extractDocumentSearchFacets as X}from"./search-facets.js";import{formatDocumentMetadata as Z}from"../../search/utils.js";import{llmsTxtLink as M}from"../../search/llmstxt/index.js";import{replaceFileExtension as ee}from"../store-definition-bundles.js";const j=new Map,Ee=({parser:s,options:c,info:n,tagOperations:r,relativePath:t,openapiContentItem:e,metadata:i,getSearchFacets:u,includeInLLMsTxt:a,excludeFromSearch:f})=>async(o,p,l,O)=>{if(f)return;const U=await o.getNavText?.()||C(o.fsPath),T=new Q(s,c,o.baseSlug||o.slug),m=T.addItem(e);if(!m)return;const w=await l.getConfig(),D=Array.isArray(m.title)?m.title.join(" "):m.title;let $,d,y=j.get(t);if((e.type==="tag"||e.type==="section"&&e.infoDefinition)&&!y){const{all:A,publiclyAccessible:g}=ue(r.tagged,T,w),{all:S,publiclyAccessible:b}=le(r.untagged,T,w);j.set(t,{taggedSearchDocuments:new Map(A),untaggedSearchDocuments:S,publiclyAccessibleTaggedSearchDocuments:new Map(g),publiclyAccessibleUntaggedSearchDocuments:b})}y=j.get(t);const h="#";switch(e.type){case"operation":const A=T.getOperation(e);$=d=ce({title:D,security:s.definition.security,document:m,version:m.version||n.version,headingLevel:h,operation:A});break;case"section":if(e.infoDefinition){y=j.get(t),d=await N({parser:s,info:n,staticData:p,relativePath:t,headingLevel:h,pageName:U,config:w}),d+=`
|
|
2
|
+
`;for(const[S,b]of y?.publiclyAccessibleTaggedSearchDocuments?.entries()||[]){if(!b.length)continue;const k=s.definition.tags?.find(L=>L.name===S);d+=E({title:k?.["x-displayName"]||S,description:k?.description,operationSearchDocuments:b,headingLevel:`${h}#`})}const g=y?.publiclyAccessibleUntaggedSearchDocuments||[];g.length&&(d+=E({title:"Other",description:void 0,operationSearchDocuments:g,headingLevel:`${h}#`})),$=await N({parser:s,info:n,staticData:p,relativePath:t,headingLevel:h,pageName:U,config:w})}else if(e.ast){const g=new q.Ast.Node("document",{},e.ast),{locale:S,translate:b}=await v(o.slug,O.getGlobalData?.().l10n),k=Array.from(new B({ast:g,partials:{},renderTag:z(O.markdocOptions.tags,S,b),getInnerContent:J,skipConditionals:!0}).transform());d=$=G(k)}break;case"tag":d=E({title:D,description:e.description,operationSearchDocuments:y?.publiclyAccessibleTaggedSearchDocuments.get(e.name)||[],headingLevel:h}),$=E({title:D,description:e.description,operationSearchDocuments:[],headingLevel:h});break;case"rsrc":case"prompt":case"tool":d=re({title:D,description:e.description,name:e.name,xMcpConfig:s.definition["x-mcp"],headingLevel:h}),$=d;break}return{async getLLMsTxts(){return[{title:e.name,description:e.type==="tag"?e.description:void 0,content:d||"",slug:o.slug,fsPath:o.fsPath,includeInLLMsTxt:a}]},async getSearchDocuments(){if(e.type==="operation"||e.type==="section"&&(e.infoDefinition||e.ast)||e.type==="tag"){const A=W(o.fsPath),g=X({...m,...i},n,u);return[{title:D,description:Array.isArray(m.text)?m.text.join(" "):m.text,content:$||"",url:m.url??o.slug,fsPath:o.fsPath,locale:A,product:o.product?.name,rbacTeams:m.rbacTeams,facets:g}]}return[]}}};async function N({parser:s,info:c,staticData:n,relativePath:r,pageName:t,headingLevel:e,config:i}){const u=Z(c["x-metadata"]);let a=c.title?`${e} ${c.title}
|
|
3
3
|
|
|
4
4
|
`:`${e} ${t}
|
|
5
5
|
|
|
@@ -12,14 +12,14 @@ import{REDOCLY_TEAMS_RBAC as w}from"@redocly/config";import{basename as _,join a
|
|
|
12
12
|
`:"",e=`${e}#`,a+=u.length?`Metadata:
|
|
13
13
|
${u}
|
|
14
14
|
`:"",a+=`
|
|
15
|
-
`,a+=
|
|
15
|
+
`,a+=ne({parser:s,headingLevel:e}),a+=se({parser:s,headingLevel:e}),a+=await te({info:c,staticData:n,relativePath:r,pageName:t,headingLevel:e,config:i}),a}function E({title:s="",description:c,operationSearchDocuments:n,headingLevel:r}){let t=`${r} ${s}
|
|
16
16
|
|
|
17
17
|
`;return c&&(t+=`${c}
|
|
18
18
|
|
|
19
19
|
`),n.length&&n.forEach(e=>{const i=Array.isArray(e.title)?e.title.join(" "):e.title;t+=`${r}# ${i}${e.deprecated?" (deprecated)":""}
|
|
20
20
|
|
|
21
|
-
`,t+=` - ${M({title:`${e.httpMethod?.toUpperCase()} ${e.httpPath}`,description:Array.isArray(e.text)?e.text.join(" "):e.text,slug:
|
|
22
|
-
`}),t}function
|
|
21
|
+
`,t+=` - ${M({title:`${e.httpMethod?.toUpperCase()} ${e.httpPath}`,description:Array.isArray(e.text)?e.text.join(" "):e.text,slug:K(e.url)})}`,t+=`
|
|
22
|
+
`}),t}function ne({parser:s,headingLevel:c}){const{servers:n}=s.definition;if(n&&n.length){let r=`${c} Servers
|
|
23
23
|
|
|
24
24
|
`;return n.forEach(t=>{r+=t.description?`${t.description}
|
|
25
25
|
`:"",r+=`\`\`\`
|
|
@@ -31,9 +31,9 @@ ${t.url}
|
|
|
31
31
|
`,r+=i.default?`Default: ${JSON.stringify(i.default)}
|
|
32
32
|
`:"",r+=i.enum?`Enum: ${i.enum.map(u=>JSON.stringify(u)).join(", ")}
|
|
33
33
|
`:""}),r+=`
|
|
34
|
-
`)}),r}return""}async function
|
|
34
|
+
`)}),r}return""}async function te({info:s,staticData:c,relativePath:n,pageName:r,headingLevel:t,config:e}){const i=_(c.props?.outdir||"",H,ee(n,".yaml")),u=e.access?.rbac,a=e.access?.requiresLogin;if(V(i,u??{},a??!1,{isAuthenticated:!1,teams:[I]})){let f=`${t} Download OpenAPI description
|
|
35
35
|
|
|
36
|
-
`;return f+=M({title:s.title||r||"OpenAPI definition",description:void 0,slug:i}),f}return""}function
|
|
36
|
+
`;return f+=M({title:s.title||r||"OpenAPI definition",description:void 0,slug:i}),f}return""}function se({parser:s,headingLevel:c}){if(!s.definition.components?.securitySchemes)return"";let n=`${c} Security
|
|
37
37
|
|
|
38
38
|
`;const{securitySchemes:r}=s.definition.components;return Object.keys(r).forEach(t=>{const e=r[t];e&&(n+=`${c}# ${t}
|
|
39
39
|
|
|
@@ -52,19 +52,19 @@ ${t.url}
|
|
|
52
52
|
`),e.flows?.password?.scopes&&(n+=`Scopes:
|
|
53
53
|
`,Object.entries(e.flows?.password?.scopes||{}).forEach(([i,u])=>{n+=`- \`${i}\`: ${u}
|
|
54
54
|
`})),n+=`
|
|
55
|
-
`)}),n}function
|
|
55
|
+
`)}),n}function ce({title:s,security:c,document:n,version:r,headingLevel:t,operation:e}){const{text:i,httpMethod:u,httpPath:a,deprecated:f}=n,o=ae(n.parameters||[],`${t}#`),p=ie(`${t}#`,n.parameters,e);let l=s?`${t} ${s}${f?" (deprecated)":""}
|
|
56
56
|
|
|
57
57
|
`:"";return l+=i?`${i}
|
|
58
58
|
|
|
59
59
|
`:"",l+=`Endpoint: ${u?.toUpperCase()} ${a}
|
|
60
60
|
`,l+=r?`Version: ${r}
|
|
61
61
|
`:"",l+=n.security?.length?`Security: ${n.security.join(", ")}
|
|
62
|
-
`:c?.length?`Security: ${c.map(
|
|
62
|
+
`:c?.length?`Security: ${c.map(O=>O.id).join(", ")}
|
|
63
63
|
`:"",l+=`
|
|
64
64
|
`,l+=o?`${o}
|
|
65
65
|
`:"",l+=`
|
|
66
66
|
`,l+=`${p.join(`
|
|
67
|
-
`)}`,l}function
|
|
67
|
+
`)}`,l}function re({title:s,name:c,xMcpConfig:n,headingLevel:r}){const t=n?.tools.find(i=>i.name===c);if(!t)return"";let e=`${r} ${s}
|
|
68
68
|
|
|
69
69
|
`;return e+=t.description?`${t.description}
|
|
70
70
|
|
|
@@ -80,15 +80,15 @@ ${JSON.stringify(t.inputSchema,null,2)}
|
|
|
80
80
|
${JSON.stringify(t.outputSchema,null,2)}
|
|
81
81
|
\`\`\`
|
|
82
82
|
|
|
83
|
-
`),e}function
|
|
84
|
-
`)}function
|
|
83
|
+
`),e}function ie(s,c,n){return!c&&!n||!n?.responses?[]:n?.responses.filter(t=>!t.content?.mediaTypes[0]?.schema).map(t=>`${s} ${R(`response ${t.code} fields`)}
|
|
84
|
+
`)}function oe(s,c,n,r){const t=JSON.stringify(s),e=r.get(t);return e?`${n}Enum: same as ${e} (${s.length} values)
|
|
85
85
|
`:(r.set(t,c),`${n}Enum: ${s.map(i=>JSON.stringify(i)).join(", ")}
|
|
86
|
-
`)}function
|
|
86
|
+
`)}function P(s,c,n,r){const t=`${c} `,e=s.oneOf,u=[...s.path||[],s.name].join("."),a=Array.isArray(s.description)?s.description.join(" "):s.description,f=!!e&&e.variants.length>1;let o=`${c}- \`${u}\` (${s.type}${s.required?", required":""})`;if(f&&(o+=e.discriminator?` \u2014 one of (discriminator: ${e.discriminator}):`:" \u2014 one of:"),o+=`
|
|
87
87
|
`,o+=a?`${t}${a.trim()}
|
|
88
|
-
`:"",s.enum){const p=r?`\`${u}\` in "${r}"`:`\`${u}\``;o+=
|
|
88
|
+
`:"",s.enum){const p=r?`\`${u}\` in "${r}"`:`\`${u}\``;o+=oe(s.enum,p,t,n)}else s.example&&(o+=`${t}Example: ${s.example}
|
|
89
89
|
`);if(f)for(const p of e.variants){o+=`${c} - ${p.title}:
|
|
90
|
-
`;for(const l of p.parameters)o+=
|
|
90
|
+
`;for(const l of p.parameters)o+=P(l,`${c} `,n,p.title)}else if(e)for(const p of e.variants[0].parameters)o+=P(p,`${c} `,n);return o}function ae(s,c){const n={};for(const e of s){const i=`${e.place}${e.mediaType?` (${e.mediaType})`:""}`;n[i]=[...n[i]||[],e]}const r=new Map;return Object.entries(n).map(([e,i])=>{const u=i.map(a=>P(a," ",r));return`${c} ${R(e)}:
|
|
91
91
|
|
|
92
92
|
${u.join(`
|
|
93
93
|
`)}`}).join(`
|
|
94
|
-
`)}function
|
|
94
|
+
`)}function ue(s,c,n){const r=[],t=[];return s.forEach((e,i)=>{const u=[],a=[];e.forEach(f=>{const o=c.addItem(f);o&&(u.push(o),F({[x]:f[x],slug:o.url},n)&&a.push(o))}),r.push([i,u]),t.push([i,a])}),{all:r,publiclyAccessible:t}}function le(s,c,n){const r=[],t=[];return s.forEach(e=>{const i=c.addItem(e);i&&(r.push(i),F({[x]:e[x],slug:i.url},n)&&t.push(i))}),{all:r,publiclyAccessible:t}}function R(s){return s.charAt(0).toUpperCase()+s.slice(1)}function F(s,c){return c.access?.requiresLogin?!0:Y(s,c)}export{Ee as getAiDocumentsStore};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{REDOCLY_TEAMS_RBAC as i}from"@redocly/config";import{combineUrls as
|
|
1
|
+
import{REDOCLY_TEAMS_RBAC as i}from"@redocly/config";import{combineUrls as l}from"@redocly/theme/core/utils";import{FEEDBACK_TYPES as c}from"../../../constants/common.js";import{normalizeRouteSlug as f}from"../../../utils/path/normalize-route-slug.js";function u(t){const{contentItems:r,sidebarItems:a,routeSlug:o,navItem:s}=t;let m=!0;for(const e of r){let n;switch(e.type){case"group":a.push({type:"separator",label:e.name,hideWhenEmpty:!0,[i]:e[i]}),u({...t,contentItems:e.items,sidebarItems:a});break;case"tag":n=l(o,e.href);const b={type:"group",label:e.name,items:[],link:n,routeSlug:n,[i]:e[i]};a.push(b),u({routeSlug:o,contentItems:e.items,sidebarItems:b.items||[],navItem:s});break;case"operation":case"schema":case"rsrc":case"prompt":case"tool":e.isWebhook&&m&&(a.push({type:"separator",label:"Webhooks",variant:"secondary",hideWhenEmpty:!0}),m=!1),n=l(o,e.href),a.push({type:"link",label:e.name,httpVerb:e.type==="operation"?e.httpVerb:e.type,routeSlug:f(n),badges:e.badges,link:n,deprecated:e.deprecated,isAdditionalOperation:e.isAdditionalOperation,[i]:e[i]});break;case"section":if(e.depth===-1)continue;n=l(o,e.href);const p=e.href==="/",d={type:e.items.length?"group":"link",label:p&&s?.label?s.label:e.name,labelTranslationKey:s?.labelTranslationKey,routeSlug:n.split("#")[0]===o?o:f(n),link:n,items:[],...p&&s?.icon&&{icon:typeof s.icon=="object"?s.icon.srcSet:s.icon},...p&&s?.badges&&{badges:s.badges}};a.push(d),e.items.length&&u({routeSlug:o,contentItems:e.items,sidebarItems:d.items});break}}}function S({item:t}){return t.id===""?!0:t.type!=="group"||t.description!==""}const I=t=>(typeof t=="string"?t:t?.raw)?.replace(/\[(.*?)\][\[\(].*?[\]\)]/g,"$1")||"";function E(t){if(!t)return;let r="";const{type:a,settings:o}=t;switch(a){case c.RATING:r="Rate this section";break;case c.SENTIMENT:r="Was this section helpful?";break;case c.MOOD:r="Was this section helpful?";break;case c.COMMENT:r="Share your feedback about this section";break;case c.SCALE:r="How would you rate this section?";break}return{...t,settings:{...o,label:o?.label||r}}}function O(t){return(typeof t=="string"?t:t?.raw||"").replace(/<[^>]*>/g,"").replace(/```([\s\S]*?)```/g,"$1").replace(/`([^`]+)`/g,"$1").replace(/\*\*(.*?)\*\*/g,"$1").replace(/\*(.*?)\*/g,"$1").trim()}function A(t){if(t?.oneOf)return t;if(t?.items?.oneOf)return t.items}export{u as convertOpenAPIDocs2Sidebar,A as getOneOfSchema,E as normalizeFeedbackOptions,I as removeMarkdownLinks,S as shouldAddRoute,O as stripFormatting};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{DEFAULT_SSO_IDP_TITLE as A}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as I}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as C}from"../../tools/notifiers/logger.js";const O="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function S(T){return{id:"sso",async processContent(i){await I("build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&C.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=O,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:A,type:"OIDC",configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid"],authorizationRequestCustomParams:p,audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{S as ssoPlugin};
|
|
1
|
+
import{DEFAULT_SSO_IDP_TITLE as A}from"../../../constants/common.js";import{envConfig as d}from"../../config/env-config.js";import{telemetryTraceStep as I}from"../../../cli/telemetry/helpers/trace-step.js";import{logger as C}from"../../tools/notifiers/logger.js";const O="https://auth.cloud.redocly.com/oidc/.well-known/openid-configuration",_="https://auth.cloud.redocly.com/api/sso/oidc/introspect";async function S(T){return{id:"sso",async processContent(i){await I("build.plugin.sso",async f=>{const o=i.getConfig(),s=o.access;if(f?.setAttribute("config",`{"ssoDirect": ${JSON.stringify(o.ssoDirect||{})}}, {"sso": ${JSON.stringify(s?.sso||{})}}, {"idps": ${JSON.stringify(s?.idps||{})}}`),o.ssoDirect&&typeof o.ssoDirect=="object"&&Object.keys(o.ssoDirect).length!==0)return;const y=!!s?.sso&&(Array.isArray(s.sso)?s.sso.length>0:!0),r=!!s?.idps&&(Array.isArray(s.idps)?s.idps.length>0:!0);if(s?.sso&&Array.isArray(s.sso)&&!s.sso.length&&!r)return;const g=!!(s?.rbac&&typeof s.rbac=="object"&&Object.keys(s.rbac).length!==0),u=s?.requiresLogin;if(!g&&!u)return;y&&r&&C.error("access.sso and access.idps both set \u2014 should have been rejected by config validation",{sso:s.sso,idps:s.idps});let c=O,a=d.REDOCLY_OAUTH_USE_INTROSPECT?_:"";const e=s?.residency;if(e){const l=e.endsWith("/")?e.slice(0,-1):e;c=`${l.replace("app.","auth.")}/oidc/.well-known/openid-configuration`,a=d.REDOCLY_OAUTH_USE_INTROSPECT?`${l}/api/sso/oidc/introspect`:""}let n="AUTO";s?.sso&&(Array.isArray(s.sso)?n=s.sso.join(","):n=s.sso);let t="";s?.idps&&(Array.isArray(s.idps)?t=s.idps.join(","):t=s.idps);const p={login_hint:"{{ process.env.ORGANIZATION_ID }}",login_type:n};t&&(p.login_idps=t);const m={oidc:{title:A,type:"OIDC",configurationUrl:c,clientId:"{{ process.env.OAUTH_CLIENT_ID }}",clientSecret:"{{ process.env.OAUTH_CLIENT_SECRET }}",teamsClaimName:"https://redocly.com/sso/teams",scopes:["openid","offline"],authorizationRequestCustomParams:p,audience:"{{ process.env.ORGANIZATION_ID }}",introspectEndpoint:a}};i.setGlobalConfig({ssoDirect:m})})},async afterRoutesCreated(i){}}}export{S as ssoPlugin};
|
|
@@ -6,8 +6,9 @@ export type SandboxResult = {
|
|
|
6
6
|
export type ExecutionBudget = {
|
|
7
7
|
/**
|
|
8
8
|
* Run `work()` as a host call: its latency is exempt from the compute budget (`timeoutMs`).
|
|
9
|
-
* While the call is in flight the idle timer is paused
|
|
10
|
-
*
|
|
9
|
+
* While the call is in flight the idle timer is paused and the remaining compute budget is
|
|
10
|
+
* frozen, resuming where it stopped when the call settles — so time spent off in the host
|
|
11
|
+
* isn't charged as guest compute and the budget is never refreshed per call.
|
|
11
12
|
*/
|
|
12
13
|
hostCall<T>(work: () => Promise<T>): Promise<T>;
|
|
13
14
|
/** Rejects when a wall-clock deadline fires */
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import type { ExecutionBudget } from '../types.js';
|
|
2
2
|
import type { QuickJSContext } from 'quickjs-emscripten-core';
|
|
3
3
|
/**
|
|
4
|
-
* Time-bounds a single sandbox run. Two deadlines — a
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Time-bounds a single sandbox run. Two deadlines — a drawn-down compute budget (`timeoutMs`,
|
|
5
|
+
* spent only while the guest runs bytecode and frozen across host-call latency) and a fixed
|
|
6
|
+
* whole-run ceiling (`maxLifetimeMs`) — are each enforced two ways, because the guest is only
|
|
7
|
+
* ever in one of two states and each enforcer reaches only one:
|
|
7
8
|
* - while the guest RUNS bytecode → the interrupt handler
|
|
8
9
|
* - while the guest is PARKED on an `await` → a wall-clock `setTimeout`
|
|
9
10
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function f(
|
|
1
|
+
function f(c,t,i){const d=Date.now()+i;let l=Date.now()+t,u=t,a=()=>{};const T=new Promise((e,o)=>{a=r=>o(new Error(r))});let n;const m=()=>{clearTimeout(n),n=setTimeout(()=>a(`Execution timed out after ${t}ms`),t)};c.runtime.setInterruptHandler(()=>{const e=Date.now();return e>l||e>d}),m();const w=setTimeout(()=>a(`Exceeded the maximum lifetime of ${i}ms`),i);let s=0;return{hostCall:e=>{u=l-Date.now(),s++,clearTimeout(n);const o=()=>{c.alive&&(l=Date.now()+u,--s===0&&m())},r=e();return r.then(o,o),r},aborted:T,dispose(){clearTimeout(n),clearTimeout(w)}}}export{f as createExecutionBudget};
|
|
@@ -2,7 +2,7 @@ import type { Node } from '@markdoc/markdoc';
|
|
|
2
2
|
import type { PageStaticData, REDOCLY_ROUTE_RBAC, REDOCLY_TEAMS_RBAC, RbacScopeItems } from '@redocly/config';
|
|
3
3
|
import type { PluginDefaultOptions, PageRouteDetails, LifecycleContext, AfterRoutesCreatedActions, MarkdownParseInput } from '../../types';
|
|
4
4
|
import type { LINK_ORIGINAL_ATTR_NAME } from '../../constants/common';
|
|
5
|
-
import type {
|
|
5
|
+
import type { RenderForLlmsRenderContext } from '@redocly/theme/markdoc/tags/types';
|
|
6
6
|
export type RoutesInfoActions = {
|
|
7
7
|
outdir: string;
|
|
8
8
|
getRouteByFsPath: (relativePath: string) => PageRouteDetails | undefined;
|
|
@@ -42,5 +42,5 @@ export type ParseMarkdocOpts = {
|
|
|
42
42
|
deps?: MarkdocDeps;
|
|
43
43
|
resource?: string;
|
|
44
44
|
};
|
|
45
|
-
export type RenderTagFn = (node: Node, context:
|
|
45
|
+
export type RenderTagFn = (node: Node, context: RenderForLlmsRenderContext) => string | undefined;
|
|
46
46
|
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export declare const IV_LENGTH_BYTES = 12;
|
|
2
|
+
export declare const AUTH_TAG_LENGTH_BYTES = 16;
|
|
3
|
+
/** Marks a JWT claim value as encrypted; unprefixed values are legacy plaintext. */
|
|
4
|
+
export declare const ENCRYPTED_CLAIM_PREFIX = "enc.v1.";
|
|
5
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const E=12,T=16,_="enc.v1.";export{T as AUTH_TAG_LENGTH_BYTES,_ as ENCRYPTED_CLAIM_PREFIX,E as IV_LENGTH_BYTES};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createDecipheriv as u}from"node:crypto";import{AUTH_TAG_LENGTH_BYTES as e,IV_LENGTH_BYTES as a}from"./constants.js";import{deriveKey as f}from"./derive-key.js";function h(o,c){const r=Buffer.from(o,"base64url"),n=r.subarray(0,a),i=r.subarray(r.length-e),s=r.subarray(a,r.length-e),t=u("aes-256-gcm",f(c),n);return t.setAuthTag(i),Buffer.concat([t.update(s),t.final()]).toString("utf8")}export{h as decryptAesGcm};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns the decrypted claim value, the value itself when it is legacy
|
|
3
|
+
* plaintext, or undefined when it is missing or fails to decrypt.
|
|
4
|
+
*/
|
|
5
|
+
export declare function decryptClaimValue(value: unknown, secret: string): string | undefined;
|
|
6
|
+
//# sourceMappingURL=decrypt-claim-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ENCRYPTED_CLAIM_PREFIX as t}from"./constants.js";import{decryptAesGcm as n}from"./decrypt-aes-gcm.js";function c(r,e){if(!(typeof r!="string"||!r)){if(!r.startsWith(t))return r;try{return n(r.slice(t.length),e)}catch{return}}}export{c as decryptClaimValue};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{hkdfSync as t}from"node:crypto";const r=32,c="redocly-portal",f="claim-encryption",n=new Map;function y(o){let e=n.get(o);return e||(e=Buffer.from(t("sha256",o,c,f,r)),n.set(o,e)),e}export{y as deriveKey};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createCipheriv as i,randomBytes as n}from"node:crypto";import{IV_LENGTH_BYTES as f}from"./constants.js";import{deriveKey as a}from"./derive-key.js";function s(r,o){const e=n(f),t=i("aes-256-gcm",a(o),e),c=Buffer.concat([t.update(r,"utf8"),t.final()]);return Buffer.concat([e,c,t.getAuthTag()]).toString("base64url")}export{s as encryptAesGcm};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encrypts a JWT claim value and prefixes it so `decryptClaimValue` can tell
|
|
3
|
+
* encrypted values apart from legacy plaintext ones.
|
|
4
|
+
*/
|
|
5
|
+
export declare function encryptClaimValue(value: string, secret: string): string;
|
|
6
|
+
//# sourceMappingURL=encrypt-claim-value.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ENCRYPTED_CLAIM_PREFIX as e}from"./constants.js";import{encryptAesGcm as m}from"./encrypt-aes-gcm.js";function p(r,t){return`${e}${m(r,t)}`}export{p as encryptClaimValue};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { TFunction } from '@redocly/theme/core/types';
|
|
2
|
+
import type { GlobalData } from '../../../types/index.js';
|
|
3
|
+
export declare function getBuildTranslateContext(slug: string, l10n: GlobalData['l10n']): Promise<{
|
|
4
|
+
locale: string;
|
|
5
|
+
translate: TFunction;
|
|
6
|
+
}>;
|
|
7
|
+
//# sourceMappingURL=get-build-translate-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import i from"i18next";import{getLocaleFromPathname as s}from"@redocly/theme/core/utils";import{DEFAULT_LOCALE_PLACEHOLDER as c}from"../../../constants/common.js";import{buildI18nConfig as l}from"../../../utils/l10n/build-i18n-config.js";import{createTranslate as f}from"../../../utils/l10n/create-translate.js";let o;function m(t){if(!o||o.l10n!==t){const e=(async()=>{const a=i.createInstance(),n=t?.defaultLocale||c;return await a.init(await l(t,n)),a})();o={l10n:t,instance:e}}return o.instance}async function x(t,e){const a=e?.defaultLocale||c,n=s(t,a,e?.locales??[]),r=await m(e);return{locale:n,translate:f(r.getFixedT(n))}}export{x as getBuildTranslateContext};
|
|
@@ -11,6 +11,7 @@ export declare function getScopeItemsForResource(rbacConfig: RbacConfig | undefi
|
|
|
11
11
|
fsPath?: string;
|
|
12
12
|
slug?: string;
|
|
13
13
|
}): RbacScopeItems;
|
|
14
|
+
export declare function hasScopeAccess(scopeItems: RbacScopeItems, teams: string[], email?: string): boolean;
|
|
14
15
|
export declare function canAccessFeature(feature: RbacFeatures, auth: AuthDetails, rbacConfig?: RbacConfig, requiresLogin?: boolean): boolean;
|
|
15
16
|
export declare function isResourcePubliclyAccessible(resource: {
|
|
16
17
|
slug: string;
|
|
@@ -140,6 +141,9 @@ export declare const normalizeRbacConfig: (rbacConfig: RbacConfig) => {
|
|
|
140
141
|
aiSearch?: {
|
|
141
142
|
[x: string]: string;
|
|
142
143
|
} | undefined;
|
|
144
|
+
mcp?: {
|
|
145
|
+
[x: string]: string;
|
|
146
|
+
} | undefined;
|
|
143
147
|
} | undefined;
|
|
144
148
|
reunite?: {
|
|
145
149
|
[x: string]: string;
|