@ggui-ai/mcp-server 0.12.0 → 0.13.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.
|
@@ -37,7 +37,7 @@ import { type McpAppAiGguiRenderMeta } from "@ggui-ai/protocol/integrations/mcp-
|
|
|
37
37
|
import { type McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
38
38
|
import type { HandlerContext } from "@ggui-ai/mcp-server-handlers";
|
|
39
39
|
import type { Logger } from "./logger.js";
|
|
40
|
-
export declare const GGUI_RENDER_SHELL_HTML = "<!doctype html>\n<html lang=\"en\" style=\"height:100%;background-color:var(--ggui-shell-background, var(--ggui-color-surface, #1e293b))\"><head><meta charset=\"utf-8\"><title>ggui render</title></head>\n<body style=\"margin:0;height:100%;min-height:480px;background-color:var(--ggui-shell-background, var(--ggui-color-surface, #1e293b))\"><div id=\"ggui-root\" data-ggui-shell=\"thin\" style=\"height:100%;min-height:480px\"></div>\n<script>\n(function(){'use strict';\n// MCP Apps shell. Speaks the canonical postMessage protocol from\n// @modelcontextprotocol/ext-apps:\n// 1. iframe -> host: ui/initialize\n// 2. iframe -> host: ui/notifications/initialized\n// 3. host -> iframe: ui/notifications/tool-result (per CallToolResult)\n// On tool-result, read the slice envelope from _meta (spec-canonical\n// CallToolResult _meta at the top level), set window.__GGUI_META__ to\n// the envelope, fetch runtime as blob, inject as script.\n// Runtime auto-mounts inline. No nested iframe (claudemcpcontent.com\n// CSP frame-src forbids cross-origin frames). State machine matches\n// buildSelfContainedShell so the same runtime mounts both paths.\n//\n// R5 (2026-05-26): the historic /r/<shortCode> HTTP fallback was\n// removed along with the bearer-by-obscurity model -- hosts that strip\n// _meta no longer have a recovery path here. Spec-canonical hosts\n// deliver _meta inline and are unaffected.\n//\n// Phase B (2026-05-27): the historic two-slice envelope\n// (`ai.ggui/session` + `ai.ggui/stack-item`) collapsed to ONE flat\n// `ai.ggui/render` slice. runtimeUrl now lives directly on the\n// render slice; sessionId is the canonical identity.\nvar rpcId=1,pending={};\nvar rootEl=document.getElementById('ggui-root');\nrootEl.style.cssText='display:flex;flex-direction:column;height:100%;min-height:300px;margin:0';\nvar mounted=false;\nvar lastEnvelope=null;\n// Text color pairs with the shell surface: themed var when the runtime\n// injected theme CSS, else the light-on-dark fallback matching the\n// shell's static #1e293b pre-theme surface. The old hardcoded #666 was\n// illegible on that dark fallback (#481).\nvar SHELL_FG='var(--ggui-color-onSurface,#e2e8f0)';\nfunction setOverlay(text){\n if(mounted)return;\n rootEl.innerHTML='<div style=\"font:13px system-ui,sans-serif;padding:24px;color:'+SHELL_FG+';opacity:.55\">'+text+'</div>';\n}\nfunction escText(s){\n return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');\n}\n// Terminal failure card (#481): plain-language summary, diagnostic\n// reachable but collapsed, Retry only when a retry can actually work.\n// Same visual vocabulary as the runtime's React error boundary so the\n// two error surfaces read as one system.\nfunction showFailure(summary,detail,retry){\n if(mounted)return;\n rootEl.innerHTML=''+\n '<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\">'+\n '<div style=\"font-size:14px;font-weight:600\">'+escText(summary)+'</div>'+\n '<div style=\"font-size:12px;opacity:.65;max-width:320px;line-height:1.45\">The interface could not start. The conversation is unaffected \u2014 you can also just ask for the view again.</div>'+\n (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>':'')+\n '<details style=\"margin-top:6px;max-width:340px;width:100%;text-align:left;opacity:.75\">'+\n '<summary style=\"cursor:pointer;font-size:12px\">Details</summary>'+\n '<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>'+\n '</details>'+\n '</div>';\n if(retry){\n var b=document.getElementById('ggui-shell-retry');\n if(b)b.onclick=retry;\n }\n}\nfunction postNotification(method,params){\n try{window.parent.postMessage({jsonrpc:'2.0',method:method,params:params||{}},'*');}catch(e){}\n}\nfunction postRpc(method,params){\n return new Promise(function(res,rej){\n var id=rpcId++;pending[id]={res:res,rej:rej};\n try{window.parent.postMessage({jsonrpc:'2.0',id:id,method:method,params:params||{}},'*');}\n catch(e){delete pending[id];rej(e);}\n });\n}\nfunction postBootstrapFailed(reason,message){\n // Surface every shell-layer bootstrap-failure path as a typed\n // RendererBootFailedMessage envelope so hosts pinning the C9\n // error pane (McpAppIframe onError, IframeErrorPane) see the\n // failure instead of staring at the inert overlay until the test\n // times out. Reason codes match BootstrapFailureReason.\n try{window.parent.postMessage({type:'ggui:bootstrap-failed',reason:reason,message:message},'*');}catch(e){}\n}\nasync function mountFromMeta(envelope){\n if(mounted)return;\n // Slice envelope shape (Phase B): { \"ai.ggui/render\": { sessionId,\n // appId, runtimeUrl, ... } }. runtimeUrl on the render slice is\n // the only load-bearing field at the shell layer \u2014 it tells us\n // which iframe-runtime bundle to fetch. Everything else is\n // optional; the runtime decides at boot time based on the meta\n // it reads from window.__GGUI_META__.\n var renderSlice=envelope&&envelope['ai.ggui/render'];\n var runtimeUrl=renderSlice&&renderSlice.runtimeUrl;\n if(!envelope||typeof runtimeUrl!=='string'){\n // No retry: without a valid envelope there is nothing to re-run.\n showFailure('This view could not start','MALFORMED_BOOTSTRAP: bootstrap payload malformed (no ai.ggui/render slice with a runtimeUrl).',null);\n postBootstrapFailed('MALFORMED_BOOTSTRAP','Bootstrap payload malformed.');\n return;\n }\n lastEnvelope=envelope;\n setOverlay('Loading UI\u2026');\n window.__GGUI_META__=envelope;\n // Load the runtime bundle via a direct cross-origin script tag\n // (governed by CSP script-src) instead of fetch + Blob (governed by\n // CSP connect-src). claude.ai's claudemcpcontent.com iframe CSP\n // forbids cross-origin connect-src so fetch throws TypeError\n // 'Failed to fetch', but allows cross-origin script-src when the\n // bundle responds with the right CORS headers (the iframe-runtime\n // mount sets them). The self-contained shell already uses this\n // pattern; legacy postMessage shell now matches it.\n try{\n var s=document.createElement('script');\n s.type='module';\n // crossorigin=anonymous opts into CORS-mode error reporting.\n // Without it, cross-origin script tags get a sanitized\n // \"script error\" with no details, masking the real cause\n // (CSP block, CORS reject, module-evaluation throw). With it,\n // the error event surfaces the actual message in the iframe\n // console -- the bundle ships ACAO=* so credentialed mode is\n // unnecessary.\n s.crossOrigin='anonymous';\n s.src=runtimeUrl;\n s.onload=function(){mounted=true;};\n s.onerror=function(e){\n var msg='Runtime bundle failed to load: '+(e&&e.message||'script error');\n showFailure('This view could not load','BUNDLE_FETCH_FAILED: '+msg,function(){mountFromMeta(lastEnvelope);});\n postBootstrapFailed('BUNDLE_FETCH_FAILED',msg);\n };\n rootEl.innerHTML='';\n document.body.appendChild(s);\n }catch(e){\n var msg='Runtime bundle failed to load: '+(e&&e.message||e);\n showFailure('This view could not load','BUNDLE_FETCH_FAILED: '+msg,function(){mountFromMeta(lastEnvelope);});\n postBootstrapFailed('BUNDLE_FETCH_FAILED',msg);\n }\n}\nfunction readMetaFromCallToolResult(params){\n // MCP Apps spec (specification/2026-01-26/apps.mdx:1145-1155):\n // ui/notifications/tool-result\n // params: CallToolResult // Standard MCP type\n // So params IS the CallToolResult and _meta lives at the top\n // level. Spec-compliant hosts (Claude Desktop, claude.ai\n // Connector, Claude Code) deliver slice-envelope material here.\n // Single slice-envelope key (Phase B: ai.ggui/render). Only the\n // render slice's runtimeUrl is load-bearing at the shell layer;\n // the runtime reads everything else off window.__GGUI_META__\n // after we set it.\n if(!params||typeof params!=='object')return null;\n var meta=params._meta;\n if(!meta||typeof meta!=='object')return null;\n var renderSlice=meta['ai.ggui/render'];\n if(!renderSlice||typeof renderSlice!=='object')return null;\n if(typeof renderSlice.runtimeUrl!=='string')return null;\n return meta;\n}\nwindow.addEventListener('message',function(ev){\n var m=ev&&ev.data;\n if(!m||m.jsonrpc!=='2.0')return;\n if(m.id!=null&&pending[m.id]){\n var p=pending[m.id];delete pending[m.id];\n if(m.error)p.rej(m.error);else p.res(m.result);\n return;\n }\n if(m.method==='ui/notifications/tool-result'){\n // Spec-compliant hosts: m.params IS the CallToolResult; _meta is\n // at the top level.\n var specMeta=readMetaFromCallToolResult(m.params);\n if(specMeta){mountFromMeta(specMeta);return;}\n // Read-plane door (ggui#537). A server running the read-plane-only\n // posture publishes only the view's IDENTITY on the result -- the\n // ui:// locator on structuredContent.resourceUri and the spec\n // pointer _meta.ui.resourceUri -- and no bootstrap material. The\n // per-render resource that locator names is the self-contained\n // shell, whose document inlines the very envelope this shell needs;\n // ask the HOST to read it (resources/read, proxied by the host's\n // own MCP client -- no fetch from this sandbox, so a host CSP with\n // no connect-src to the server is not in the way). R5 (2026-05-26)\n // removed the /r/<shortCode> HTTP fallback with the bearer-by-\n // obscurity model; this door is the spec-canonical replacement.\n var locator=readLocatorFromCallToolResult(m.params);\n if(locator){mountFromLocator(locator);return;}\n }\n});\nfunction readLocatorFromCallToolResult(params){\n if(!params||typeof params!=='object')return null;\n var sc=params.structuredContent, meta=params._meta, uri=null;\n if(sc&&typeof sc==='object'&&typeof sc.resourceUri==='string')uri=sc.resourceUri;\n else if(meta&&typeof meta==='object'&&meta.ui&&typeof meta.ui==='object'&&typeof meta.ui.resourceUri==='string')uri=meta.ui.resourceUri;\n if(!uri||uri.indexOf('ui://ggui/render/')!==0)return null;\n return uri;\n}\nfunction envelopeFromResourceDoc(text){\n // The per-render self-contained shell inlines its envelope on ONE\n // line inside its meta script tag: globalThis.__GGUI_META__ = {...};\n // (protocol gguiShellHtml). The JSON is angle-bracket-escaped by the\n // assembler, so the first ';' followed by the closing script tag\n // after the marker is the terminator.\n if(typeof text!=='string')return null;\n var marker='globalThis.__GGUI_META__ = ';\n var start=text.indexOf(marker);\n if(start<0)return null;\n start+=marker.length;\n var end=text.indexOf(';<'+'/script>',start);\n if(end<0)return null;\n try{var env=JSON.parse(text.slice(start,end));}catch(e){return null;}\n return (env&&typeof env==='object'&&env['ai.ggui/render']&&typeof env['ai.ggui/render'].runtimeUrl==='string')?env:null;\n}\nasync function mountFromLocator(uri){\n if(mounted)return;\n setOverlay('Resolving view\u2026');\n var res;\n try{res=await postRpc('resources/read',{uri:uri});}\n catch(e){\n var rmsg='READ_DOOR_FAILED: the host could not read '+uri+' -- '+(e&&e.message||JSON.stringify(e));\n showFailure('This view could not be resolved',rmsg,function(){mountFromLocator(uri);});\n postBootstrapFailed('MALFORMED_BOOTSTRAP',rmsg);\n return;\n }\n var c=res&&res.contents&&res.contents[0];\n var env=envelopeFromResourceDoc(c&&c.text);\n if(!env){\n var emsg='MALFORMED_BOOTSTRAP: resource '+uri+' carried no ai.ggui/render envelope with a runtimeUrl.';\n showFailure('This view could not start',emsg,function(){mountFromLocator(uri);});\n postBootstrapFailed('MALFORMED_BOOTSTRAP',emsg);\n return;\n }\n mountFromMeta(env);\n}\n// Named so the failure card's Retry can re-run the whole handshake \u2014\n// a host that missed or rejected the first ui/initialize may answer a\n// second (observed with hosts that attach their listener late).\nfunction startInit(){\n setOverlay('Initializing\u2026');\n var initTimer=setTimeout(function(){\n showFailure('This view did not hear back from its host','INIT_TIMEOUT: no response to ui/initialize within 3s.',startInit);\n },3000);\n postRpc('ui/initialize',{\n appCapabilities:{},\n appInfo:{name:'ggui-render',version:'0.12.0'},\n protocolVersion:'2026-01-26'\n }).then(function(){\n clearTimeout(initTimer);\n postNotification('ui/notifications/initialized',{});\n // Wait for the host to send ui/notifications/tool-result carrying\n // the slice envelope in _meta \u2014 the spec-canonical delivery channel.\n // The ui/initialize result itself carries no slice meta (the\n // McpUiInitializeResult schema defines no such field).\n setOverlay('Waiting for tool result\u2026');\n }).catch(function(e){\n clearTimeout(initTimer);\n showFailure('This view could not connect to its host','ui/initialize failed: '+(e&&e.message||JSON.stringify(e)),startInit);\n });\n}\nstartInit();\n})();\n</script></body></html>";
|
|
40
|
+
export declare const GGUI_RENDER_SHELL_HTML: string;
|
|
41
41
|
/**
|
|
42
42
|
* CSP `script-src` source expression that authorises the inline
|
|
43
43
|
* `<script>` block of {@link GGUI_RENDER_SHELL_HTML} when it executes
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-apps-outbound.d.ts","sourceRoot":"","sources":["../src/mcp-apps-outbound.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAEH,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAEhB,WAAW,EACZ,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAML,KAAK,YAAY,EAOjB,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACpB,MAAM,sCAAsC,CAAC;AAmB9C,OAAO,
|
|
1
|
+
{"version":3,"file":"mcp-apps-outbound.d.ts","sourceRoot":"","sources":["../src/mcp-apps-outbound.ts"],"names":[],"mappings":"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"}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
*/
|
|
34
34
|
import { deriveBundleOrigins, deriveContractBundle, derivePublicEnvProjection, deriveRenderMeta, withResolvedThemeBase, filterDescriptorsToContract, findBlueprintExact, resolveSliceTheme, spreadRenderMetaViewOntoSlice, wsOriginToHttpOrigin, } from "@ggui-ai/mcp-server-handlers/renders";
|
|
35
35
|
import { GGUI_WAVE_VERSION, 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, composeSessionApiUrls, deriveContextName, escapeInlineScript, gguiShellHtml, parseEpochUri, toMcpAppEnvelope, } from "@ggui-ai/protocol/integrations/mcp-apps";
|
|
36
|
+
import { GGUI_RENDER_RESOURCE_MIME, GGUI_RENDER_RESOURCE_URI, GGUI_RENDER_SHELL_SCHEME_STYLE, GGUI_RENDER_SHELL_SURFACE, GGUI_SHELL_LOADING_INDICATOR_HTML, 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";
|
|
@@ -152,10 +152,11 @@ rootEl.style.cssText='display:flex;flex-direction:column;height:100%;min-height:
|
|
|
152
152
|
var mounted=false;
|
|
153
153
|
var lastEnvelope=null;
|
|
154
154
|
// Text color pairs with the shell surface: themed var when the runtime
|
|
155
|
-
// injected theme CSS, else the
|
|
156
|
-
//
|
|
157
|
-
//
|
|
158
|
-
|
|
155
|
+
// injected theme CSS, else the scheme-scoped pre-theme ink the shell's
|
|
156
|
+
// own scheme <style> defines (#662) — legible on whichever neutral
|
|
157
|
+
// ground prefers-color-scheme picked. (#481 killed the illegible
|
|
158
|
+
// hardcoded #666; #662 killed the dark-only fallback.)
|
|
159
|
+
var SHELL_FG='var(--ggui-color-onSurface,var(--ggui-shell-scheme-on-surface,#374151))';
|
|
159
160
|
function setOverlay(text){
|
|
160
161
|
if(mounted)return;
|
|
161
162
|
rootEl.innerHTML='<div style="font:13px system-ui,sans-serif;padding:24px;color:'+SHELL_FG+';opacity:.55">'+text+'</div>';
|
|
@@ -379,7 +380,7 @@ startInit();
|
|
|
379
380
|
// `<head>` by the iframe-runtime at boot (react-renderer.ts ->
|
|
380
381
|
// `<style id="ggui-theme-vars">`), so the `var()` resolves to the
|
|
381
382
|
// active theme's exact per-mode surface color at runtime. The static
|
|
382
|
-
//
|
|
383
|
+
// scheme-scoped fallback (#662: neutral per prefers-color-scheme) covers the pre-resolve
|
|
383
384
|
// first paint + browsers that drop unresolved custom properties.
|
|
384
385
|
//
|
|
385
386
|
// # Why paint the document background here (Safari white-canvas fix)
|
|
@@ -424,8 +425,8 @@ startInit();
|
|
|
424
425
|
// The self-contained shell (`buildSelfContainedShell`) has no overlay
|
|
425
426
|
// script and therefore no anchor div at all.
|
|
426
427
|
export const GGUI_RENDER_SHELL_HTML = `<!doctype html>
|
|
427
|
-
<html lang="en" style="height:100%;background-color:${GGUI_RENDER_SHELL_SURFACE}"><head><meta charset="utf-8"><title>ggui render</title></head>
|
|
428
|
-
<body style="margin:0;height:100%;min-height:480px;background-color:${GGUI_RENDER_SHELL_SURFACE}"
|
|
428
|
+
<html lang="en" style="height:100%;background-color:${GGUI_RENDER_SHELL_SURFACE}"><head><meta charset="utf-8"><meta name="color-scheme" content="light dark">${GGUI_RENDER_SHELL_SCHEME_STYLE}<title>ggui render</title></head>
|
|
429
|
+
<body style="margin:0;height:100%;min-height:480px;background-color:${GGUI_RENDER_SHELL_SURFACE}">${GGUI_SHELL_LOADING_INDICATOR_HTML}<div id="ggui-root" data-ggui-shell="thin" style="height:100%;min-height:480px"></div>
|
|
429
430
|
<script>${GGUI_RENDER_SHELL_SCRIPT_BODY}</script></body></html>`;
|
|
430
431
|
/**
|
|
431
432
|
* CSP `script-src` source expression that authorises the inline
|
|
@@ -535,8 +536,8 @@ export function buildInlineRenderShellHtml(runtimeSource) {
|
|
|
535
536
|
// no-container posture as `gguiShellHtml`; the shell marker rides
|
|
536
537
|
// on `<body>`.
|
|
537
538
|
return `<!doctype html>
|
|
538
|
-
<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"
|
|
539
|
-
<body style="margin:0;background-color:${GGUI_RENDER_SHELL_SURFACE}" data-ggui-shell="inline"
|
|
539
|
+
<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">${GGUI_RENDER_SHELL_SCHEME_STYLE}<title>ggui render</title></head>
|
|
540
|
+
<body style="margin:0;background-color:${GGUI_RENDER_SHELL_SURFACE}" data-ggui-shell="inline">${GGUI_SHELL_LOADING_INDICATOR_HTML}
|
|
540
541
|
<script>${GGUI_INLINE_SHELL_BUFFER_SCRIPT_BODY}</script>
|
|
541
542
|
<script type="module" data-ggui-runtime="inline">${escapeInlineScript(runtimeSource)}</script></body></html>`;
|
|
542
543
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ggui-ai/mcp-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Self-hosted MCP server for the ggui protocol. An HTTP/MCP binding layer over @ggui-ai/mcp-server-handlers and the reference adapters from @ggui-ai/mcp-server-core — run it via `ggui serve`.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ggui",
|
|
@@ -32,17 +32,17 @@
|
|
|
32
32
|
"resend": "^6.12.2",
|
|
33
33
|
"ws": "^8.20.1",
|
|
34
34
|
"zod": "^4.3.6",
|
|
35
|
-
"@ggui-ai/
|
|
36
|
-
"@ggui-ai/
|
|
37
|
-
"@ggui-ai/
|
|
38
|
-
"@ggui-ai/
|
|
39
|
-
"@ggui-ai/mcp-server-handlers": "0.
|
|
40
|
-
"@ggui-ai/negotiator": "0.
|
|
41
|
-
"@ggui-ai/
|
|
42
|
-
"@ggui-ai/
|
|
43
|
-
"@ggui-ai/
|
|
44
|
-
"@ggui-ai/ui-gen": "0.
|
|
45
|
-
"@ggui-ai/
|
|
35
|
+
"@ggui-ai/console": "0.13.0",
|
|
36
|
+
"@ggui-ai/design": "0.13.0",
|
|
37
|
+
"@ggui-ai/iframe-runtime": "0.13.0",
|
|
38
|
+
"@ggui-ai/mcp-server-core": "0.13.0",
|
|
39
|
+
"@ggui-ai/mcp-server-handlers": "0.13.0",
|
|
40
|
+
"@ggui-ai/negotiator": "0.13.0",
|
|
41
|
+
"@ggui-ai/preview-a2ui": "0.13.0",
|
|
42
|
+
"@ggui-ai/project-config": "0.13.0",
|
|
43
|
+
"@ggui-ai/protocol": "0.13.0",
|
|
44
|
+
"@ggui-ai/ui-gen": "0.13.0",
|
|
45
|
+
"@ggui-ai/ui-registry": "0.13.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/express": "^5.0.0",
|
|
@@ -51,7 +51,7 @@
|
|
|
51
51
|
"@types/ws": "^8.5.10",
|
|
52
52
|
"typescript": "^5.0.0",
|
|
53
53
|
"vitest": "^3.2.6",
|
|
54
|
-
"@ggui-ai/protocol-conformance": "0.
|
|
54
|
+
"@ggui-ai/protocol-conformance": "0.13.0"
|
|
55
55
|
},
|
|
56
56
|
"repository": {
|
|
57
57
|
"type": "git",
|
|
@@ -70,7 +70,7 @@
|
|
|
70
70
|
},
|
|
71
71
|
"author": "ggui contributors <hello@ggui.ai>",
|
|
72
72
|
"scripts": {
|
|
73
|
-
"build": "rm -rf dist && tsc -p tsconfig.build.json && node ../scripts/fix-esm-imports.mjs dist",
|
|
73
|
+
"build": "rm -rf dist.staging && tsc -p tsconfig.build.json --outDir dist.staging && node ../scripts/fix-esm-imports.mjs dist.staging && node ../scripts/atomic-swap.mjs dist.staging dist",
|
|
74
74
|
"dev": "tsc --watch",
|
|
75
75
|
"typecheck": "tsc --noEmit",
|
|
76
76
|
"test": "vitest run",
|