@redocly/realm 0.136.0-next.7 → 0.136.0-next.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +42 -0
- package/dist/server/api-routes/helpers/enhance-context.js +1 -1
- package/dist/server/api-routes/run-api-routes-worker.js +1 -1
- package/dist/server/config/env-config.d.ts +0 -2
- package/dist/server/config/env-schema.d.ts +0 -5
- package/dist/server/config/env-schemas/feature-flags.d.ts +0 -4
- package/dist/server/config/env-schemas/feature-flags.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.js +1 -1
- package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/code-audit.d.ts +12 -0
- package/dist/server/plugins/mcp/codemode/code-audit.js +1 -0
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.d.ts +11 -0
- package/dist/server/plugins/mcp/codemode/code-execution-telemetry.js +1 -0
- package/dist/server/plugins/mcp/codemode/tools/describe-tools.d.ts +2 -3
- package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +1 -1
- package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/constants.d.ts +1 -1
- package/dist/server/plugins/mcp/constants.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +19 -18
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +2 -2
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-bridge.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.d.ts +2 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/fetch-telemetry.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.d.ts +6 -0
- package/dist/server/plugins/mcp/gateway-mcp/fetch/normalize-path.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.d.ts +8 -0
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/rate-limit-telemetry.js +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/upstream-auth.d.ts +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/handlers/errors.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.d.ts +2 -3
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.d.ts +10 -14
- package/dist/server/plugins/mcp/servers/mcp-server.js +1 -1
- package/dist/server/plugins/mcp/types.d.ts +6 -6
- package/dist/server/plugins/mcp/utils/json-schema-validator.d.ts +9 -0
- package/dist/server/plugins/mcp/utils/json-schema-validator.js +1 -0
- package/dist/server/plugins/mcp/utils/mode.js +1 -1
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.d.ts +9 -1
- package/dist/server/plugins/mcp/workers/mcp-tool-telemetry.js +1 -1
- package/dist/server/plugins/search/ai-indexer/prepare-semantic-documents.js +2 -2
- package/dist/server/plugins/search/engines/flexsearch/index.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
- package/dist/server/plugins/search/engines/typesense/index.js +1 -1
- package/dist/server/tools/notifiers/logger.js +1 -1
- package/dist/server/tools/notifiers/reporter.js +6 -6
- package/dist/server/types/plugins/common.d.ts +1 -1
- package/dist/server/web-server/auth.js +3 -3
- package/dist/server/web-server/middleware/telemetry-middleware.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-related-entities.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog-revisions.js +1 -1
- package/dist/server/web-server/routes/catalog/bff-catalog.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog-relations.js +1 -1
- package/dist/server/web-server/routes/catalog/catalog.js +1 -1
- package/dist/server/web-server/routes/dynamic-route.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/a2a.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/agent-card.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
- package/dist/server/web-server/routes/page-data.js +1 -1
- package/dist/server/web-server/routes/search.js +1 -1
- package/dist/server/web-server/routes/skills/skill-markdown.js +1 -1
- package/dist/server/web-server/routes/skills/skills-index.js +1 -1
- package/dist/utils/url/parse-preview-url.d.ts +22 -0
- package/dist/utils/url/parse-preview-url.js +1 -0
- package/package.json +9 -10
- package/dist/server/plugins/mcp/handlers/sse-keepalive.d.ts +0 -15
- package/dist/server/plugins/mcp/handlers/sse-keepalive.js +0 -3
- package/dist/server/plugins/mcp/servers/session-manager.d.ts +0 -15
- package/dist/server/plugins/mcp/servers/session-manager.js +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,40 @@
|
|
|
1
1
|
# @redocly/realm
|
|
2
2
|
|
|
3
|
+
## 0.136.0-next.9
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 8a7207311bf: Improved credential handling and rate limiting in the experimental gateway MCP.
|
|
8
|
+
- 9310f9f2f61: Fixed an issue in the Typesense search engine where search requests failed with a 500 error when the query matched an API reference parameter whose search highlight did not include a deep link.
|
|
9
|
+
- 807da14929c: Updated the project MCP server to the official MCP TypeScript SDK v2.
|
|
10
|
+
|
|
11
|
+
Added support for the 2026-07-28 MCP protocol revision, including secure upstream API credential prompts for clients on the new revision.
|
|
12
|
+
Existing MCP clients keep working unchanged.
|
|
13
|
+
|
|
14
|
+
- 807da14929c: Fixed intermittent `Session not found` errors from the MCP server.
|
|
15
|
+
- 5201784becc: Fixed security vulnerabilities `CVE-2026-69207` by upgrading `hono` to version `4.12.34`.
|
|
16
|
+
- Updated dependencies [425dcb52e77]
|
|
17
|
+
- Updated dependencies [eeb60efed5a]
|
|
18
|
+
- Updated dependencies [f585e1a2be9]
|
|
19
|
+
- @redocly/api-docs@0.1.0-next.1
|
|
20
|
+
- @redocly/realm-asyncapi-sdk@0.14.0-next.2
|
|
21
|
+
- @redocly/theme@0.68.0-next.5
|
|
22
|
+
- @redocly/openapi-docs@3.24.0-next.8
|
|
23
|
+
- @redocly/asyncapi-docs@1.13.0-next.8
|
|
24
|
+
- @redocly/graphql-docs@1.13.0-next.8
|
|
25
|
+
- @redocly/portal-plugin-mock-server@0.21.0-next.8
|
|
26
|
+
|
|
27
|
+
## 0.136.0-next.8
|
|
28
|
+
|
|
29
|
+
### Patch Changes
|
|
30
|
+
|
|
31
|
+
- 17dd03b5965: Hardened access control of `llms.txt` on the homepage Markdown page.
|
|
32
|
+
- b6c997c11b1: Fixed fetch capability in an experimental gateway MCP.
|
|
33
|
+
- 17dd03b5965: Improved response time on sites with many pages that use the `llms.txt` feature.
|
|
34
|
+
- Updated dependencies [b6c997c11b1]
|
|
35
|
+
- @redocly/realm-asyncapi-sdk@0.14.0-next.1
|
|
36
|
+
- @redocly/theme@0.68.0-next.5
|
|
37
|
+
|
|
3
38
|
## 0.136.0-next.7
|
|
4
39
|
|
|
5
40
|
### Minor Changes
|
|
@@ -153,6 +188,13 @@
|
|
|
153
188
|
- @redocly/graphql-docs@1.13.0-next.0
|
|
154
189
|
- @redocly/portal-plugin-mock-server@0.21.0-next.0
|
|
155
190
|
|
|
191
|
+
## 0.135.2
|
|
192
|
+
|
|
193
|
+
### Patch Changes
|
|
194
|
+
|
|
195
|
+
- c6f35a51db4: Hardened access control of `llms.txt` on the homepage Markdown page.
|
|
196
|
+
- c6f35a51db4: Improved response time on sites with many pages that use the `llms.txt` feature.
|
|
197
|
+
|
|
156
198
|
## 0.135.1
|
|
157
199
|
|
|
158
200
|
### Patch Changes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{deleteCookie as p,getCookie as
|
|
1
|
+
import{deleteCookie as p,getCookie as g,setCookie as k}from"hono/cookie";import{createQuickJsMockExecutor as b}from"../mock-server/mock-js-executor.js";import{createKvStateStore as j}from"../mock-server/kv-state-store.js";const q=new Set([101,103,204,205,304]),l=t=>t!==void 0&&q.has(t),E=({honoCtx:t,ctx:m,telemetry:u,getKv:d})=>{const c=t.req.routePath,f=t.req.param(),S=Object.fromEntries(Object.entries(f).map(([e,r])=>{if(r&&(c.includes(`/:${e}{.*}`)||c.includes(`/:${e}{.+}`))){const a=r.split("/").filter(Boolean);return[e,a.length?a:void 0]}return[e,r]}));let n;const o=e=>{n=e,t.status(e)},s={...t.res,status:e=>(o(e),s),json:e=>l(n)?t.body(null):t.json(e),text:(e,r)=>(r&&o(r),l(n)?t.body(null):t.text(e)),redirect:(e,r=302)=>t.redirect(e,r),setCookie:(e,r,i)=>(k(t,e,r,i),s),deleteCookie:e=>(p(t,e),s)};return{...m,...s,params:S,query:t.req.query()||{},cookies:g(t),telemetry:u?{sendCustomMessage:e=>u.sendCustomMessage([{...e,id:e.name,object:"customEvent",uri:`urn:redocly:realm:api:customEvent:${e.name}`}])}:void 0,getKv:d}};function A(t){return{...E(t),executor:b(),store:j(t.getKv,["mock",String(t.slug??"default")])}}export{E as enhanceContext,A as enhanceMockServerContext};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as p from"workerpool";import{withPathPrefix as E}from"@redocly/theme/core/utils";import{envConfig as u}from"../config/env-config.js";import{telemetry as a}from"../telemetry/index.js";import{TimeoutExceededError as f}from"./errors/timeout-exceeded.js";import{serializeRequest as g}from"./helpers/serialize-request.js";import{apiRoutesWorkers as A,API_ROUTES_WORKER_KEY as T}from"../workers/api-routes-worker-pool.js";import{API_FUNCTIONS_REQUEST_HANDLER_ID as
|
|
1
|
+
import*as p from"workerpool";import{withPathPrefix as E}from"@redocly/theme/core/utils";import{envConfig as u}from"../config/env-config.js";import{telemetry as a}from"../telemetry/index.js";import{TimeoutExceededError as f}from"./errors/timeout-exceeded.js";import{serializeRequest as g}from"./helpers/serialize-request.js";import{apiRoutesWorkers as A,API_ROUTES_WORKER_KEY as T}from"../workers/api-routes-worker-pool.js";import{API_FUNCTIONS_REQUEST_HANDLER_ID as m}from"../plugins/api-functions/index.js";const h=1e4,S=15;async function v(e,r,i){a.initialize();const t=r.get("auth"),s=await i.resolveRouteStaticData(e)||{},n=E(e.slug);try{const{status:o,headers:d,body:c}=await A.exec(T,[{serverOutDir:i.serverOutDir,slug:n,requestHandlerId:e.requestHandlerId,maxResponseSizeMB:S,ctxData:{user:{teams:t.teams,email:t.claims.email,claims:t.claims,idpAccessToken:t.idpAccessToken,idpId:t.claims.idpId,isAuthenticated:t.isAuthenticated},config:i.config,outdir:i.outdir,baseUrl:new URL(r.req.url).origin},staticData:{...s,props:{...s.props,routeSlug:n,outdir:i.outdir}},req:await g(r.req.raw),sqldRemoteDatabaseUrl:u.SQLD_REMOTE_DATABASE_URL,sqldRemoteDatabaseAuthToken:u.SQLD_REMOTE_DATABASE_AUTH_TOKEN}],{timeout:h});R({requestHandlerId:e.requestHandlerId,status:o,ctx:r});const l=c.data?Buffer.from(c.data):null;return new Response(l,{status:o,headers:d})}catch(o){throw _({requestHandlerId:e.requestHandlerId,error:o}),o instanceof p.Promise.TimeoutError?new f("Timeout exceeded"):o}}function R({requestHandlerId:e,status:r,ctx:i}){e.startsWith(m)?a.sendApiFunctionCalledMessage([{id:"apiFunctionId",object:"apiFunction",uri:"urn:redocly:realm:api:apiFunction:apiFunctionId",handler:e,status:r,message:null}]):a.sendMockServerCalledMessage([{id:e,object:"mockServer",uri:`urn:redocly:realm:api:mockServer:${e}`,error:null,handler:e,headers:{"user-agent":i.req.header("user-agent")??null},status:r}])}function _({requestHandlerId:e,error:r}){e.startsWith(m)?a.sendApiFunctionErrorMessage([{id:"apiFunctionId",object:"apiFunction",uri:"urn:redocly:realm:api:apiFunction:apiFunctionId",status:500,handler:e,message:r.message}]):a.sendMockServerErrorMessage([{id:e,object:"mockServer",uri:`urn:redocly:realm:api:mockServer:${e}`,handler:e,message:r.message}])}export{v as runApiRoutesWorker,_ as sendTelemetryErrorMessage};
|
|
@@ -53,7 +53,6 @@ declare function loadEnvConfig(): {
|
|
|
53
53
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
54
54
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
55
55
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: boolean | undefined;
|
|
56
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: boolean | undefined;
|
|
57
56
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
58
57
|
SEARCH_DEV_DEBUG: boolean;
|
|
59
58
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -134,7 +133,6 @@ export declare const envConfig: {
|
|
|
134
133
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
135
134
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
136
135
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: boolean | undefined;
|
|
137
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: boolean | undefined;
|
|
138
136
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
139
137
|
SEARCH_DEV_DEBUG: boolean;
|
|
140
138
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -57,7 +57,6 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
|
|
|
57
57
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL: z.ZodOptional<z.ZodString>;
|
|
58
58
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT: z.ZodOptional<z.ZodString>;
|
|
59
59
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
|
|
60
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
|
|
61
60
|
} & {
|
|
62
61
|
SEARCH_DEV_REINIT: z.ZodOptional<z.ZodString>;
|
|
63
62
|
SEARCH_DEV_DEBUG: z.ZodEffects<z.ZodDefault<z.ZodEnum<["true", "false"]>>, boolean, "false" | "true" | undefined>;
|
|
@@ -135,7 +134,6 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
|
|
|
135
134
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
136
135
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
137
136
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: boolean | undefined;
|
|
138
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: boolean | undefined;
|
|
139
137
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
140
138
|
SEARCH_DEV_DEBUG: boolean;
|
|
141
139
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -206,7 +204,6 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
|
|
|
206
204
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
207
205
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
208
206
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: "false" | "true" | undefined;
|
|
209
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: "false" | "true" | undefined;
|
|
210
207
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
211
208
|
SEARCH_DEV_DEBUG?: "false" | "true" | undefined;
|
|
212
209
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -277,7 +274,6 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
|
|
|
277
274
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
278
275
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
279
276
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: boolean | undefined;
|
|
280
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: boolean | undefined;
|
|
281
277
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
282
278
|
SEARCH_DEV_DEBUG: boolean;
|
|
283
279
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -348,7 +344,6 @@ export declare const envSchema: z.ZodEffects<z.ZodObject<{
|
|
|
348
344
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
349
345
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
350
346
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: "false" | "true" | undefined;
|
|
351
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: "false" | "true" | undefined;
|
|
352
347
|
SEARCH_DEV_REINIT?: string | undefined;
|
|
353
348
|
SEARCH_DEV_DEBUG?: "false" | "true" | undefined;
|
|
354
349
|
TYPESENSE_API_URL?: string | undefined;
|
|
@@ -17,8 +17,6 @@ export declare const featureFlagsSchema: z.ZodObject<{
|
|
|
17
17
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT: z.ZodOptional<z.ZodString>;
|
|
18
18
|
/** Escape hatch: disables the Node Permission Model sandbox on API function and MCP tool worker processes (hosted Reunite environments only). */
|
|
19
19
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
|
|
20
|
-
/** Prompt for upstream API credentials via URL-mode elicitation. Enabled by default wherever the gateway capability is enabled; set to `false` to disable. */
|
|
21
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED: z.ZodEffects<z.ZodOptional<z.ZodEnum<["true", "false"]>>, boolean | undefined, "false" | "true" | undefined>;
|
|
22
20
|
}, "strip", z.ZodTypeAny, {
|
|
23
21
|
NEW_CATALOG_ENABLED?: boolean | undefined;
|
|
24
22
|
NEW_SCORECARDS_ENABLED?: boolean | undefined;
|
|
@@ -30,7 +28,6 @@ export declare const featureFlagsSchema: z.ZodObject<{
|
|
|
30
28
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
31
29
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
32
30
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: boolean | undefined;
|
|
33
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: boolean | undefined;
|
|
34
31
|
}, {
|
|
35
32
|
NEW_CATALOG_ENABLED?: "false" | "true" | undefined;
|
|
36
33
|
NEW_SCORECARDS_ENABLED?: "false" | "true" | undefined;
|
|
@@ -42,6 +39,5 @@ export declare const featureFlagsSchema: z.ZodObject<{
|
|
|
42
39
|
REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL?: string | undefined;
|
|
43
40
|
REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT?: string | undefined;
|
|
44
41
|
REDOCLY_DISABLE_API_FUNCTION_SANDBOX?: "false" | "true" | undefined;
|
|
45
|
-
REDOCLY_EXP_MCP_ELICITATION_ENABLED?: "false" | "true" | undefined;
|
|
46
42
|
}>;
|
|
47
43
|
//# sourceMappingURL=feature-flags.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const
|
|
1
|
+
import{z as _}from"zod";import{envBooleanStringOptional as E}from"../../utils/envs/env-boolean-string.js";const o=_.object({NEW_CATALOG_ENABLED:E(),NEW_SCORECARDS_ENABLED:E(),ENABLE_COMMENTS:_.string().optional(),REDOCLY_EXP_DISABLE_MD_VALIDATION:E(),ENABLE_SOURCE_MAPS:E(),PLAN_GATES:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_ENABLED:E(),REDOCLY_EXP_LLMSTXT_AGENT_FEEDBACK_URL:_.string().optional(),REDOCLY_EXP_LLMSTXT_AGENT_ENDPOINT:_.string().optional(),REDOCLY_DISABLE_API_FUNCTION_SANDBOX:E()});export{o as featureFlagsSchema};
|
package/dist/server/plugins/catalog-entities/database/repositories/catalog-entities-repository.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as s}from"../../../../tools/notifiers/logger.js";import{telemetryTraceStep as r}from"../../../../telemetry/helpers/trace-step.js";import{BaseRepository as a}from"../../../../providers/database/base-repository.js";import{createDatabaseRepositoryInstance as n}from"../../../../providers/database/instance-cache-resolver.js";import{RelationsReadRepository as c}from"./relations/relations-read-repository.js";import{RevisionRepository as l}from"./common/revision-repository.js";import{BffEntitiesReadRepository as p}from"./bffEntities/bff-entities-read-repository.js";import{EntitiesReadRepository as y}from"./entities/entities-read-repository.js";import{EntitiesWriteRepository as R}from"./entities/entities-write-repository.js";import{RelationsWriteRepository as m}from"./relations/relations-write-repository.js";import{FiltersRepository as g}from"./common/filters-repository.js";class o extends a{entitiesRead;entitiesWrite;relationsRead;relationsWrite;bffEntitiesRead;filters;revisions;get transactionsManager(){return this.databaseClient.transactionsManager}constructor(t){super(t),this.revisions=new l(t.client),this.bffEntitiesRead=new p(t.client),this.relationsRead=new c(t.client),this.entitiesRead=new y(t.client),this.entitiesWrite=new R(t.client,this.organizationId,this.projectId),this.relationsWrite=new m(t.client,this.organizationId,this.projectId),this.filters=new g(t.client)}async sync(){return r("com.redocly.catalogEntities.repository.sync",async t=>{t?.setAttribute("id","catalogEntitiesRepositoryId"),t?.setAttribute("object","catalogEntitiesRepository"),t?.setAttribute("uri","urn:redocly:realm:api:catalogEntitiesRepository:catalogEntitiesRepositoryId"),await this.databaseClient.sync()})}static async create(t){return await r("com.redocly.catalogEntities.repository.getInstance",async i=>{i?.setAttribute("id","catalogEntitiesRepositoryId"),i?.setAttribute("object","catalogEntitiesRepository"),i?.setAttribute("uri","urn:redocly:realm:api:catalogEntitiesRepository:catalogEntitiesRepositoryId");try{return await n(t,"catalog entities",o)}catch(e){throw s.error("Error creating db connection for catalog entities repository",e),i?.error(e),e}})}}export{o as CatalogEntitiesRepository};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolAnnotations } from '@
|
|
1
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { McpToolContext } from '../../types.js';
|
|
3
3
|
/** A capability is a per-request-gated global the code-mode sandbox exposes beyond the schema-driven `tools.*` surface. */
|
|
4
4
|
export type SandboxCapability = {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolAnnotations } from '@
|
|
1
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { McpToolSchema } from '../../../../types';
|
|
3
3
|
import type { McpToolContext } from '../../types.js';
|
|
4
4
|
import type { SandboxCapability } from './types.js';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type CodeAudit = {
|
|
2
|
+
sha256: string;
|
|
3
|
+
length: number;
|
|
4
|
+
flags: string;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Fingerprint model-supplied code for the audit trail. The body itself is never reported — it can
|
|
8
|
+
* contain data the model already pulled from a customer API — so callers get a hash plus flags for
|
|
9
|
+
* patterns worth reviewing. The sandbox blocks all of the flagged targets; a flag is an attempt.
|
|
10
|
+
*/
|
|
11
|
+
export declare function auditCode(code: string): CodeAudit;
|
|
12
|
+
//# sourceMappingURL=code-audit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{createHash as e}from"node:crypto";const n=/(169\.254\.169\.254|metadata\.google\.internal|\.consul\b|\.internal\b|localhost|127\.0\.0\.1|\b10\.\d{1,3}\.\d{1,3}\.\d{1,3}\b|\b192\.168\.\d{1,3}\.\d{1,3}\b|\b172\.(?:1[6-9]|2\d|3[01])\.\d{1,3}\.\d{1,3}\b)/i,a=/(process\s*(?:\.\s*env\b|\[)|globalThis|require\s*\(|__proto__)/;function r(t){const s=[];return a.test(t)&&s.push("env_probe"),n.test(t)&&s.push("internal_target"),{sha256:e("sha256").update(t,"utf8").digest("hex"),length:t.length,flags:s.sort().join(",")}}export{r as auditCode};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { CodeAudit } from './code-audit.js';
|
|
2
|
+
type CodeExecutedEvent = {
|
|
3
|
+
audit: CodeAudit;
|
|
4
|
+
fetchCount: number;
|
|
5
|
+
outcome: 'ok' | 'error';
|
|
6
|
+
durationMs: number;
|
|
7
|
+
};
|
|
8
|
+
/** Audit record for one sandbox run. Carries the code fingerprint, never the code. */
|
|
9
|
+
export declare function reportCodeExecuted({ audit, fetchCount, outcome, durationMs, }: CodeExecutedEvent): void;
|
|
10
|
+
export {};
|
|
11
|
+
//# sourceMappingURL=code-execution-telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{telemetry as c}from"../../../telemetry/index.js";import{logger as s}from"../../../tools/notifiers/logger.js";import{McpServerType as f}from"../constants.js";import{serverAttributes as g}from"../utils/telemetry-attributes.js";function p({audit:e,fetchCount:o,outcome:r,durationMs:t}){try{c.sendMcpCodeExecutedMessage([{...g(f.Docs),code_sha256:e.sha256,code_length:e.length,fetch_count:o,outcome:r,flags:e.flags,duration_ms:t}])}catch{}s.info(`Gateway MCP code executed [${e.sha256.slice(0,12)}] outcome=${r} codeLength=${e.length} fetchCount=${o}`+(e.flags?` flags=${e.flags}`:"")+` durationMs=${t}`)}export{p as reportCodeExecuted};
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import type { ToolCallback } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
2
1
|
import type { McpToolSchema } from '../../../../types';
|
|
3
|
-
import type { McpToolContext } from '../../types.js';
|
|
2
|
+
import type { McpToolCallback, McpToolContext } from '../../types.js';
|
|
4
3
|
import { type SandboxCapability } from '../capabilities/index.js';
|
|
5
4
|
export declare function describeToolsSchema(tools: McpToolSchema[], capabilities: SandboxCapability[]): Record<string, unknown>;
|
|
6
|
-
export declare function describeTools(tools: McpToolSchema[], isToolAvailable: (toolName: string) => Promise<boolean>, capabilities: SandboxCapability[], context: McpToolContext):
|
|
5
|
+
export declare function describeTools(tools: McpToolSchema[], isToolAvailable: (toolName: string) => Promise<boolean>, capabilities: SandboxCapability[], context: McpToolContext): McpToolCallback;
|
|
7
6
|
//# sourceMappingURL=describe-tools.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ToolAnnotations } from '@
|
|
1
|
+
import type { ToolAnnotations } from '@modelcontextprotocol/server';
|
|
2
2
|
import type { McpToolSchema } from '../../../../types';
|
|
3
3
|
export declare const EXECUTE_BASE_ANNOTATIONS: ToolAnnotations;
|
|
4
4
|
export declare const EXECUTE_TOOL_SCHEMA: McpToolSchema;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{mcpToolHandlers as l}from"../../../../../client/mcp-tool-handlers-entry.js";import{runInSandbox as
|
|
1
|
+
import{mcpToolHandlers as l}from"../../../../../client/mcp-tool-handlers-entry.js";import{runInSandbox as p}from"../../../../sandbox/sandbox.js";import{isMcpToolAvailable as h}from"../../workers/execute-mcp-tool.js";import{buildExecuteHostFetch as b,isFetchCapable as E}from"../../gateway-mcp/fetch-capability.js";import{withAuthRequiredMeta as T}from"../../gateway-mcp/upstream-auth.js";import{CODE_MODE_TOOL_NAMES as O,EXECUTE_TOOL_NAME as A}from"../constants.js";import{sanitizeToolName as C}from"../build-tool-type-declarations.js";import{invokeTool as w}from"../invoke-tool.js";import{createSandboxSetup as x}from"../sandbox/create-sandbox-setup.js";import{auditCode as M}from"../code-audit.js";import{reportCodeExecuted as v}from"../code-execution-telemetry.js";const y=async(t,e,r)=>{const o=await N(e,r),n=[],i=E(e)?b(e,s=>n.push(s)):void 0;let c=0;const u=i?s=>(c+=1,i(s)):void 0,d=M(t.code),m=Date.now(),{result:f,error:a}=await p(t.code,{setupContext:x(o,u)});return v({audit:d,fetchCount:c,outcome:a===void 0?"ok":"error",durationMs:Date.now()-m}),T({content:[{type:"text",text:JSON.stringify({result:f,error:a})}],isError:a!==void 0},n)};async function N(t,e){const r={};for(const o of Object.keys(l))O.has(o)||!await h({toolName:o,context:t}).catch(()=>!1)||(r[C(o)]=i=>w(o,i,t,e));return r}var B={[A]:y};export{B as default};
|
|
@@ -8,7 +8,7 @@ export declare const McpErrorCodes: {
|
|
|
8
8
|
readonly MethodNotFound: -32601;
|
|
9
9
|
readonly InvalidParams: -32602;
|
|
10
10
|
};
|
|
11
|
-
export declare const MCP_PROTOCOL_VERSION = "2025-
|
|
11
|
+
export declare const MCP_PROTOCOL_VERSION = "2025-11-25";
|
|
12
12
|
export declare const DEFAULT_CONNECTION_TIMEOUT_MS = 30000;
|
|
13
13
|
export declare const SSE_KEEPALIVE_INTERVAL_MS = 15000;
|
|
14
14
|
export declare const MAX_DOCUMENTS_PER_CATEGORY = 3;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
import{LATEST_PROTOCOL_VERSION as o}from"@modelcontextprotocol/server";const E={Docs:"docs"},e={InternalError:-32603,ServerError:-32e3,InvalidRequest:-32600,MethodNotFound:-32601,InvalidParams:-32602},t=o,_=3e4,O=15e3,s=3,n="mcp-not-allowed",T="Docs MCP server",S="createAnonymousSession";export{S as CREATE_ANONYMOUS_SESSION_TOOL_NAME,_ as DEFAULT_CONNECTION_TIMEOUT_MS,T as DEFAULT_DOCS_MCP_SERVER_NAME,s as MAX_DOCUMENTS_PER_CATEGORY,n as MCP_NOT_ALLOWED_TEMPLATE_ID,t as MCP_PROTOCOL_VERSION,e as McpErrorCodes,E as McpServerType,O as SSE_KEEPALIVE_INTERVAL_MS};
|
|
@@ -1,27 +1,28 @@
|
|
|
1
|
+
import type { InputRequiredResult } from '@modelcontextprotocol/server';
|
|
1
2
|
import type { UpstreamAuthRequiredEvent } from './upstream-auth.js';
|
|
2
3
|
import type { UpstreamAuthScheme } from './upstream-auth-scheme.js';
|
|
3
4
|
import type { KvService } from '@redocly/config';
|
|
4
|
-
export declare const
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
status: 'fallback';
|
|
14
|
-
text: string;
|
|
15
|
-
} | {
|
|
16
|
-
status: 'skipped';
|
|
17
|
-
};
|
|
18
|
-
export declare function runUpstreamCredentialElicitation({ sendRequest, clientSupportsElicitation, subject, baseUrl, events, auth, kv, }: {
|
|
19
|
-
sendRequest: SendElicitRequest;
|
|
20
|
-
clientSupportsElicitation: boolean;
|
|
5
|
+
export declare const CREDENTIALS_INPUT_REQUEST_KEY = "credentials";
|
|
6
|
+
export declare function isCredentialElicitationDeclined(inputResponses: Record<string, unknown> | undefined): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The 2026-07-28-era credentials prompt: the tool call returns an input-required result the
|
|
9
|
+
* client fulfils and retries, with no push `elicitation/create` and no session behind it.
|
|
10
|
+
* Nothing has to survive the round trip - the secrets are keyed by `subject`, which is
|
|
11
|
+
* recomputed from the caller's identity on every request.
|
|
12
|
+
*/
|
|
13
|
+
export declare function buildUpstreamCredentialInputRequired({ subject, baseUrl, events, auth, kv, }: {
|
|
21
14
|
subject: string;
|
|
22
15
|
baseUrl: string;
|
|
23
16
|
events: UpstreamAuthRequiredEvent[];
|
|
24
17
|
auth: UpstreamAuthScheme;
|
|
25
18
|
kv: KvService;
|
|
26
|
-
}): Promise<
|
|
19
|
+
}): Promise<InputRequiredResult>;
|
|
20
|
+
/** Fallback text for a 2026-07-28-era client without URL-elicitation support. */
|
|
21
|
+
export declare function buildUpstreamCredentialFallback({ subject, baseUrl, events, auth, kv, }: {
|
|
22
|
+
subject: string;
|
|
23
|
+
baseUrl: string;
|
|
24
|
+
events: UpstreamAuthRequiredEvent[];
|
|
25
|
+
auth: UpstreamAuthScheme;
|
|
26
|
+
kv: KvService;
|
|
27
|
+
}): Promise<string>;
|
|
27
28
|
//# sourceMappingURL=elicitation.d.ts.map
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{
|
|
2
|
-
`)}export{
|
|
1
|
+
import{inputRequired as s,inputResponse as p}from"@modelcontextprotocol/server";import{secretStore as h,ELICITATION_TTL_MS as m}from"./secret-store.js";import{ANONYMOUS_SUBJECT_PREFIX as c}from"./subject.js";const l="credentials";function k(e){const t=p(e,l);return t.kind==="elicit"&&(t.action==="decline"||t.action==="cancel")}async function v({subject:e,baseUrl:t,events:n,auth:a,kv:r}){const{url:i}=await u(r,e,t,n,a);return s({inputRequests:{[l]:s.elicitUrl({message:T(n[0].name),url:i})}})}async function A({subject:e,baseUrl:t,events:n,auth:a,kv:r}){const{url:i}=await u(r,e,t,n,a);return E(n,i,f(e))}async function u(e,t,n,a,r){const i=a[0],o=await h.createElicitation(e,{subject:t,api:i.api,name:i.name,auth:r});return{token:o,url:g(n,o)}}function f(e){return e.startsWith(c)?e.slice(c.length):void 0}function T(e){return`The "${e}" API requires credentials. Open the link to provide them securely; they never pass through the chat.`}function g(e,t){if(!e)return`/mcp/credentials?token=${t}`;try{const n=new URL("/mcp/credentials",e);return n.searchParams.set("token",t),n.toString()}catch{return`${e}/mcp/credentials?token=${t}`}}function E(e,t,n){const[a,...r]=e,i=[`The upstream API "${a.name}" returned 401 Unauthorized.`,"",`**Action required: show the user the link below and ask them to open it in a browser to provide the API credentials (valid ${Math.round(m/6e4)} minutes):**`,"",t,"",n?`Then call this tool again with sessionHandle: "${n}" - the credentials are stored against that handle, applied server-side, and never appear in the conversation.`:"Then call this tool again - the credentials are applied server-side and never appear in the conversation."];if(r.length>0){const o=r.map(d=>`"${d.name}"`).join(", ");i.push("",`The remaining APIs (${o}) will prompt for credentials on subsequent calls.`)}return i.join(`
|
|
2
|
+
`)}export{l as CREDENTIALS_INPUT_REQUEST_KEY,A as buildUpstreamCredentialFallback,v as buildUpstreamCredentialInputRequired,k as isCredentialElicitationDeclined};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Agent as
|
|
1
|
+
import{Agent as P}from"undici";import{envConfig as W}from"../../../../config/env-config.js";import{logger as C}from"../../../../tools/notifiers/logger.js";import{assertUrlAllowed as H}from"./ssrf-guard.js";import{createSsrfSafeLookup as J}from"./ssrf-safe-lookup.js";import{SsrfBlockedError as U}from"./ssrf-blocklist.js";import{GatewayFetchBlockedError as $,GatewayFetchSystemError as K,GatewayFetchUserError as A}from"./fetch-errors.js";import{redactHeaders as x,redactSecretsFromString as V}from"./redact.js";import{normalizeFetchPath as X}from"./normalize-path.js";import{reportGatewayFetch as O}from"./fetch-telemetry.js";const G="x-forwarded-for",Y=3e4,z=1024*1024;let k;function I(){if(!k){const t=W.isDevelopMode;t&&C.warn("Gateway MCP SSRF guard: loopback upstreams are ALLOWED (develop mode only, never in runtime)."),k=new P({connect:{lookup:J({allowLoopback:t})}})}return k}function we({allowedHosts:t,apis:e=[],authorization:r,onAuthRequired:n,fetchImpl:s=fetch,dispatcher:u=I(),timeoutMs:c=Y,maxResponseBytes:h=z,maxFetchesPerExec:f,clientIp:m}){const v=[...t,...e.flatMap(o=>o.matchers)],N=[r,...e.map(o=>o.secret?.value)].filter(o=>!!o),D=e.map(o=>o.secret?.header).filter(o=>!!o);let F=0;return async o=>{const g=o.method??"GET",T=Date.now();let M,b,E,S={},R,L;try{if(f!==void 0){const l=Math.max(0,f);if(F+=1,F>l)throw new A(`Outbound fetch budget exceeded (max ${l} fetches per execute); split the work across calls`)}const i=H(o.url,v);M=i.hostname,b=X(i.pathname);const y=e.filter(l=>l.matchers.some(j=>j.test(i.hostname))),a=y.length===1?y[0]:void 0;E=a?.slug,S=ne(o.headers,a?.secret,r,m);const p=new AbortController;L=setTimeout(()=>p.abort(),c);const d=await s(i,{method:g,headers:S,body:o.body,redirect:"manual",signal:p.signal,dispatcher:u});R=d.status,d.status===401&&a&&n&&n({api:a.slug,name:a.name});const _=await oe(d,h);let w=ae(d.headers);if(ee(d.status)){w=x(w,D);const{location:l}=w;l&&!te(l,i,v)&&delete w.location}return O({host:i.hostname,method:g,outcome:"success",durationMs:Date.now()-T,path:b,api:E,status:d.status,bytes:Buffer.byteLength(_,"utf8")}),{status:d.status,statusText:d.statusText,ok:d.ok,headers:w,bodyText:_}}catch(i){const{outcome:y,userSafe:a}=Z(i),p=M??(a instanceof $?a.host:void 0)??q(o.url)??"invalid-url";throw O({host:p,method:g,outcome:y,durationMs:Date.now()-T,path:b,api:E,status:R}),a||(C.error(`Gateway MCP fetch failed [${g} ${p}]: ${V(re(i),N)} headers=${JSON.stringify(x(S,D))}`),new K("Upstream fetch failed due to an internal error"))}finally{L!==void 0&&clearTimeout(L)}}}function Q(t){let e=t;for(let r=0;r<5&&e instanceof Error;r++){if(e instanceof A||e instanceof U)return e;e=e.cause}}function Z(t){const e=Q(t);return{outcome:e instanceof $||e instanceof U?"blocked":e?"user_error":"system_error",userSafe:e}}function q(t){try{return new URL(t).hostname||void 0}catch{return}}function ee(t){return t>=300&&t<400}function te(t,e,r){try{return!!H(new URL(t,e).href,r)}catch{return!1}}function re(t){if(!(t instanceof Error))return String(t);const e=t.cause;return e instanceof Error?`${t.message}: ${e.message}`:t.message}async function oe(t,e){const r=Number(t.headers.get("content-length"));if(Number.isFinite(r)&&r>e)throw B(e,r);if(!t.body)return"";const n=t.body.getReader(),s=new TextDecoder;let u=0,c="";try{for(;;){const{done:h,value:f}=await n.read();if(h)break;if(u+=f.byteLength,u>e)throw B(e,u);c+=s.decode(f,{stream:!0})}return c+s.decode()}finally{await n.cancel().catch(()=>{})}}function B(t,e){return new A(`Response is too large (over ${t} bytes, got ${e}); request less data`)}function ne(t,e,r,n){const s={},u=new Set;for(const[h,f]of Object.entries(t??{})){const m=h.toLowerCase();m==="host"||m==="content-length"||m!==G&&(u.add(m),s[h]=f)}n&&(s[G]=n);const c=e??(r?{header:"Authorization",value:r}:void 0);return c&&!u.has(c.header.toLowerCase())&&(s[c.header]=c.value),s}function ae(t){const e={};return t.forEach((r,n)=>{e[n.toLowerCase()]=r}),e}export{we as buildFetchBridge,I as getDefaultAgent,oe as readCappedBody};
|
|
@@ -4,10 +4,11 @@ type GatewayFetchEvent = {
|
|
|
4
4
|
method: string;
|
|
5
5
|
outcome: GatewayFetchOutcome;
|
|
6
6
|
durationMs: number;
|
|
7
|
+
path?: string;
|
|
7
8
|
api?: string;
|
|
8
9
|
status?: number;
|
|
9
10
|
bytes?: number;
|
|
10
11
|
};
|
|
11
|
-
export declare function reportGatewayFetch({ host, method, outcome, durationMs, api, status, bytes, }: GatewayFetchEvent): void;
|
|
12
|
+
export declare function reportGatewayFetch({ host, method, outcome, durationMs, path, api, status, bytes, }: GatewayFetchEvent): void;
|
|
12
13
|
export {};
|
|
13
14
|
//# sourceMappingURL=fetch-telemetry.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetry as
|
|
1
|
+
import{telemetry as m}from"../../../../telemetry/index.js";import{logger as c}from"../../../../tools/notifiers/logger.js";import{McpServerType as u}from"../../constants.js";import{serverAttributes as $}from"../../utils/telemetry-attributes.js";function g({host:f,method:i,outcome:o,durationMs:t,path:e,api:r,status:n,bytes:d}){try{m.sendMcpGatewayFetchPerformedMessage([{...$(u.Docs),host:f,method:i,outcome:o,...e!==void 0&&{path:e},...r!==void 0&&{api:r},...n!==void 0&&{status:n},...d!==void 0&&{bytes:d},duration_ms:t}])}catch{}c.info(`Gateway MCP fetch [${i} ${f}] outcome=${o}`+(e!==void 0?` path=${e}`:"")+(r!==void 0?` api=${r}`:"")+(n!==void 0?` status=${n}`:"")+(d!==void 0?` bytes=${d}`:"")+` durationMs=${t}`)}export{g as reportGatewayFetch};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reduce a request path to something safe to report: no query string (it carries tokens), no
|
|
3
|
+
* identifiers (they explode cardinality and can be customer data), bounded length.
|
|
4
|
+
*/
|
|
5
|
+
export declare function normalizeFetchPath(pathname: string): string;
|
|
6
|
+
//# sourceMappingURL=normalize-path.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const A=200,a=12,c=/^\d+$/,i=/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i,E=/^[0-9a-f]{16,}$/i,_=/^[a-z]{2,6}_[A-Za-z0-9]{8,}$/,f=/^(?=.*\d)[A-Za-z0-9._~-]{20,}$/;function r(t){return t&&(c.test(t)||i.test(t)||E.test(t)||_.test(t)||f.test(t)?"{id}":t)}function M(t){if(!t||t==="/")return"/";const o=t.split("/"),s=o.slice(0,13).map(r);o.length>13&&s.push("...");const n=s.join("/")||"/";return n.length>200?`${n.slice(0,200)}...`:n}export{M as normalizeFetchPath};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CacheService as a}from"../../../../persistence/cache/services/cache-service.js";import{logger as
|
|
1
|
+
import{CacheService as a}from"../../../../persistence/cache/services/cache-service.js";import{logger as s}from"../../../../tools/notifiers/logger.js";import{ipRateLimitKey as c}from"./ip-key.js";import{checkEdgeRateLimit as p}from"./edge-limiter.js";import{resolveGatewayFetchLimits as m}from"./limits.js";import{reportMcpRateLimited as d}from"./rate-limit-telemetry.js";async function S(o,n){const i=c(o);if(!i)return;let e,r;try{const t=await a.getInstance({baseDbDir:n.serverOutDir,databaseType:"local"});r=m(),e=await p({cache:t,ip:i,limits:r,now:Date.now()})}catch(t){s.warn(`gateway rate-limit init error, failing open: ${String(t)}`);return}if(!e.allowed)return d({scope:e.scope,retryAfterSeconds:e.retryAfterSeconds,limit:e.scope==="rate"?r.ratePerMin:r.quotaPerDay}),new Response(JSON.stringify({jsonrpc:"2.0",error:{code:-32029,message:`Rate limit exceeded (${e.scope}); retry after ${e.retryAfterSeconds}s`},id:null}),{status:429,headers:{"Content-Type":"application/json","Retry-After":String(e.retryAfterSeconds)}})}export{S as applyEdgeRateLimit};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
type RateLimitedEvent = {
|
|
2
|
+
scope: 'rate' | 'quota';
|
|
3
|
+
retryAfterSeconds: number;
|
|
4
|
+
limit: number;
|
|
5
|
+
};
|
|
6
|
+
export declare function reportMcpRateLimited({ scope, retryAfterSeconds, limit }: RateLimitedEvent): void;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=rate-limit-telemetry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{telemetry as o}from"../../../../telemetry/index.js";import{logger as i}from"../../../../tools/notifiers/logger.js";import{McpServerType as m}from"../../constants.js";import{serverAttributes as p}from"../../utils/telemetry-attributes.js";function d({scope:e,retryAfterSeconds:r,limit:t}){try{o.sendMcpRateLimitedMessage([{...p(m.Docs),scope:e,retry_after_seconds:r,limit:t}])}catch{}i.warn(`Gateway MCP rate limited [scope=${e}] retryAfterSeconds=${r} limit=${t}`)}export{d as reportMcpRateLimited};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CallToolResult } from '@
|
|
1
|
+
import type { CallToolResult } from '@modelcontextprotocol/server';
|
|
2
2
|
export declare const UPSTREAM_AUTH_REQUIRED_META = "com.redocly/upstream-auth-required";
|
|
3
3
|
export type UpstreamAuthRequiredEvent = {
|
|
4
4
|
api: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{logger as g}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as O}from"../../../web-server/utils/feedback-ip.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as v}from"../../../../constants/common.js";import{isObject as F}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as N}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as _}from"../../../utils/skills/get-skill-url.js";import{createDocsMcpServer as L}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as k,filterGraphqlDescriptionsByRbac as B}from"../utils.js";import{createMethodNotAllowedError as P,withErrorHandling as H}from"./errors.js";import{constructForbiddenResponse as j,constructInvalidTokenResponse as V,constructUnauthorizedResponse as G,handleMcpAuth as J,shouldHandleMcpAuth as $}from"../auth/auth-handlers.js";import{extractTokenFromAuthHeader as z}from"../utils/jwt.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as K}from"../constants.js";import{canAccessFeature as Y}from"../../../utils/rbac.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as W,RbacFeatures as X}from"../../../../constants/common.js";const u="X-Redocly-AI-Metadata";function Q(r){if(r)try{const e=JSON.parse(r);if(F(e))return e;g.warn(`Ignoring ${u} header: not a JSON object.`)}catch{g.warn(`Ignoring ${u} header: invalid JSON.`)}}const Z=async(r,e,s)=>{const i=!!e?.config?.access?.requiresLogin,t=e?.config?.access?.rbac||{},f=s?.props?.config?.mcpMode??"tools",h=s?.props?.config?.gatewayFetchBudgetPerExec??v.budgetPerExec;let p;const m=r.headers.get("Authorization");if($(i,t)){const{isAuthenticated:d,isTokenValid:o,currentUser:c,accessToken:l}=await J(r,e);if(!d)return G(new URL(r.url).origin);if(!o)return V();c&&(e.user=c),p=l}else m&&(p=z(m||"")??void 0);const A={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[W],claims:e.user?.claims??{}};if(!Y(X.MCP,A,t,i))return j();let a;return await H(async()=>{const d=s?.props?.config?.elicitationEnabled??!1;if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP Client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return P();const o=s,c=o?.props?.config?.apiDescriptionsMap||{},l=o?.props?.config?.graphqlDescriptions||[],M=o?.props?.config?.mcpDocsServerName||K,{config:{mcp:E={}}}=e,T=k(c,e.user,t,i),D=B(l,e.user,t,i),R=e.config.products?Object.values(e.config.products).map(n=>n?.name):[],w=E.docs?.name||M,S=Q(r.headers.get(u)),b=o?.props?.tools||[],y=o?.props?.skillsBaseUrl||new URL(r.url).origin,U=N(o?.props?.skills||[],e.user,t,i).map(n=>({slug:n.slug,name:n.name,description:n.description,content:n.content,uri:_(y,n.slug)})),C=await r.json(),I={name:w,tools:b,skills:U,context:{...e,accessToken:p,outdir:e.outdir||"",baseUrl:e.baseUrl||new URL(r.url).origin,apiDescriptionsMap:T,graphqlDescriptions:D,products:R,metadata:S,mcpMode:f,elicitationEnabled:d,gatewayFetchBudgetPerExec:h,clientIp:O(r)}};return a=await L({...I,getKv:e.getKv}),await q(r,a,C)},async()=>{a&&(await a.cleanup(),a=void 0)},f)};async function q(r,e,s){return e.transport.handleRequest(r,s!==void 0?{parsedBody:s}:void 0)}var me=Z;export{me as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as s,McpServerType as d}from"../constants.js";import{serverAttributes as i}from"../utils/telemetry-attributes.js";class n extends Error{code;data;requestId;constructor(e,t,o,a){super(t),this.name="McpError",this.code=e,this.data=o,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=u(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}function u(r){switch(r){case s.InvalidRequest:case s.InvalidParams:return 400;case s.MethodNotFound:return 404;case s.ServerError:return 405;case s.InternalError:default:return 500}}function h(r){return new n(s.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function p(r,e,t="tools"){const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;return c.sendMcpErrorMessage([{...i(d.Docs),message:o,stack:a||"",mode:t}]),new n(s.InternalError,"Internal server error mcp",o,e).createErrorResponse()}function
|
|
1
|
+
import{telemetry as c}from"../../../telemetry/index.js";import{McpErrorCodes as s,McpServerType as d}from"../constants.js";import{serverAttributes as i}from"../utils/telemetry-attributes.js";class n extends Error{code;data;requestId;constructor(e,t,o,a){super(t),this.name="McpError",this.code=e,this.data=o,this.requestId=a}createErrorResponse(){const e={jsonrpc:"2.0",error:{code:this.code,message:this.message,...this.data?{data:this.data}:{}},id:this.requestId??null},t=u(this.code);return new Response(JSON.stringify(e),{status:t,headers:{"Content-Type":"application/json"}})}}function u(r){switch(r){case s.InvalidRequest:case s.InvalidParams:return 400;case s.MethodNotFound:return 404;case s.ServerError:return 405;case s.InternalError:default:return 500}}function h(r){return new n(s.ServerError,"Method not allowed",void 0,r).createErrorResponse()}function p(r,e,t="tools"){const o=r instanceof Error?r.message:String(r),a=r instanceof Error?r.stack:void 0;return c.sendMcpErrorMessage([{...i(d.Docs),message:o,stack:a||"",error_class:"server_error",mode:t}]),new n(s.InternalError,"Internal server error mcp",o,e).createErrorResponse()}function v(r="Invalid request",e){return new n(s.InvalidRequest,r,void 0,e).createErrorResponse()}function I(r="Invalid parameters",e){return new n(s.InvalidParams,r,void 0,e).createErrorResponse()}async function g(r,e,t="tools"){try{return await r()}catch(o){return c.sendMcpErrorMessage([{...i(d.Docs),message:o?.message||"",stack:o?.stack||"",error_class:"server_error",mode:t}]),e&&e(),p(o,void 0,t)}}export{n as McpError,p as createInternalServerError,I as createInvalidParamsError,v as createInvalidRequestError,h as createMethodNotAllowedError,g as withErrorHandling};
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import type { McpToolSchema } from '../../../types';
|
|
2
2
|
import type { McpToolContext, SkillMcpResource } from '../types.js';
|
|
3
3
|
import type { KvService } from '@redocly/config';
|
|
4
|
-
import { type McpServerInstance
|
|
5
|
-
export declare function createDocsMcpServer({ name, tools, context,
|
|
4
|
+
import { type McpServerInstance } from './mcp-server.js';
|
|
5
|
+
export declare function createDocsMcpServer({ name, tools, context, skills, getKv, }: {
|
|
6
6
|
name: string;
|
|
7
7
|
tools: McpToolSchema[];
|
|
8
8
|
context: McpToolContext;
|
|
9
|
-
sessionHooks?: McpSessionHooks;
|
|
10
9
|
skills?: SkillMcpResource[];
|
|
11
10
|
getKv: () => Promise<KvService>;
|
|
12
11
|
}): Promise<McpServerInstance>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{fromJsonSchema as _}from"@modelcontextprotocol/server";import{logger as h}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as C,MCP_TOOL_IS_AVAILABLE_KEY as b}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as A}from"../constants.js";import{isAnonymousSessionToolAvailable as T}from"../docs-mcp/tools/core/create-anonymous-session.js";import{EXECUTE_TOOL_SCHEMA as M}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as S,DESCRIBE_TOOLS_TOOL_NAME as g,CODE_MODE_TOOL_NAMES as L,FETCH_TOOL_NAME as v}from"../codemode/constants.js";import{buildCodeModeInstructions as y,buildExecuteDescription as D,DESCRIBE_TOOLS_DESCRIPTION as I}from"../codemode/prompts.js";import{composeExecuteAnnotations as x,getActiveCapabilities as N}from"../codemode/capabilities/index.js";import{describeToolsSchema as k,describeTools as w}from"../codemode/tools/describe-tools.js";import{mcpJsonSchemaValidator as R}from"../utils/json-schema-validator.js";import{connectMcpServer as F,createMcpServer as H,createToolDispatch as P,extractSerializableContext as B}from"./mcp-server.js";function U(a){const o=M.schema;if(T(a))return o;const{sessionHandle:t,...c}=o.properties;return{...o,properties:c}}async function Z({name:a,tools:o,context:t,skills:c=[],getKv:u}){const m=t.mcpMode==="code",n=m?N(t):[],d=n.some(e=>e.id===v),{server:r,transport:O}=H(a,m?y(d):void 0),s=e=>_(e,R),E=B(t),p=P(E,{getClientCapabilities:()=>r.server.getClientCapabilities(),getKv:u}),f=async e=>{try{return await C.exec(b,[{toolName:e,context:E}],{timeout:1e4})}catch(i){return h.error(`Failed to check MCP tool availability for "${e}": ${i instanceof Error?i.message:String(i)}`),!1}};if(m){const e=o.filter(l=>!L.has(l.name));r.registerTool(S,{description:D(d),inputSchema:s(U(t)),annotations:x(n)},p(S)),r.registerTool(g,{description:I,inputSchema:s(k(e,n))},w(e,f,n,t));const i=o.find(l=>l.name===A);i&&T(t)&&r.registerTool(i.name,{description:i.description,inputSchema:s(i.schema),annotations:i.annotations??{title:i.name}},p(i.name))}else await Promise.all(o.map(async e=>{const i=r.registerTool(e.name,{description:e.description,inputSchema:s(e.schema),annotations:e.annotations||{title:e.name}},p(e.name));await f(e.name)||i.disable()}));for(const e of c)r.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 F(r,O)}export{Z as createDocsMcpServer};
|
|
@@ -1,29 +1,25 @@
|
|
|
1
|
-
import { McpServer } from '@
|
|
2
|
-
import {
|
|
3
|
-
import type { ToolCallback } from '@redocly/mcp-typescript-sdk/server/mcp.js';
|
|
4
|
-
import type { McpToolContext } from '../types.js';
|
|
1
|
+
import { McpServer, WebStandardStreamableHTTPServerTransport } from '@modelcontextprotocol/server';
|
|
2
|
+
import type { McpToolCallback, McpToolContext } from '../types.js';
|
|
5
3
|
import type { KvService } from '@redocly/config';
|
|
6
4
|
export type McpServerInstance = {
|
|
7
5
|
server: McpServer;
|
|
8
|
-
transport:
|
|
6
|
+
transport: WebStandardStreamableHTTPServerTransport;
|
|
9
7
|
cleanup: () => Promise<void>;
|
|
10
8
|
};
|
|
11
|
-
export
|
|
12
|
-
onInitialized: (sessionId: string) => void;
|
|
13
|
-
onClosed: (sessionId: string) => void;
|
|
14
|
-
};
|
|
15
|
-
export declare function createMcpServer(name: string, instructions?: string, sessionHooks?: McpSessionHooks): {
|
|
9
|
+
export declare function createMcpServer(name: string, instructions?: string): {
|
|
16
10
|
server: McpServer;
|
|
17
|
-
transport:
|
|
11
|
+
transport: WebStandardStreamableHTTPServerTransport;
|
|
18
12
|
};
|
|
19
|
-
export declare function connectMcpServer(server: McpServer, transport:
|
|
13
|
+
export declare function connectMcpServer(server: McpServer, transport: WebStandardStreamableHTTPServerTransport): Promise<McpServerInstance>;
|
|
20
14
|
export type ToolDispatchDeps = {
|
|
21
15
|
getClientCapabilities: () => {
|
|
22
|
-
elicitation?:
|
|
16
|
+
elicitation?: {
|
|
17
|
+
url?: unknown;
|
|
18
|
+
};
|
|
23
19
|
} | undefined;
|
|
24
20
|
getKv: () => Promise<KvService>;
|
|
25
21
|
};
|
|
26
22
|
/** Build the tool callback that ships a tool call to the worker pool. */
|
|
27
|
-
export declare function createToolDispatch(serializableContext: McpToolContext, deps?: ToolDispatchDeps): (toolName: string) =>
|
|
23
|
+
export declare function createToolDispatch(serializableContext: McpToolContext, deps?: ToolDispatchDeps): (toolName: string) => McpToolCallback;
|
|
28
24
|
export declare function extractSerializableContext(context: McpToolContext): McpToolContext;
|
|
29
25
|
//# sourceMappingURL=mcp-server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{McpServer as b,WebStandardStreamableHTTPServerTransport as M}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as y,MCP_TOOL_WORKER_KEY as k}from"../../../workers/mcp-tool-worker-pool.js";import{SSE_KEEPALIVE_INTERVAL_MS as I}from"../constants.js";import{secretStore as q}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as v,stripAuthRequiredMeta as g}from"../gateway-mcp/upstream-auth.js";import{buildUpstreamCredentialFallback as E,buildUpstreamCredentialInputRequired as T,isCredentialElicitationDeclined as R}from"../gateway-mcp/elicitation.js";import{resolveUpstreamAuthScheme as w}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as _,resolveSecretSubject as U}from"../gateway-mcp/subject.js";const A=6e4,m=new Map;function D(e,t){const r=m.get(e);if(r)return r;const n=t().finally(()=>{m.delete(e)});return m.set(e,n),n}function V(e,t){const r=new b({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}}),n=new M({keepAliveMs:I,sessionIdGenerator:void 0});return{server:r,transport:n}}async function Y(e,t){return await e.connect(t),{server:e,transport:t,cleanup:async()=>{t.close()}}}function J(e,t){return r=>async(n,i)=>{S.info(`MCP tool called: ${r}`);const o=e.elicitationEnabled??!1,d=i.mcpReq.envelope!==void 0,s=o?U(e.user,n.sessionHandle):{kind:"anonymous"},u=s.kind==="resolved"?s.subject:void 0;if(s.kind==="invalid")return{content:[{type:"text",text:s.message}],isError:!0};const h=async()=>{if(!(!o||!u||!t?.getKv))try{const a=await t.getKv();return await q.getSecretsForSubject(a,u)}catch(a){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(a)}`);return}},f=async()=>{const a=await h(),p={toolName:r,args:n,context:{...e,upstreamSecrets:a},extra:P(i)};return await y.exec(k,[p],{timeout:A})};let c=await f();const l=v(c);if(l.length>0&&o&&!u)return g({...c,content:[{type:"text",text:_}],isError:!0});if(l.length>0&&o&&u&&t?.getKv){const a=await t.getKv(),p=d?await K(e,i,l,u,a,t):await L(e,l,u,a);switch(p.kind){case"inputRequired":return p.result;case"retry":c=await f();break;case"appendText":c={...c,content:[...c.content,{type:"text",text:p.text}]};break;case"none":break}}return g(c)}}function O(e){return!!e?.getClientCapabilities()?.elicitation?.url}async function K(e,t,r,n,i,o){if(R(t.mcpReq.inputResponses))return{kind:"none"};const d=e.baseUrl??"",s=await w(e,r[0].api);return O(o)?{kind:"inputRequired",result:await T({subject:n,baseUrl:d,events:r,auth:s,kv:i})}:{kind:"appendText",text:await E({subject:n,baseUrl:d,events:r,auth:s,kv:i})}}async function L(e,t,r,n){const i=await w(e,t[0].api);return{kind:"appendText",text:await D(`${r}:${t[0].api}`,()=>E({subject:r,baseUrl:e.baseUrl??"",events:t,auth:i,kv:n}))}}function P(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function Q(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{Y as connectMcpServer,V as createMcpServer,J as createToolDispatch,Q as extractSerializableContext};
|