@redocly/realm 0.138.0-next.1 → 0.138.0-next.3
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 +58 -0
- package/dist/client/App.js +1 -1
- package/dist/client/TestProvider.d.ts +3 -1
- package/dist/client/TestProvider.js +1 -1
- package/dist/client/app/Sidebar/Sidebar.js +1 -1
- package/dist/client/app/hooks/codeHighlight/useCodeHighlight.js +1 -1
- package/dist/client/app/hooks/index.d.ts +1 -0
- package/dist/client/app/hooks/index.js +1 -1
- package/dist/client/app/hooks/useConsent.d.ts +11 -0
- package/dist/client/app/hooks/useConsent.js +1 -0
- package/dist/client/app/l10n/L10nContext.d.ts +10 -0
- package/dist/client/app/l10n/L10nContext.js +1 -0
- package/dist/client/app/l10n/hooks/useL10n.js +1 -1
- package/dist/client/app/l10n/hooks/useTranslate.js +1 -1
- package/dist/client/app/l10n/hooks/useTranslationKeys.d.ts +2 -0
- package/dist/client/app/l10n/hooks/useTranslationKeys.js +1 -1
- package/dist/client/app/l10n/ssrL10n.d.ts +4 -0
- package/dist/client/app/l10n/ssrL10n.js +1 -0
- package/dist/client/app/webmcp/index.d.ts +2 -0
- package/dist/client/app/webmcp/index.js +1 -0
- package/dist/client/app/webmcp/tools/api-tools.d.ts +8 -0
- package/dist/client/app/webmcp/tools/api-tools.js +1 -0
- package/dist/client/app/webmcp/tools/shared.d.ts +13 -0
- package/dist/client/app/webmcp/tools/shared.js +1 -0
- package/dist/client/app/webmcp/tools/site-tools.d.ts +5 -0
- package/dist/client/app/webmcp/tools/site-tools.js +3 -0
- package/dist/client/app/webmcp/types.d.ts +36 -0
- package/dist/client/app/webmcp/types.js +0 -0
- package/dist/client/app/webmcp/useWebMcpTools.d.ts +9 -0
- package/dist/client/app/webmcp/useWebMcpTools.js +1 -0
- package/dist/client/providers/theme/ThemeDataProvider.js +1 -1
- package/dist/client/server-entry.d.ts +2 -1
- package/dist/client/server-entry.js +1 -1
- package/dist/constants/common.d.ts +1 -0
- package/dist/constants/common.js +1 -1
- package/dist/constants/l10n/langs/ar.js +1 -1
- package/dist/constants/l10n/langs/de.js +1 -1
- package/dist/constants/l10n/langs/en.js +1 -1
- package/dist/constants/l10n/langs/es.js +1 -1
- package/dist/constants/l10n/langs/fr.js +1 -1
- package/dist/constants/l10n/langs/hi.js +1 -1
- package/dist/constants/l10n/langs/it.js +1 -1
- package/dist/constants/l10n/langs/ja.js +1 -1
- package/dist/constants/l10n/langs/ko.js +1 -1
- package/dist/constants/l10n/langs/pl.js +1 -1
- package/dist/constants/l10n/langs/pt-BR.js +1 -1
- package/dist/constants/l10n/langs/pt.js +1 -1
- package/dist/constants/l10n/langs/ru.js +1 -1
- package/dist/constants/l10n/langs/uk.js +1 -1
- package/dist/constants/l10n/langs/zh.js +1 -1
- package/dist/markdoc/nodes/table.d.ts +2 -0
- package/dist/markdoc/nodes/table.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/constants/plugins/consent.d.ts +3 -0
- package/dist/server/constants/plugins/consent.js +1 -0
- package/dist/server/constants/plugins/search.js +1 -1
- package/dist/server/plugins/analytics/adobe/index.js +1 -1
- package/dist/server/plugins/analytics/amplitude/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/amplitude/index.js +1 -1
- package/dist/server/plugins/analytics/fullstory/index.js +1 -1
- package/dist/server/plugins/analytics/ga/index.js +1 -1
- package/dist/server/plugins/analytics/gtm/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/gtm/index.js +1 -1
- package/dist/server/plugins/analytics/heap/browser-hooks.js +1 -1
- package/dist/server/plugins/analytics/rudderstack/index.js +1 -1
- package/dist/server/plugins/analytics/segment/index.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.d.ts +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/revision-repository.js +1 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.d.ts +5 -1
- package/dist/server/plugins/catalog-entities/database/repositories/common/version-repository.js +7 -1
- package/dist/server/plugins/catalog-entities/database/repositories/entities/entities-write-repository.js +1 -1
- package/dist/server/plugins/config-parser/format-custom-tags.d.ts +1 -0
- package/dist/server/plugins/config-parser/format-custom-tags.js +1 -1
- package/dist/server/plugins/config-parser/index.js +1 -1
- package/dist/server/plugins/config-parser/loaders/redocly-config-loader.js +1 -1
- package/dist/server/plugins/config-parser/loaders/versions-config-loader.js +1 -1
- package/dist/server/plugins/consent/build-consent-script.d.ts +6 -0
- package/dist/server/plugins/consent/build-consent-script.js +230 -0
- package/dist/server/plugins/consent/gate-ssr-components.d.ts +5 -0
- package/dist/server/plugins/consent/gate-ssr-components.js +1 -0
- package/dist/server/plugins/consent/index.d.ts +3 -0
- package/dist/server/plugins/consent/index.js +1 -0
- package/dist/server/plugins/consent/is-consent-enabled.d.ts +8 -0
- package/dist/server/plugins/consent/is-consent-enabled.js +1 -0
- package/dist/server/plugins/consent/zone-modes.d.ts +8 -0
- package/dist/server/plugins/consent/zone-modes.js +1 -0
- package/dist/server/plugins/lifecycle.js +2 -2
- package/dist/server/plugins/markdown/markdoc/markdoc-options.d.ts +2 -0
- package/dist/server/plugins/markdown/search/get-ai-search-documents.js +9 -9
- package/dist/server/plugins/markdown/search/nodes/tag-node.d.ts +1 -1
- package/dist/server/plugins/markdown/search/nodes/tag-node.js +1 -1
- package/dist/server/plugins/mcp/audit/audit-log.js +1 -1
- package/dist/server/plugins/mcp/auth/assistant-anonymous-token.d.ts +10 -0
- package/dist/server/plugins/mcp/auth/assistant-anonymous-token.js +1 -0
- package/dist/server/plugins/mcp/auth/auth-handlers.d.ts +5 -3
- package/dist/server/plugins/mcp/auth/auth-handlers.js +1 -1
- package/dist/server/plugins/mcp/codemode/build-tool-type-declarations.js +4 -4
- package/dist/server/plugins/mcp/codemode/capabilities/types.d.ts +0 -1
- package/dist/server/plugins/mcp/codemode/capabilities/utils.d.ts +1 -2
- package/dist/server/plugins/mcp/codemode/capabilities/utils.js +4 -4
- package/dist/server/plugins/mcp/codemode/tools/describe-tools.js +2 -2
- package/dist/server/plugins/mcp/codemode/tools/execute-schema.d.ts +0 -2
- package/dist/server/plugins/mcp/codemode/tools/execute-schema.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/execute.js +1 -1
- package/dist/server/plugins/mcp/codemode/tools/manage-credentials.js +2 -2
- package/dist/server/plugins/mcp/docs-mcp/tool-schemas.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/core/create-anonymous-session.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.d.ts +2 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/constants.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.d.ts +6 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/endpoint-suggestions.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/get-endpoint-info.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.d.ts +2 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/load-api-description.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.d.ts +5 -0
- package/dist/server/plugins/mcp/docs-mcp/tools/openapi/utils.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.d.ts +20 -14
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
- package/dist/server/plugins/mcp/handlers/docs-mcp-handler.js +1 -1
- package/dist/server/plugins/mcp/servers/docs-server.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.js +3 -3
- package/dist/server/plugins/mcp/utils/disabled-tools.d.ts +3 -0
- package/dist/server/plugins/mcp/utils/disabled-tools.js +1 -0
- package/dist/server/plugins/mcp/utils/tool-registration.d.ts +2 -1
- package/dist/server/plugins/mcp/utils/tool-registration.js +1 -1
- package/dist/server/plugins/mcp/workers/execute-mcp-tool.js +1 -1
- package/dist/server/plugins/search/engines/flexsearch/search-index.js +1 -1
- package/dist/server/ssr/render.js +1 -1
- package/dist/server/types/plugins/search.d.ts +1 -1
- package/dist/server/utils/rbac-expand.js +1 -1
- package/dist/server/utils/rbac.js +1 -1
- package/dist/server/utils/redact-url.d.ts +6 -0
- package/dist/server/utils/redact-url.js +1 -0
- package/dist/server/utils/search/highlight-text-for-search.d.ts +1 -0
- package/dist/server/utils/search/highlight-text-for-search.js +1 -1
- package/dist/server/utils/search/text-match.d.ts +6 -0
- package/dist/server/utils/search/text-match.js +1 -0
- package/dist/server/web-server/jwt/jwt.js +1 -1
- package/dist/server/web-server/jwt/types.d.ts +4 -4
- package/dist/server/web-server/jwt/types.js +1 -1
- package/dist/server/web-server/middleware/telemetry-middleware.js +1 -1
- package/dist/server/web-server/routes/ask-ai.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-server-card.js +1 -1
- package/dist/types/entitlements.d.ts +1 -0
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
import{SEMANTIC_SEARCH_API_URL as y}from"../../../constants/common.js";import{shouldHandleMcpAuth as f}from"../../../utils/rbac/should-handle-mcp-auth.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as g,SUBMIT_FEEDBACK_TOOL_NAME as b}from"../constants.js";import{GRAPHQL_TYPE_KINDS as l,GRAPHQL_LIST_SCOPES as v}from"./tools/graphql/constants.js";import{OPERATION_METHODS as c}from"./tools/openapi/constants.js";const i={type:"string",nullable:!0},s={limit:{type:"number"},total:{type:"number"},page:{type:"number"},totalPages:{type:"number"}},a={codemodeType:"OpenApiServer[]"},o={codemodeType:"OpenApiSecurityRequirement[]"},u={codemodeType:"Record<string, OpenApiSecurityScheme>"},P={codemodeType:"OpenApiDocument"},A={codemodeType:"OpenApiOperation & { path: string; method: string }"},n={filePath:{type:"string",description:"API definition file path"},otherMatches:{type:"array",description:"Other API definitions the lookup also matched. Present only when several matched; pass `filePath` to pick another one",items:{type:"object",required:["filePath"],properties:{version:{type:"string"},filePath:{type:"string"}}}}},r="When several definitions match the name, the highest version or the shortest file path is used and the rest are listed in `otherMatches`; tell the user which version or file the answer is based on.",S={type:"object",additionalProperties:!1,required:[],properties:{filter:{type:"string",description:"Matches part of an API name, or of a description when no name matches",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of APIs per page. Default is 300",minimum:1,default:300,nullable:!0}}},p={type:"object",required:[],additionalProperties:!1,properties:{name:{type:"string",description:"API name, or a unique part of it. Omit when `filePath` is given.",minLength:1,nullable:!0},apiName:{type:"string",description:"Alias of `name`",nullable:!0},api:{type:"string",description:"Alias of `name`",nullable:!0},version:{type:"string",description:"API version. When omitted and several versions exist, the highest one is used",nullable:!0},filePath:{type:"string",description:"API definition file path, as returned by `listApis`",nullable:!0}}},H={type:"object",required:["path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name, or a unique part of it. Omit when `filePath` is given.",minLength:1,nullable:!0},apiName:{type:"string",description:"Alias of `name`",nullable:!0},api:{type:"string",description:"Alias of `name`",nullable:!0},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...c.map(e=>e.toUpperCase()),...c],minLength:1},version:{type:"string",description:"API version. When omitted and several versions exist, the highest one is used",nullable:!0},filePath:{type:"string",description:"API definition file path, as returned by `listApis`",nullable:!0}}},L={type:"object",required:[],additionalProperties:!1,properties:{}},q={type:"object",required:[],additionalProperties:!1,properties:{}},O={type:"object",required:["path","summary"],additionalProperties:!1,properties:{path:{type:"string",description:"Path or URL of the documentation page the feedback is about (e.g. /guides/auth)",minLength:1,maxLength:1e3},summary:{type:"string",description:"One sentence that names what is wrong with the page",minLength:1,maxLength:500},details:{type:"string",description:"Expected versus actual behavior, missing steps, or the snippet that failed",maxLength:4e3,nullable:!0},targetFeature:{type:"string",description:"The API or feature the page documents",maxLength:500,nullable:!0}}};function T(e){const t=[{name:"list-apis",title:"List APIs",description:"Lists the APIs documented in this project",schema:S,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:i,version:i,servers:a,filePath:{type:"string",description:"API definition file path"},ambiguousTitle:{type:"boolean",description:"true = another API shares this title; a lookup picks the highest version, or the shortest file path at the same version, and lists the rest in `otherMatches`. Pass `filePath` to pick another one"},...e.hasCallableApis?{callable:{type:"boolean",description:"true = the documented hosts of this API are reachable via `fetch`; false = documentation only"}}:{}}}},...s}}},{name:"get-endpoints",title:"Get endpoints",description:`Get all endpoints for a specific API. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,servers:a,endpoints:{type:"array",items:{type:"object",properties:{path:{type:"string"},method:{type:"string"},summary:i,description:i,security:o}}}}}},{name:"get-endpoint-info",title:"Get endpoint info",description:`Get comprehensive information about specific endpoint including parameters, security, and examples. ${r}`,schema:H,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,servers:a,endpoint:A,globalSecurity:o,securitySchemes:u}}},{name:"get-security-schemes",title:"Get security schemes",description:`Get the security schemes for a specific API. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{name:i,version:i,...n,securitySchemes:u,security:o}}},{name:"get-full-api-description",title:"Get full API description",description:`Get the complete OpenAPI description. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,definition:P}}},...y?[d(e.products,e.locales)]:[]];return f(e.requiresLogin,e.rbac)&&t.push({name:"whoami",title:"Who am I",description:"Get information about the currently authenticated user",schema:L,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{email:{type:"string"},name:{type:"string"},subject:{type:"string"},clientId:{type:"string"},scope:{type:"string"},issuedAt:{type:"string"},expiresAt:{type:"string"}}}}),e.feedbackHidden||t.push({name:b,title:"Submit feedback",description:"Report a documentation page that is wrong or incomplete",schema:O,annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"object",required:["status","page","message"],properties:{status:{type:"string"},page:{type:"string"},message:{type:"string"}}}}),e.hasGraphqlApis&&t.push(...E()),e.elicitationEnabled&&e.hasCallableApis&&t.push({name:g,title:"Create anonymous session",description:"Create an anonymous session handle for storing upstream API credentials. Pass the returned sessionHandle to execute when an API needs credentials and the caller is not signed in. Treat it as a secret and reuse it across calls.",schema:q,annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"object",required:["sessionHandle"],properties:{sessionHandle:{type:"string"}}}}),t}const G={type:"object",required:[],additionalProperties:!1,properties:{filter:{type:"string",description:"GraphQL schema name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},w={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},kind:{type:"string",description:'Optional: return only a single category of schema members. With scope "fields", restricts to the fields of that parent category ("objects", "interfaces", or "inputs" only).',enum:[...l,null],nullable:!0},scope:{type:"string",description:'Optional: what each list item is. "members" (default) lists top-level types and operations. "fields" flattens every field of every object/interface/input type into "ParentType.fieldName" entries with their descriptions \u2014 combine with `filter` to search nested fields anywhere in the schema.',enum:[...v,null],nullable:!0},filter:{type:"string",description:'Optional: only members whose name or description contains this substring, case-insensitive (e.g. "custom tags")',minLength:1,nullable:!0},referencesType:{type:"string",description:'Optional: only members that reference this type directly or transitively (via return, field, argument, union-member or input-field types). Finds cross-cutting members that never name it \u2014 e.g. referencesType "Book" surfaces a search query returning a union that includes Book.',minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},I={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},type:{type:"string",description:"Name of the type, operation, or directive",minLength:1,nullable:!0},typeName:{type:"string",description:"Alias of `type`",nullable:!0},includeReferencedTypes:{type:"boolean",description:"Also include the SDL of every type referenced transitively. Gives the whole subgraph at once, but can be large for highly-connected types.",default:!1,nullable:!0}}},j={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1}}};function E(){return[{name:"list-graphql-apis",title:"List GraphQL APIs",description:"Lists available GraphQL schemas with their context and purpose",schema:G,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:i}}},...s}}},{name:"get-graphql-type-list",title:"Get GraphQL type list",description:'List all operations and types in a GraphQL schema as a flat, paginated list. Each item is tagged with its kind (query, object, enum, \u2026) and carries a one-line description; operations also include their return type and argument signature \u2014 use it to decide which members to fetch in detail. Narrow the result with `kind` (one category), `filter` (case-insensitive substring of the member name or description, e.g. "book"), or `referencesType` (only members that use a given type, directly or transitively) to explore a domain cheaply instead of pulling the full schema. To search nested fields \u2014 not just type names \u2014 set scope "fields": it flattens every field of every object/interface/input type into "ParentType.fieldName" entries with their descriptions, so `filter` finds things like an input field whose docstring mentions your keyword.',schema:w,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{name:{type:"string"},items:{type:"array",items:{type:"object",properties:{kind:{type:"string",enum:l},name:{type:"string"},description:i,type:{type:"string"},args:{type:"string"},directives:{type:"string"}}}},...s}}},{name:"get-graphql-type",title:"Get GraphQL type",description:'Get the SDL for a single GraphQL type, operation (query/mutation/subscription field), or directive. Without includeReferencedTypes, the SDL is followed by a one-level manifest of every directly referenced type\'s field names (e.g. "input ActionOperationInput { addTags, removeTags }"), so you can see what nested types contain before fetching them. Set includeReferencedTypes to instead pull in the full SDL of every type it references transitively \u2014 the whole structural subgraph in one call, ideal for complete exploration of an entity (e.g. Book and all the types it touches). That traversal only follows what the target depends on; to go the other direction and find the members that use a type, call get-graphql-type-list with `referencesType`.',schema:I,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}},{name:"get-graphql-schema",title:"Get GraphQL schema",description:"Get the complete GraphQL schema as SDL \u2014 the whole type graph in one call. Returns everything, so it can be very large and token-expensive for big schemas; prefer get-graphql-type-list (filter/paginate) plus targeted get-graphql-type calls, and reach for this only for small schemas or when you truly need the full SDL.",schema:j,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}}]}function d(e,t){const h=e&&e.length>0,m=t&&t.length>0;return{name:"search",title:"Search documentation",description:"Search across the documentation to fetch relevant content for a given query",schema:{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1},...h?{product:{type:"string",description:"Optional product name to filter search results by specific product.",enum:[...e,null],nullable:!0}}:{},...m?{locale:{type:"string",description:"Optional locale code to filter search results by documentation language (e.g. 'en', 'ja'). Use the locale matching the language of the user's request. Defaults to the project's default locale.",enum:[...t,null],nullable:!0}}:{}}},annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"string"}}}const x=new Set([...T({requiresLogin:!0,hasGraphqlApis:!0,elicitationEnabled:!0,hasCallableApis:!0}).map(e=>e.name),d().name]);export{x as ALL_DEFAULT_TOOL_NAMES,T as getDefaultToolSchemas};
|
|
1
|
+
import{SEMANTIC_SEARCH_API_URL as y}from"../../../constants/common.js";import{shouldHandleMcpAuth as f}from"../../../utils/rbac/should-handle-mcp-auth.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as g,SUBMIT_FEEDBACK_TOOL_NAME as b}from"../constants.js";import{GRAPHQL_TYPE_KINDS as l,GRAPHQL_LIST_SCOPES as v}from"./tools/graphql/constants.js";import{OPERATION_METHODS as c}from"./tools/openapi/constants.js";const i={type:"string",nullable:!0},s={limit:{type:"number"},total:{type:"number"},page:{type:"number"},totalPages:{type:"number"}},a={codemodeType:"OpenApiServer[]"},o={codemodeType:"OpenApiSecurityRequirement[]"},u={codemodeType:"Record<string, OpenApiSecurityScheme>"},A={codemodeType:"OpenApiDocument"},P={codemodeType:"OpenApiOperation & { path: string; method: string }"},S={codemodeType:"OpenApiComponents",description:"Components the endpoint references. A `$ref` in `endpoint` resolves against the root of the result."},n={filePath:{type:"string",description:"API definition file path"},otherMatches:{type:"array",description:"Other API definitions the lookup also matched. Present only when several matched; pass `filePath` to pick another one",items:{type:"object",required:["filePath"],properties:{version:{type:"string"},filePath:{type:"string"}}}}},r="When several definitions match the name, the highest version or the shortest file path is used and the rest are listed in `otherMatches`; tell the user which version or file the answer is based on.",H="A `$ref` in `endpoint` points into the `components` key at the root of the result: read `#/components/<section>/<name>` there.",L={type:"object",additionalProperties:!1,required:[],properties:{filter:{type:"string",description:"Matches part of an API name, or of a description when no name matches",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of APIs per page. Default is 300",minimum:1,default:300,nullable:!0}}},p={type:"object",required:[],additionalProperties:!1,properties:{name:{type:"string",description:"API name, or a unique part of it. Omit when `filePath` is given.",minLength:1,nullable:!0},apiName:{type:"string",description:"Alias of `name`",nullable:!0},api:{type:"string",description:"Alias of `name`",nullable:!0},version:{type:"string",description:"API version. When omitted and several versions exist, the highest one is used",nullable:!0},filePath:{type:"string",description:"API definition file path, as returned by `listApis`",nullable:!0}}},O={type:"object",required:["path","method"],additionalProperties:!1,properties:{name:{type:"string",description:"API name, or a unique part of it. Omit when `filePath` is given.",minLength:1,nullable:!0},apiName:{type:"string",description:"Alias of `name`",nullable:!0},api:{type:"string",description:"Alias of `name`",nullable:!0},path:{type:"string",description:"Endpoint path (e.g. /api/v1/users)",minLength:1},method:{type:"string",description:"HTTP method (GET, POST, PUT, DELETE, etc.)",enum:[...c.map(e=>e.toUpperCase()),...c],minLength:1},version:{type:"string",description:"API version. When omitted and several versions exist, the highest one is used",nullable:!0},filePath:{type:"string",description:"API definition file path, as returned by `listApis`",nullable:!0}}},T={type:"object",required:[],additionalProperties:!1,properties:{}},q={type:"object",required:[],additionalProperties:!1,properties:{}},G={type:"object",required:["path","summary"],additionalProperties:!1,properties:{path:{type:"string",description:"Path or URL of the documentation page the feedback is about (e.g. /guides/auth)",minLength:1,maxLength:1e3},summary:{type:"string",description:"One sentence that names what is wrong with the page",minLength:1,maxLength:500},details:{type:"string",description:"Expected versus actual behavior, missing steps, or the snippet that failed",maxLength:4e3,nullable:!0},targetFeature:{type:"string",description:"The API or feature the page documents",maxLength:500,nullable:!0}}};function I(e){const t=[{name:"list-apis",title:"List APIs",description:"Lists the APIs documented in this project",schema:L,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:i,version:i,servers:a,filePath:{type:"string",description:"API definition file path"},ambiguousTitle:{type:"boolean",description:"true = another API shares this title; a lookup picks the highest version, or the shortest file path at the same version, and lists the rest in `otherMatches`. Pass `filePath` to pick another one"},...e.hasCallableApis?{callable:{type:"boolean",description:"true = the documented hosts of this API are reachable via `fetch`; false = documentation only"}}:{}}}},...s}}},{name:"get-endpoints",title:"Get endpoints",description:`Get all endpoints for a specific API. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,servers:a,endpoints:{type:"array",items:{type:"object",properties:{path:{type:"string"},method:{type:"string"},summary:i,description:i,security:o}}}}}},{name:"get-endpoint-info",title:"Get endpoint info",description:`Get comprehensive information about specific endpoint including parameters, security, and examples. ${H} ${r}`,schema:O,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,servers:a,endpoint:P,globalSecurity:o,securitySchemes:u,components:S}}},{name:"get-security-schemes",title:"Get security schemes",description:`Get the security schemes for a specific API. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{name:i,version:i,...n,securitySchemes:u,security:o}}},{name:"get-full-api-description",title:"Get full API description",description:`Get the complete OpenAPI description. ${r}`,schema:p,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",required:["filePath"],properties:{api:{type:"string"},version:{type:"string"},...n,definition:A}}},...y?[d(e.products,e.locales)]:[]];return f(e.requiresLogin,e.rbac)&&t.push({name:"whoami",title:"Who am I",description:"Get information about the currently authenticated user",schema:T,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{email:{type:"string"},name:{type:"string"},subject:{type:"string"},clientId:{type:"string"},scope:{type:"string"},issuedAt:{type:"string"},expiresAt:{type:"string"}}}}),e.feedbackHidden||t.push({name:b,title:"Submit feedback",description:"Report a documentation page that is wrong or incomplete",schema:G,annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"object",required:["status","page","message"],properties:{status:{type:"string"},page:{type:"string"},message:{type:"string"}}}}),e.hasGraphqlApis&&t.push(...k()),e.elicitationEnabled&&e.hasCallableApis&&t.push({name:g,title:"Create anonymous session",description:"Create an anonymous session handle for storing upstream API credentials. Pass the returned sessionHandle to execute when an API needs credentials and the caller is not signed in. Treat it as a secret and reuse it across calls.",schema:q,annotations:{readOnlyHint:!1,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"object",required:["sessionHandle"],properties:{sessionHandle:{type:"string"}}}}),t}const w={type:"object",required:[],additionalProperties:!1,properties:{filter:{type:"string",description:"GraphQL schema name (or part of it)",minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},j={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},kind:{type:"string",description:'Optional: return only a single category of schema members. With scope "fields", restricts to the fields of that parent category ("objects", "interfaces", or "inputs" only).',enum:[...l,null],nullable:!0},scope:{type:"string",description:'Optional: what each list item is. "members" (default) lists top-level types and operations. "fields" flattens every field of every object/interface/input type into "ParentType.fieldName" entries with their descriptions \u2014 combine with `filter` to search nested fields anywhere in the schema.',enum:[...v,null],nullable:!0},filter:{type:"string",description:'Optional: only members whose name or description contains this substring, case-insensitive (e.g. "custom tags")',minLength:1,nullable:!0},referencesType:{type:"string",description:'Optional: only members that reference this type directly or transitively (via return, field, argument, union-member or input-field types). Finds cross-cutting members that never name it \u2014 e.g. referencesType "Book" surfaces a search query returning a union that includes Book.',minLength:1,nullable:!0},page:{type:"number",description:"Page number",minimum:1,default:1,nullable:!0},limit:{type:"number",description:"Number of results per page. Default is 300",minimum:1,default:300,nullable:!0}}},E={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1},type:{type:"string",description:"Name of the type, operation, or directive",minLength:1,nullable:!0},typeName:{type:"string",description:"Alias of `type`",nullable:!0},includeReferencedTypes:{type:"boolean",description:"Also include the SDL of every type referenced transitively. Gives the whole subgraph at once, but can be large for highly-connected types.",default:!1,nullable:!0}}},N={type:"object",required:["name"],additionalProperties:!1,properties:{name:{type:"string",description:"GraphQL schema name",minLength:1}}};function k(){return[{name:"list-graphql-apis",title:"List GraphQL APIs",description:"Lists available GraphQL schemas with their context and purpose",schema:w,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{items:{type:"array",items:{type:"object",properties:{name:{type:"string"},description:i}}},...s}}},{name:"get-graphql-type-list",title:"Get GraphQL type list",description:'List all operations and types in a GraphQL schema as a flat, paginated list. Each item is tagged with its kind (query, object, enum, \u2026) and carries a one-line description; operations also include their return type and argument signature \u2014 use it to decide which members to fetch in detail. Narrow the result with `kind` (one category), `filter` (case-insensitive substring of the member name or description, e.g. "book"), or `referencesType` (only members that use a given type, directly or transitively) to explore a domain cheaply instead of pulling the full schema. To search nested fields \u2014 not just type names \u2014 set scope "fields": it flattens every field of every object/interface/input type into "ParentType.fieldName" entries with their descriptions, so `filter` finds things like an input field whose docstring mentions your keyword.',schema:j,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"object",properties:{name:{type:"string"},items:{type:"array",items:{type:"object",properties:{kind:{type:"string",enum:l},name:{type:"string"},description:i,type:{type:"string"},args:{type:"string"},directives:{type:"string"}}}},...s}}},{name:"get-graphql-type",title:"Get GraphQL type",description:'Get the SDL for a single GraphQL type, operation (query/mutation/subscription field), or directive. Without includeReferencedTypes, the SDL is followed by a one-level manifest of every directly referenced type\'s field names (e.g. "input ActionOperationInput { addTags, removeTags }"), so you can see what nested types contain before fetching them. Set includeReferencedTypes to instead pull in the full SDL of every type it references transitively \u2014 the whole structural subgraph in one call, ideal for complete exploration of an entity (e.g. Book and all the types it touches). That traversal only follows what the target depends on; to go the other direction and find the members that use a type, call get-graphql-type-list with `referencesType`.',schema:E,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}},{name:"get-graphql-schema",title:"Get GraphQL schema",description:"Get the complete GraphQL schema as SDL \u2014 the whole type graph in one call. Returns everything, so it can be very large and token-expensive for big schemas; prefer get-graphql-type-list (filter/paginate) plus targeted get-graphql-type calls, and reach for this only for small schemas or when you truly need the full SDL.",schema:N,annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!0,openWorldHint:!1},outputSchema:{type:"string"}}]}function d(e,t){const h=e&&e.length>0,m=t&&t.length>0;return{name:"search",title:"Search documentation",description:"Search across the documentation to fetch relevant content for a given query",schema:{type:"object",required:["query"],additionalProperties:!1,properties:{query:{type:"string",description:"Search query. Should be a single word or that phrase that is presented in a documentation.",minLength:1},...h?{product:{type:"string",description:"Optional product name to filter search results by specific product.",enum:[...e,null],nullable:!0}}:{},...m?{locale:{type:"string",description:"Optional locale code to filter search results by documentation language (e.g. 'en', 'ja'). Use the locale matching the language of the user's request. Defaults to the project's default locale.",enum:[...t,null],nullable:!0}}:{}}},annotations:{readOnlyHint:!0,destructiveHint:!1,idempotentHint:!1,openWorldHint:!1},outputSchema:{type:"string"}}}const Q=new Set([...I({requiresLogin:!0,hasGraphqlApis:!0,elicitationEnabled:!0,hasCallableApis:!0}).map(e=>e.name),d().name]);export{Q as ALL_DEFAULT_TOOL_NAMES,I as getDefaultToolSchemas};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as
|
|
1
|
+
import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as t}from"../../../constants.js";import{isFetchCapable as o}from"../../../gateway-mcp/callable-apis.js";import{createSessionHandle as n}from"../../../gateway-mcp/subject.js";const i=async()=>{const e={sessionHandle:n()};return{content:[{type:"text",text:JSON.stringify(e)}],structuredContent:e}};function s(e){return!!e.elicitationEnabled&&e.mcpMode==="code"&&o(e)&&!e.user?.isAuthenticated}var u={[t]:{execute:i,isAvailable:s}};export{u as default,s as isAnonymousSessionToolAvailable};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
1
|
export declare const OPERATION_METHODS: readonly ['get', 'put', 'post', 'delete', 'options', 'head', 'patch', 'trace', 'query', 'x-query'];
|
|
2
2
|
export declare const HTTP_METHODS: Set<string>;
|
|
3
|
+
export declare const MAX_ENDPOINT_INFO_BYTES: number;
|
|
4
|
+
export declare const MAX_INLINED_ENDPOINT_BYTES: number;
|
|
3
5
|
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
1
|
+
const t=["get","put","post","delete","options","head","patch","trace","query","x-query"],e=new Set(t),o=8*1024*1024,T=1024*1024;export{e as HTTP_METHODS,o as MAX_ENDPOINT_INFO_BYTES,T as MAX_INLINED_ENDPOINT_BYTES,t as OPERATION_METHODS};
|
|
@@ -4,6 +4,12 @@ import type { McpMode } from '../../../types.js';
|
|
|
4
4
|
export declare function visibleMethodsAt(definition: OpenAPIDefinition, path: string): string[];
|
|
5
5
|
/** Paths with at least one visible operation. */
|
|
6
6
|
export declare function visiblePaths(definition: OpenAPIDefinition): string[];
|
|
7
|
+
/** The tools that recover a lookup miss. The sandbox calls the same tools by their JS names. */
|
|
8
|
+
export declare function recoveryToolNames(mcpMode?: McpMode): {
|
|
9
|
+
endpoints: string;
|
|
10
|
+
search: string;
|
|
11
|
+
listApis: string;
|
|
12
|
+
};
|
|
7
13
|
/** Message for a path the definition does not document, or documents only behind `x-mcp`. */
|
|
8
14
|
export declare function describePathMiss(definition: OpenAPIDefinition, apiTitle: string, path: string, mcpMode?: McpMode): string;
|
|
9
15
|
/** Message for a visible path that does not document the requested method, or hides it. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{isEndpointHidden as
|
|
1
|
+
import{isEndpointHidden as r}from"../../../utils/xmcp-utils.js";import{formatCandidates as i}from"../../utils/api-name-matching.js";import{HTTP_METHODS as c}from"./constants.js";import{isMcpEndpoint as h}from"./utils.js";function p(t,s){const e=t.paths?.[s];return!e||r(e,"docs")?[]:Object.entries(e).filter(([n,o])=>c.has(n.toLowerCase())&&h(o)&&!r(o,"docs")).map(([n])=>n.toUpperCase()).sort()}function l(t){return Object.keys(t.paths??{}).filter(s=>p(t,s).length>0).sort()}function f(t){return t==="code"?{endpoints:"tools.getEndpoints",search:"tools.search",listApis:"tools.listApis"}:{endpoints:"get-endpoints",search:"search",listApis:"list-apis"}}function E(t,s,e,n){const o=l(t);if(o.length===0)return"Endpoint not found";const{endpoints:d,search:a}=f(n);return`No path "${e}" in "${s}". Documented paths: ${i(o)}. Call ${d} for the full list, or ${a} with a keyword from the request.`}function M(t,s,e,n){const o=p(t,e);return o.length===0?"Endpoint not found":`"${e}" in "${s}" documents no ${n.toUpperCase()}. Available methods: ${i(o)}.`}export{M as describeMethodMiss,E as describePathMiss,f as recoveryToolNames,p as visibleMethodsAt,l as visiblePaths};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{inlineOperation as g,resolveOperation as v}from"../../utils/resolve-refs.js";import{isMcpEndpoint as N,matchDocumentedMethod as D,matchDocumentedPath as I}from"./utils.js";import{MAX_ENDPOINT_INFO_BYTES as y,MAX_INLINED_ENDPOINT_BYTES as O}from"./constants.js";import{describeMethodMiss as T,describePathMiss as b,visibleMethodsAt as S}from"./endpoint-suggestions.js";import{loadApiDescription as _}from"./load-api-description.js";import{checkEndpointAndDeleteXMcp as $}from"../../../utils/xmcp-utils.js";const A=async(h,n)=>{const{path:d,method:o}=h;if(!d||!o)return{content:[{type:"text",text:'Both "path" and "method" are required (e.g. path: "/tickets", method: "GET").'}],isError:!0};let m;try{m=await _(h,n)}catch(a){return{content:[{type:"text",text:a.message}],isError:!0}}const{description:t,filePath:E,otherMatches:i}=m,l=i?` Other definitions share this title: ${i.map(a=>`"${a.filePath}"`).join(", ")}. Pass "filePath" to check them.`:"",e=I(t,d),{title:s=""}=t.info||{},r=t.paths?.[e];if(!r||S(t,e).length===0)return{content:[{type:"text",text:b(t,s,e,n.mcpMode)+l}],isError:!0};const c=r[D(r,o)];if(!N(c)||!$(c,"docs"))return{content:[{type:"text",text:T(t,s,e,o)+l}],isError:!0};const M=r?.parameters||[],f={operation:c,pathParams:M,definition:t},x=n.mcpMode==="code"?g(f,O):void 0,{operation:P,components:u}=x??v(f),p=JSON.stringify({api:s,version:t.info?.version||"",filePath:E,otherMatches:i,servers:t.servers||[],endpoint:{path:e,method:o.toUpperCase(),...P},globalSecurity:t.security||[],securitySchemes:t.components?.securitySchemes||{},...u?{components:u}:{}},null,2);return p.length>y?{content:[{type:"text",text:`${o.toUpperCase()} ${e} is ${p.length} bytes, over the ${y} byte limit.`}],isError:!0}:{content:[{type:"text",text:p}]}};var j={"get-endpoint-info":A};export{j as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{describeAvailableApis as
|
|
1
|
+
import{describeAvailableApis as l,findApiDescriptionByNameAndVersion as b,formatCandidates as d}from"../../utils/api-name-matching.js";import{apiTitleKey as A,compareApiDescriptions as P}from"../../utils/api-titles.js";import{recoveryToolNames as f,visibleMethodsAt as g}from"./endpoint-suggestions.js";import{absolutePath as u,getApiDescriptionFromFs as I,matchDocumentedPath as M}from"./utils.js";function m(i){return`Pass \`name\` (the API title, or a unique part of it) or \`filePath\` from ${f(i).listApis}.`}const D=10;function N({name:i,version:e,filePath:n},t){const o=Object.values(t);if(n)return o.filter(a=>a.relativePath===n);const r=o.find(a=>a.relativePath===i);if(r)return[r];const s=b(t,i??"",e);return s?[s.description,...s.otherMatches??[]]:[]}function w({version:i,relativePath:e}){return{...i?{version:i}:{},filePath:e}}function h({relativePath:i},e){return I({relativePath:i,outdir:e.outdir||"",user:e.user,rbac:e?.config?.access?.rbac||{},requiresLogin:!!e?.config?.access?.requiresLogin})}async function S(i,e){const{version:n,filePath:t}=i,o=i.name??i.apiName??i.api;if(!t&&!o)return y(i,e);const r=N({name:o,version:n,filePath:t},e.apiDescriptionsMap);return F(r,{name:o,filePath:t},e)}async function y({path:i,method:e,version:n},t){const o=Object.values(t.apiDescriptionsMap);if(o.length===0)throw new Error("This project documents no OpenAPI description.");if(o.length===1){const[p]=o;if(n&&p.version!==n)throw new Error(`"${p.name}" has no version "${n}". Available versions: ${p.version||"(no version)"}.`);const $=await h(p,t);if(!$)throw new Error(`Could not read the API definition "${p.relativePath}". ${m(t.mcpMode)}`);return{description:$,filePath:p.relativePath}}if(!i||!e||o.length>D)throw new Error(`${m(t.mcpMode)} Available APIs: ${l(t.apiDescriptionsMap,"")}.`);const r=await k(o,i,e,t),{documenting:s,otherMethods:a}=r;if(s.length===0)throw C(t,a,i,e);if(!n)return v(s,r.best,i,e,t);const c=s.filter(p=>p.version===n);if(c.length===0)throw j(s,i,n);return v(c,r.best,i,e,t)}async function v(i,e,n,t,o){const r=new Set(i.map(({name:p})=>A(p)));if(r.size>1)throw E(i,r,n,t,o.mcpMode);const[s,...a]=i,c=s===e?.api?e.description:await h(s,o);if(!c)throw new Error(`Could not read the API definition "${s.relativePath}". ${m(o.mcpMode)}`);return{description:c,filePath:s.relativePath,otherMatches:a.length>0?a.map(w):void 0}}function E(i,e,n,t,o){const r=[...e].map(s=>{const[a]=i.filter(c=>A(c.name)===s);return`"${a.name}" (${a.relativePath})`});return new Error(`${t.toUpperCase()} ${u(n)} is documented by ${e.size} APIs: ${d(r)}. Pass \`name\` or \`filePath\` from ${f(o).listApis} to pick one.`)}function C(i,e,n,t){if(e.length>0){const s=e.map(({api:a,methods:c})=>`"${a.name}" (${a.relativePath}) documents ${d(c)}.`).join(" ");return new Error(`No API documents ${t.toUpperCase()} ${u(n)}. ${s}`)}const{endpoints:o,search:r}=f(i.mcpMode);return new Error(`No API in this project documents ${u(n)}. Available APIs: ${l(i.apiDescriptionsMap,"")}. Call ${o} with one of them, or ${r} with a keyword from the request.`)}function j(i,e,n){const t=[...new Set(i.map(({version:o})=>o||"(no version)"))];return new Error(`No API documenting "${u(e)}" has version "${n}". Available versions: ${d(t)}.`)}async function k(i,e,n,t){const o=[],r=[];let s;for(const a of i){const c=await h(a,t);if(!c)continue;const p=g(c,M(c,e));p.includes(n.toUpperCase())?(o.push(a),(!s||P(a,s.api)<0)&&(s={api:a,description:c})):p.length>0&&r.push({api:a,methods:p})}return{documenting:o.sort(P),best:s,otherMethods:r}}async function F(i,{name:e,filePath:n},t){if(i.length===0){if(n)throw new Error(`No API found with filePath "${n}". File paths are returned by the ${f(t.mcpMode).listApis} tool.`);const r=l(t.apiDescriptionsMap,e??"");throw new Error(r?`No API found matching "${e}". Available APIs: ${r}.`:`No API found matching "${e}".`)}for(const r of i){const s=await h(r,t);if(!s)continue;const a=i.filter(c=>c!==r);return{description:s,filePath:r.relativePath,otherMatches:a.length>0?a.map(w):void 0}}const o=i.map(({relativePath:r})=>`"${r}"`).join(", ");throw new Error(i.length>1?`No API found matching "${n||e}". None of the matching definitions could be loaded: ${o}.`:`No API found matching "${n||e}".`)}export{S as loadApiDescription};
|
|
@@ -14,5 +14,10 @@ export declare function getApiDescriptionFromFs({ relativePath, outdir, user, rb
|
|
|
14
14
|
rbac?: RbacConfig;
|
|
15
15
|
requiresLogin?: boolean;
|
|
16
16
|
}): Promise<OpenAPIDefinition | undefined>;
|
|
17
|
+
export declare function absolutePath(requestedPath: string): string;
|
|
18
|
+
/** Models copy a path and lose its casing; the definition's own spelling still answers. */
|
|
19
|
+
export declare function matchDocumentedPath(description: OpenAPIDefinition, requestedPath: string): string;
|
|
20
|
+
/** Definitions sometimes key an operation in upper case; the documented key still answers. */
|
|
21
|
+
export declare function matchDocumentedMethod(pathItem: object, requestedMethod: string): string;
|
|
17
22
|
export {};
|
|
18
23
|
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import m from"node:path";import{existsSync as f}from"node:fs";import{readFile as d}from"node:fs/promises";import{replaceFileExtension as u}from"../../../../../plugins/api-docs/utils/replace-file-extension.js";import{PUBLIC_API_DEFINITIONS_FOLDER as h}from"../../../../../constants/common.js";import{filterDataByAccessDeep as l}from"../../../../../utils/rbac.js";import{checkEndpointAndDeleteXMcp as p}from"../../../utils/xmcp-utils.js";import{HTTP_METHODS as y}from"./constants.js";function A(t){return typeof t=="object"&&t!==null&&"responses"in t&&typeof t.responses=="object"}function I(t){const{paths:o={}}=t,e=[];for(const[s,n]of Object.entries(o)){const r=!p(n,"docs");for(const[c,i]of Object.entries(n))y.has(c.toLowerCase())&&(r||!p(i,"docs")||e.push({path:s,method:c.toUpperCase(),summary:i.summary,description:i.description,security:i.security}))}return e}async function P({relativePath:t,outdir:o,user:e,rbac:s={},requiresLogin:n=!1}){const r=m.join(o||"",h,u(t,".json"));if(!f(r))return;const i=await d(r,"utf-8"),a=JSON.parse(i);return l(a,{isAuthenticated:e?.isAuthenticated,email:e?.email,teams:e?.teams},s,n)}function D(t){return t.startsWith("/")?t:`/${t}`}function M(t,o){const e=D(o);if(t.paths?.[e])return e;const s=e.toLowerCase();return Object.keys(t.paths??{}).find(r=>r.toLowerCase()===s)??e}function S(t,o){const e=o.toLowerCase();return Object.keys(t).find(n=>n.toLowerCase()===e)??e}export{D as absolutePath,P as getApiDescriptionFromFs,I as getEndpointsFromPaths,A as isMcpEndpoint,S as matchDocumentedMethod,M as matchDocumentedPath};
|
|
@@ -1,20 +1,26 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
type
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
currentDepth?: number;
|
|
1
|
+
import type { OpenAPIParameter, Referenced, OpenAPIDefinition } from '@redocly/api-docs';
|
|
2
|
+
import type { McpEndpoint } from '../../types.js';
|
|
3
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
4
|
+
[key: string]: JsonValue;
|
|
5
|
+
};
|
|
6
|
+
type JsonObject = {
|
|
7
|
+
[key: string]: JsonValue;
|
|
9
8
|
};
|
|
10
|
-
export
|
|
11
|
-
|
|
9
|
+
export type ResolvedOperation = {
|
|
10
|
+
operation: JsonObject;
|
|
11
|
+
components?: Record<string, JsonObject>;
|
|
12
|
+
};
|
|
13
|
+
export declare function resolveRef<T>(ref: string, def?: OpenAPIDefinition): T | undefined;
|
|
14
|
+
type ResolveOperationParams = {
|
|
15
|
+
operation: McpEndpoint;
|
|
12
16
|
pathParams: Referenced<OpenAPIParameter>[];
|
|
13
|
-
opParams: Referenced<OpenAPIParameter>[];
|
|
14
17
|
definition: OpenAPIDefinition;
|
|
15
18
|
};
|
|
16
|
-
export declare function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
+
export declare function resolveOperation({ operation, pathParams, definition, }: ResolveOperationParams): ResolvedOperation;
|
|
20
|
+
/**
|
|
21
|
+
* The operation with every `$ref` it follows inlined, or undefined when the followed targets pass
|
|
22
|
+
* `maxBytes` or the inliner cannot read the operation.
|
|
23
|
+
*/
|
|
24
|
+
export declare function inlineOperation({ operation, pathParams, definition }: ResolveOperationParams, maxBytes: number): ResolvedOperation | undefined;
|
|
19
25
|
export {};
|
|
20
26
|
//# sourceMappingURL=resolve-refs.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function
|
|
1
|
+
const S=/^#\/components\/([^/]+)\/([^/]+)(\/.*)?$/;function w(e){return e.replace(/~1/g,"/").replace(/~0/g,"~")}function d(e,s){if(!s||!e?.startsWith("#/"))return;const n=e.slice(2).split("/").map(w);let t=s;for(const r of n)if(typeof t=="object"&&t!==null&&r in t)t=t[r];else return;return t}function h(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function O(e,s){const n={},t=new Set,r=new Set,o=[e];for(;o.length>0;){const c=o.pop();if(!(c===null||typeof c!="object")){if(h(c)&&typeof c.$ref=="string"&&!t.has(c.$ref)){t.add(c.$ref);const[,i,f]=S.exec(c.$ref)??[],u=f&&w(f);if(i&&u&&!r.has(`${i}/${u}`)){const l=d(`#/components/${i}/${f}`,s);l!==void 0&&(r.add(`${i}/${u}`),(n[i]??={})[u]=l,o.push(l))}}for(const i of Object.values(c))o.push(i)}}return Object.keys(n).length>0?n:void 0}function R(e,s){const n=h(e)&&typeof e.$ref=="string"?d(e.$ref,s)??e:e,{name:t,in:r}=h(n)?n:{};return typeof t=="string"&&typeof r=="string"?`${r}:${t}`:JSON.stringify(e)}function g(e,s,n){const t=new Map;for(const r of[...e,...s])r&&t.set(R(r,n),r);return[...t.values()]}function C({operation:e,pathParams:s,definition:n}){const t={...e,parameters:g(s,e.parameters??[],n)};return{operation:t,components:O(t,n)}}class E extends Error{}function j(e,s){if(e.remainingBytes-=s,e.remainingBytes<0)throw new E}function $(e,s){return j(e,JSON.stringify(s).length),s}function m(e,s,n){const t=d(e,s);if(t===void 0)return;const r=n.bytesByRef.get(e)??JSON.stringify(t).length;return n.bytesByRef.set(e,r),j(n,r),t}function y(e,s,n){const t=$(n,Object.fromEntries(Object.entries(e).filter(([r,o])=>r!=="$ref"&&o!==void 0)));return{...s,...t}}function a({schema:e,definition:s,budget:n,visitedRefs:t=new Set,maxDepth:r=50,currentDepth:o=0}){if(!e)return;if(o>=r)return $(n,{type:"object",description:`Maximum resolution depth exceeded (${r})`});if("$ref"in e&&e.$ref){if(t.has(e.$ref))return $(n,{type:"object",description:`Circular reference detected: ${e.$ref}`,"x-circular-ref":e.$ref});const f=new Set(t);f.add(e.$ref);const u=m(e.$ref,s,n);if(!u)return $(n,{type:"object",description:`Could not resolve reference: ${e.$ref}`,"x-unresolved-ref":e.$ref});const l=a({schema:u,definition:s,budget:n,visitedRefs:f,maxDepth:r,currentDepth:o+1});return l&&y(e,l,n)}const c={...e};if(c.properties){const f={};for(const[u,l]of Object.entries(c.properties)){const p=a({schema:l,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});f[u]=p||l}c.properties=f}if(c.items&&typeof c.items=="object")if(Array.isArray(c.items))c.items=c.items.map(f=>a({schema:f,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1})||f);else{const f=a({schema:c.items,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});f&&(c.items=f)}return["allOf","anyOf","oneOf"].forEach(f=>{const u=c[f];Array.isArray(u)&&(c[f]=u.reduce((l,p)=>{const v=a({schema:p,definition:s,budget:n,visitedRefs:new Set(t),maxDepth:r,currentDepth:o+1});return v&&l.push(v),l},[]))}),c}function P({pathParams:e,opParams:s,definition:n,budget:t}){return[...e,...s].reduce((r,o)=>{if(!o)return r;if("$ref"in o&&o.$ref){const c=m(o.$ref,n,t);if(!c)return r;const i=y(o,c,t);return r.push({...i,schema:"schema"in i&&i.schema?a({schema:i.schema,definition:n,budget:t}):void 0}),r}return r.push({...o,schema:"schema"in o&&o.schema?a({schema:o.schema,definition:n,budget:t}):void 0}),r},[])}function x(e,s,n){const t={...e};if(e.example!==void 0&&(t.example=e.example),!e.examples)return t;const r={};for(const[o,c]of Object.entries(e.examples))if("$ref"in c){const i=m(c.$ref,s,n);i&&(r[o]=i)}else r[o]=c;return t.examples=r,t}function A(e,s,n){if(!e)return;const t="$ref"in e&&e.$ref?m(e.$ref,s,n):e;if(!t)return;const r=y(e,t,n),o={...r};if("content"in r&&r.content){const c={};for(const[i,f]of Object.entries(r.content))c[i]={...x(f,s,n),schema:f.schema?a({schema:f.schema,definition:s,budget:n}):void 0};o.content=c}return o}function B(e,s,n){return Object.entries(e).reduce((t,[r,o])=>{const c="$ref"in o&&o.$ref?m(o.$ref,s,n):o;if(!c)return t;const i=y(o,c,n),f={...i};if("content"in i&&i.content){const u={};for(const[l,p]of Object.entries(i.content))u[l]={...x(p,s,n),schema:p.schema?a({schema:p.schema,definition:s,budget:n}):void 0};f.content=u}return t[r]=f,t},{})}function N({operation:e,pathParams:s,definition:n},t){const r={remainingBytes:t,bytesByRef:new Map};try{const o={...e,parameters:P({pathParams:s,opParams:e.parameters||[],definition:n,budget:r}),requestBody:A(e.requestBody,n,r),responses:B(e.responses,n,r)};return{operation:o,components:O(o,n)}}catch{return}}export{N as inlineOperation,C as resolveOperation,d as resolveRef};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as g}from"../../../tools/notifiers/logger.js";import{getFeedbackClientIp as F}from"../../../web-server/utils/feedback-ip.js";import{getForwardedOrigin as h,getInternalOrigin as N}from"../../../web-server/utils/get-request-origin.js";import{GATEWAY_FETCH_LIMIT_DEFAULTS as v,DEFAULT_ANONYMOUS_VISITOR_TEAM as B,RbacFeatures as L}from"../../../../constants/common.js";import{isObject as H}from"../../../../utils/guards/is-object.js";import{getAccessibleSkills as V}from"../../../utils/skills/get-accessible-skills.js";import{getSkillUrl as $}from"../../../utils/skills/get-skill-url.js";import{createMcpHandler as j}from"@modelcontextprotocol/server";import{createDocsMcpServer as G}from"../servers/docs-server.js";import{filterApiDescriptionsByRbac as J,filterGraphqlDescriptionsByRbac as K}from"../utils.js";import{McpClientInputError as Y,createMethodNotAllowedError as z,withErrorHandling as W}from"./errors.js";import{constructForbiddenResponse as X,constructInvalidTokenResponse as Q,constructUnauthorizedResponse as Z,handleMcpAuth as q}from"../auth/auth-handlers.js";import{isAssistantAnonymousToken as x}from"../auth/assistant-anonymous-token.js";import{shouldHandleMcpAuth as ee}from"../../../utils/rbac/should-handle-mcp-auth.js";import{canAnonymousAccessMcpFeature as re}from"../../../utils/rbac/can-anonymous-access-mcp-feature.js";import{extractTokenFromAuthHeader as oe}from"../utils/jwt.js";import{resolveMcpClient as se}from"../utils/mcp-client.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as ne,SSE_KEEPALIVE_INTERVAL_MS as ie}from"../constants.js";import{withPathPrefix as te}from"@redocly/theme/core/utils";import{PUBLIC_MCP_ROUTE as ce}from"@redocly/theme/core/constants/mcp";import{canAccessFeature as ae}from"../../../utils/rbac.js";import{ANONYMOUS_AUTH_DETAILS as pe}from"../../../constants/rbac.js";const A="X-Redocly-AI-Metadata";function de(r){if(r)try{const e=JSON.parse(r);if(H(e))return e;g.warn(`Ignoring ${A} header: not a JSON object.`)}catch{g.warn(`Ignoring ${A} header: invalid JSON.`)}}function b(){return{...pe,email:"",idpAccessToken:void 0,idpId:void 0}}const le=async(r,e,c)=>{const i=!!e?.config?.access?.requiresLogin,t=e?.config?.access?.rbac||{},M=c?.props?.config?.mcpMode??"tools",y=c?.props?.config?.gatewayFetchBudgetPerExec??v.budgetPerExec,S=c?.props?.config?.searchIgnoredRoutes??[],s=c,I=!!s?.props?.config?.isPublicEndpoint;let u;const E=r.headers.get("Authorization");if(I)e.user=b();else if(ee(i,t)){const{isAuthenticated:n,isTokenValid:p,isFirstPartyAnonymous:m,currentUser:d,accessToken:f}=await q(r,e);if(m)e.user=b();else if(n)d&&(e.user=d),u=f;else{const a=h(r),l=e.config.mcp?.docs?.publicEndpoint&&re(t,i)?`${a}${te(ce)}`:void 0;return p===!1?Q(a,l):Z(a,l)}}else if(E){const n=oe(E)??void 0;u=(n?await x(n):!1)?void 0:n}const U={isAuthenticated:!!e.user?.isAuthenticated,teams:e.user?.teams||[B],claims:e.user?.claims??{}};return ae(L.MCP,U,t,i)?await W(async()=>{const n=c?.props?.config?.elicitationEnabled??!1;if(r.method==="GET")return new Response(JSON.stringify({error:"Method Not Allowed",message:`In order to use this MCP server, you need to register it in your MCP client (VS Code, Cursor, Claude Code, etc.) using this URL: ${r.url}`}),{status:405,headers:{"Content-Type":"application/json"}});if(r.method!=="POST")return z();const p=s?.props?.config?.apiDescriptionsMap||{},m=s?.props?.config?.graphqlDescriptions||[],d=s?.props?.config?.mcpDocsServerName||ne,{config:{mcp:f={}}}=e,a=J(p,e.user,t,i),l=K(m,e.user,t,i),w=e.config.products?Object.values(e.config.products).map(o=>o?.name):[],C=f.docs?.name||d,R=de(r.headers.get(A)),_=s?.props?.tools||[],D=s?.props?.skillsBaseUrl||h(r),O=V(s?.props?.skills||[],e.user,t,i).map(o=>({slug:o.slug,name:o.name,description:o.description,content:o.content,uri:$(D,o.slug)})),T=await ue(r),P={name:C,tools:_,skills:O,context:{...e,accessToken:u,outdir:e.outdir||"",baseUrl:e.baseUrl||h(r),internalBaseUrl:N(r),apiDescriptionsMap:a,graphqlDescriptions:l,products:w,metadata:R,mcpMode:M,elicitationEnabled:n,gatewayFetchBudgetPerExec:y,searchIgnoredRoutes:S,clientIp:F(r),...se(r)}},k=await G({...P,getKv:e.getKv});return await j(async()=>k,{keepAliveMs:ie,onerror:o=>g.warn(`MCP handler: ${o.message}`)}).fetch(r,T!==void 0?{parsedBody:T}:void 0)},M):X()};async function ue(r){try{return await r.json()}catch(e){throw new Y(e instanceof Error?e.message:String(e),{cause:e})}}var ve=le;export{ve as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as
|
|
1
|
+
import{logger as v}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as L,MCP_TOOL_IS_AVAILABLE_KEY as k}from"../../../workers/mcp-tool-worker-pool.js";import{CREATE_ANONYMOUS_SESSION_TOOL_NAME as C,MANAGE_API_CREDENTIALS_TOOL_NAME as y}from"../constants.js";import{isAnonymousSessionToolAvailable as D}from"../docs-mcp/tools/core/create-anonymous-session.js";import{isManageApiCredentialsToolAvailable as N,manageApiCredentials as x,manageApiCredentialsSchema as w}from"../codemode/tools/manage-credentials.js";import{EXECUTE_TOOL_SCHEMA as _}from"../codemode/tools/execute-schema.js";import{EXECUTE_TOOL_NAME as I,CODE_MODE_TOOL_NAMES as H,FETCH_TOOL_NAME as P}from"../codemode/constants.js";import{buildCodeModeInstructions as R,buildExecuteDescription as U}from"../codemode/prompts.js";import{toToolListEntries as F}from"../codemode/build-tool-list.js";import{composeExecuteAnnotations as z,getActiveCapabilities as B}from"../codemode/capabilities/index.js";import{describeToolsSchema as W,describeTools as X}from"../codemode/tools/describe-tools.js";import{availableSandboxTools as Y}from"../utils/available-sandbox-tools.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{toRegisterToolConfig as h}from"../utils/tool-registration.js";import{createMcpServer as $,createToolDispatch as j,extractSerializableContext as G}from"./mcp-server.js";function O(r,t){const o=t.schema;if(r)return o;const{sessionHandle:T,...p}=o.properties;return{...o,properties:p}}function K(r){return Object.fromEntries(r.map(t=>[t.name,t.schema]))}async function me({name:r,tools:t,context:o,skills:T=[],getKv:p}){const n=G(o),s=o.mcpMode==="code",l=s?B(o):[],b=l.some(e=>e.id===P),c=s?await Y(t.filter(e=>!H.has(e.name)),n):[],E=F(c,l),d=D(o)&&!S(C,o.metadata),g=s&&N(o)&&!S(y,o.metadata),m=$(r,s?R(b,E):void 0),u={getClientCapabilities:()=>m.server.getClientCapabilities(),getKv:p},f=j(s?{...n,sandboxToolSchemas:K(c)}:n,u),A=async e=>{try{return await L.exec(k,[{toolName:e,context:n}],{timeout:1e4})}catch(i){return v.error(`Failed to check MCP tool availability for "${e}": ${i instanceof Error?i.message:String(i)}`),!1}};if(s){const e=[{tool:{..._,description:U(b,E),schema:O(d,_),annotations:z(c,l)},callback:f(I)},{tool:W(c,l),callback:X(c,A,l,o)}],i=t.find(a=>a.name===C);if(i&&d&&e.push({tool:i,callback:f(i.name)}),g){const a=w(o);e.push({tool:{...a,schema:O(d,a)},callback:x(n,u)})}for(const{tool:a,callback:M}of e)m.registerTool(a.name,h(a),M)}else await Promise.all(t.map(async e=>{const i=m.registerTool(e.name,h({...e,outputSchema:void 0}),f(e.name));await A(e.name)||i.disable()}));for(const e of T)m.registerResource(e.slug,e.uri,{title:e.name,description:e.description,mimeType:"text/markdown"},async()=>({contents:[{uri:e.uri,mimeType:"text/markdown",text:e.content}]}));return m}export{me as createDocsMcpServer};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as j}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as D,MCP_TOOL_WORKER_KEY as F}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as K}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as L,stripAuthRequiredMeta as y,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{buildCredentialsToolHint as H,buildSchemeChoiceHint as P,buildUpstreamCredentialFallback as T,buildUpstreamCredentialInputRequired as $,dedupeElicitation as B,isCredentialElicitationDeclined as x,isStatelessRequest as N,schemeLabelOf as v,supportsUrlElicitation as G}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as q,resolveUpstreamApiAuth as V,schemeChoicesOf as W}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as Y,resolveSecretSubject as J}from"../gateway-mcp/subject.js";const Q=6e4;function pe(e,t){return new j({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function me(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,c=N(s.mcpReq),a=i?J(e.user,n.sessionHandle):{kind:"anonymous"},o=a.kind==="resolved"?a.subject:void 0;if(a.kind==="invalid")return{content:[{type:"text",text:a.message}],isError:!0};const d=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await K.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let u;const l=async()=>{u=await d();const m={toolName:r,args:n,context:{...e,upstreamSecrets:u},extra:ne(s)};return await D.exec(F,[m],{timeout:Q})};let p=await l();const f=L(p);if(f.length>0&&i&&!o)return y(R(p,[{type:"text",text:Y}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${c?"2026-07-28":"2025"} clientElicitation=${X(t)}`);const m=await t.getKv(),h=await Z(e,f),k=f.map(O=>z(O,h)),E=ee(u),g=c?await te(e,s,k,o,m,E,h,t):await re(e,k,o,m,E,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await l();break;case"prependText":p=R(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return y(p)}}function R(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function X(e){const t=e?.getClientCapabilities()?.elicitation;if(!t)return"none";const r=[t.form?"form":void 0,t.url?"url":void 0].filter(Boolean);return r.length>0?r.join("+"):"none"}async function Z(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await V(e,n));return r}function z(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??q};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function ee(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function M(e,t){return e.status===401&&!t.has(b(e))}function C(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?v(r.schemes,n):void 0}function A(e,t){const r=t.get(e.api);return!r||!e.schemes?.length?[]:W(r,e.schemes)}function I(e,t){return A(e,t).length>1}function w(e,t){return e.map(r=>H(r,C(r,t))).join(`
|
|
2
2
|
|
|
3
|
-
`)}function
|
|
3
|
+
`)}function U(e,t,r){const n=e.map(s=>P(s,A(s,r)));return t.length>0&&n.push(w(t,r)),n.join(`
|
|
4
4
|
|
|
5
|
-
`)}function
|
|
5
|
+
`)}function _(e,t,r,n,s){const[i,...c]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??q,d=C(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...d?{schemeLabel:d}:{}},auth:a?.schemes[o]??{kind:"raw"},...a?{apiAuth:a}:{},kv:n,hasExistingSecret:!1,reason:{kind:"authFailure",status:i.status,...i.detail?{detail:i.detail}:{},otherApiNames:c.map(u=>u.name)}}}async function te(e,t,r,n,s,i,c,a){if(x(t.mcpReq.inputResponses))return{kind:"none"};const o=r.filter(l=>M(l,i));if(o.length===0)return{kind:"prependText",text:w(r,c)};const d=o.filter(l=>I(l,c));if(d.length>0){const l=r.filter(p=>!d.includes(p));return{kind:"prependText",text:U(d,l,c)}}const u=_(e,o,n,s,c);return G(a?.getClientCapabilities())?{kind:"inputRequired",result:await $(u)}:{kind:"prependText",text:await T(u)}}async function re(e,t,r,n,s,i){const c=t.filter(u=>M(u,s));if(c.length===0)return{kind:"prependText",text:w(t,i)};const a=c.filter(u=>I(u,i));if(a.length>0){const u=t.filter(l=>!a.includes(l));return{kind:"prependText",text:U(a,u,i)}}const o=_(e,c,r,n,i);return{kind:"prependText",text:await B(`${r}:${b(c[0])}`,()=>T(o))}}function ne(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function fe(e){return{user:e.user,config:e.config,outdir:e.outdir,baseUrl:e.baseUrl,params:e.params,query:e.query,cookies:e.cookies,apiDescriptionsMap:e.apiDescriptionsMap,graphqlDescriptions:e.graphqlDescriptions,products:e.products,accessToken:e.accessToken,metadata:e.metadata,upstreamAuthorization:e.upstreamAuthorization,mcpMode:e.mcpMode,elicitationEnabled:e.elicitationEnabled,gatewayFetchBudgetPerExec:e.gatewayFetchBudgetPerExec,clientIp:e.clientIp,client:e.client,clientVersion:e.clientVersion,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{pe as createMcpServer,me as createToolDispatch,fe as extractSerializableContext};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
function r(o,s){const l=s?.disabledTools;return Array.isArray(l)&&l.includes(o)}export{r as isToolDisabledByCaller};
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { McpToolSchema } from '../../../types';
|
|
2
2
|
import type { ToolArgs } from '../types.js';
|
|
3
3
|
export declare function normalizeToolDisplayName(tool: McpToolSchema): McpToolSchema;
|
|
4
|
-
/** The `registerTool` config for a tool schema, with its input
|
|
4
|
+
/** The `registerTool` config for a tool schema, with its input and output schemas compiled for validation. */
|
|
5
5
|
export declare function toRegisterToolConfig(tool: McpToolSchema): {
|
|
6
6
|
title: string | undefined;
|
|
7
7
|
description: string;
|
|
8
8
|
inputSchema: import("@modelcontextprotocol/server").StandardSchemaWithJSON<ToolArgs, ToolArgs>;
|
|
9
|
+
outputSchema?: import("@modelcontextprotocol/server").StandardSchemaWithJSON<unknown, unknown> | undefined;
|
|
9
10
|
annotations: {
|
|
10
11
|
title?: string | undefined;
|
|
11
12
|
readOnlyHint?: boolean | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fromJsonSchema as
|
|
1
|
+
import{fromJsonSchema as i}from"@modelcontextprotocol/server";import{mcpJsonSchemaValidator as e}from"./json-schema-validator.js";function c(t){const n=t.title??t.annotations?.title;return n?{...t,title:n,annotations:{...t.annotations,title:n}}:t}function u(t){const{title:n,description:a,schema:r,outputSchema:o,annotations:m}=c(t);return{title:n,description:a,inputSchema:i(r,e),...o?{outputSchema:i(o,e)}:{},annotations:m}}export{c as normalizeToolDisplayName,u as toRegisterToolConfig};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as _,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{importMcpToolHandlers as b}from"./import-mcp-tool-handlers.js";function A(
|
|
1
|
+
import{telemetry as h}from"../../../telemetry/index.js";import{McpServerType as c}from"../constants.js";import{EXECUTE_TOOL_NAME as w}from"../codemode/constants.js";import{isPlainObject as p}from"../../../../utils/guards/is-plain-object.js";import{logMcpToolCallAudit as g,reportMcpToolCalled as _,reportMcpToolError as u}from"./mcp-tool-telemetry.js";import{isToolDisabledByCaller as S}from"../utils/disabled-tools.js";import{attachToolFileSystem as E}from"./tool-file-system.js";import{importMcpToolHandlers as b}from"./import-mcp-tool-handlers.js";function A(e){return e.content.map(t=>t.type==="text"?t.text:"")}async function F(e){h.initialize();const{toolName:t,args:o,extra:s}=e,r=E(e.context),n=r?.mcpMode??"tools",a={client:r?.client,clientVersion:r?.clientVersion},d=performance.now();try{const i=await M(t);if(!i)throw new Error(`MCP tool "${t}" is not registered or its module does not export a handler for "${t}". Expected \`export default { '${t}': handler }\` or a single tool definition with \`description\` and \`execute\` as the default export.`);const C=typeof i=="function"?i:i.execute,l=k(t,await C(o,r,s),n),m=Math.round(performance.now()-d),{errorClass:y}=l;delete l.errorClass;const f=l.isError?y??(t===w?"sandbox_error":"tool_error"):void 0,v=t===w&&y==="tool_error",x=A(l),T=x.join("");return g({tool:t,mode:n,serverType:c.Docs,args:o,result:T,errorClass:f,...a}),f?v||u({tool:t,message:x.join(" "),mode:n,serverType:c.Docs,durationMs:m,errorClass:f,...a}):_({tool:t,mode:n,serverType:c.Docs,durationMs:m,outputLength:T.length,...a}),l}catch(i){throw g({tool:t,mode:n,serverType:c.Docs,args:o,errorClass:"server_error",...a}),u({tool:t,message:i instanceof Error?i.message:String(i),mode:n,serverType:c.Docs,durationMs:Math.round(performance.now()-d),stack:i instanceof Error&&i.stack||"",errorClass:"server_error",...a}),i}}function O(e){return"execute"in e&&typeof e.execute=="function"&&"description"in e&&typeof e.description=="string"}async function M(e){const t=(await b())[e];if(!t)return;const{default:o}=await t();return P(o,e)}function P(e,t){return O(e)?e:e[t]}function k(e,t,o){if(j(t))return t;if(typeof t=="string")return{content:[{type:"text",text:t}]};let s;try{s=JSON.stringify(t)}catch(n){throw new Error(`MCP tool "${e}" returned a value that cannot be serialized to JSON: `+(n instanceof Error?n.message:String(n)))}if(s===void 0)throw new Error(`MCP tool "${e}" returned an invalid result.`);const r=o==="code"?JSON.parse(s):void 0;return p(r)?{content:[{type:"text",text:s}],structuredContent:r}:{content:[{type:"text",text:s}]}}const L=new Set(["text","image","audio","resource","resource_link"]);function j(e){if(!p(e))return!1;const{content:t}=e;return Array.isArray(t)&&t.every(o=>p(o)&&L.has(o.type))}async function N(e){h.initialize();const{toolName:t}=e;if(S(t,e.context.metadata))return!1;const o=E(e.context),s=performance.now();try{const r=await M(t);return r?typeof r=="object"&&typeof r.isAvailable=="function"?await r.isAvailable(o):!0:!1}catch(r){throw u({tool:t,message:"Failed to check if MCP tool is available: "+(r instanceof Error?r.message:String(r)),mode:o?.mcpMode??"tools",serverType:c.Docs,durationMs:Math.round(performance.now()-s),stack:r instanceof Error&&r.stack||"",errorClass:"server_error",client:o?.client,clientVersion:o?.clientVersion}),r}}async function U(e){const{toolNames:t,context:o}=e,s=await Promise.all(t.map(r=>N({toolName:r,context:o}).catch(()=>!1)));return Object.fromEntries(t.map((r,n)=>[r,s[n]]))}export{F as executeMcpTool,N as isMcpToolAvailable,U as mcpToolAvailability,P as resolveToolHandler};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import _ from"flexsearch";import{REDOCLY_TEAMS_RBAC as L}from"@redocly/config";import{DISABLE_DEEP_LINK_IF_FIELDS_EXIST as b,SEARCH_LIMIT as R}from"../../../../constants/plugins/search.js";import{telemetryTraceStep as j}from"../../../../telemetry/helpers/trace-step.js";import{highlightTextForSearch as m,markMatchedValue as D}from"../../../../utils/search/highlight-text-for-search.js";import{MIN_QUERY_WORD_LENGTH as M,containsQueryWord as S,matchableQueryWords as C}from"../../../../utils/search/text-match.js";function k(I){const{name:e,description:t,place:r,path:i,deepLink:s,example:n,enum:a}=I,o=s?.indexOf("#")??-1;return{name:e,description:t,place:r,...i&&{path:i},...s&&{deepLink:o>=0?s.slice(o+1):s},example:n,enum:a}}class T{#t;#e=new Map;#s=1;id;constructor(e,t){this.id=e,this.#t=new _.Document(t)}get documents(){return this.#e.entries()}get documentsCount(){return this.#s}clearDocuments(){this.#e.clear()}async export(e){await this.#t.export(e)}async import(e){const{documents:t,index:r}=e;this.#e.clear();for(const[i,s]of t)this.#e.set(i,s);for(const[i,s]of Object.entries(r))await this.#t.import(i,s)}add(e){const t={...e,tags:e.tags??[],[L]:e[L],...e.parameters&&{parameters:e.parameters.map(k)}};this.#e.set(this.#s,t),this.#t.add(this.#s,t),this.#s++}async search(e){return await j("com.redocly.search.performed",async t=>{t?.setAttribute("id","searchQueryId"),t?.setAttribute("object","searchQuery"),t?.setAttribute("uri","urn:redocly:realm:api:searchQuery:searchQueryId");const{query:r,offset:i,auth:s,product:n,versions:a}=e,o=[],l=s.teams,p={limit:R,offset:i},c=this.#r(r);if(!c.length&&r.trim())return{documents:{[this.id]:[]},facets:{},hasCoveringHit:!1};let d=new Map,g=await this.#t.searchAsync(r,{...p,tag:l});if(n){const h=await this.#t.searchAsync(r,{...p,tag:n});g=this.#a(g,h),t?.setAttribute("product",n)}if(a&&a.length){const h=await this.#t.searchAsync(r,{...p,tag:a});g=this.#a(g,h),t?.setAttribute("versions",a.join(","))}for(const h of g)for(const u of h.result){const f=d.get(u)?.fields||[];d.set(u,{fields:h.field?[...f,h.field]:[...f]})}!i&&c.length&&!d.size&&(d=this.#l(c,l,n,a));const x=[];for(const[h,u]of d.entries()){const f=this.#e.get(h);f&&!this.#d(f,a)&&x.push({document:f,fields:u.fields,score:this.#m(c,f)})}const y=x.filter(h=>h.score>=c.length),A=y.length?y:x;A.sort((h,u)=>u.score-h.score);for(const h of A.slice(0,R))o.push({document:this.#o(h.document,r,h.fields),highlight:this.#h(h.document,r,h.fields)});return{documents:{[this.id]:o},facets:{},hasCoveringHit:y.length>0}})}#o(e,t,r){return this.#g(e,t,r)}#h(e,t,r){const i={};let s=!1;for(const n of r)if(n==="path")i.path=e.path?e.path.map(a=>m(t,a)):[];else if(n.includes("parameters")){if(!s){const a=n.split(":")[1],o=this.#n(t,a,e.parameters);o&&(i.parameters=[{name:m(t,o.name),description:m(t,o.description),place:m(t,o.place),path:o.path?o.path.map(l=>m(t,l)):[],...this.#c(t,o)}],s=!0)}}else n!=="httpMethod"&&(i[n]=m(t,e[n]));return i}#c(e,t){return{enum:D(e,(t.enum??[]).join(", ")),example:D(e,t.example??"")}}#r(e){return C(e)}#l(e,t,r,i){const s=new Map;if(!e.length)return s;for(const[n,a]of this.#e)this.#p(a,t,r,i)&&this.#f(e,a)&&s.set(n,{fields:this.#u(e,a)});return s}#f(e,t){const r=i=>{if(i==null)return!1;const s=(Array.isArray(i)?i.join(" "):String(i)).toLowerCase();return!!s&&e.every(n=>S(s,n))};return r(t.title)||r(t.text)||r(t.httpPath)||r(t.path)?!0:(t.parameters??[]).some(i=>r(i.name)||r(i.description)||r(i.example)||r(i.enum))}#p(e,t,r,i){const s=new Set(e.tags??[]);return!(t.length&&!t.some(n=>s.has(n))||r&&!s.has(r)||i&&i.length&&!i.some(n=>s.has(n)))}#u(e,t){const r=s=>{if(s==null)return!1;const n=(Array.isArray(s)?s.join(" "):String(s)).toLowerCase();return e.some(a=>S(n,a))},i=[];r(t.title)&&i.push("title"),r(t.text)&&i.push("text"),r(t.path)&&i.push("path"),t.httpMethod&&e.some(s=>s.length>=M&&t.httpMethod?.toLowerCase().startsWith(s))&&i.push("httpMethod"),r(t.httpPath)&&i.push("httpPath");for(const s of["name","description","path","example","enum"])t.parameters?.some(n=>r(n[s]))&&i.push(`parameters[]:${s}`);return i}#i(e,t){const r=t.toLowerCase().replace(/\s+/g," "),i=e.filter(n=>S(r,n)).length;let s=0;for(let n=1;n<e.length;n++)r.includes(`${e[n-1]} ${e[n]}`)&&s++;return i+s/e.length}#m(e,t){let r=0;const i=s=>{if(s==null)return;const n=this.#i(e,String(s));n>r&&(r=n)};if(i(t.title),i(t.text),i(t.httpPath),i(t.path?.join(" ")),t.httpMethod){const s=t.httpMethod.toLowerCase(),n=e.filter(a=>a.length>=M&&s.startsWith(a)).length;n>r&&(r=n)}for(const s of t.parameters??[])i([s.name,s.description,s.place,s.example,s.enum?.join(" ")].filter(Boolean).join(" "));return r}#n(e,t,r){const i=this.#r(e);let s,n=0;for(const a of r??[]){const o=a[t],l=(Array.isArray(o)?o:[o]).filter(c=>c!=null).map(c=>String(c)).join(" "),p=this.#i(i,l);p>n&&(n=p,s=a)}return s}#a(e,t){const r=[];for(const i of e){const s=[];for(const n of t)for(const a of i.result){const o=n.result.find(l=>l===a);o&&s.push(o)}s.length&&r.push({result:s,field:i.field})}return r}#d(e,t){return!!(t&&t.length&&e.isDefaultVersion&&e.versionFolderId&&e.version&&t.some(r=>r.includes(e.versionFolderId??""))&&!t.some(r=>r.includes(e.version??"")))}#g(e,t,r){for(const s of b)if(r.some(n=>n===s))return e;let i;for(const s of r)if(s.includes("parameters")){const n=s.split(":")[1],a=this.#n(t,n,e.parameters);if(a){i=a.deepLink;break}}return i?{...e,url:`${e.url}#${i}`}:e}}export{T as FlexSearchIndex};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{pathToFileURL as
|
|
1
|
+
import{pathToFileURL as J}from"url";import{HelmetProvider as K}from"@dr.pogodin/react-helmet";import{renderToString as m}from"react-dom/server";import{StaticRouterProvider as Q,createStaticHandler as V,createStaticRouter as W}from"react-router";import r from"react";import{readFile as X}from"fs/promises";import{join as Y}from"path";import{withPathPrefix as p,getLocaleFromPathname as Z,withoutPathPrefix as tt,removeTrailingSlash as et,getSafeClassName as rt}from"@redocly/theme/core/utils";import{RUNTIME_RESOURCES_DIR as T}from"../constants/common.js";import{slash as ot}from"../../utils/path/slash.js";import{reporter as st}from"../tools/notifiers/reporter.js";import{envConfig as g}from"../config/env-config.js";import{slug as nt}from"../../utils/slugger.js";import{shouldForwardProp as at}from"../../utils/should-forward-prop.js";import{htmlTemplate as it}from"./template.js";import{detectColorSchemaScript as ct,generatePreloadPageData as lt,generatePreloadSharedData as mt}from"./utils.js";import"./hijack-console.js";import{getSitemapLinkTag as pt}from"./get-sitemap-link-tag.js";let u="";async function gt(t){return g.isRuntimeMode?await import("../../client/server-entry.js"):await import(J(`${ot(t)}/server-entry.js`)+"?"+new Date)}async function kt(t){if(!g.isRuntimeMode){const e=st.getCompilationProblems();if(e.length>0){const{renderCompilationError:n}=await import("./render-compilation-error.js");return n(e)}}const{Loader:h,App:C,routes:R,ServerStyleSheet:w,StyleSheetManager:E,ErrorDetails:P,L10nContext:D,createSsrL10nContext:y}=await gt(t.serverOutDir),{page:S,store:{globalData:d,hasSitemap:v},sharedData:x,ssrHref:b}=t,i=d?.l10n,c=Z(tt(S.slug),i?.defaultLocale,i?.locales),f=t.page.request?.url||"http://localhost/";await h.prepare({...S,slug:et(new URL(f).pathname)},x,d,c);const L=await y(i,c),l=new w,{query:M,dataRoutes:B}=V([{Component:C,path:p("*"),children:R}]),s=await M(new Request(f));if(s instanceof Response)throw s;const j=W(B,s);try{globalThis.SSR_HOSTNAME=b,globalThis.SSR_USER_AGENT=t.userAgent,globalThis.SSR_OMIT_SUSPENSE=t.omitSuspense;const e={},n=m(r.createElement(D.Provider,{value:L},r.createElement(K,{context:e},r.createElement(E,{sheet:l.instance,shouldForwardProp:at},r.createElement(Q,{router:j,context:s}))))),k=v?pt():"",a=e.helmet,_=a?.title.toString()||"",F=t.store.globalData?.logo?.favicon,o=t.store.config,H=`<link rel="preload" as="fetch" crossorigin="anonymous" href="${p("/app-data.json")}" />`,U=lt(t.page.slug),A=mt(t.page.sharedDataIds),N=ct(o),$=t.page.product?.name?rt(`product-${nt(t.page.product.name)}`):"",I=t.store.ssr.headTags.join(""),O=t.store.ssr.postBodyTags.join(""),q=t.store.ssr.preBodyTags.join(""),z=`<link rel="stylesheet" href="${p(T)}/browser-entry.css" />`;!g.isDevelopMode&&!u&&(u=`<style>${await X(Y(t.outdir,T,"browser-entry.css"),"utf-8")}</style>`);const G={bodyHtml:n,linkTags:o.linkTags+l.getStyleTags()+(a?.link.toString()||""),title:_,favicon:F,headScriptTags:k+N+o.headScriptTags+I+(a?.script.toString()||"")+(a?.meta.toString()||""),preload:[H,U,...A],postBodyScriptTags:o.postBodyScriptTags+O,preBodyScriptTags:o.preBodyScriptTags||""+q,lang:c,productClass:$,runtimeCss:u||z};return{html:it(G),statusCode:200}}catch(e){return t.telemetry.sendSsrErrorCaughtMessage([{id:"ssr",object:"error",uri:"urn:redocly:realm:cli:error:ssr",message:e.message}]),{html:m(r.createElement(P,{error:e})),statusCode:500,error:e}}finally{l.seal(),h.clear()}}function _t(t){return m(r.createElement(r.Fragment,null,...t))}export{kt as render,_t as renderComponents};
|
|
@@ -87,7 +87,7 @@ export type SearchDocument = {
|
|
|
87
87
|
[SEARCH_DOCUMENT_METADATA_KEY]?: SearchDocumentMetadata;
|
|
88
88
|
};
|
|
89
89
|
/** Parameter fields kept in the FlexSearch index and its export; the rest never leaves the build. */
|
|
90
|
-
export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink'>;
|
|
90
|
+
export type IndexedParameter = Pick<OperationParameter, 'name' | 'description' | 'place' | 'path' | 'deepLink' | 'example' | 'enum'>;
|
|
91
91
|
export type IndexedSearchDocument = Omit<SearchDocument, 'parameters'> & {
|
|
92
92
|
parameters?: IndexedParameter[];
|
|
93
93
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{getHigherRole as c}from"./rbac.js";function d(e,r){if(!e)return;if(!p(e))return e;const t={reunite:{},content:f(e)},n=i(e,r);for(const o of n)t.reunite[o.teamName]=o.projectRole,t.content={...t.content,...Object.fromEntries((e.teamFolders||[]).flatMap(a=>{const l={...e.teamFoldersBaseRoles||{authenticated:"READ"},[o.teamName]:o.projectRole,"redocly.owners":"ADMIN"},m=a.replaceAll("{teamPathSegment}",o.teamPathSegment),s=m+"/**";return[[m,l],[s,l]]}))};return{reunite:{...e.reunite,...t.reunite},content:{...P(e.content||{},t.content)}}}function p(e){return!!(e.teamNamePatterns&&e.teamFolders)}function u(e,r){for(const t of e.teamNamePatterns||[]){if(!t.includes("{teamPathSegment}")&&!t.includes("{projectRole}"))continue;const n="^"+t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)").replace("{projectRole}","(?<projectRole>admin|maintain|triage|write|read|none)")+"$",a=new RegExp(n,"i").exec(r)?.groups;if(a?.projectRole||a?.teamPathSegment)return{teamName:r,projectRole:a.projectRole?.toUpperCase(),teamPathSegment:a.teamPathSegment?.toLowerCase()}}return null}function g(e,r){for(const t of e?.teamFolders||[]){if(!t.includes("{teamPathSegment}"))continue;const n=`^${t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)")}($|/)`,o=new RegExp(n,"i");for(const a of r){const l=o.exec(a)?.groups;if(l?.teamPathSegment)return{teamPathSegment:l.teamPathSegment.toLowerCase()}}}return null}function i(e,r){const t=r.map(o=>u(e,o));let n=null;for(const o of t)o?.projectRole&&!o.teamPathSegment&&(n=n?c(n,o.projectRole):o.projectRole);return t.map(o=>!o?.teamPathSegment||!o.projectRole&&!n?null:{...o,projectRole:o?.projectRole??n}).filter(Boolean)}function f(e){const r={};if(e.teamFoldersBaseRoles)for(const t of e.teamFolders){const n=t.replaceAll("{teamPathSegment}","**");r[n]=e.teamFoldersBaseRoles}return r}function P(e,r){const t={...e};for(const[n,o]of Object.entries(r))t[n]?t[n]={...t[n],...o}:t[n]=o;return t}export{p as canExpandConfig,d as expandRbacConfig,f as getTeamFolderDefaults,g as parseTeamFoldersTemplate,u as parseTeamNameTemplate,i as parseTeams};
|
|
1
|
+
import{getHigherRole as c}from"./rbac.js";function d(e,r){if(!e)return;if(!p(e))return e;const t={reunite:{},content:f(e)},n=i(e,r);for(const o of n)t.reunite[o.teamName]=o.projectRole,t.content={...t.content,...Object.fromEntries((e.teamFolders||[]).flatMap(a=>{const l={...e.teamFoldersBaseRoles||{authenticated:"READ"},[o.teamName]:o.projectRole,"redocly.owners":"ADMIN"},m=a.replaceAll("{teamPathSegment}",o.teamPathSegment),s=m+"/**";return[[m,l],[s,l]]}))};return{...e,reunite:{...e.reunite,...t.reunite},content:{...P(e.content||{},t.content)}}}function p(e){return!!(e.teamNamePatterns&&e.teamFolders)}function u(e,r){for(const t of e.teamNamePatterns||[]){if(!t.includes("{teamPathSegment}")&&!t.includes("{projectRole}"))continue;const n="^"+t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)").replace("{projectRole}","(?<projectRole>admin|maintain|triage|write|read|none)")+"$",a=new RegExp(n,"i").exec(r)?.groups;if(a?.projectRole||a?.teamPathSegment)return{teamName:r,projectRole:a.projectRole?.toUpperCase(),teamPathSegment:a.teamPathSegment?.toLowerCase()}}return null}function g(e,r){for(const t of e?.teamFolders||[]){if(!t.includes("{teamPathSegment}"))continue;const n=`^${t.replace("{teamPathSegment}","(?<teamPathSegment>[a-zA-Z0-9_.-]+)")}($|/)`,o=new RegExp(n,"i");for(const a of r){const l=o.exec(a)?.groups;if(l?.teamPathSegment)return{teamPathSegment:l.teamPathSegment.toLowerCase()}}}return null}function i(e,r){const t=r.map(o=>u(e,o));let n=null;for(const o of t)o?.projectRole&&!o.teamPathSegment&&(n=n?c(n,o.projectRole):o.projectRole);return t.map(o=>!o?.teamPathSegment||!o.projectRole&&!n?null:{...o,projectRole:o?.projectRole??n}).filter(Boolean)}function f(e){const r={};if(e.teamFoldersBaseRoles)for(const t of e.teamFolders){const n=t.replaceAll("{teamPathSegment}","**");r[n]=e.teamFoldersBaseRoles}return r}function P(e,r){const t={...e};for(const[n,o]of Object.entries(r))t[n]?t[n]={...t[n],...o}:t[n]=o;return t}export{p as canExpandConfig,d as expandRbacConfig,f as getTeamFolderDefaults,g as parseTeamFoldersTemplate,u as parseTeamNameTemplate,i as parseTeams};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as
|
|
1
|
+
import R from"path";import P from"picomatch";import"../node-crypto-polyfill.js";import{REDOCLY_TEAMS_RBAC as L,REDOCLY_ROUTE_RBAC as A}from"@redocly/config";import{MCP_ROUTE as U,PUBLIC_MCP_ROUTE as k}from"@redocly/theme/core/constants/mcp";import{ServerRoutes as M}from"../../constants/api.js";import{DEFAULT_ANONYMOUS_VISITOR_TEAM as g,PUBLIC_RBAC_SCOPE_ITEM as E,RBAC_ALL_OTHER_TEAMS as l,DEFAULT_RBAC_SCOPE as C}from"../../constants/common.js";import{DEPRECATED_PUBLIC_API_DEFINITIONS_FOLDER as j,PUBLIC_API_DEFINITIONS_FOLDER as I,PUBLIC_ASSETS_FOLDER as B}from"../constants/common.js";import{MCP_CREDENTIALS_ROUTE as b}from"../constants/mcp.js";import{ANONYMOUS_AUTH_DETAILS as W}from"../constants/rbac.js";import{removeTrailingSlash as _}from"../../utils/url/remove-trailing-slash.js";import{removeLeadingSlash as $}from"../../utils/url/remove-leading-slash.js";import{parsePathVersions as v}from"../../utils/path/parse-path-versions.js";import{reporter as Y}from"../tools/notifiers/reporter.js";import{bold as z}from"../tools/notifiers/helpers/colors.js";import{shaDirPathShort as H}from"../utils/crypto/sha-dir-path-short.js";import{isTruthy as K}from"../../utils/guards/is-truthy.js";import{canExpandConfig as G,expandRbacConfig as V,getTeamFolderDefaults as J,parseTeamFoldersTemplate as Q,parseTeamNameTemplate as X}from"./rbac-expand.js";import{getUserParamsFromCookies as Z}from"../web-server/auth.js";import{getDeeperGlobPattern as q}from"./globs.js";import{EntitlementsProvider as tt}from"../entitlements/entitlements-provider.js";const F=["NONE","READ","TRIAGE","WRITE","MAINTAIN","ADMIN"],et=new Set(["x-parsed-md-description","x-parsed-md-summary"]),rt=new Set(Object.values(M).map(t=>_(t.split(":")[0])));function jt(t,e){const r=F.indexOf(t.toUpperCase()),n=F.indexOf(e.toUpperCase());return r>n?t:e}const y={};function T(t,e){if(!t?.content)return E;const r=t.content,{slug:n,fsPath:o}=e;if(!n&&!o)return E;const s=a=>{const d=`slug:${a}`,p=y[d]??P(a);y[d]=p;const S=`fsPath:${a}`,D=y[S]??P($(a));return y[S]=D,!!(n&&p(n))||!!(o&&D(o))};if(st(n||o||"")&&Object.keys(r).filter(p=>s(p)).length===0)return r[C]||E;const f=Object.keys(r).filter(a=>s(a));if(f.length==0)return E;const u=f.map(a=>P.scan(a,{tokens:!0,parts:!0}));let h=u[0];for(let a=1;a<u.length;a++)h=q(h,u[a]);return r[h.input]}function N(t,e,r){const n=r?[...e,r]:e,o=[];for(const s of n)t[s]?o.push(t[s]):t[l]&&s!==r&&o.push(t[l]);return o.some(s=>s.toLowerCase()!=="none")}function It(t,e,r={},n=!1){if(n&&Object.keys(r).length===0)return e.isAuthenticated;const o=r.features?.[t];return o?N(o,e.teams):!0}function Ft(t,e){return O(t,W,e.access?.rbac||{},e.access?.requiresLogin||!1)}function O(t,e={},r={},n=!1){if(t.slug&&typeof t.slug=="string"&&rt.has(_(t.slug))||(t.slug===U||t.slug===k||t.slug===b)&&tt.instance().canAccessFeature("mcp"))return!0;if(n&&Object.keys(r).length===0)return!!e.isAuthenticated;const o=V(r,e.teams||[]),s=t[L]||T(o,t[A]||{});return Object.keys(s||{}).length===0?!1:Object.keys(s).length===1&&s[l]&&s[l].toLowerCase()!=="none"?!0:N(s,e?.teams||[],e?.email)}function Nt(t,e,r,n){if(!t.startsWith(I)&&!t.startsWith(j))return!0;const o=t.replace(new RegExp(`^${I}/`),"").replace(new RegExp(`^${j}/`),""),c=o==="."?"":o,i={[A]:{slug:t,fsPath:c},slug:t};return O(i,n,e,r)}function wt(t,e,r,n,o){if(!t.startsWith(B))return!0;const s=t.match(/.*\..{64}\.([A-Fa-f0-9]{8})\.[^.]+$/)?.[1];if(!s)return!0;const c=n[s];if(!c)return!0;const{base:i,ext:f}=R.parse(t),u=i.split(".")[0],h=f.split(".").join(""),d=c==="."?"":c,p={[A]:{slug:t,fsPath:R.posix.join(d,`${u}.${h}`)},slug:t};return O(p,o,e,r)}async function Ut(t,e){const{isAuthenticated:r=!1,idpAccessToken:n,federatedAccessToken:o,federatedIdToken:s,...c}=await Z(t,e),{teams:i=[]}=c;let f;return r?f=i.filter(u=>u!==g):f=[g],{isAuthenticated:r,idpAccessToken:n,teams:f,claims:c}}function w(t,e,r={},n=!1){if(!t)return t;if(Array.isArray(t)){const o=[];for(const s of t){const c=w(s,e,r,n);c!==void 0&&o.push(c)}return o}if(typeof t=="object"){if(!O(t,e,r,n))return;let o=!1;const s={};for(const c in t){if(c===L||c===A)continue;if(et.has(c)){s[c]=t[c];continue}const i=w(t[c],e,r,n);if(c==="items"&&Array.isArray(i)&&i.length===0&&t[c].length!==0){o=!0;continue}i!==void 0&&(s[c]=i),c==="paths"&&nt(i)&&ot(i)}return o?void 0:s}return t}function kt(t){return typeof t=="string"?t.split(" ").filter(Boolean):Array.isArray(t)?t.map(e=>e.toString()):[]}function Mt(t,e){if(!e)return;const r=e.content;if(!r)return e;const n=Object.entries(r).flatMap(([s,c])=>s===C?[[s,c]]:[[s,c],...t.localeFolders.map(i=>[s.startsWith("/")?`/${i.toLocaleLowerCase()}${s}`:R.posix.join(t.localizationFolder,i,s),c])]),o=Object.fromEntries(n);return{...e,content:o}}async function Bt(t,e){if(!e)return{};const r={},n=new Set((await t.scan()).flatMap(({relativePath:o})=>{const{versionFolderPath:s}=v(o)||{},c=R.dirname(o);return s?[s,c]:c}));for(const o of n)r[H(o)]=o;return r}const m=t=>typeof t=="object"&&t!==null&&!Array.isArray(t);function nt(t){return m(t)&&Object.keys(t).length>0}function ot(t){for(const e of Object.keys(t)){const r=t[e];m(r)&&Object.keys(r).length===0&&delete t[e]}}function st(t){return t?t.split("/").filter(Boolean).some(r=>r.startsWith(".")):!1}const ct=t=>{if(t&&m(t)&&("content"in t&&m(t.content)||"reunite"in t&&m(t.reunite)||"features"in t&&m(t.features)||t.teamFolders&&t.teamNamePatterns)){const e=Object.values(t.content||{});if(e.length===0)return!0;if(e.every(m))return e.every(r=>Object.values(r).every(n=>typeof n=="string"))}return!1},bt=async t=>{if(t){if(Object.keys(t).length===0)return{};if(ct(t))return it(t);await Y.panicOnContentError(`You are using an incorrect format of ${z("rbac:")} configuration. See: https://redocly.com/docs/realm/access`)}},it=t=>{const e={...t};if(e.content){const r={};for(const n in e.content)if(e.content[n]!==void 0){const o=_(n);r[o]=e.content[n]}e.content=r}return e};function Wt(t,e){const r=t.fsPath,n=t.slug,o=[];if(G(e)&&(r||n)){const s=[r,n].filter(K),c=Q(e,s);if(c){const i=e?.teamNamePatterns?.map(u=>u.replace("{teamPathSegment}",c.teamPathSegment).replace("{projectRole}","read"))??[];o.push(...i);const f=T({content:{...J(e),...e.content}},t);o.push(...x(f))}else{const i=T(e,t);o.push(...x(i))}}else{const s=T(e,t);o.push(...x(s))}return at(e,o)}function x(t){if(!t)return[];const e=[],r=l in t?{authenticated:t[l],anonymous:t[l]}:{};for(const[n,o]of Object.entries({...r,...t}))o.toLowerCase()!=="none"&&n!==l&&e.push(n);return e}function at(t,e){return e.map(n=>X(t,n)??{teamName:n}).map(n=>n.projectRole&&n.projectRole!=="READ"?n.teamName?.toLowerCase().replace(n.projectRole?.toLowerCase?.()??"","read")??"":n.teamName?.toLowerCase()??"")}export{F as PROJECT_ROLES_ORDERED_BY_ACCESS_LEVEL,Mt as applyL10nToRbacConfig,wt as canAccessAsset,It as canAccessFeature,O as canAccessResource,Nt as canDownloadApiDefinition,at as expandTeamsForRead,x as extractTeamsFromScopeItems,w as filterDataByAccessDeep,Ut as getAuthDetailsFromCookies,jt as getHigherRole,Wt as getRbacTeamsListForResource,T as getScopeItemsForResource,N as hasScopeAccess,ct as isRbacConfigValid,Ft as isResourcePubliclyAccessible,it as normalizeRbacConfig,bt as parseRbacConfig,kt as parseTeamClaimToArray,Bt as resolveDirectoryHashes};
|