@ggui-ai/mcp-server 0.8.0 → 0.9.0
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/dist/api-renders-routes.d.ts.map +1 -1
- package/dist/api-renders-routes.js +32 -23
- package/dist/api-renders-stream-route.d.ts +80 -0
- package/dist/api-renders-stream-route.d.ts.map +1 -0
- package/dist/api-renders-stream-route.js +311 -0
- package/dist/build-mcp.d.ts +10 -0
- package/dist/build-mcp.d.ts.map +1 -1
- package/dist/build-mcp.js +64 -4
- package/dist/console-session-routes.d.ts.map +1 -1
- package/dist/console-session-routes.js +11 -0
- package/dist/ggui-session-channel/action-ingress.d.ts +2 -2
- package/dist/ggui-session-channel/action-ingress.d.ts.map +1 -1
- package/dist/ggui-session-channel/channel-subscriptions.d.ts +4 -4
- package/dist/ggui-session-channel/channel-subscriptions.d.ts.map +1 -1
- package/dist/ggui-session-channel/internal-types.d.ts +63 -9
- package/dist/ggui-session-channel/internal-types.d.ts.map +1 -1
- package/dist/ggui-session-channel/outbound.d.ts +15 -5
- package/dist/ggui-session-channel/outbound.d.ts.map +1 -1
- package/dist/ggui-session-channel/outbound.js +64 -24
- package/dist/ggui-session-channel/socket-router.d.ts +8 -3
- package/dist/ggui-session-channel/socket-router.d.ts.map +1 -1
- package/dist/ggui-session-channel/socket-router.js +6 -1
- package/dist/ggui-session-channel/subscribe.d.ts +48 -3
- package/dist/ggui-session-channel/subscribe.d.ts.map +1 -1
- package/dist/ggui-session-channel/subscribe.js +97 -36
- package/dist/ggui-session-channel/subscriber-lifecycle.d.ts +23 -13
- package/dist/ggui-session-channel/subscriber-lifecycle.d.ts.map +1 -1
- package/dist/ggui-session-channel/subscriber-lifecycle.js +24 -11
- package/dist/ggui-session-channel.d.ts +58 -11
- package/dist/ggui-session-channel.d.ts.map +1 -1
- package/dist/ggui-session-channel.js +55 -19
- package/dist/index.d.ts +4 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -1
- package/dist/instructions-presets.js +10 -10
- package/dist/mcp-apps-outbound.d.ts +49 -4
- package/dist/mcp-apps-outbound.d.ts.map +1 -1
- package/dist/mcp-apps-outbound.js +359 -63
- package/dist/mcp-endpoint-routes.d.ts +17 -5
- package/dist/mcp-endpoint-routes.d.ts.map +1 -1
- package/dist/mcp-endpoint-routes.js +2 -0
- package/dist/oauth-as-routes.d.ts.map +1 -1
- package/dist/oauth-as-routes.js +36 -0
- package/dist/oauth.d.ts.map +1 -1
- package/dist/oauth.js +8 -1
- package/dist/runtime-bundle-hash.d.ts +43 -0
- package/dist/runtime-bundle-hash.d.ts.map +1 -0
- package/dist/runtime-bundle-hash.js +66 -0
- package/dist/runtime-bundle-route.js +1 -1
- package/dist/server.d.ts +16 -5
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +93 -19
- package/package.json +12 -12
|
@@ -27,13 +27,13 @@
|
|
|
27
27
|
* The thin shell is static content; it depends on nothing except the
|
|
28
28
|
* MIME constant and the HTML. Keeping it next to the registration
|
|
29
29
|
* means a future refactor of the shell edits one file. The
|
|
30
|
-
* `@ggui-ai/react` package does NOT ship the shell as a separate
|
|
30
|
+
* `@ggui-ai/mcp-apps-react` package does NOT ship the shell as a separate
|
|
31
31
|
* build target — per the design lock, the shell is served by the
|
|
32
32
|
* same `@ggui-ai/mcp-server` instance that mints the bootstrap.
|
|
33
33
|
*/
|
|
34
|
-
import { deriveBundleOrigins, deriveContractBundle, derivePublicEnvProjection, deriveRenderMeta, filterDescriptorsToContract, findBlueprintExact, } from "@ggui-ai/mcp-server-handlers/renders";
|
|
34
|
+
import { deriveBundleOrigins, deriveContractBundle, derivePublicEnvProjection, deriveRenderMeta, filterDescriptorsToContract, findBlueprintExact, spreadRenderMetaViewOntoSlice, wsOriginToHttpOrigin, } from "@ggui-ai/mcp-server-handlers/renders";
|
|
35
35
|
import { RESOURCE_NOT_FOUND_MESSAGE, deriveContextDefault, isRecord, resolveAppGadgets, resourceReadErrorToJsonRpc, } from "@ggui-ai/protocol";
|
|
36
|
-
import { GGUI_RENDER_RESOURCE_MIME, GGUI_RENDER_RESOURCE_URI, GGUI_RENDER_SHELL_SURFACE, MCP_APPS_UI_CAPABILITY, MCP_APP_BOOTSTRAP_FAILED_TYPE, asGguiRenderBootstrap, deriveContextName, escapeInlineScript, gguiShellHtml, toMcpAppEnvelope, } from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
36
|
+
import { GGUI_RENDER_RESOURCE_MIME, GGUI_RENDER_RESOURCE_URI, GGUI_RENDER_SHELL_SURFACE, MCP_APPS_UI_CAPABILITY, MCP_APP_BOOTSTRAP_FAILED_TYPE, asGguiRenderBootstrap, composeSessionApiUrls, deriveContextName, escapeInlineScript, gguiShellHtml, parseEpochUri, toMcpAppEnvelope, } from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
37
37
|
import { ResourceTemplate } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
38
38
|
import { registerAppResource } from "@modelcontextprotocol/ext-apps/server";
|
|
39
39
|
import { createHash } from "node:crypto";
|
|
@@ -150,9 +150,39 @@ var rpcId=1,pending={};
|
|
|
150
150
|
var rootEl=document.getElementById('ggui-root');
|
|
151
151
|
rootEl.style.cssText='display:flex;flex-direction:column;height:100%;min-height:300px;margin:0';
|
|
152
152
|
var mounted=false;
|
|
153
|
+
var lastEnvelope=null;
|
|
154
|
+
// Text color pairs with the shell surface: themed var when the runtime
|
|
155
|
+
// injected theme CSS, else the light-on-dark fallback matching the
|
|
156
|
+
// shell's static #1e293b pre-theme surface. The old hardcoded #666 was
|
|
157
|
+
// illegible on that dark fallback (#481).
|
|
158
|
+
var SHELL_FG='var(--ggui-color-onSurface,#e2e8f0)';
|
|
153
159
|
function setOverlay(text){
|
|
154
160
|
if(mounted)return;
|
|
155
|
-
rootEl.innerHTML='<div style="font:
|
|
161
|
+
rootEl.innerHTML='<div style="font:13px system-ui,sans-serif;padding:24px;color:'+SHELL_FG+';opacity:.55">'+text+'</div>';
|
|
162
|
+
}
|
|
163
|
+
function escText(s){
|
|
164
|
+
return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"');
|
|
165
|
+
}
|
|
166
|
+
// Terminal failure card (#481): plain-language summary, diagnostic
|
|
167
|
+
// reachable but collapsed, Retry only when a retry can actually work.
|
|
168
|
+
// Same visual vocabulary as the runtime's React error boundary so the
|
|
169
|
+
// two error surfaces read as one system.
|
|
170
|
+
function showFailure(summary,detail,retry){
|
|
171
|
+
if(mounted)return;
|
|
172
|
+
rootEl.innerHTML=''+
|
|
173
|
+
'<div style="display:flex;flex-direction:column;align-items:center;justify-content:center;gap:10px;padding:32px 24px;min-height:160px;font-family:system-ui,sans-serif;color:'+SHELL_FG+';text-align:center">'+
|
|
174
|
+
'<div style="font-size:14px;font-weight:600">'+escText(summary)+'</div>'+
|
|
175
|
+
'<div style="font-size:12px;opacity:.65;max-width:320px;line-height:1.45">The interface could not start. The conversation is unaffected — you can also just ask for the view again.</div>'+
|
|
176
|
+
(retry?'<button id="ggui-shell-retry" style="margin-top:2px;padding:7px 18px;border-radius:8px;border:1px solid currentColor;background:transparent;color:inherit;opacity:.75;font:500 13px system-ui,sans-serif;cursor:pointer">Retry</button>':'')+
|
|
177
|
+
'<details style="margin-top:6px;max-width:340px;width:100%;text-align:left;opacity:.75">'+
|
|
178
|
+
'<summary style="cursor:pointer;font-size:12px">Details</summary>'+
|
|
179
|
+
'<pre style="margin:6px 0 0;font:11px/1.5 ui-monospace,Menlo,monospace;white-space:pre-wrap;word-break:break-word">'+escText(detail)+'</pre>'+
|
|
180
|
+
'</details>'+
|
|
181
|
+
'</div>';
|
|
182
|
+
if(retry){
|
|
183
|
+
var b=document.getElementById('ggui-shell-retry');
|
|
184
|
+
if(b)b.onclick=retry;
|
|
185
|
+
}
|
|
156
186
|
}
|
|
157
187
|
function postNotification(method,params){
|
|
158
188
|
try{window.parent.postMessage({jsonrpc:'2.0',method:method,params:params||{}},'*');}catch(e){}
|
|
@@ -183,10 +213,12 @@ async function mountFromMeta(envelope){
|
|
|
183
213
|
var renderSlice=envelope&&envelope['ai.ggui/render'];
|
|
184
214
|
var runtimeUrl=renderSlice&&renderSlice.runtimeUrl;
|
|
185
215
|
if(!envelope||typeof runtimeUrl!=='string'){
|
|
186
|
-
|
|
216
|
+
// No retry: without a valid envelope there is nothing to re-run.
|
|
217
|
+
showFailure('This view could not start','MALFORMED_BOOTSTRAP: bootstrap payload malformed (no ai.ggui/render slice with a runtimeUrl).',null);
|
|
187
218
|
postBootstrapFailed('MALFORMED_BOOTSTRAP','Bootstrap payload malformed.');
|
|
188
219
|
return;
|
|
189
220
|
}
|
|
221
|
+
lastEnvelope=envelope;
|
|
190
222
|
setOverlay('Loading UI…');
|
|
191
223
|
window.__GGUI_META__=envelope;
|
|
192
224
|
// Load the runtime bundle via a direct cross-origin script tag
|
|
@@ -212,14 +244,14 @@ async function mountFromMeta(envelope){
|
|
|
212
244
|
s.onload=function(){mounted=true;};
|
|
213
245
|
s.onerror=function(e){
|
|
214
246
|
var msg='Runtime bundle failed to load: '+(e&&e.message||'script error');
|
|
215
|
-
|
|
247
|
+
showFailure('This view could not load','BUNDLE_FETCH_FAILED: '+msg,function(){mountFromMeta(lastEnvelope);});
|
|
216
248
|
postBootstrapFailed('BUNDLE_FETCH_FAILED',msg);
|
|
217
249
|
};
|
|
218
250
|
rootEl.innerHTML='';
|
|
219
251
|
document.body.appendChild(s);
|
|
220
252
|
}catch(e){
|
|
221
253
|
var msg='Runtime bundle failed to load: '+(e&&e.message||e);
|
|
222
|
-
|
|
254
|
+
showFailure('This view could not load','BUNDLE_FETCH_FAILED: '+msg,function(){mountFromMeta(lastEnvelope);});
|
|
223
255
|
postBootstrapFailed('BUNDLE_FETCH_FAILED',msg);
|
|
224
256
|
}
|
|
225
257
|
}
|
|
@@ -262,26 +294,32 @@ window.addEventListener('message',function(ev){
|
|
|
262
294
|
// above.
|
|
263
295
|
}
|
|
264
296
|
});
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
297
|
+
// Named so the failure card's Retry can re-run the whole handshake —
|
|
298
|
+
// a host that missed or rejected the first ui/initialize may answer a
|
|
299
|
+
// second (observed with hosts that attach their listener late).
|
|
300
|
+
function startInit(){
|
|
301
|
+
setOverlay('Initializing…');
|
|
302
|
+
var initTimer=setTimeout(function(){
|
|
303
|
+
showFailure('This view did not hear back from its host','INIT_TIMEOUT: no response to ui/initialize within 3s.',startInit);
|
|
304
|
+
},3000);
|
|
305
|
+
postRpc('ui/initialize',{
|
|
306
|
+
appCapabilities:{},
|
|
307
|
+
appInfo:{name:'ggui-render',version:'1.0.0'},
|
|
308
|
+
protocolVersion:'2026-01-26'
|
|
309
|
+
}).then(function(){
|
|
310
|
+
clearTimeout(initTimer);
|
|
311
|
+
postNotification('ui/notifications/initialized',{});
|
|
312
|
+
// Wait for the host to send ui/notifications/tool-result carrying
|
|
313
|
+
// the slice envelope in _meta — the spec-canonical delivery channel.
|
|
314
|
+
// The ui/initialize result itself carries no slice meta (the
|
|
315
|
+
// McpUiInitializeResult schema defines no such field).
|
|
316
|
+
setOverlay('Waiting for tool result…');
|
|
317
|
+
}).catch(function(e){
|
|
318
|
+
clearTimeout(initTimer);
|
|
319
|
+
showFailure('This view could not connect to its host','ui/initialize failed: '+(e&&e.message||JSON.stringify(e)),startInit);
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
startInit();
|
|
285
323
|
})();
|
|
286
324
|
`;
|
|
287
325
|
// `--ggui-color-surface` is injected at `:root` on this document's
|
|
@@ -431,9 +469,16 @@ try{
|
|
|
431
469
|
* deliberately untouched.
|
|
432
470
|
*/
|
|
433
471
|
export function buildInlineRenderShellHtml(runtimeSource) {
|
|
472
|
+
// No anchor div: the runtime appends its own mount target to
|
|
473
|
+
// `document.body` at boot, so a thin-shell-style `#ggui-root`
|
|
474
|
+
// placeholder here would just stack empty space ABOVE the rendered
|
|
475
|
+
// card (min-height'd blank div + content below it — the "long upper
|
|
476
|
+
// space" bug from the first claude.ai live test). Same
|
|
477
|
+
// no-container posture as `gguiShellHtml`; the shell marker rides
|
|
478
|
+
// on `<body>`.
|
|
434
479
|
return `<!doctype html>
|
|
435
|
-
<html lang="en" style="
|
|
436
|
-
<body style="margin:0;
|
|
480
|
+
<html lang="en" style="background-color:${GGUI_RENDER_SHELL_SURFACE}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="light dark"><title>ggui render</title></head>
|
|
481
|
+
<body style="margin:0;background-color:${GGUI_RENDER_SHELL_SURFACE}" data-ggui-shell="inline">
|
|
437
482
|
<script>${GGUI_INLINE_SHELL_BUFFER_SCRIPT_BODY}</script>
|
|
438
483
|
<script type="module" data-ggui-runtime="inline">${escapeInlineScript(runtimeSource)}</script></body></html>`;
|
|
439
484
|
}
|
|
@@ -483,7 +528,17 @@ function buildCspMeta(publicBaseUrl,
|
|
|
483
528
|
* references `:6786/_ggui/iframe-runtime.js`) trips a `script-src`
|
|
484
529
|
* violation that blanks the iframe — verified live 2026-05-27.
|
|
485
530
|
*/
|
|
486
|
-
runtimeUrl
|
|
531
|
+
runtimeUrl,
|
|
532
|
+
/**
|
|
533
|
+
* Origins of server-stamped fetch/stream URLs (`sseUrl`,
|
|
534
|
+
* `pollingUrl`) — each parseable entry's origin is unioned into
|
|
535
|
+
* `connectDomains` (deduplicated). Same-origin deployments add
|
|
536
|
+
* nothing new; split-origin session APIs (dedicated streaming host)
|
|
537
|
+
* would otherwise be silently blocked by `connect-src` on
|
|
538
|
+
* spec-compliant hosts — EventSource and fetch are both
|
|
539
|
+
* connect-src-governed.
|
|
540
|
+
*/
|
|
541
|
+
extraConnectUrls) {
|
|
487
542
|
const source = publicBaseUrl ?? runtimeUrl;
|
|
488
543
|
if (!source)
|
|
489
544
|
return undefined;
|
|
@@ -492,10 +547,26 @@ runtimeUrl) {
|
|
|
492
547
|
const origin = parsed.origin;
|
|
493
548
|
const wsScheme = parsed.protocol === "https:" ? "wss:" : "ws:";
|
|
494
549
|
const wsOrigin = `${wsScheme}//${parsed.host}`;
|
|
550
|
+
const connectDomains = [origin, wsOrigin];
|
|
551
|
+
for (const url of extraConnectUrls ?? []) {
|
|
552
|
+
if (url === undefined)
|
|
553
|
+
continue;
|
|
554
|
+
let extraOrigin;
|
|
555
|
+
try {
|
|
556
|
+
extraOrigin = new URL(url).origin;
|
|
557
|
+
}
|
|
558
|
+
catch {
|
|
559
|
+
// Unparseable stamped URL — nothing to declare for it; the
|
|
560
|
+
// base declaration stands.
|
|
561
|
+
continue;
|
|
562
|
+
}
|
|
563
|
+
if (!connectDomains.includes(extraOrigin))
|
|
564
|
+
connectDomains.push(extraOrigin);
|
|
565
|
+
}
|
|
495
566
|
return {
|
|
496
567
|
ui: {
|
|
497
568
|
csp: {
|
|
498
|
-
connectDomains
|
|
569
|
+
connectDomains,
|
|
499
570
|
resourceDomains: [origin],
|
|
500
571
|
},
|
|
501
572
|
},
|
|
@@ -518,21 +589,53 @@ export function registerGguiRenderResource(server, shellHtml = GGUI_RENDER_SHELL
|
|
|
518
589
|
* declaration at all and spec-compliant hosts applied the
|
|
519
590
|
* restrictive default (`connect-src 'none'`).
|
|
520
591
|
*/
|
|
521
|
-
runtimeUrl
|
|
522
|
-
|
|
592
|
+
runtimeUrl,
|
|
593
|
+
/**
|
|
594
|
+
* Additional URLs whose origins the mounted iframe must be able to
|
|
595
|
+
* `connect-src` — unioned into `connectDomains` by
|
|
596
|
+
* {@link buildCspMeta}. The load-bearing entries are the live-channel
|
|
597
|
+
* origins (`wsUrl` + its ws→http origin flip): the STATIC shell is
|
|
598
|
+
* the resource cross-origin hosts (claude.ai) mount and derive the
|
|
599
|
+
* frame CSP from, so origins declared only on per-render resources
|
|
600
|
+
* never reach the frame. Without these, deployments that set no
|
|
601
|
+
* `publicBaseUrl` (the cloud pod — it feeds Origin/Host enforcement)
|
|
602
|
+
* declare only the runtime-CDN origin and every SSE / HTTP-polling /
|
|
603
|
+
* WS rung of the failover ladder is CSP-blocked in the mounted
|
|
604
|
+
* iframe — observed live on claude.ai (#471 round 11: frame booted
|
|
605
|
+
* with `connect-src assets.mcp.ggui.ai` only).
|
|
606
|
+
*/
|
|
607
|
+
extraConnectUrls) {
|
|
608
|
+
const cspMeta = buildCspMeta(publicBaseUrl, runtimeUrl, extraConnectUrls);
|
|
609
|
+
// Content-addressed shell URI (2026-08-12, the stale-shell bust).
|
|
610
|
+
// Hosts cache the prefetched shell keyed on the RESOURCE URI —
|
|
611
|
+
// claude.ai's backend was observed serving days-old shell bytes
|
|
612
|
+
// across our deploys, fresh pages, and connector re-connects,
|
|
613
|
+
// because `ui://ggui/render` never changes. Hash the FULL SERVED
|
|
614
|
+
// REPRESENTATION — shell bytes (wrapper + any inlined runtime) AND
|
|
615
|
+
// the `_meta.ui.csp` declaration — into the advertised URI so any
|
|
616
|
+
// change a host may have cached mints a NEW URI, and an unchanged
|
|
617
|
+
// one never does; the same content-address discipline the hashed
|
|
618
|
+
// `/_ggui/iframe-runtime.<sha12>.js` HTTP route applies one layer
|
|
619
|
+
// down. The meta MUST be in the hash input: hosts cache the
|
|
620
|
+
// declaration alongside the bytes (claude.ai derives the frame's
|
|
621
|
+
// connect-src from it), so a meta-only change — e.g. adding the
|
|
622
|
+
// live-channel origins to `connectDomains` — would otherwise ship a
|
|
623
|
+
// new policy under an old URI and never reach cached frames. The
|
|
624
|
+
// bare URI stays registered for grandfathered sessions and hosts
|
|
625
|
+
// that read it directly.
|
|
626
|
+
const shellHash = createHash("sha256")
|
|
627
|
+
.update(shellHtml)
|
|
628
|
+
.update(JSON.stringify(cspMeta ?? null))
|
|
629
|
+
.digest("hex")
|
|
630
|
+
.slice(0, 12);
|
|
631
|
+
const versionedUri = `${GGUI_RENDER_RESOURCE_URI}/rt-${shellHash}`;
|
|
523
632
|
// `registerAppResource` (from `@modelcontextprotocol/ext-apps/server`)
|
|
524
633
|
// defaults `mimeType` to `RESOURCE_MIME_TYPE` — the same
|
|
525
634
|
// `text/html;profile=mcp-app` value `GGUI_RENDER_RESOURCE_MIME`
|
|
526
635
|
// carries. Letting the canonical helper own the default means the
|
|
527
636
|
// mimeType string lives in ONE place across the ecosystem (the SDK)
|
|
528
637
|
// rather than duplicated in our protocol package.
|
|
529
|
-
|
|
530
|
-
// `title` / `description` show up in MCP clients that surface
|
|
531
|
-
// resource metadata. Short + concrete.
|
|
532
|
-
title: "ggui render",
|
|
533
|
-
description: "Thin-shell iframe bundle that bootstraps a ggui render. MCP Apps hosts fetch this when they see `_meta.ui.resourceUri` on a ggui_render result.",
|
|
534
|
-
mimeType: GGUI_RENDER_RESOURCE_MIME,
|
|
535
|
-
}, async (uri) => ({
|
|
638
|
+
const serveShell = async (uri) => ({
|
|
536
639
|
contents: [
|
|
537
640
|
{
|
|
538
641
|
uri: uri.href,
|
|
@@ -541,7 +644,44 @@ runtimeUrl) {
|
|
|
541
644
|
...(cspMeta !== undefined ? { _meta: cspMeta } : {}),
|
|
542
645
|
},
|
|
543
646
|
],
|
|
544
|
-
})
|
|
647
|
+
});
|
|
648
|
+
registerAppResource(server, "ggui-render", GGUI_RENDER_RESOURCE_URI, {
|
|
649
|
+
// `title` / `description` show up in MCP clients that surface
|
|
650
|
+
// resource metadata. Short + concrete.
|
|
651
|
+
title: "ggui render",
|
|
652
|
+
description: "Thin-shell iframe bundle that bootstraps a ggui render. MCP Apps hosts fetch this when they see `_meta.ui.resourceUri` on a ggui_render result.",
|
|
653
|
+
mimeType: GGUI_RENDER_RESOURCE_MIME,
|
|
654
|
+
}, serveShell);
|
|
655
|
+
registerAppResource(server, "ggui-render-versioned", versionedUri, {
|
|
656
|
+
title: "ggui render (content-addressed)",
|
|
657
|
+
description: "Content-addressed twin of ui://ggui/render — the URI embeds the shell-bytes hash so host prefetch caches miss exactly when the shell changed. Tool declarations advertise THIS URI.",
|
|
658
|
+
mimeType: GGUI_RENDER_RESOURCE_MIME,
|
|
659
|
+
}, serveShell);
|
|
660
|
+
// STALE-HASH grandfather template — `rt-{shellHash}` for ANY hash.
|
|
661
|
+
// Hosts snapshot tool declarations (claude.ai stores the connector's
|
|
662
|
+
// tool list server-side), so after a shell-changing deploy they keep
|
|
663
|
+
// asking for the PREVIOUS deploy's versioned URI. Without this
|
|
664
|
+
// template that read falls through to the per-session
|
|
665
|
+
// `ui://ggui/render/{sessionId}` template (a bare `rt-abc…` segment
|
|
666
|
+
// parses as a sessionId), resolves no render, and the host shows
|
|
667
|
+
// "unable to reach" — observed live on claude.ai the first deploy
|
|
668
|
+
// after the URI scheme changed (#471 round 12). Serving the CURRENT
|
|
669
|
+
// shell under the stale URI restores the pre-content-addressing
|
|
670
|
+
// behavior for stale hosts (at worst they cache today's shell under
|
|
671
|
+
// yesterday's key) while fresh declarations keep the cache-bust
|
|
672
|
+
// property. MUST register before the session templates
|
|
673
|
+
// (`installMcpAppsOutbound` orders this call first; the SDK matches
|
|
674
|
+
// templates in registration order).
|
|
675
|
+
server.registerResource("ggui-render-versioned-grandfather", new ResourceTemplate(`${GGUI_RENDER_RESOURCE_URI}/rt-{shellHash}`, {
|
|
676
|
+
// No list-callback — same posture as the session templates; the
|
|
677
|
+
// canonical URI is the one advertised on tool declarations.
|
|
678
|
+
list: undefined,
|
|
679
|
+
}), {
|
|
680
|
+
title: "ggui render (content-addressed, any revision)",
|
|
681
|
+
description: "Grandfather route for content-addressed shell URIs from earlier deploys — hosts holding a stale tool-declaration snapshot read their old rt-<hash> URI and receive the CURRENT shell.",
|
|
682
|
+
mimeType: GGUI_RENDER_RESOURCE_MIME,
|
|
683
|
+
}, serveShell);
|
|
684
|
+
return versionedUri;
|
|
545
685
|
}
|
|
546
686
|
/**
|
|
547
687
|
* Advertise the `io.modelcontextprotocol/ui` extension capability on
|
|
@@ -650,7 +790,11 @@ export function buildSelfContainedShell(opts) {
|
|
|
650
790
|
// WS-only mode (legacy behavior). See SelfContainedShellInputs
|
|
651
791
|
// .pollingUrl for the URL shape.
|
|
652
792
|
...(opts.pollingUrl !== undefined ? { pollingUrl: opts.pollingUrl } : {}),
|
|
793
|
+
// SSE middle rung — same stamping posture as pollingUrl. See
|
|
794
|
+
// SelfContainedShellInputs.sseUrl for the stream contract.
|
|
795
|
+
...(opts.sseUrl !== undefined ? { sseUrl: opts.sseUrl } : {}),
|
|
653
796
|
...(opts.lastSequence !== undefined ? { lastSequence: opts.lastSequence } : {}),
|
|
797
|
+
...(opts.epoch !== undefined ? { epoch: opts.epoch } : {}),
|
|
654
798
|
// Visible-bits surface — what the iframe is mounting right now.
|
|
655
799
|
// Static-content discriminators (codeUrl / kind) are mutually
|
|
656
800
|
// exclusive; the iframe-runtime rejects the both-set mix.
|
|
@@ -959,18 +1103,24 @@ export function registerGguiRenderResourceTemplate(server, opts) {
|
|
|
959
1103
|
* claude.ai's iframe CSP and the component fails to render. Returns
|
|
960
1104
|
* `undefined` when there's no base CSP at all (publicBaseUrl
|
|
961
1105
|
* absent — first-party same-origin host).
|
|
1106
|
+
*
|
|
1107
|
+
* `base` defaults to the registration-time `templateCspMeta`;
|
|
1108
|
+
* `serveMount` passes a per-render base recomputed with the stamped
|
|
1109
|
+
* session-API URLs (`sseUrl` / `pollingUrl`) so their origins ride
|
|
1110
|
+
* `connectDomains` even when they differ from the publicBaseUrl
|
|
1111
|
+
* origin (ws→http origin-flip fallback).
|
|
962
1112
|
*/
|
|
963
|
-
const augmentCspMeta = (gadgetOrigins) => {
|
|
964
|
-
if (
|
|
1113
|
+
const augmentCspMeta = (gadgetOrigins, base = templateCspMeta) => {
|
|
1114
|
+
if (base === undefined)
|
|
965
1115
|
return undefined;
|
|
966
1116
|
if (gadgetOrigins === undefined)
|
|
967
|
-
return
|
|
1117
|
+
return base;
|
|
968
1118
|
return {
|
|
969
1119
|
ui: {
|
|
970
1120
|
csp: {
|
|
971
|
-
connectDomains: [...
|
|
1121
|
+
connectDomains: [...base.ui.csp.connectDomains, ...gadgetOrigins.connect],
|
|
972
1122
|
resourceDomains: [
|
|
973
|
-
...
|
|
1123
|
+
...base.ui.csp.resourceDomains,
|
|
974
1124
|
...gadgetOrigins.script,
|
|
975
1125
|
...gadgetOrigins.style,
|
|
976
1126
|
],
|
|
@@ -1476,6 +1626,20 @@ export function registerGguiRenderResourceTemplate(server, opts) {
|
|
|
1476
1626
|
channelFault ??= { cause };
|
|
1477
1627
|
}
|
|
1478
1628
|
}
|
|
1629
|
+
// Token-bearing session-API URL pair (pollingUrl + sseUrl) —
|
|
1630
|
+
// composed via the protocol's ONE composer so this surface cannot
|
|
1631
|
+
// drift from the render/update resultMeta stamping. Stamped only
|
|
1632
|
+
// when the mint above produced a token (both URLs embed it); base
|
|
1633
|
+
// = publicBaseUrl when configured, else the ws→http origin flip
|
|
1634
|
+
// of the minted wsUrl (session API served on the WS origin — OSS
|
|
1635
|
+
// defaults + the cloud pod's single ingress).
|
|
1636
|
+
let sessionApiUrls;
|
|
1637
|
+
if (wsToken !== undefined) {
|
|
1638
|
+
const base = opts.publicBaseUrl ?? (wsUrl !== undefined ? wsOriginToHttpOrigin(wsUrl) : undefined);
|
|
1639
|
+
if (base !== undefined) {
|
|
1640
|
+
sessionApiUrls = composeSessionApiUrls(base, sessionId, wsToken);
|
|
1641
|
+
}
|
|
1642
|
+
}
|
|
1479
1643
|
// Mount-mode gate (below the live-channel mint): a compiled
|
|
1480
1644
|
// component needs ONE of the two channels. A deployment that wires
|
|
1481
1645
|
// no codeStore (codeUrl === undefined) but DOES wire mintWsToken
|
|
@@ -1532,24 +1696,23 @@ export function registerGguiRenderResourceTemplate(server, opts) {
|
|
|
1532
1696
|
: {}),
|
|
1533
1697
|
...(opts.themeId !== undefined ? { themeId: opts.themeId } : {}),
|
|
1534
1698
|
...(opts.themeMode !== undefined ? { themeMode: opts.themeMode } : {}),
|
|
1535
|
-
//
|
|
1536
|
-
//
|
|
1537
|
-
// resource-served
|
|
1538
|
-
|
|
1539
|
-
...(view
|
|
1540
|
-
...(view.contextSlots !== undefined ? { contextSlots: view.contextSlots } : {}),
|
|
1541
|
-
...(view.permissionsPolicy !== undefined
|
|
1542
|
-
? { permissionsPolicy: view.permissionsPolicy }
|
|
1543
|
-
: {}),
|
|
1544
|
-
...(view.gadgets !== undefined && view.gadgets.length > 0
|
|
1545
|
-
? { gadgets: view.gadgets }
|
|
1546
|
-
: {}),
|
|
1699
|
+
// State + policy view fields (theme overlay, propsJson,
|
|
1700
|
+
// contextSlots, permissionsPolicy, gadgets, #483 epoch) — ONE
|
|
1701
|
+
// shared spread so the resource-served shell cannot drift from
|
|
1702
|
+
// the postMessage-path emitters.
|
|
1703
|
+
...spreadRenderMetaViewOntoSlice(view),
|
|
1547
1704
|
...(contractHash !== undefined && validatorsUrl !== undefined
|
|
1548
1705
|
? { contractHash, validatorsUrl }
|
|
1549
1706
|
: {}),
|
|
1550
1707
|
...(resourcePublicEnv !== undefined && Object.keys(resourcePublicEnv).length > 0
|
|
1551
1708
|
? { publicEnv: resourcePublicEnv }
|
|
1552
1709
|
: {}),
|
|
1710
|
+
// Token-bearing HTTP fallback rungs — present exactly when the
|
|
1711
|
+
// mint above produced a token and a base resolved (see the
|
|
1712
|
+
// composition above the mount-mode gate).
|
|
1713
|
+
...(sessionApiUrls !== undefined
|
|
1714
|
+
? { pollingUrl: sessionApiUrls.pollingUrl, sseUrl: sessionApiUrls.sseUrl }
|
|
1715
|
+
: {}),
|
|
1553
1716
|
// R6 — ledger cursor stamp for polling-cursor alignment.
|
|
1554
1717
|
lastSequence: accessibleStored.eventSequence,
|
|
1555
1718
|
});
|
|
@@ -1563,21 +1726,121 @@ export function registerGguiRenderResourceTemplate(server, opts) {
|
|
|
1563
1726
|
// derives these via deriveBundleOrigins; this is the per-call
|
|
1564
1727
|
// resource mirror.
|
|
1565
1728
|
const gadgetOrigins = deriveBundleOrigins(picked.source);
|
|
1566
|
-
|
|
1729
|
+
// Per-render CSP base: recompute with the stamped session-API
|
|
1730
|
+
// URLs so their origins ride `connectDomains` (EventSource +
|
|
1731
|
+
// fetch are connect-src-governed). Same-origin stamps dedupe to
|
|
1732
|
+
// the registration-time declaration; a base derived from the
|
|
1733
|
+
// wsUrl origin flip (publicBaseUrl absent) adds the flip origin
|
|
1734
|
+
// that would otherwise be silently blocked.
|
|
1735
|
+
const renderCspBase = sessionApiUrls !== undefined
|
|
1736
|
+
? buildCspMeta(opts.publicBaseUrl, opts.runtimeUrl, [
|
|
1737
|
+
sessionApiUrls.sseUrl,
|
|
1738
|
+
sessionApiUrls.pollingUrl,
|
|
1739
|
+
])
|
|
1740
|
+
: templateCspMeta;
|
|
1741
|
+
return shellContents(uri, html, augmentCspMeta(gadgetOrigins, renderCspBase));
|
|
1742
|
+
}
|
|
1743
|
+
/**
|
|
1744
|
+
* Reconstruct the props of history record `#epoch` from the event
|
|
1745
|
+
* ledger (#483): walk ascending, apply every `ui.updated`, and stop
|
|
1746
|
+
* at the `ui.reminted` boundary that LEAVES the pinned epoch
|
|
1747
|
+
* (`data.epoch === epoch + 1`) — so the record includes the amends
|
|
1748
|
+
* made during its reign, matching the live freeze semantics
|
|
1749
|
+
* (state-at-supersession). Returns `null` when the walk cannot reach
|
|
1750
|
+
* the boundary (ledger horizon evicted the record's reign) — the
|
|
1751
|
+
* caller surfaces the standard not-found posture; the record aged
|
|
1752
|
+
* out of what this server can serve.
|
|
1753
|
+
*/
|
|
1754
|
+
async function reconstructPropsAtEpoch(sessionId, epoch) {
|
|
1755
|
+
let since = 0;
|
|
1756
|
+
let currentProps = null;
|
|
1757
|
+
for (;;) {
|
|
1758
|
+
const page = await opts.renderStore.listEventsSince(sessionId, since, 200);
|
|
1759
|
+
if (page === null || page.events.length === 0)
|
|
1760
|
+
return null;
|
|
1761
|
+
for (const event of page.events) {
|
|
1762
|
+
if (event.type === "ui.updated") {
|
|
1763
|
+
const data = event.data;
|
|
1764
|
+
// Epoch-stamped filtering: the update that MINTS epoch N+1
|
|
1765
|
+
// appends its props event (stamped N+1) BEFORE the N+1
|
|
1766
|
+
// boundary — those props belong to the NEXT record, never
|
|
1767
|
+
// to #N. Pre-#483 events carry no stamp and read as
|
|
1768
|
+
// belonging to the then-current (≤ pinned) epoch.
|
|
1769
|
+
if ((data.epoch ?? 0) <= epoch) {
|
|
1770
|
+
currentProps = data.props;
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
else if (event.type === "ui.reminted") {
|
|
1774
|
+
const data = event.data;
|
|
1775
|
+
if (data.epoch === epoch + 1)
|
|
1776
|
+
return currentProps;
|
|
1777
|
+
}
|
|
1778
|
+
since = event.seq;
|
|
1779
|
+
}
|
|
1780
|
+
if (!page.hasMore && page.lastSequence <= since)
|
|
1781
|
+
return null;
|
|
1782
|
+
}
|
|
1567
1783
|
}
|
|
1568
1784
|
// Single shared handler powers both templates. `blueprintKey` is
|
|
1569
1785
|
// optional in the variables map — present for the resume URI shape,
|
|
1570
1786
|
// absent for the legacy single-segment shape.
|
|
1571
1787
|
async function handle(uri, variables) {
|
|
1572
1788
|
const sessionIdRaw = variables["sessionId"];
|
|
1573
|
-
|
|
1789
|
+
let sessionId = Array.isArray(sessionIdRaw) ? sessionIdRaw[0] : sessionIdRaw;
|
|
1790
|
+
const blueprintKeyRaw = variables["blueprintKey"];
|
|
1791
|
+
let blueprintKey = Array.isArray(blueprintKeyRaw) ? blueprintKeyRaw[0] : blueprintKeyRaw;
|
|
1792
|
+
// Epoch pin (#483): `…#N` names the immutable history record N;
|
|
1793
|
+
// bare names the live head. Depending on the transport's URL
|
|
1794
|
+
// handling the pin may arrive as `uri.hash`, glued RAW onto the
|
|
1795
|
+
// last matched variable, or PERCENT-ENCODED inside it (`%23N`) —
|
|
1796
|
+
// resolve all three tolerantly via the one seam, cleaning the
|
|
1797
|
+
// variable either way.
|
|
1798
|
+
const parsePin = (segment) => {
|
|
1799
|
+
const direct = parseEpochUri(segment);
|
|
1800
|
+
if (direct.epoch !== undefined) {
|
|
1801
|
+
return { base: direct.baseUri, epoch: direct.epoch };
|
|
1802
|
+
}
|
|
1803
|
+
try {
|
|
1804
|
+
const decoded = decodeURIComponent(segment);
|
|
1805
|
+
if (decoded !== segment) {
|
|
1806
|
+
const parsed = parseEpochUri(decoded);
|
|
1807
|
+
if (parsed.epoch !== undefined) {
|
|
1808
|
+
return { base: parsed.baseUri, epoch: parsed.epoch };
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
}
|
|
1812
|
+
catch {
|
|
1813
|
+
// Malformed percent-encoding — not a pin; segment passes
|
|
1814
|
+
// through whole (same tolerant posture as parseEpochUri).
|
|
1815
|
+
}
|
|
1816
|
+
return { base: segment };
|
|
1817
|
+
};
|
|
1818
|
+
// ALWAYS clean the variables (transports have been observed to
|
|
1819
|
+
// deliver the pin BOTH as uri.hash and glued raw onto the matched
|
|
1820
|
+
// variable); the pin resolves from whichever source carried it.
|
|
1821
|
+
let pinnedEpoch;
|
|
1822
|
+
if (uri.hash.length > 1) {
|
|
1823
|
+
pinnedEpoch = parseEpochUri(`x${uri.hash}`).epoch;
|
|
1824
|
+
}
|
|
1825
|
+
if (typeof blueprintKey === "string") {
|
|
1826
|
+
const parsed = parsePin(blueprintKey);
|
|
1827
|
+
if (parsed.epoch !== undefined) {
|
|
1828
|
+
pinnedEpoch = pinnedEpoch ?? parsed.epoch;
|
|
1829
|
+
blueprintKey = parsed.base;
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
if (typeof sessionId === "string") {
|
|
1833
|
+
const parsed = parsePin(sessionId);
|
|
1834
|
+
if (parsed.epoch !== undefined) {
|
|
1835
|
+
pinnedEpoch = pinnedEpoch ?? parsed.epoch;
|
|
1836
|
+
sessionId = parsed.base;
|
|
1837
|
+
}
|
|
1838
|
+
}
|
|
1574
1839
|
if (typeof sessionId !== "string" || sessionId.length === 0) {
|
|
1575
1840
|
// A URI with no session segment names no locator, which is the
|
|
1576
1841
|
// same thing as naming one that does not exist.
|
|
1577
1842
|
throw new ResourceReadFailure(NOT_FOUND_FAILURE);
|
|
1578
1843
|
}
|
|
1579
|
-
const blueprintKeyRaw = variables["blueprintKey"];
|
|
1580
|
-
const blueprintKey = Array.isArray(blueprintKeyRaw) ? blueprintKeyRaw[0] : blueprintKeyRaw;
|
|
1581
1844
|
const hasResumeKey = typeof blueprintKey === "string" && blueprintKey.length > 0;
|
|
1582
1845
|
// The failure this read ends in if nothing mounts. Seeded from a
|
|
1583
1846
|
// property of the SERVER, never of the locator, so a caller cannot
|
|
@@ -1610,6 +1873,38 @@ export function registerGguiRenderResourceTemplate(server, opts) {
|
|
|
1610
1873
|
})
|
|
1611
1874
|
? stored
|
|
1612
1875
|
: null;
|
|
1876
|
+
// Pinned history read (#483): `#N` where N is a SUPERSEDED epoch
|
|
1877
|
+
// reconstructs that record's props from the ledger and serves a
|
|
1878
|
+
// shell frozen at them. N === head falls through to the live
|
|
1879
|
+
// mount (the pinned URI of the current head IS the head); N >
|
|
1880
|
+
// head names a record that does not exist.
|
|
1881
|
+
if (accessibleStored && pinnedEpoch !== undefined) {
|
|
1882
|
+
const headEpoch = accessibleStored.render.epoch ?? 0;
|
|
1883
|
+
if (pinnedEpoch > headEpoch) {
|
|
1884
|
+
throw new ResourceReadFailure(NOT_FOUND_FAILURE);
|
|
1885
|
+
}
|
|
1886
|
+
if (pinnedEpoch < headEpoch && accessibleStored.render.type !== "mcpApps") {
|
|
1887
|
+
const historicalProps = await reconstructPropsAtEpoch(sessionId, pinnedEpoch);
|
|
1888
|
+
if (historicalProps === null) {
|
|
1889
|
+
// The record's reign aged out of the ledger horizon — this
|
|
1890
|
+
// server can no longer serve it. Same terminal posture as a
|
|
1891
|
+
// locator that never existed (see #483 SPEC note).
|
|
1892
|
+
throw new ResourceReadFailure(failure);
|
|
1893
|
+
}
|
|
1894
|
+
const pinnedRow = {
|
|
1895
|
+
...accessibleStored,
|
|
1896
|
+
render: {
|
|
1897
|
+
...accessibleStored.render,
|
|
1898
|
+
props: historicalProps,
|
|
1899
|
+
epoch: pinnedEpoch,
|
|
1900
|
+
},
|
|
1901
|
+
};
|
|
1902
|
+
const served = await serveMount(uri, sessionId, pinnedRow);
|
|
1903
|
+
if (served !== null)
|
|
1904
|
+
return served;
|
|
1905
|
+
throw new ResourceReadFailure(failure);
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1613
1908
|
// Live state first: render present and renderable mounts with the
|
|
1614
1909
|
// current props + current contextSpec values.
|
|
1615
1910
|
if (accessibleStored) {
|
|
@@ -1797,8 +2092,9 @@ export function installMcpAppsOutbound(server, opts = {}) {
|
|
|
1797
2092
|
// static registration's CSP-declaration fallback — deployments that
|
|
1798
2093
|
// set no `publicBaseUrl` (it also feeds Origin/Host enforcement +
|
|
1799
2094
|
// OAuth) still declare their origin to spec-compliant hosts.
|
|
1800
|
-
registerGguiRenderResource(server, opts.shellHtml, opts.publicBaseUrl, opts.selfContained?.runtimeUrl);
|
|
2095
|
+
const shellResourceUri = registerGguiRenderResource(server, opts.shellHtml, opts.publicBaseUrl, opts.selfContained?.runtimeUrl, opts.extraConnectUrls);
|
|
1801
2096
|
if (opts.selfContained) {
|
|
1802
2097
|
registerGguiRenderResourceTemplate(server, opts.selfContained);
|
|
1803
2098
|
}
|
|
2099
|
+
return { shellResourceUri };
|
|
1804
2100
|
}
|
|
@@ -46,6 +46,22 @@ interface PerAppRouting {
|
|
|
46
46
|
readonly pathPrefix?: string;
|
|
47
47
|
readonly authorize?: (urlAppId: string, identity: AuthResult) => Promise<void>;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* Return shape for an `errorMapper` hook — a domain error mapped onto
|
|
51
|
+
* an HTTP/JSON-RPC response triple, with optional response headers.
|
|
52
|
+
*
|
|
53
|
+
* `headers` is deliberately generic HTTP plumbing (e.g. `Retry-After`
|
|
54
|
+
* on a `503`), not a deployment-specific concept — any operator
|
|
55
|
+
* mapping a domain error to a status code that conventionally carries
|
|
56
|
+
* a header can use it.
|
|
57
|
+
*/
|
|
58
|
+
export interface ErrorMapperResult {
|
|
59
|
+
readonly status: number;
|
|
60
|
+
readonly code: number;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
/** Response headers to set before the JSON body is written. */
|
|
63
|
+
readonly headers?: Readonly<Record<string, string>>;
|
|
64
|
+
}
|
|
49
65
|
interface MountOptions {
|
|
50
66
|
/** Express app to mount onto. */
|
|
51
67
|
readonly app: Express;
|
|
@@ -79,11 +95,7 @@ interface MountOptions {
|
|
|
79
95
|
/** Operator-configured issuer URL override (OAuth). */
|
|
80
96
|
readonly oauthIssuerUrl?: string;
|
|
81
97
|
/** Operator-supplied error → HTTP/JSON-RPC mapping hook. */
|
|
82
|
-
readonly errorMapper?: (err: unknown) =>
|
|
83
|
-
readonly status: number;
|
|
84
|
-
readonly code: number;
|
|
85
|
-
readonly message: string;
|
|
86
|
-
} | undefined;
|
|
98
|
+
readonly errorMapper?: (err: unknown) => ErrorMapperResult | undefined;
|
|
87
99
|
/**
|
|
88
100
|
* Per-boot `buildMcpServer` options. Assembled once by the composer
|
|
89
101
|
* (every input is fixed at composition time); the handler spreads a
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-endpoint-routes.d.ts","sourceRoot":"","sources":["../src/mcp-endpoint-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElF,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAEvC,OAAO,EAAkB,KAAK,qBAAqB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM7F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,sFAAsF;AACtF,UAAU,aAAa;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED,UAAU,YAAY;IACpB,iCAAiC;IACjC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAC1E;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IACjF,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAChD,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAChD,qDAAqD;IACrD,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC;IAC3D,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,
|
|
1
|
+
{"version":3,"file":"mcp-endpoint-routes.d.ts","sourceRoot":"","sources":["../src/mcp-endpoint-routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AACxE,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAElF,OAAO,KAAK,EAAE,OAAO,EAAqB,MAAM,SAAS,CAAC;AAC1D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,KAAK,CAAC;AAEvC,OAAO,EAAkB,KAAK,qBAAqB,EAAE,KAAK,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAM7F,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAGlD,sFAAsF;AACtF,UAAU,aAAa;IACrB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAChF;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,+DAA+D;IAC/D,QAAQ,CAAC,OAAO,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;CACrD;AAED,UAAU,YAAY;IACpB,iCAAiC;IACjC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,iEAAiE;IACjE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,yDAAyD;IACzD,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,uEAAuE;IACvE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC;IAC1B,+EAA+E;IAC/E,QAAQ,CAAC,QAAQ,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IAC1E;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;IACjF,sEAAsE;IACtE,QAAQ,CAAC,WAAW,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IAChD,sEAAsE;IACtE,QAAQ,CAAC,GAAG,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAC;IAChD,qDAAqD;IACrD,QAAQ,CAAC,iBAAiB,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,MAAM,CAAC;IAC3D,wEAAwE;IACxE,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,sEAAsE;IACtE,QAAQ,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IACvC,iEAAiE;IACjE,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC;IAC/B,uDAAuD;IACvD,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IACjC,4DAA4D;IAC5D,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,iBAAiB,GAAG,SAAS,CAAC;IACvE;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,qBAAqB,CAAC;CACjD;AAyBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,CA2U1D"}
|