@cloudgrid-io/mcp 0.21.16 → 0.21.18

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cloudgrid-io/mcp",
3
- "version": "0.21.16",
3
+ "version": "0.21.18",
4
4
  "description": "MCP access to CloudGrid — the live runtime environment where the user's apps run WITH the infrastructure they need out of the box: managed MongoDB, Redis (cache/queues/pub-sub), a pgvector store, persistent disk, and built-in AI with no API keys, in any language or stack, no Docker or Kubernetes to manage. Brainstorm, build, plug, and improve apps, games, dashboards, and tools; instant single-page publishes and full runtime-app deploys with a live URL — for developers and non-technical users. Three editions: local stdio (full toolset), hosted web (light, CLI-free), and a public docs-search server.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -27,7 +27,10 @@ export const ANON_HTML_MAX_BYTES = 2_000_000;
27
27
  // ~6x stricter by design — a normal page is well under 1 MB, and past
28
28
  // 25 MB the right shape is a folder plug (multipart, see deploy.js:756).
29
29
  export const AUTHED_HTML_MAX_BYTES = 25_000_000;
30
- export const CONSOLE_URL = "https://console.cloudgrid.io/";
30
+ // The Console's canonical host is my.cloudgrid.io (cloudgrid-io/cloudgrid#4135).
31
+ // console.cloudgrid.io stays as a permanent redirect, so links printed by
32
+ // earlier releases still land.
33
+ export const CONSOLE_URL = "https://my.cloudgrid.io/";
31
34
 
32
35
  // The console link handed to a user AFTER a plug. When the grid slug is known it
33
36
  // points at THAT grid (verified live: /home?grid=<slug> -> 200) instead of the
@@ -64,25 +67,36 @@ export const VISIBILITY_LABELS = {
64
67
  // the widget HTML is verified to render. The resources stay registered either
65
68
  // way (harmless when no tool references them via outputTemplate).
66
69
  //
67
- // 2026-08-25 (#308): the black frame was diagnosed as a MIME mismatch. ChatGPT
68
- // discovers an Apps-SDK widget by a tool carrying openai/outputTemplate PLUS a
69
- // ui:// resource whose mimeType is `text/html+skybridge` (verified against
70
- // OpenAI's shipped example servers — openai/openai-apps-sdk-examples
71
- // solar-system/shopping_cart/kitchen_sink main.py). Our two ChatGPT widgets
72
- // declared `text/html;profile=mcp-app` — the SEP-1865/MCP-Apps MIME that CLAUDE
73
- // reads (RESOURCE_MIME_TYPE in @modelcontextprotocol/ext-apps). ChatGPT saw the
74
- // outputTemplate pointer, opened the skybridge iframe (dark chrome), but the
75
- // resource was not a skybridge document, so the HTML/bridge never populated —
76
- // the empty dark frame covering the text. CHATGPT_WIDGET_MIME below is the
77
- // correct type. The flag STAYS OFF until a card is seen rendering in real
78
- // ChatGPT (Developer Mode custom connector against staging); this only makes the
79
- // machinery correct for that verification.
70
+ // 2026-08-31 (#308, corrected): the widgets targeted a RETIRED MIME. At DevDay
71
+ // (Oct 2025) ChatGPT's Apps SDK used `text/html+skybridge`, and #309 switched us
72
+ // to it. But the Apps SDK merged with MCP Apps into SEP-1865, ratified
73
+ // 2026-01-26, and OpenAI's CURRENT docs (developers.openai.com/apps-sdk
74
+ // build/custom-ux, deploy/troubleshooting) now specify `text/html;profile=mcp-app`
75
+ // — the same MIME Claude reads. skybridge is not mentioned anywhere in the
76
+ // current docs. So ChatGPT opened the iframe on our skybridge resource, could not
77
+ // recognise it, and never populated it — the empty frame over the text.
78
+ //
79
+ // The clincher: our own Claude sign-in card (#303) RENDERS, and it declares
80
+ // `text/html;profile=mcp-app`. The MIME that renders is the standard one; the one
81
+ // that does not is skybridge. The two hosts converged; the old separation was the
82
+ // defect. CHATGPT_WIDGET_MIME below now equals RESOURCE_MIME_TYPE by value. The
83
+ // widget bridge (window.openai.toolOutput / openExternal / callTool /
84
+ // ui/notifications/tool-result) is already current — verified against
85
+ // developers.openai.com/apps-sdk/reference — so only the MIME changes.
86
+ //
87
+ // The flag stays where the platform sets it; this only makes the resource the
88
+ // type ChatGPT now expects. Done is a card seen rendering in real ChatGPT.
80
89
  export const APPS_WIDGETS_ENABLED = process.env.MCP_APPS_WIDGETS === "1";
81
90
  // The mimeType ChatGPT's Apps-SDK renderer requires for a ui:// widget resource.
82
- // Distinct from RESOURCE_MIME_TYPE (`text/html;profile=mcp-app`, the SEP-1865
83
- // key Claude reads) — the two hosts key off different MIME types, so the ChatGPT
84
- // widgets and the Claude sign-in card must NOT share one.
85
- export const CHATGPT_WIDGET_MIME = "text/html+skybridge";
91
+ // Since SEP-1865 (2026-01-26) this EQUALS RESOURCE_MIME_TYPE (`text/html;profile=
92
+ // mcp-app`): both hosts now render the standard MCP-Apps MIME. Both hosts also
93
+ // read the SAME binding key, `_meta.ui.resourceUri`; ChatGPT honors
94
+ // `openai/outputTemplate` only as a compatibility alias (OpenAI's own
95
+ // deploy/troubleshooting page). So our two mechanisms stay separate not because
96
+ // the hosts key off different MIMEs or different keys, but because WE bind them
97
+ // on different keys: the ChatGPT widget via `openai/outputTemplate` (the alias,
98
+ // which Claude ignores), the Claude card via `_meta.ui.resourceUri`.
99
+ export const CHATGPT_WIDGET_MIME = "text/html;profile=mcp-app";
86
100
  export const LIVE_RESULT_URI = "ui://cloudgrid/live-result.html";
87
101
  // URI/resource-name/filename stay `org-picker` — that's the stable contract the
88
102
  // web card is registered under; only the JS identifier moves toward grid.
@@ -133,9 +133,10 @@ export function registerTools(server, ctx) {
133
133
 
134
134
  // ── Widget resources (web edition, ChatGPT Apps SDK) ──────────────────────
135
135
  if (ctx.edition === "web") {
136
- // ChatGPT Apps-SDK widgets. mimeType MUST be text/html+skybridge
137
- // (CHATGPT_WIDGET_MIME) — NOT the MCP-Apps `text/html;profile=mcp-app` the
138
- // Claude card uses; that mismatch was the black frame (#308). widgetAccessible
136
+ // ChatGPT Apps-SDK widgets. mimeType is CHATGPT_WIDGET_MIME, which since
137
+ // SEP-1865 (2026-01-26) IS `text/html;profile=mcp-app` — the standard MCP-Apps
138
+ // type. The old `text/html+skybridge` was retired and was the black frame
139
+ // (#308); the hosts stay separated by binding, not MIME. widgetAccessible
139
140
  // lets the widget call tools back over window.openai.callTool (the visibility
140
141
  // pills call grid_visibility). These make no direct network requests, so no
141
142
  // openai/widgetCSP is declared — the default deny is correct.
@@ -538,11 +539,12 @@ export function registerTools(server, ctx) {
538
539
  // live at a public URL in place. Versions + grid rollback exist, but the
539
540
  // honest MCP annotation for overwrite-live-state is destructive.
540
541
  annotations: { readOnlyHint: false, destructiveHint: true, openWorldHint: true },
541
- // ChatGPT-only binding: openai/outputTemplate points at the skybridge
542
- // widget. Deliberately NOT the MCP-Apps `ui.resourceUri` key — that is
543
- // Claude's, and the live-result resource is now text/html+skybridge, which
544
- // Claude cannot render; carrying it here would regress the Claude path when
545
- // this flag is flipped. The two mechanisms stay independent (#308/#303).
542
+ // Bound via openai/outputTemplate, which ChatGPT honors as a compatibility
543
+ // alias for `_meta.ui.resourceUri` and which Claude ignores — so this
544
+ // widget renders in ChatGPT only. Deliberately NOT `_meta.ui.resourceUri`:
545
+ // since SEP-1865 both hosts read THAT key, so binding there would render the
546
+ // widget in Claude too. The two mechanisms stay independent because they
547
+ // bind on different keys, not different MIMEs (#308/#303).
546
548
  ...(ctx.edition === "web" && APPS_WIDGETS_ENABLED ? {
547
549
  _meta: { "openai/outputTemplate": LIVE_RESULT_URI },
548
550
  } : {}),
@@ -717,10 +719,11 @@ export function registerTools(server, ctx) {
717
719
  login_url: z.string().describe("URL to open in a browser to complete sign-in."),
718
720
  },
719
721
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
720
- // Bind the SEP-1865 sign-in card on the web edition (Claude web). This is
721
- // the SEP-1865 key (_meta.ui.resourceUri); ChatGPT reads openai/outputTemplate
722
- // and ignores it, and a client without the UI extension ignores it too and
723
- // gets the text-first result below. NOT gated behind MCP_APPS_WIDGETS — a
722
+ // Bind the SEP-1865 sign-in card on the web edition (Claude web) via the
723
+ // standard `_meta.ui.resourceUri` key. It carries NO openai/outputTemplate
724
+ // and is not gated by MCP_APPS_WIDGETS, so it is the Claude sign-in card;
725
+ // a client without the UI extension ignores _meta.ui and gets the
726
+ // text-first result below. NOT gated behind MCP_APPS_WIDGETS — a
724
727
  // second, independent mechanism (see constants.js). The result shape is
725
728
  // unchanged: content[0] stays the sign-in URL text so the link is never
726
729
  // unreachable if the card does not render.
@@ -1194,6 +1197,13 @@ export function registerTools(server, ctx) {
1194
1197
  error: z.boolean().optional().describe("True when the grid listing failed (network/auth error). The text carries a human-readable message. Do NOT treat this as needs_grid_create."),
1195
1198
  },
1196
1199
  annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: true },
1200
+ // ChatGPT Apps-SDK card, same binding as grid_plug: grid_hello returns a
1201
+ // runPlug result, so it deserves the same live-result widget. Without this a
1202
+ // grid_hello success renders no card even when the MIME is correct (#308).
1203
+ // openai/outputTemplate is ChatGPT-only; Claude ignores it, so #303 is safe.
1204
+ ...(ctx.edition === "web" && APPS_WIDGETS_ENABLED ? {
1205
+ _meta: { "openai/outputTemplate": LIVE_RESULT_URI },
1206
+ } : {}),
1197
1207
  },
1198
1208
  async (input) => {
1199
1209
  try {