@redocly/realm 0.138.0-next.11 → 0.138.0-next.13
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 +41 -0
- package/dist/client/app/pages/Invite/Invite.js +1 -1
- package/dist/client/runtime/loader.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/server/plugins/api-docs/index.js +1 -1
- package/dist/server/plugins/api-docs/loader.js +3 -3
- package/dist/server/plugins/api-docs/utils/decorators.d.ts +11 -0
- package/dist/server/plugins/api-docs/utils/decorators.js +1 -1
- package/dist/server/plugins/catalog-entities/extensions/extractors/api-description/openapi-entities-extractor.js +1 -1
- package/dist/server/plugins/catalog-entities/utils/extract-parts-from-channels-message-ref.js +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/code-walkthrough/file-chunk-parser.d.ts +1 -1
- package/dist/server/plugins/markdown/attribute-resolvers/resolve-link.js +1 -1
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.d.ts +2 -2
- package/dist/server/plugins/mcp/docs-mcp/utils/resolve-refs.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.d.ts +1 -0
- package/dist/server/plugins/mcp/gateway-mcp/elicitation.js +5 -5
- package/dist/server/plugins/mcp/gateway-mcp/rate-limit/apply-edge-rate-limit.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.d.ts +9 -3
- package/dist/server/plugins/mcp/gateway-mcp/secret-store.js +1 -1
- package/dist/server/plugins/mcp/gateway-mcp/subject.js +1 -1
- package/dist/server/plugins/mcp/handlers/credentials-page/constants.d.ts +7 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/constants.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-contract.d.ts +5 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-contract.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-page.d.ts +14 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/form-page.js +62 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/layout.d.ts +17 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/layout.js +11 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/outcome-pages.d.ts +10 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/outcome-pages.js +11 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/site-branding.d.ts +10 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/site-branding.js +1 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/styles.d.ts +4 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/styles.js +186 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/types.d.ts +32 -0
- package/dist/server/plugins/mcp/handlers/credentials-page/types.js +0 -0
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.d.ts +0 -1
- package/dist/server/plugins/mcp/handlers/mcp-credentials-handler.js +1 -1
- package/dist/server/plugins/mcp/index.js +1 -1
- package/dist/server/plugins/mcp/servers/mcp-server.js +2 -2
- package/dist/server/plugins/mcp/types.d.ts +6 -0
- package/dist/server/plugins/mcp/utils/mode.d.ts +4 -1
- package/dist/server/plugins/mcp/utils/mode.js +1 -1
- package/dist/server/plugins/scorecard-classic/template/components.js +1 -1
- package/dist/server/providers/database/client.d.ts +5 -0
- package/dist/server/providers/database/client.js +1 -1
- package/dist/server/providers/database/copy-migrations.js +1 -1
- package/dist/server/providers/database/database-connections-manager.js +1 -1
- package/dist/server/providers/database/has-project-database.d.ts +3 -0
- package/dist/server/providers/database/has-project-database.js +1 -0
- package/dist/server/web-server/auth.d.ts +0 -1
- package/dist/server/web-server/auth.js +4 -4
- package/dist/server/web-server/jwt/token-types.d.ts +1 -0
- package/dist/server/web-server/jwt/token-types.js +1 -1
- package/dist/server/web-server/routes/auth.js +1 -1
- package/dist/server/web-server/routes/catalog/helpers/create-entity-schema.d.ts +1756 -1756
- package/dist/server/web-server/routes/catalog/helpers/create-entity-update-schema.d.ts +295 -295
- package/dist/server/web-server/routes/mcp-routes/mcp-consent-page.d.ts +24 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-consent-page.js +35 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth-store.d.ts +15 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth-store.js +1 -0
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.d.ts +3 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-oauth.js +1 -1
- package/dist/server/web-server/routes/mcp-routes/mcp-routes.js +1 -1
- package/package.json +5 -5
- package/dist/server/plugins/mcp/handlers/mcp-credentials-page.d.ts +0 -12
- package/dist/server/plugins/mcp/handlers/mcp-credentials-page.js +0 -225
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import{ELICITATION_TTL_MINUTES as p}from"../../gateway-mcp/secret-store.js";import{credentialSchemesOf as $}from"./form-contract.js";import{ICONS as a,code as f,escapeHtml as r,targetTitle as k}from"./layout.js";const v={success:a.check,danger:a.cross,neutral:a.cross,warning:a.clock};function y(n,{action:e,schemes:o,stored:t}){const s=e==="saved",i=$(n).length>1,c=r(n.name),d=t.filter(m=>!o.includes(m)),g=i?`We ${e} ${u(o)} for ${c}.`:`We ${e} your credentials for ${r(k(n))}.`,h=t.length===0?`Calls to ${c} now go without credentials.`:d.length>0?`${s?"Also stored":"Still stored"}: ${u(d)}.`:"";return l(s?"success":"danger",s?"Credentials saved":"Credentials removed",[g,h,s?"Go back to your AI client and tell it that you saved them.":""])}function S(){return l("neutral","Link declined",["We saved nothing, and this link no longer works.","If you did not ask for this link, tell your AI client to stop."])}function A(){return l("warning","This link no longer works",[`The link is not valid, was already used, or is older than ${p} minutes.`,"Ask your AI client for a new link."])}function l(n,e,o){const t=o.filter(Boolean).map(i=>`<p>${i}</p>`).join(`
|
|
2
|
+
`),s=n==="warning"?"":'<p class="muted small">You can close this tab.</p>';return{title:e,body:`<div class="page narrow">
|
|
3
|
+
<main class="card outcome">
|
|
4
|
+
<span class="status-icon ${n}">${v[n]}</span>
|
|
5
|
+
<h1>${r(e)}</h1>
|
|
6
|
+
<div class="message">
|
|
7
|
+
${t}
|
|
8
|
+
${s}
|
|
9
|
+
</div>
|
|
10
|
+
</main>
|
|
11
|
+
</div>`}}function u(n){const e=n.map(f);return e.length>1?`${e.slice(0,-1).join(", ")} and ${e.at(-1)}`:e.join("")}export{S as declinedPage,A as expiredPage,y as outcomePage,l as statusPage};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { RedoclyConfig } from '@redocly/config';
|
|
2
|
+
import type { GlobalData } from '../../../../../types/index.js';
|
|
3
|
+
import type { SiteBranding } from './types.js';
|
|
4
|
+
/** `logo` is the resolved theme logo from global data, whose paths point at served assets. */
|
|
5
|
+
export declare function resolveSiteBranding({ seo, logo, colorMode, }: {
|
|
6
|
+
seo?: RedoclyConfig['seo'];
|
|
7
|
+
logo?: GlobalData['logo'];
|
|
8
|
+
colorMode?: RedoclyConfig['colorMode'];
|
|
9
|
+
}): SiteBranding;
|
|
10
|
+
//# sourceMappingURL=site-branding.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{parseSrcSet as h}from"../../../../utils/attribute-parser.js";function o({seo:t,logo:e,colorMode:d}){const n=t?.title||t?.projectTitle||e?.altText||void 0,i=e?.srcSet?h(e.srcSet):new Map,r=s(i.get("light")??e?.image),a=s(i.get("dark")),c=f(d);return{...n?{name:n}:{},...r?{logo:{light:r,...a?{dark:a}:{}}}:{},...c?{colorScheme:c}:{}}}function f(t){if(t?.hide)return"light";if(t?.ignoreDetection)return t.modes?.[0]==="dark"?"dark":"light"}function s(t){return t?.startsWith("/")&&!t.startsWith("//")?t:void 0}export{o as resolveSiteBranding};
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
const e=`
|
|
2
|
+
--font-family-base:system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
|
|
3
|
+
--page-bg:#f7f7f9;
|
|
4
|
+
--page-dot:#e3e4ea;
|
|
5
|
+
--bg-color:#ffffff;
|
|
6
|
+
--border-color-primary:#dcdde5;
|
|
7
|
+
--panel-bg:#f3f3f6;
|
|
8
|
+
--layer-color:#fbfbfc;
|
|
9
|
+
--input-border-color:#dcdde5;
|
|
10
|
+
--border-color-secondary:#ededf2;
|
|
11
|
+
--stored-bg:#ededf2;
|
|
12
|
+
--text-color-primary:#1a1c21;
|
|
13
|
+
--text-color-secondary:#3b3c45;
|
|
14
|
+
--text-color-description:#555761;
|
|
15
|
+
--placeholder:#9b9ca8;
|
|
16
|
+
--input-bg-color:#ffffff;
|
|
17
|
+
--primary-bg:#1a1c21;
|
|
18
|
+
--primary-hover:#3b3c45;
|
|
19
|
+
--primary-text:#ffffff;
|
|
20
|
+
--focus:#4561db;
|
|
21
|
+
--code-bg:#ededf2;
|
|
22
|
+
--code-text:#2a2b33;
|
|
23
|
+
--tag-bg:#ededf2;
|
|
24
|
+
--tag-text:#3b3c45;
|
|
25
|
+
--tag-stored-bg:#f0f4ff;
|
|
26
|
+
--tag-stored-text:#4561db;
|
|
27
|
+
--danger:#c8174f;
|
|
28
|
+
--danger-bg:#fff1f5;
|
|
29
|
+
--danger-border:#f7a8c0;
|
|
30
|
+
--success:#1f9d55;
|
|
31
|
+
--success-glow:rgba(31,157,85,.18);
|
|
32
|
+
--warning:#e08a00;
|
|
33
|
+
--warning-glow:rgba(224,138,0,.18);
|
|
34
|
+
--warning-bg:#fff8eb;
|
|
35
|
+
--warning-border:#f5c97a;
|
|
36
|
+
--danger-icon:#f9316d;
|
|
37
|
+
--danger-glow:rgba(249,49,109,.18);
|
|
38
|
+
--neutral-glow:rgba(85,87,97,.14);
|
|
39
|
+
`,o=`
|
|
40
|
+
--page-bg:#1a1b20;
|
|
41
|
+
--page-dot:#2c2e36;
|
|
42
|
+
--bg-color:#22242b;
|
|
43
|
+
--border-color-primary:#555761;
|
|
44
|
+
--panel-bg:#2a2b33;
|
|
45
|
+
--layer-color:#2a2b33;
|
|
46
|
+
--input-border-color:#3b3c45;
|
|
47
|
+
--border-color-secondary:#3b3c45;
|
|
48
|
+
--stored-bg:#32343e;
|
|
49
|
+
--text-color-primary:#fbfbfc;
|
|
50
|
+
--text-color-secondary:#c4c6d1;
|
|
51
|
+
--text-color-description:#9b9ca8;
|
|
52
|
+
--placeholder:#6e6f7a;
|
|
53
|
+
--input-bg-color:#22242b;
|
|
54
|
+
--primary-bg:#fbfbfc;
|
|
55
|
+
--primary-hover:#dcdde5;
|
|
56
|
+
--primary-text:#1a1c21;
|
|
57
|
+
--focus:#8fa6ff;
|
|
58
|
+
--code-bg:#3b3c45;
|
|
59
|
+
--code-text:#c4c6d1;
|
|
60
|
+
--tag-bg:#3b3c45;
|
|
61
|
+
--tag-text:#c4c6d1;
|
|
62
|
+
--tag-stored-bg:#1f2a4d;
|
|
63
|
+
--tag-stored-text:#8fa6ff;
|
|
64
|
+
--danger:#ff6b95;
|
|
65
|
+
--danger-bg:#3a1822;
|
|
66
|
+
--danger-border:#7a2b44;
|
|
67
|
+
--success:#3ccf74;
|
|
68
|
+
--success-glow:rgba(60,207,116,.2);
|
|
69
|
+
--warning:#f5a524;
|
|
70
|
+
--warning-glow:rgba(245,165,36,.2);
|
|
71
|
+
--warning-bg:#33260f;
|
|
72
|
+
--warning-border:#7a5a1e;
|
|
73
|
+
--danger-icon:#ff6b95;
|
|
74
|
+
--danger-glow:rgba(255,107,149,.2);
|
|
75
|
+
--neutral-glow:rgba(155,156,168,.16);
|
|
76
|
+
`,r=`
|
|
77
|
+
*{box-sizing:border-box}
|
|
78
|
+
body{margin:0;min-height:100vh;padding:48px 24px;font-family:var(--font-family-base);font-size:14px;line-height:22px;color:var(--text-color-primary);background-color:var(--page-bg);background-image:radial-gradient(var(--page-dot) 1px,transparent 1px);background-size:16px 16px}
|
|
79
|
+
.page{display:grid;grid-template-columns:minmax(0,692px) minmax(0,348px);gap:16px;justify-content:center;min-height:calc(100vh - 96px);margin:0 auto}
|
|
80
|
+
.page.narrow{grid-template-columns:minmax(0,864px)}
|
|
81
|
+
.card{display:flex;flex-direction:column;background:var(--bg-color);border:1px solid var(--border-color-primary);border-radius:24px;padding:40px 48px 24px}
|
|
82
|
+
.panel{display:flex;flex-direction:column;gap:16px;background:var(--panel-bg);border:1px solid var(--border-color-primary);border-radius:24px;padding:32px 24px 24px}
|
|
83
|
+
.site{display:flex;align-items:center;justify-content:space-between;gap:16px;padding-bottom:24px;margin-bottom:24px;border-bottom:1px solid var(--border-color-secondary)}
|
|
84
|
+
.site-name{font-size:18px;line-height:24px;font-weight:600;overflow-wrap:anywhere}
|
|
85
|
+
.site-host{font-size:16px;line-height:24px;color:var(--text-color-secondary);overflow-wrap:anywhere;text-align:right}
|
|
86
|
+
.site-logo{display:block;max-height:32px;max-width:200px;width:auto}
|
|
87
|
+
h1{margin:0;font-size:20px;line-height:28px;font-weight:600}
|
|
88
|
+
h2{margin:0;font-size:16px;line-height:24px;font-weight:600}
|
|
89
|
+
p{margin:0}
|
|
90
|
+
.lede{margin-top:12px}
|
|
91
|
+
.muted{color:var(--text-color-description)}
|
|
92
|
+
.small{font-size:12px;line-height:20px}
|
|
93
|
+
.strong{font-weight:600}
|
|
94
|
+
code{font:inherit;background:var(--code-bg);color:var(--code-text);padding:1px 8px;border-radius:6px;overflow-wrap:anywhere}
|
|
95
|
+
.banner{display:flex;gap:8px;align-items:flex-start;margin-top:24px;padding:12px 16px;border:1px solid var(--danger-border);border-radius:8px;background:var(--danger-bg);color:var(--text-color-primary)}
|
|
96
|
+
.banner svg{flex:none;margin-top:3px;color:var(--danger)}
|
|
97
|
+
.banner.warning{border-color:var(--warning-border);background:var(--warning-bg)}
|
|
98
|
+
.banner.warning svg{color:var(--warning)}
|
|
99
|
+
form.credentials{display:flex;flex-direction:column;flex:1}
|
|
100
|
+
.schemes{display:flex;flex-direction:column;gap:12px;margin-top:24px}
|
|
101
|
+
.scheme{background:var(--layer-color);border:1px solid var(--border-color-secondary);border-radius:16px;padding:24px 32px 24px 24px}
|
|
102
|
+
.info-card{margin-top:24px;padding:8px 24px;background:var(--layer-color);border:1px solid var(--border-color-secondary);border-radius:16px}
|
|
103
|
+
.info-card section{display:flex;flex-direction:column;gap:2px;padding:16px 0}
|
|
104
|
+
.info-card section+section{border-top:1px solid var(--border-color-secondary)}
|
|
105
|
+
.info-card h2{font-size:14px;line-height:22px;font-weight:500;color:var(--text-color-secondary)}
|
|
106
|
+
.scheme-body{display:flex;flex-direction:column;gap:16px}
|
|
107
|
+
details.scheme>.scheme-body{margin-top:16px;padding-left:24px}
|
|
108
|
+
details.scheme>summary{display:grid;grid-template-columns:16px minmax(0,1fr) auto;column-gap:8px;row-gap:4px;cursor:pointer;list-style:none}
|
|
109
|
+
details.scheme>summary::-webkit-details-marker{display:none}
|
|
110
|
+
details.scheme>summary::before,details.operations>summary::before{content:"";flex:none;width:6px;height:6px;margin:8px 0 0 4px;border-right:1.5px solid var(--text-color-secondary);border-bottom:1.5px solid var(--text-color-secondary);transform:rotate(-45deg);transition:transform .15s}
|
|
111
|
+
details[open]>summary::before{transform:rotate(45deg);margin-top:6px}
|
|
112
|
+
details.scheme>summary:focus-visible{outline:2px solid var(--focus);outline-offset:4px;border-radius:4px}
|
|
113
|
+
.summary-title{grid-column:2;font-size:16px;line-height:24px;font-weight:600;overflow-wrap:anywhere}
|
|
114
|
+
.summary-tag{grid-column:3;grid-row:1}
|
|
115
|
+
.summary-line{grid-column:2/4}
|
|
116
|
+
.scheme-head{display:flex;flex-direction:column;gap:4px}
|
|
117
|
+
.tag{display:inline-block;padding:1px 8px;border-radius:4px;font-size:14px;line-height:22px;background:var(--tag-bg);color:var(--tag-text);white-space:nowrap}
|
|
118
|
+
.tag.stored{background:var(--tag-stored-bg);color:var(--tag-stored-text)}
|
|
119
|
+
.tags{display:flex;flex-wrap:wrap;align-items:center;gap:4px 8px}
|
|
120
|
+
.stored-box{display:flex;align-items:center;justify-content:space-between;gap:16px;padding:12px 16px;border-radius:8px;background:var(--stored-bg)}
|
|
121
|
+
.field{display:flex;flex-direction:column;gap:4px;min-width:0}
|
|
122
|
+
.field-row{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px}
|
|
123
|
+
label{font-weight:500;color:var(--text-color-secondary)}
|
|
124
|
+
input[type=text],input[type=password]{width:100%;height:34px;padding:0 12px;font-family:var(--font-family-base);font-size:14px;color:var(--text-color-primary);background:var(--input-bg-color);border:1px solid var(--input-border-color);border-radius:8px}
|
|
125
|
+
input::placeholder{color:var(--placeholder)}
|
|
126
|
+
input:focus{outline:2px solid transparent;border-color:var(--focus);box-shadow:0 0 0 1px var(--focus)}
|
|
127
|
+
input[aria-invalid=true]{border-color:var(--danger)}
|
|
128
|
+
input[aria-invalid=true]:focus{box-shadow:0 0 0 3px var(--danger-border)}
|
|
129
|
+
.divider{border:0;border-top:1px solid var(--border-color-secondary);margin:0}
|
|
130
|
+
details.operations>summary{display:flex;gap:8px;cursor:pointer;list-style:none;width:max-content;max-width:100%}
|
|
131
|
+
details.operations>summary::-webkit-details-marker{display:none}
|
|
132
|
+
details.operations>summary:focus-visible{outline:2px solid var(--focus);outline-offset:2px;border-radius:4px}
|
|
133
|
+
details.operations ul{margin:8px 0 0;padding-left:20px;display:flex;flex-direction:column;gap:4px}
|
|
134
|
+
.actions{margin-top:auto;padding-top:40px}
|
|
135
|
+
.actions-row{display:flex;align-items:center;gap:16px;padding-top:24px;border-top:1px solid var(--border-color-secondary)}
|
|
136
|
+
.actions-row .primary{flex:1}
|
|
137
|
+
button{font-family:var(--font-family-base);font-size:16px;line-height:24px;font-weight:400;cursor:pointer;border-radius:12px}
|
|
138
|
+
button:focus-visible{outline:2px solid var(--focus);outline-offset:2px}
|
|
139
|
+
.primary{height:40px;padding:0 20px;border:0;background:var(--primary-bg);color:var(--primary-text)}
|
|
140
|
+
.primary:hover{background:var(--primary-hover)}
|
|
141
|
+
.secondary{height:40px;padding:0 20px;border:0;box-shadow:inset 0 0 0 1px var(--border-color-primary);background:var(--bg-color);color:var(--text-color-primary)}
|
|
142
|
+
.actions-row .secondary{flex:1}
|
|
143
|
+
.secondary:hover{background:var(--panel-bg)}
|
|
144
|
+
.text-danger{padding:0 20px;height:40px;border:0;background:none;color:var(--danger)}
|
|
145
|
+
.text-danger.small{height:auto;padding:0 8px;font-size:14px;line-height:22px}
|
|
146
|
+
.text-danger:hover{text-decoration:underline}
|
|
147
|
+
.link-button{padding:0;border:0;background:none;color:var(--text-color-secondary);font-size:12px;line-height:20px;text-decoration:underline;text-underline-offset:2px}
|
|
148
|
+
.decline{margin-top:12px;text-align:center;color:var(--text-color-secondary)}
|
|
149
|
+
.panel h2{display:flex;align-items:center;gap:12px;font-weight:500}
|
|
150
|
+
.panel-steps{display:flex;flex-direction:column;gap:16px}
|
|
151
|
+
.panel-steps-toggle{display:none}
|
|
152
|
+
.panel-steps-toggle>summary{display:flex;align-items:center;justify-content:space-between;gap:12px;cursor:pointer;list-style:none}
|
|
153
|
+
.panel-steps-toggle>summary::-webkit-details-marker{display:none}
|
|
154
|
+
.panel-steps-toggle>summary::after{content:"";flex:none;width:7px;height:7px;margin:0 4px 4px 0;border-right:1.5px solid var(--text-color-secondary);border-bottom:1.5px solid var(--text-color-secondary);transform:rotate(45deg);transition:transform .15s}
|
|
155
|
+
.panel-steps-toggle[open]>summary::after{transform:rotate(-135deg);margin:4px 4px 0 0}
|
|
156
|
+
.panel-steps-toggle>summary:focus-visible{outline:2px solid var(--focus);outline-offset:4px;border-radius:4px}
|
|
157
|
+
.panel-steps-toggle>.steps{margin-top:16px}
|
|
158
|
+
.steps{margin:0;padding:0;list-style:none;display:flex;flex-direction:column;gap:16px;counter-reset:step}
|
|
159
|
+
.steps li{display:grid;grid-template-columns:20px minmax(0,1fr);gap:12px;counter-increment:step;font-size:16px;line-height:24px}
|
|
160
|
+
.steps li::before{content:counter(step);display:flex;align-items:center;justify-content:center;height:20px;margin-top:2px;border-radius:5px;background:var(--bg-color);font-size:14px;line-height:16px}
|
|
161
|
+
.link-facts{display:flex;flex-direction:column;gap:8px;margin-top:auto;padding-top:32px;border-top:1px solid var(--border-color-primary);color:var(--text-color-secondary)}
|
|
162
|
+
.pill{display:inline-flex;align-items:center;gap:8px;width:max-content;max-width:100%;padding:1px 8px;border-radius:999px;background:var(--bg-color);font-size:12px;line-height:20px}
|
|
163
|
+
.pill::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:var(--success)}
|
|
164
|
+
.outcome{display:flex;flex-direction:column;align-items:center;text-align:center;gap:24px;padding:56px 0}
|
|
165
|
+
.status-icon{display:flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:50%;color:#ffffff}
|
|
166
|
+
.status-icon.success{background:var(--success);box-shadow:0 0 16px 10px var(--success-glow)}
|
|
167
|
+
.status-icon.warning{background:var(--warning);box-shadow:0 0 16px 10px var(--warning-glow)}
|
|
168
|
+
.status-icon.danger{background:var(--danger-icon);box-shadow:0 0 16px 10px var(--danger-glow)}
|
|
169
|
+
.status-icon.neutral{background:var(--text-color-description);box-shadow:0 0 16px 10px var(--neutral-glow)}
|
|
170
|
+
.message{display:flex;flex-direction:column;gap:8px;width:100%;max-width:640px;padding:24px 32px;border:1px solid var(--border-color-secondary);border-radius:12px;background:var(--layer-color)}
|
|
171
|
+
@media (max-width:960px){
|
|
172
|
+
body{padding:16px}
|
|
173
|
+
.page{grid-template-columns:minmax(0,1fr);min-height:0}
|
|
174
|
+
.card{padding:24px}
|
|
175
|
+
.site{flex-direction:column;align-items:flex-start;gap:0}
|
|
176
|
+
.site-host{text-align:left}
|
|
177
|
+
.panel-steps{display:none}
|
|
178
|
+
.panel-steps-toggle{display:block}
|
|
179
|
+
.link-facts{padding-top:16px}
|
|
180
|
+
.scheme{padding:16px}
|
|
181
|
+
.info-card{padding:4px 16px}
|
|
182
|
+
.field-row{grid-template-columns:minmax(0,1fr)}
|
|
183
|
+
.outcome{padding:32px 0}
|
|
184
|
+
.message{padding:16px}
|
|
185
|
+
}
|
|
186
|
+
`;function t(a){switch(a){case"light":return`:root{color-scheme:light;${e}}${r}`;case"dark":return`:root{color-scheme:dark;${e}${o}}${r}`;default:return`:root{color-scheme:light dark;${e}}@media (prefers-color-scheme:dark){:root{${o}}}${r}`}}export{t as pageStyles};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type SiteBranding = {
|
|
2
|
+
name?: string;
|
|
3
|
+
logo?: {
|
|
4
|
+
light: string;
|
|
5
|
+
dark?: string;
|
|
6
|
+
};
|
|
7
|
+
/** Set when the portal always shows one color mode. */
|
|
8
|
+
colorScheme?: PageColorScheme;
|
|
9
|
+
};
|
|
10
|
+
export type PageColorScheme = 'light' | 'dark';
|
|
11
|
+
export type PageSite = SiteBranding & {
|
|
12
|
+
host: string;
|
|
13
|
+
};
|
|
14
|
+
/** One page, before the shared document shell wraps it. */
|
|
15
|
+
export type PageContent = {
|
|
16
|
+
title: string;
|
|
17
|
+
body: string;
|
|
18
|
+
};
|
|
19
|
+
export type SchemeField = 'secret' | 'client_id' | 'client_secret';
|
|
20
|
+
/** A rejected submission. `schemeIndex` and `field` name the input to mark, when there is one. */
|
|
21
|
+
export type FormError = {
|
|
22
|
+
message: string;
|
|
23
|
+
schemeIndex?: number;
|
|
24
|
+
field?: SchemeField;
|
|
25
|
+
};
|
|
26
|
+
/** What one submission changed, and the schemes that hold a credential after it. */
|
|
27
|
+
export type CredentialsOutcome = {
|
|
28
|
+
action: 'saved' | 'removed';
|
|
29
|
+
schemes: readonly string[];
|
|
30
|
+
stored: readonly string[];
|
|
31
|
+
};
|
|
32
|
+
//# sourceMappingURL=types.d.ts.map
|
|
File without changes
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import type { ApiRoutesHandler } from '@redocly/config';
|
|
2
|
-
export declare function setCredentialsFetchImpl(impl: typeof fetch): void;
|
|
3
2
|
declare const mcpCredentialsHandler: ApiRoutesHandler;
|
|
4
3
|
export default mcpCredentialsHandler;
|
|
5
4
|
//# sourceMappingURL=mcp-credentials-handler.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{secretStore as
|
|
1
|
+
import{secretStore as d}from"../gateway-mcp/secret-store.js";import{rejectCredential as _}from"../gateway-mcp/credential-validation.js";import{buildAllowedHostMatchers as C}from"../gateway-mcp/fetch/allowed-hosts.js";import{assertUrlAllowed as A}from"../gateway-mcp/fetch/ssrf-guard.js";import{readCappedBody as T,getDefaultAgent as P}from"../gateway-mcp/fetch/fetch-bridge.js";import{logger as x}from"../../../tools/notifiers/logger.js";import{FORM_ACTIONS as k}from"./credentials-page/constants.js";import{credentialSchemesOf as w,schemeFieldName as f}from"./credentials-page/form-contract.js";import{formPage as N}from"./credentials-page/form-page.js";import{htmlDocument as O}from"./credentials-page/layout.js";import{declinedPage as R,expiredPage as I,outcomePage as j}from"./credentials-page/outcome-pages.js";const D={"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store","X-Frame-Options":"DENY","Referrer-Policy":"no-referrer","Content-Security-Policy":"default-src 'none'; style-src 'unsafe-inline'; img-src 'self'; form-action 'self'; frame-ancestors 'none'; base-uri 'none'"},$=3e4,F=64*1024,M=/^bearer\s+/i,U=/^\d+$/,B=async(e,t,o)=>{const n=await t.getKv(),r=L(e,t.baseUrl,o);if(e.method==="GET"){const i=new URL(e.url).searchParams.get("token")??"",c=await d.peekElicitation(n,i);return c?S({kv:n,site:r,token:i,target:c},{},200):p(r)}if(e.method==="POST"){const i=await e.formData(),c=u(i,"token"),a=await d.peekElicitation(n,c);if(!a)return p(r);const s={kv:n,site:r,token:c,target:a,form:i};switch(u(i,"action")){case k.remove:return b(s,z(a,u(i,"scheme")));case k.removeAll:return b(s,w(a));case k.decline:return K(s);default:return H(s)}}return new Response("Method Not Allowed",{status:405,headers:{Allow:"GET, POST"}})};async function H(e){const{target:t,form:o}=e,n=w(t),r=n.map((s,l)=>u(o,f("client_id",l)).trim()),i=s=>S(e,{error:s,clientIds:r},400),c=X(n,o);if("error"in c)return i(c.error);if(c.writes.length===0)return i(G(n));const a=[];for(const s of c.writes){if(s.kind!=="exchange"){a.push(s);continue}const l=await J(s.auth,s.clientId,s.clientSecret);if(!l.ok)return x.warn(`gateway oauth2 client_credentials exchange failed for ${t.api}: ${l.reason}`),i(E(n,s.schemeIndex,"client_id","We could not exchange those client credentials for a token. Check the client ID and secret, then try again."));a.push({kind:"set",scheme:s.scheme,secret:l.secret})}return v(e,a)}function X(e,t){const o=[];for(const[n,r]of e.entries()){const i=u(t,f("secret",n)).trim();if(i){const s=_(r.auth,i);if(s)return{error:E(e,n,"secret",s)};o.push({kind:"set",scheme:r.name,secret:W(r.auth,i)});continue}if(r.auth.kind!=="oauth2ClientCredentials")continue;const c=u(t,f("client_id",n)).trim(),a=u(t,f("client_secret",n)).trim();if(c&&a)o.push({kind:"exchange",scheme:r.name,schemeIndex:n,auth:r.auth,clientId:c,clientSecret:a});else if(c||a)return{error:E(e,n,c?"client_secret":"client_id","Enter both the client ID and the client secret, or leave both blank.")}}return{writes:o}}function G(e){return e.length>1?{message:"Fill in at least one credential before saving."}:{message:e[0].auth.kind==="oauth2ClientCredentials"?"Enter an access token, or the client ID and the client secret, before saving.":"Enter a value before saving.",schemeIndex:0,field:"secret"}}function E(e,t,o,n){return{message:e.length>1?`${e[t].name}: ${n}`:n,schemeIndex:t,field:o}}async function b(e,t){const{kv:o,target:n}=e,r=await d.getStoredSchemes(o,n.subject,n.api),i=t.filter(c=>r[c.name]).map(c=>({kind:"remove",scheme:c.name}));return i.length===0?S(e,{error:{message:"No credential is stored there, so there is nothing to remove."}},400):v(e,i)}function z(e,t){const o=U.test(t)?w(e)[Number(t)]:void 0;return o?[o]:[]}async function K({kv:e,site:t,token:o}){return await d.consumeElicitation(e,o)?h(t,R(),200):p(t)}async function v({kv:e,site:t,token:o},n){const r=await d.consumeElicitation(e,o);if(!r)return p(t);for(const a of n)a.kind==="remove"?await d.deleteSecret(e,r.subject,r.api,a.scheme):await d.setSecret(e,r.subject,r.api,a.scheme,a.secret);const i=await d.getStoredSchemes(e,r.subject,r.api),c={action:n.some(a=>a.kind==="set")?"saved":"removed",schemes:n.map(a=>a.scheme),stored:Object.keys(i).sort()};return h(t,j(r,c),200)}async function S({kv:e,site:t,token:o,target:n},r,i){const c=await d.getStoredSchemes(e,n.subject,n.api);return h(t,N({site:t,target:n,token:o,stored:c,...r}),i)}function L(e,t,o){const n=o?.props?.branding??{},r=t&&URL.canParse(t)?t:e.url;return{...n,host:new URL(r).host}}async function J(e,t,o){try{const n=C([{url:e.tokenUrl}]),r=A(e.tokenUrl,n),i=new AbortController,c=setTimeout(()=>i.abort(),$);let a;try{a=await fetch(r,{method:"POST",headers:{"content-type":"application/x-www-form-urlencoded"},body:new URLSearchParams({grant_type:"client_credentials",client_id:t,client_secret:o}),redirect:"manual",signal:i.signal,dispatcher:P()})}finally{clearTimeout(c)}if(!a.ok)return m(`token endpoint returned ${a.status}`);let s;try{s=await T(a,F)}catch{return m("token response exceeded the size cap")}let l;try{l=JSON.parse(s)}catch{return m("token response was not valid JSON")}const y=typeof l=="object"&&l!==null&&"access_token"in l?l.access_token:void 0,g=typeof y=="string"?y.trim():"";return g?_(e,g)?m("token response had an access_token that cannot be sent in a header"):{ok:!0,secret:{header:"Authorization",value:`Bearer ${g}`}}:m("token response had no access_token")}catch(n){return m(n instanceof Error?n.message:String(n))}}function m(e){return{ok:!1,reason:e}}function u(e,t){const o=e.get(t);return typeof o=="string"?o:""}function h(e,t,o){return new Response(O(t,e.colorScheme),{status:o,headers:D})}function p(e){return h(e,I(),404)}function W(e,t){return e.kind==="apiKey"?{header:e.header,value:t}:e.kind==="cookie"?{header:"Cookie",value:`${e.name}=${t}`}:e.kind==="bearer"||e.kind==="oauth2ClientCredentials"?{header:"Authorization",value:Y(t)}:{header:"Authorization",value:t}}function Y(e){return`Bearer ${e.replace(M,"")}`}var ie=B;export{ie as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{fileURLToPath as U}from"node:url";import{dirname as $,join as
|
|
1
|
+
import{fileURLToPath as U}from"node:url";import{dirname as $,join as M}from"node:path";import{MCP_ROUTE as k,PUBLIC_MCP_ROUTE as b}from"@redocly/theme/core/constants/mcp";import{logger as p}from"../../tools/notifiers/logger.js";import{reporter as F}from"../../tools/notifiers/reporter.js";import{isDefined as B}from"../../../utils/guards/is-defined.js";import{MCP_CREDENTIALS_HANDLER_ID as P,MCP_CREDENTIALS_ROUTE as V,MCP_DOCS_SERVER_HANDLER_ID as T,MCP_NOT_ALLOWED_TEMPLATE_ID as x}from"../../constants/mcp.js";import{bundledOpenApiDocumentsToMcpOpenApi as J,bundledGraphqlDocumentsToMcpOpenApi as W,buildGraphqlDescriptions as X,collectIgnoredRoutes as z,filterIgnoredApiDescriptions as A,getCleanedUpApiDescriptions as K,isMcpInRedirects as Q}from"./utils.js";import{getMcpMode as R,isMcpElicitationEnabled as Y,isMcpGatewayEnabled as Z}from"./utils/mode.js";import{getPublicMcpEndpointStatus as _}from"./utils/public-endpoint.js";import{findGatedToolNames as ee}from"./utils/find-gated-tool-names.js";import{getDefaultToolSchemas as oe}from"./docs-mcp/tool-schemas.js";import{EXECUTE_TOOL_SCHEMA as te}from"./codemode/tools/execute-schema.js";import{isGatewayCapabilityEnabled as ie,isGatewayEligible as re}from"./gateway-mcp/eligibility.js";import{resolveGatewayFetchLimits as se}from"./gateway-mcp/rate-limit/limits.js";import{resetCustomMcpTools as ne,scanCustomMcpTools as ae}from"./custom-tools/scan-custom-tools.js";import{resolveSiteBranding as ce}from"./handlers/credentials-page/site-branding.js";import{telemetryTraceStep as pe}from"../../../cli/telemetry/helpers/trace-step.js";import{DEFAULT_DOCS_MCP_SERVER_NAME as S}from"./constants.js";const C=$(U(import.meta.url));async function de(){let i;const m={registeredToolNames:[],warnedNoOutputSchemaTools:new Set};let u=0,f=!1;return{id:"mcp",async processContent(e,a){await pe("com.redocly.build.plugin.mcp",async s=>{const t=await a.getConfig(),{mcp:r,redirects:g}=t;if(s?.setAttribute("config",JSON.stringify(r||{})),s?.setAttribute("mcpMode",R()),s?.setAttribute("mcpGateway",String(Z())),r?.hide||r?.docs?.hide){ne(e,m);return}Q(g)&&await F.panicOnBuildContentError('The reserved route "/mcp" cannot be used in redirect configuration. Please remove any redirects involving "/mcp" from your redocly.yaml config.'),e.createTemplate(x,"@redocly/theme/layouts/McpNotAllowed");const l=!!t?.access?.requiresLogin,h=t?.access?.rbac||{},d=R(),c=Y(),{budgetPerExec:D}=se();if(!i){p.info("Configuring MCP servers...");const w=J(await e.loadApiDocuments(a)),O=W(await e.loadApiDocuments(a)),v=r?.docs?.ignore||[],L=K(A(w,v)),q=ie(r),E=new Map;for(const o of L){const H=o.definition.info?.title||"",j=o.definition.info?.version||"";E.set(o.relativePath,{name:H,description:typeof o.definition.info?.description=="string"?o.definition.info.description:"",version:j,servers:o.definition.servers||[],relativePath:o.relativePath,...q&&re(o.definition.info,o.relativePath,h)?{fetchEligible:!0}:{}})}const y=X(A(O,v)),G=Object.values(t.products||{}).map(o=>o?.name).filter(B),I=t.l10n?.locales?.map(o=>o.code)??a.fs.localeFolders,N=oe({products:G,locales:I,requiresLogin:l,rbac:h,hasGraphqlApis:y.length>0,elicitationEnabled:c,hasCallableApis:E.values().some(o=>o.fetchEligible),feedbackHidden:t.feedback?.hide===!0});e.addMcpTools(M(C,"./docs-mcp/tools/index.js"),N),d==="code"&&e.addMcpTools(M(C,"./codemode/tools/execute.js"),[te]),i={apiDescriptionsMap:Object.fromEntries(E),graphqlDescriptions:y}}const n=await ae(e,a,m);s?.setAttribute("customToolsCount",String(n)),n!==u&&(u=n,n>0&&p.info(`Registered ${n} custom MCP tool${n===1?"":"s"} from @mcp folders`)),await le({actions:e,handlerPath:M(C,"./handlers/docs-mcp-handler.js"),apiDescriptionsMap:i.apiDescriptionsMap,graphqlDescriptions:i.graphqlDescriptions,mcpConfig:r,mcpMode:d,elicitationEnabled:c,gatewayFetchBudgetPerExec:D,publicEndpointStatus:_(t)}),f||(p.info("Registered Docs MCP Server endpoint at /mcp"),f=!0)})},async afterRoutesCreated(e,a){const s=await a.getConfig(),{mcp:t}=s,r=!t?.hide&&!t?.docs?.hide;e.markGatedMcpTools(await ee(e.getMcpTools())),e.setGlobalData({mcpData:{docs:{enabled:r,name:t?.docs?.name||S,publicEndpoint:_(s)==="served"}}})}}}var Oe=de;async function le({actions:i,handlerPath:m,apiDescriptionsMap:u,graphqlDescriptions:f,mcpConfig:e,mcpMode:a,elicitationEnabled:s,gatewayFetchBudgetPerExec:t,publicEndpointStatus:r}){i.createRequestHandler(T,m);const g=l=>async(h,d)=>{const c=z(d.getAllRoutes(),e?.docs?.ignore||[]);return c.length>0&&p.verbose(`mcp.docs.ignore: hiding ${c.length} page routes from MCP search`),{props:{config:{apiDescriptionsMap:u,graphqlDescriptions:f,mcpDocsServerName:e?.docs?.name||S,mcpMode:a,elicitationEnabled:s,gatewayFetchBudgetPerExec:t,searchIgnoredRoutes:c,...l?{isPublicEndpoint:l}:{}},serverOutDir:i.serverOutDir,tools:i.getMcpTools().map(({importPath:D,...n})=>n)}}};if(i.addApiRoute({slug:k,requestHandlerId:T,httpMethod:"all",getStaticData:g(!1)}),r==="no-protected-content"?p.info(`mcp.docs.publicEndpoint is enabled, but the project has no protected content - /mcp already serves anonymous users, skipping ${b}.`):r==="anonymous-denied"?p.info(`mcp.docs.publicEndpoint is enabled, but anonymous users are denied the MCP feature (rbac.features.mcp or requiresLogin) - skipping ${b}.`):r==="served"&&(i.addApiRoute({slug:b,requestHandlerId:T,httpMethod:"all",getStaticData:g(!0)}),p.verbose(`Registered public Docs MCP Server endpoint at ${b}`)),s){const l=M(C,"./handlers/mcp-credentials-handler.js");i.createRequestHandler(P,l),i.addApiRoute({slug:V,requestHandlerId:P,httpMethod:"all",getStaticData:async(h,d)=>{const{seo:c,colorMode:D}=d.getConfig(),{logo:n}=d.getGlobalData();return{props:{branding:ce({seo:c,logo:n,colorMode:D})}}}}),p.verbose("Registered MCP credentials endpoint at /mcp/credentials")}}export{Oe as default,de as mcpServerPlugin};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{McpServer as C}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as
|
|
1
|
+
import{McpServer as C}from"@modelcontextprotocol/server";import{logger as S}from"../../../tools/notifiers/logger.js";import{mcpToolWorkers as _,MCP_TOOL_WORKER_KEY as O}from"../../../workers/mcp-tool-worker-pool.js";import{secretStore as L}from"../gateway-mcp/secret-store.js";import{readAuthRequiredMeta as D,stripAuthRequiredMeta as E,upstreamAuthKey as b}from"../gateway-mcp/upstream-auth.js";import{acceptedCredentialsLink as K,buildCredentialsAcceptedHint as j,buildCredentialsToolHint as F,buildUpstreamCredentialFallback as q,buildUpstreamCredentialInputRequired as v,credentialElicitationAnswer as H,dedupeElicitation as N,isStatelessRequest as P,schemeLabelOf as $,supportsUrlElicitation as B}from"../gateway-mcp/elicitation.js";import{DEFAULT_SCHEME_NAME as y,resolveUpstreamApiAuth as G}from"../gateway-mcp/upstream-auth-scheme.js";import{MISSING_SESSION_HANDLE_MESSAGE as V,resolveSecretSubject as W}from"../gateway-mcp/subject.js";const Y=6e4;function ue(e,t){return new C({name:e,version:new Date().toISOString().slice(0,10)},{capabilities:{logging:{}},...t?{instructions:t}:{}})}function le(e,t){return r=>async(n,s)=>{S.info(`MCP tool called: ${r}`);const i=e.elicitationEnabled??!1,u=P(s.mcpReq),a=i?W(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 c=async()=>{if(!(!i||!o||!t?.getKv))try{const m=await t.getKv();return await L.getSecretsForSubject(m,o)}catch(m){S.warn(`gateway mcp secret store error, continuing unauthenticated: ${String(m)}`);return}};let l;const d=async()=>{l=await c();const m={toolName:r,args:n,context:{...e,upstreamSecrets:l},extra:ee(s)};return await _.exec(O,[m],{timeout:Y})};let p=await d();const f=D(p);if(f.length>0&&i&&!o)return E(I(p,[{type:"text",text:V}]));if(f.length>0&&i&&o&&t?.getKv){S.info(`gateway mcp credentials prompt: era=${u?"2026-07-28":"2025"} clientElicitation=${J(t)}`);const m=await t.getKv(),h=await Q(e,f),w=f.map(U=>X(U,h)),k=Z(l),g=u?await x(e,s,w,o,m,k,h,t):await z(e,w,o,m,k,h);switch(g.kind){case"inputRequired":return g.result;case"retry":p=await d();break;case"prependText":p=I(p,[{type:"text",text:g.text},...p.content]);break;case"none":break}}return E(p)}}function I(e,t){const{structuredContent:r,...n}=e;return{...n,content:t,isError:!0}}function J(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 Q(e,t){const r=new Map;for(const n of new Set(t.map(s=>s.api)))r.set(n,await G(e,n));return r}function X(e,t){const r=t.get(e.api);if(!r)return{...e,scheme:e.scheme??y};const n=e.scheme&&r.schemes[e.scheme]?e.scheme:r.defaultScheme;return{...e,scheme:n}}function Z(e){const t=new Set;for(const[r,n]of Object.entries(e??{}))for(const s of Object.keys(n))t.add(b({api:r,scheme:s}));return t}function R(e,t){return e.status===401&&!t.has(b(e))}function T(e,t){const r=t.get(e.api),n=e.sentScheme??e.scheme;return r&&n?$(r.schemes,n):void 0}function M(e,t){return e.map(r=>F(r,T(r,t))).join(`
|
|
2
2
|
|
|
3
|
-
`)}function A(e,t,r,n,s){const[i,...
|
|
3
|
+
`)}function A(e,t,r,n,s){const[i,...u]=t,a=s.get(i.api),o=i.scheme??a?.defaultScheme??y,c=i.schemes&&i.schemes.length>1?i.schemes:void 0,l=c?void 0:T(i,s);return{subject:r,baseUrl:e.baseUrl??"",target:{api:i.api,name:i.name,scheme:o,...l?{schemeLabel:l}:{},...c?{acceptedSchemes:c}:{}},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:u.map(d=>d.name)}}}async function x(e,t,r,n,s,i,u,a){const o=H(t.mcpReq.inputResponses);if(o==="declined")return{kind:"none"};const c=r.filter(d=>R(d,i));if(c.length===0)return{kind:"prependText",text:M(r,u)};if(o==="accepted"){const d=await K(t.mcpReq.requestState(),{kv:s,subject:n,baseUrl:e.baseUrl??"",apis:c.map(f=>f.api)}),p=d?.apiName??c[0].name;return{kind:"prependText",text:j(p,d?.url)}}const l=A(e,c,n,s,u);return B(a?.getClientCapabilities())?{kind:"inputRequired",result:await v(l)}:{kind:"prependText",text:await q(l)}}async function z(e,t,r,n,s,i){const u=t.filter(c=>R(c,s));if(u.length===0)return{kind:"prependText",text:M(t,i)};const a=A(e,u,r,n,i);return{kind:"prependText",text:await N(`${r}:${b(u[0])}`,()=>q(a))}}function ee(e){return{sessionId:e.sessionId,authInfo:e.http?.authInfo,requestId:e.mcpReq.id,_meta:e.mcpReq._meta}}function de(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,requestId:e.requestId,messageId:e.messageId,upstreamSecrets:e.upstreamSecrets,searchIgnoredRoutes:e.searchIgnoredRoutes,internalBaseUrl:e.internalBaseUrl,sandboxToolSchemas:e.sandboxToolSchemas,fs:void 0}}export{ue as createMcpServer,le as createToolDispatch,de as extractSerializableContext};
|
|
@@ -5,6 +5,7 @@ import type { McpErrorCodes, McpServerType } from './constants';
|
|
|
5
5
|
import type { McpToolSchema } from '../../types';
|
|
6
6
|
import type { Skill } from '../../types/plugins/skills.js';
|
|
7
7
|
import type { UpstreamSecrets } from './gateway-mcp/secret-store.js';
|
|
8
|
+
import type { SiteBranding } from './handlers/credentials-page/types.js';
|
|
8
9
|
type ObjectValues<T> = T[keyof T];
|
|
9
10
|
export type McpServerType = ObjectValues<typeof McpServerType>;
|
|
10
11
|
export type McpErrorCodeTypes = ObjectValues<typeof McpErrorCodes>;
|
|
@@ -40,6 +41,11 @@ export type McpDocsStaticData = PageStaticData & {
|
|
|
40
41
|
skillsBaseUrl?: string;
|
|
41
42
|
};
|
|
42
43
|
};
|
|
44
|
+
export type CredentialsPageStaticData = PageStaticData & {
|
|
45
|
+
props?: {
|
|
46
|
+
branding?: SiteBranding;
|
|
47
|
+
};
|
|
48
|
+
};
|
|
43
49
|
export type SkillMcpResource = {
|
|
44
50
|
slug: string;
|
|
45
51
|
name: string;
|
|
@@ -10,7 +10,10 @@ import type { McpMode } from '../types.js';
|
|
|
10
10
|
* data / McpToolContext instead (see docs-mcp-handler / execute-mcp-tool).
|
|
11
11
|
*/
|
|
12
12
|
export declare function isMcpCodeModeEnabled(): boolean;
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* The gateway capability: a guarded `fetch` in the `execute` sandbox. Requires code mode and a
|
|
15
|
+
* project database.
|
|
16
|
+
*/
|
|
14
17
|
export declare function isMcpGatewayEnabled(): boolean;
|
|
15
18
|
export declare function isMcpElicitationEnabled(): boolean;
|
|
16
19
|
export declare function getMcpMode(): McpMode;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EntitlementsProvider as e}from"../../../entitlements/entitlements-provider.js";function t(){return e.instance().entitlements?.mcpMode==="code"}function
|
|
1
|
+
import{EntitlementsProvider as e}from"../../../entitlements/entitlements-provider.js";import{hasProjectDatabase as n}from"../../../providers/database/has-project-database.js";function t(){return e.instance().entitlements?.mcpMode==="code"}function o(){return!!e.instance().canAccessFeature("mcpGateway")&&t()&&n()}function i(){return o()}function a(){return t()?"code":"tools"}export{a as getMcpMode,t as isMcpCodeModeEnabled,i as isMcpElicitationEnabled,o as isMcpGatewayEnabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as
|
|
1
|
+
import*as e from"react";import{useState as i}from"react";import{getScorecardColorVariable as s}from"@redocly/theme/core/utils";import{Button as m}from"@redocly/theme/components/Button/Button";import{SubtractIcon as u}from"@redocly/theme/icons/SubtractIcon/SubtractIcon";import{AddIcon as p}from"@redocly/theme/icons/AddIcon/AddIcon";import{Gauge as E}from"./Gauge";import{Code as f,Dot as o,FilePreview as d,InstanceControlsWrap as v,InstanceMessage as x,InstanceReference as C,InstanceWrap as I,ContentWithDotWrap as a,EmojiWrap as b}from"./index.styles";import{SEVERITY_TO_COLOR as g,severityColor as S,severityIcon as R}from"./utils";function D({level:t,colorVariable:r}){return e.createElement(a,null,e.createElement(o,{colorVariable:r}),e.createElement("span",null,t))}function L({summary:t}){const r=Object.keys(t.levels).length;return e.createElement(E,{chunks:Object.entries(t.levels).map(([l,n],c)=>({share:n/t.total*100,colorVariable:s(c,r),title:`${n} ${l}`}))})}function P({severity:t}){return e.createElement(o,{colorVariable:g[t]})}function A({errors:t,warnings:r}){return e.createElement(a,null,e.createElement(o,{colorVariable:`--scorecard-color-${t>0?"error":r>0?"warning":"success"}`}),e.createElement("span",null,t>0?"Problem":r>0?"Warning":"Normal"))}function N({errors:t,warnings:r}){return e.createElement(o,{colorVariable:`--scorecard-color-${t>0?"error":r>0?"warning":"success"}`})}function V({problem:t}){const[r,l]=i(!1);return e.createElement(v,{onClick:()=>l(n=>!n),className:r?"expanded":""},e.createElement(m,{variant:"text",size:"medium",icon:r?e.createElement(u,null):e.createElement(p,null)}),e.createElement(I,{borderColor:S(t.severity)},e.createElement("div",null,e.createElement(x,null,e.createElement(b,null,R(t.severity))," ",t.message)),r?e.createElement(d,{onClick:n=>n.stopPropagation()},e.createElement(C,null,e.createElement("strong",null,t.location.source.absoluteRef),t.location.pointer),e.createElement(f,null,t.codeframe)):null))}const T=t=>e.createElement(V,{problem:t});export{D as ApiLevel,V as Instance,P as InstanceStatus,N as LevelStatus,A as RuleStatus,L as StatusDistribution,T as renderRowSubComponent};
|
|
@@ -17,6 +17,11 @@ export declare class DatabaseClient {
|
|
|
17
17
|
static init(config: Config, options?: DatabaseClientInitOptions): Promise<DatabaseClient>;
|
|
18
18
|
migrate(prefix: string, suffix?: string): Promise<void>;
|
|
19
19
|
close(): Promise<void>;
|
|
20
|
+
/**
|
|
21
|
+
* Closes the client during error handling. Never throws, so the caller can rethrow
|
|
22
|
+
* the original error; a close failure is logged.
|
|
23
|
+
*/
|
|
24
|
+
closeAfterFailure(): Promise<void>;
|
|
20
25
|
sync(): Promise<void>;
|
|
21
26
|
}
|
|
22
27
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import o from"node:path";import{sql as c}from"drizzle-orm";import{drizzle as l}from"drizzle-orm/libsql";import{migrate as m}from"drizzle-orm/libsql/migrator";import{logger as d}from"../../tools/notifiers/logger.js";import{TransactionsManager as h}from"./transactions-manager.js";class n{dbClient;#t;constructor(t,r){this.dbClient=l(r(t)),this.#t=new h(this.dbClient)}get transactionsManager(){return this.#t}get client(){return this.#t.tx??this.dbClient}static async init(t,r){const{createClient:a}=await import("@libsql/client"),i=new n(t,a);if(r?.runWithPragmaWalWriteOptimization)try{await i.dbClient.run(c.raw("PRAGMA journal_mode = WAL;"))}catch(s){throw await i.closeAfterFailure(),s}return i}async migrate(t,r=""){await m(this.dbClient,{migrationsFolder:o.join(t,"migrations",r)})}async close(){this.dbClient.$client.close()}async closeAfterFailure(){try{await this.close()}catch(t){d.warn("Failed to close the database client: %s",t)}}async sync(){try{await this.dbClient.$client.sync()}catch(t){if(u(t))return;throw t}}}function u(e){if(!(e instanceof Error))return!1;const t=e.message.toLowerCase();return t.includes("syncnotsupported")&&(t.includes('("file")')||t.includes('"file"'))}export{n as DatabaseClient};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import
|
|
1
|
+
import n from"node:path";import{cpSync as m,existsSync as i,mkdirSync as c}from"node:fs";import{logger as e}from"../../tools/notifiers/logger.js";import{fromCurrentDir as u}from"../../utils/index.js";import{hasProjectDatabase as f}from"./has-project-database.js";const D=r=>{if(!f())return;const o="sqlite-db",t=u(import.meta.url,`./databases/${o}/migrations`),a=n.join(r.serverOutDir,"migrations",o);if(!i(t)){e.warn(`Migrations folder not found at ${t}`);return}i(r.serverOutDir)||c(r.serverOutDir,{recursive:!0});try{m(t,a,{recursive:!0})}catch(s){e.error("Failed to copy migrations folder: %s",s)}};export{D as copyMigrationsFolder};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{logger as c}from"../../tools/notifiers/logger.js";import{SqldNotRunningError as y}from"./sqld-not-running-error.js";import{retryAsyncOperation as
|
|
1
|
+
import{logger as c}from"../../tools/notifiers/logger.js";import{SqldNotRunningError as y}from"./sqld-not-running-error.js";import{retryAsyncOperation as h}from"./utils/retry-async-operation.js";import{DatabasePathGenerator as w}from"./database-path-generator.js";import{DatabaseClient as g}from"./client.js";import{describeTransientError as z}from"./transient-sqld-error.js";const u="_redocly_db_preconnect_cache_";class i{static get#t(){const t=globalThis;if(!t[u]){const r={connections:new Map,pendingConnections:new Map,failedConnections:new Set};t[u]=r}return t[u]}static get#i(){return i.#t.connections}static get#e(){return i.#t.failedConnections}static get#r(){return i.#t.pendingConnections}static async getLocalConnection(t){return i.#n(t,async()=>i.#a(t))}static async getRemoteConnection(t){return i.#n(t,async()=>i.#d(t))}static async#n(t,r){const e=i.#o(t),n=i.#i.get(e);if(n)if(n.client.dbClient.$client.closed)c.warn("Cached database client is closed. Reinitializing connection..."),i.#i.delete(e);else return n;return i.#l({key:e,initializer:r})}static#o=t=>{const r="syncUrl"in t&&typeof t.syncUrl=="string"?`|${t.syncUrl}`:"",e=t.additionalFolder??"";return`${t.baseDbDir}|${e}|${t.databaseName}${r}`};static async#l({key:t,initializer:r}){let e=i.#r.get(t);e||(i.#e.has(t)&&c.warn("Error connecting to the database, retrying..."),e=i.#s(t,r),i.#r.set(t,e));try{return await e}catch(n){return c.error("Error connecting to the database: %s",z(n)),i.#e.add(t),null}finally{i.#r.delete(t)}}static async#s(t,r){const e=await r();return i.#i.set(t,e),i.#e.delete(t),e}static async#a({removeExisting:t,baseDbDir:r,runWithPragmaWalWriteOptimization:e,databaseName:n,additionalFolder:a,migrationsFolder:d}){c.info("Initializing local database client...");const l=c.startTiming(),s=await i.#c({removeExisting:t,baseDbDir:r,databaseName:n,additionalFolder:a,migrationsFolder:d,runWithPragmaWalWriteOptimization:e});return c.infoTime(l,"Local database client initialized"),s}static async#d({removeExisting:t,baseDbDir:r,syncUrl:e,authToken:n,databaseName:a,additionalFolder:d,migrationsFolder:l}){c.info("Initializing remote database client...");const s=c.startTiming();return await h(async()=>{try{const o=await i.#c({removeExisting:t,baseDbDir:r,databaseName:a,additionalFolder:d,migrationsFolder:l,syncUrl:e,authToken:n});return c.infoTime(s,"Remote database client initialized"),o}catch(o){throw y.isSqldNotRunningError(o)?new y("SQLD server is not running yet, wait for production deployment",{cause:o}):o}},{maxRetries:3,retryStrategy:"exponential",delay:1e3,logger:c,messages:{retry:"Retrying remote database client initialization",maxRetriesReached:"Max retries reached, remote database client initialization failed"}})}static async#c({removeExisting:t,baseDbDir:r,databaseName:e,additionalFolder:n,migrationsFolder:a,runWithPragmaWalWriteOptimization:d,syncUrl:l,authToken:s}){const{databasePath:o}=await w.prepareDatabasePath({baseDir:r,databaseName:e,additionalFolder:n,removeExisting:t}),p=l&&s?{url:`file:${o}`,syncUrl:l,authToken:s}:{url:`file:${o}`},m=await g.init(p,{runWithPragmaWalWriteOptimization:d});try{await m.migrate(r,a)}catch(f){throw await m.closeAfterFailure(),f}return{client:m,path:o}}}export{i as DatabaseConnectionsManager};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{PACKAGE_NAME as e}from"../../../config/product-gates.js";const r=["@redocly/realm","@redocly/reef","@redocly/redoc-reef","@redocly/revel-reef"];function c(){return r.includes(e)}export{c as hasProjectDatabase};
|