Charming
Server Details
Build personal interactive apps with real URLs and persistent storage, using any AI.
Glama couldn't complete the latest health check. If this server requires authentication, missing or expired test credentials may be the cause. A test profile lets Glama authenticate for health checks and discover tools; it is separate from your personal connections.
If you are the author, claim ownership, then add or update a test profile under Admin → Test Profile.
- Status
- Unhealthy
- Uptime
- 40.0% over 48 days
- OAuth
- Works in Glama
- Last Tested
- Transport
- Streamable HTTP
- URL
- Repository
- tambo-labs/charming-mcp
- GitHub Stars
- 1
- Server Listing
- Charming
TDQS
Scored across 33 tools
Almost every tool maps to a distinct resource and action—app CRUD, builds, routines, shares, templates, feedback, assets, docs—and the descriptions are detailed enough to prevent most misselection. The only real overlap is set_remixable/unset_remixable, which are explicitly deprecated aliases of set_template/unset_template with identical effects.
All tools follow the same imperative verb_noun pattern in snake_case, with consistent clusters like create/update/delete/list and set/unset pairs. Minor variations such as unshare_app and cancel_app_build are still predictable verbs, so the naming is essentially uniform.
At 33 tools, the surface is above the ideal range and carries some redundancy—deprecated remixable aliases and four separate feedback-related tools add selection overhead. However, the server's purpose is genuinely broad, covering app lifecycle, builds, sharing, templates, routines, assets, and docs, so the count is defensible for the scope.
Core workflows are well covered: app create/read/update/delete, source and build management, runtime data operations, sharing/revocation, templates, routines, feedback, assets, and documentation lookup. The main gaps are the lack of a claim_app flow for anonymous apps, no asset listing/deletion, and no team management beyond roles.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
4 tool updates
- Changed
create_app1 field changed- changed
Input schema / properties / module / descriptionPrevious value: -"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the declared origins; neither bypasses them."New value: +"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside a chat host and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone AND embedded inline, where the host's injected CSP blocks a cross-origin `<img src>` — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone and in a host that injects no such CSP, but not in every embed; prefer `images.load(...)` whenever the app may be embedded. Both enforce the declared origins; neither bypasses them."
- Changed
get_app3 fields changed- changed
Output schema / properties / recentIssues / properties / counts / properties / apiFailures / descriptionPrevious value: -"Failed calls to the app API proxy."New value: +"Failed calls to the app API proxy, including calls refused at the app run ceiling, which are recorded one row per 10-second window." - added
Output schema / properties / recentIssues / properties / sinceAdded value: +{ + "description": "Set when the plan's window hid older issues: the cutoff the counts start from (ISO-8601).", + "type": "string" +} - changed
Output schema / properties / recentIssues / properties / total / descriptionPrevious value: -"Issue events counted for the current revision, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list."New value: +"Failed calls counted for the current revision, read from the newest 1000 issue rows. One row can stand for a burst of refused calls, so this can exceed 1000. Use GET /app/:id/activity for the exact, paginated list."
- Changed
set_starter_prompt2 fields changed- changed
Input schema / properties / starter_prompt / descriptionPrevious value: -"Getting-started instruction the chat host receives when a visitor clicks \"Open in Claude\" / \"Open in ChatGPT\". The authored text leads; the app's name, description, URL, and (for unclaimed apps) an access token are appended automatically as context — so write a generic 1–3 sentence instruction (the first action you want the visitor to take, plus any persona/voice), NOT a self-contained prompt and NOT the app's URL. Pass null or \"\" to clear and revert to the generic default. Max 2000 characters."New value: +"Getting-started instruction the assistant receives when a visitor opens the app there. The authored text leads; the app's name, description, URL, and (for unclaimed apps) an access token are appended automatically as context — so write a generic 1–3 sentence instruction (the first action you want the visitor to take, plus any persona/voice), NOT a self-contained prompt and NOT the app's URL. Pass null or \"\" to clear and revert to the generic default. Max 2000 characters." - changed
Output schema / properties / message / descriptionPrevious value: -"Consequence copy the agent should surface to the user. Explains where the prompt is rendered (Open in Claude / Open in ChatGPT) and how to clear it."New value: +"Consequence copy the agent should surface to the user. Says where the prompt appears, when a visitor opens the app in their AI assistant, and how to clear it."
- Changed
update_app1 field changed- changed
Input schema / properties / module / descriptionPrevious value: -"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`."New value: +"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside a chat host and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`."
4 tool updates
- Changed
cancel_app_build1 field changed- added
Output schema / properties / error / properties / detailsAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] +}
- Changed
create_app2 fields changed- changed
Output schema / anyOfPrevious value: -[ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "advisories": { - "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", - "items": { - "additionalProperties": false, - "properties": { - "data": { - "additionalProperties": {}, - "description": "Kind-specific structured payload. Shape varies per advisory kind.", - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "doc_url": { - "description": "Optional docs pointer for this advisory kind.", - "type": "string" - }, - "kind": { - "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", - "type": "string" - }, - "severity": { - "description": "Severity; omitted advisories are treated as 'info'.", - "enum": [ - "info", - "warn" - ], - "type": "string" - }, - "summary": { - "description": "Agent-facing summary. Self-sufficient; no extra context required.", - "type": "string" - }, - "userSummary": { - "description": "End-user-facing summary. Set when the advisory should render in-app.", - "type": "string" - } - }, - "required": [ - "kind", - "summary" - ], - "type": "object" - }, - "type": "array" - }, - "appName": { - "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", - "type": [ - "string", - "null" - ] - }, - "icon": { - "additionalProperties": false, - "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", - "properties": { - "bg": { - "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", - "type": "string" - }, - "emoji": { - "description": "The single emoji rendered on the icon.", - "type": "string" - } - }, - "required": [ - "emoji", - "bg" - ], - "type": "object" - }, - "id": { - "description": "UUID of the created or updated app.", - "type": "string" - }, - "ok": { - "const": true, - "description": "Indicates success. Errors arrive as content with isError:true.", - "type": "boolean" - }, - "revision": { - "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "shareUrl": { - "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", - "type": "string" - }, - "url": { - "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", - "type": "string" - }, - "warnings": { - "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "ok", - "id", - "url", - "shareUrl", - "revision", - "icon" - ], - "type": "object" - }, - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "acceptedAt": { - "type": "string" - }, - "activeRevision": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "appId": { - "description": "Existing target app ID, or the created app ID after publication.", - "type": "string" - }, - "attempts": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "buildId": { - "description": "Durable build ID. Use get_app_build to inspect progress or source.", - "type": "string" - }, - "deadline": { - "type": "string" - }, - "desiredRevision": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "elapsedMs": { - "minimum": 0, - "type": "number" - }, - "error": { - "additionalProperties": false, - "properties": { - "column": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "kind": { - "type": "string" - }, - "line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "message": { - "type": "string" - }, - "retryable": { - "type": "boolean" - }, - "specifier": { - "type": "string" - }, - "target": { - "type": "string" - } - }, - "required": [ - "kind", - "message", - "retryable" - ], - "type": "object" - }, - "finishedAt": { - "type": [ - "string", - "null" - ] - }, - "idempotencyExpiresAt": { - "type": [ - "string", - "null" - ] - }, - "inputDigest": { - "type": "string" - }, - "inspectionExpiresAt": { - "type": [ - "string", - "null" - ] - }, - "intent": { - "description": "The accepted operation: create, update, migrate, restore, or copy.", - "type": "string" - }, - "lockDigest": { - "type": "string" - }, - "lockState": { - "enum": [ - "locked", - "unresolved" - ], - "type": "string" - }, - "ok": { - "const": true, - "type": "boolean" - }, - "queueDeadline": { - "type": "string" - }, - "resolvedDependencies": { - "additionalProperties": false, - "properties": { - "client": { - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "server": { - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "server", - "client" - ], - "type": "object" - }, - "retryAfterSeconds": { - "description": "Wait at least this many seconds before polling again.", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - }, - "revision": { - "description": "Published app source revision.", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - }, - "source": { - "additionalProperties": false, - "description": "Exact accepted source, returned only when include_source is true.", - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "module": { - "type": "string" - }, - "styles": { - "type": [ - "string", - "null" - ] - }, - "ui": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "module", - "ui", - "styles", - "description" - ], - "type": "object" - }, - "sourceEtag": { - "description": "ETag identifying the immutable input accepted for this build.", - "type": "string" - }, - "state": { - "enum": [ - "queued", - "resolving", - "building", - "validating", - "published", - "failed", - "superseded", - "canceled", - "expired" - ], - "type": "string" - }, - "statusUrl": { - "description": "Authenticated HTTP status URL for this build.", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "description": "App URL. Present only after successful publication.", - "type": "string" - } - }, - "required": [ - "ok", - "buildId", - "intent", - "state", - "sourceEtag", - "statusUrl", - "attempts", - "acceptedAt", - "updatedAt", - "finishedAt", - "queueDeadline", - "deadline", - "inspectionExpiresAt", - "idempotencyExpiresAt", - "elapsedMs", - "lockState", - "inputDigest" - ], - "type": "object" - } -]New value: +[ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "advisories": { + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "appName": { + "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", + "type": [ + "string", + "null" + ] + }, + "icon": { + "additionalProperties": false, + "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", + "properties": { + "bg": { + "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", + "type": "string" + }, + "emoji": { + "description": "The single emoji rendered on the icon.", + "type": "string" + } + }, + "required": [ + "emoji", + "bg" + ], + "type": "object" + }, + "id": { + "description": "UUID of the created or updated app.", + "type": "string" + }, + "ok": { + "const": true, + "description": "Indicates success. Errors arrive as content with isError:true.", + "type": "boolean" + }, + "revision": { + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "shareUrl": { + "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", + "type": "string" + }, + "url": { + "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", + "type": "string" + }, + "warnings": { + "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "ok", + "id", + "url", + "shareUrl", + "revision", + "icon" + ], + "type": "object" + }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "acceptedAt": { + "type": "string" + }, + "activeRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "appId": { + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" + }, + "attempts": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "buildId": { + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" + }, + "deadline": { + "type": "string" + }, + "desiredRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "elapsedMs": { + "minimum": 0, + "type": "number" + }, + "error": { + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "details": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" + }, + "finishedAt": { + "type": [ + "string", + "null" + ] + }, + "idempotencyExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "inputDigest": { + "type": "string" + }, + "inspectionExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "intent": { + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" + }, + "lockDigest": { + "type": "string" + }, + "lockState": { + "enum": [ + "locked", + "unresolved" + ], + "type": "string" + }, + "ok": { + "const": true, + "type": "boolean" + }, + "queueDeadline": { + "type": "string" + }, + "resolvedDependencies": { + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" + }, + "retryAfterSeconds": { + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "revision": { + "description": "Published app source revision.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "source": { + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" + }, + "sourceEtag": { + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" + }, + "state": { + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" + }, + "statusUrl": { + "description": "Authenticated HTTP status URL for this build.", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "url": { + "description": "App URL. Present only after successful publication.", + "type": "string" + } + }, + "required": [ + "ok", + "buildId", + "intent", + "state", + "sourceEtag", + "statusUrl", + "attempts", + "acceptedAt", + "updatedAt", + "finishedAt", + "queueDeadline", + "deadline", + "inspectionExpiresAt", + "idempotencyExpiresAt", + "elapsedMs", + "lockState", + "inputDigest" + ], + "type": "object" + } +] - added
Output schema / properties / error / properties / detailsAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] +}
- Changed
get_app_build1 field changed- added
Output schema / properties / error / properties / detailsAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] +}
- Changed
update_app2 fields changed- changed
Output schema / anyOfPrevious value: -[ - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "advisories": { - "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", - "items": { - "additionalProperties": false, - "properties": { - "data": { - "additionalProperties": {}, - "description": "Kind-specific structured payload. Shape varies per advisory kind.", - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "doc_url": { - "description": "Optional docs pointer for this advisory kind.", - "type": "string" - }, - "kind": { - "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", - "type": "string" - }, - "severity": { - "description": "Severity; omitted advisories are treated as 'info'.", - "enum": [ - "info", - "warn" - ], - "type": "string" - }, - "summary": { - "description": "Agent-facing summary. Self-sufficient; no extra context required.", - "type": "string" - }, - "userSummary": { - "description": "End-user-facing summary. Set when the advisory should render in-app.", - "type": "string" - } - }, - "required": [ - "kind", - "summary" - ], - "type": "object" - }, - "type": "array" - }, - "appName": { - "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", - "type": [ - "string", - "null" - ] - }, - "icon": { - "additionalProperties": false, - "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", - "properties": { - "bg": { - "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", - "type": "string" - }, - "emoji": { - "description": "The single emoji rendered on the icon.", - "type": "string" - } - }, - "required": [ - "emoji", - "bg" - ], - "type": "object" - }, - "id": { - "description": "UUID of the created or updated app.", - "type": "string" - }, - "ok": { - "const": true, - "description": "Indicates success. Errors arrive as content with isError:true.", - "type": "boolean" - }, - "revision": { - "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "shareUrl": { - "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", - "type": "string" - }, - "url": { - "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", - "type": "string" - }, - "warnings": { - "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", - "items": { - "type": "string" - }, - "type": "array" - } - }, - "required": [ - "ok", - "id", - "url", - "shareUrl", - "revision", - "icon" - ], - "type": "object" - }, - { - "$schema": "https://json-schema.org/draft/2020-12/schema", - "additionalProperties": false, - "properties": { - "acceptedAt": { - "type": "string" - }, - "activeRevision": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "appId": { - "description": "Existing target app ID, or the created app ID after publication.", - "type": "string" - }, - "attempts": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "buildId": { - "description": "Durable build ID. Use get_app_build to inspect progress or source.", - "type": "string" - }, - "deadline": { - "type": "string" - }, - "desiredRevision": { - "maximum": 9007199254740991, - "minimum": 0, - "type": "integer" - }, - "elapsedMs": { - "minimum": 0, - "type": "number" - }, - "error": { - "additionalProperties": false, - "properties": { - "column": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "kind": { - "type": "string" - }, - "line": { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - "message": { - "type": "string" - }, - "retryable": { - "type": "boolean" - }, - "specifier": { - "type": "string" - }, - "target": { - "type": "string" - } - }, - "required": [ - "kind", - "message", - "retryable" - ], - "type": "object" - }, - "finishedAt": { - "type": [ - "string", - "null" - ] - }, - "idempotencyExpiresAt": { - "type": [ - "string", - "null" - ] - }, - "inputDigest": { - "type": "string" - }, - "inspectionExpiresAt": { - "type": [ - "string", - "null" - ] - }, - "intent": { - "description": "The accepted operation: create, update, migrate, restore, or copy.", - "type": "string" - }, - "lockDigest": { - "type": "string" - }, - "lockState": { - "enum": [ - "locked", - "unresolved" - ], - "type": "string" - }, - "ok": { - "const": true, - "type": "boolean" - }, - "queueDeadline": { - "type": "string" - }, - "resolvedDependencies": { - "additionalProperties": false, - "properties": { - "client": { - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - }, - "server": { - "additionalProperties": { - "type": "string" - }, - "propertyNames": { - "type": "string" - }, - "type": "object" - } - }, - "required": [ - "server", - "client" - ], - "type": "object" - }, - "retryAfterSeconds": { - "description": "Wait at least this many seconds before polling again.", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - }, - "revision": { - "description": "Published app source revision.", - "exclusiveMinimum": 0, - "maximum": 9007199254740991, - "type": "integer" - }, - "source": { - "additionalProperties": false, - "description": "Exact accepted source, returned only when include_source is true.", - "properties": { - "description": { - "type": [ - "string", - "null" - ] - }, - "module": { - "type": "string" - }, - "styles": { - "type": [ - "string", - "null" - ] - }, - "ui": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "module", - "ui", - "styles", - "description" - ], - "type": "object" - }, - "sourceEtag": { - "description": "ETag identifying the immutable input accepted for this build.", - "type": "string" - }, - "state": { - "enum": [ - "queued", - "resolving", - "building", - "validating", - "published", - "failed", - "superseded", - "canceled", - "expired" - ], - "type": "string" - }, - "statusUrl": { - "description": "Authenticated HTTP status URL for this build.", - "type": "string" - }, - "updatedAt": { - "type": "string" - }, - "url": { - "description": "App URL. Present only after successful publication.", - "type": "string" - } - }, - "required": [ - "ok", - "buildId", - "intent", - "state", - "sourceEtag", - "statusUrl", - "attempts", - "acceptedAt", - "updatedAt", - "finishedAt", - "queueDeadline", - "deadline", - "inspectionExpiresAt", - "idempotencyExpiresAt", - "elapsedMs", - "lockState", - "inputDigest" - ], - "type": "object" - } -]New value: +[ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "advisories": { + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "appName": { + "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", + "type": [ + "string", + "null" + ] + }, + "icon": { + "additionalProperties": false, + "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", + "properties": { + "bg": { + "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", + "type": "string" + }, + "emoji": { + "description": "The single emoji rendered on the icon.", + "type": "string" + } + }, + "required": [ + "emoji", + "bg" + ], + "type": "object" + }, + "id": { + "description": "UUID of the created or updated app.", + "type": "string" + }, + "ok": { + "const": true, + "description": "Indicates success. Errors arrive as content with isError:true.", + "type": "boolean" + }, + "revision": { + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "shareUrl": { + "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", + "type": "string" + }, + "url": { + "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", + "type": "string" + }, + "warnings": { + "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "ok", + "id", + "url", + "shareUrl", + "revision", + "icon" + ], + "type": "object" + }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "acceptedAt": { + "type": "string" + }, + "activeRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "appId": { + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" + }, + "attempts": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "buildId": { + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" + }, + "deadline": { + "type": "string" + }, + "desiredRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "elapsedMs": { + "minimum": 0, + "type": "number" + }, + "error": { + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "details": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" + }, + "finishedAt": { + "type": [ + "string", + "null" + ] + }, + "idempotencyExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "inputDigest": { + "type": "string" + }, + "inspectionExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "intent": { + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" + }, + "lockDigest": { + "type": "string" + }, + "lockState": { + "enum": [ + "locked", + "unresolved" + ], + "type": "string" + }, + "ok": { + "const": true, + "type": "boolean" + }, + "queueDeadline": { + "type": "string" + }, + "resolvedDependencies": { + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" + }, + "retryAfterSeconds": { + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "revision": { + "description": "Published app source revision.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "source": { + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" + }, + "sourceEtag": { + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" + }, + "state": { + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" + }, + "statusUrl": { + "description": "Authenticated HTTP status URL for this build.", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "url": { + "description": "App URL. Present only after successful publication.", + "type": "string" + } + }, + "required": [ + "ok", + "buildId", + "intent", + "state", + "sourceEtag", + "statusUrl", + "attempts", + "acceptedAt", + "updatedAt", + "finishedAt", + "queueDeadline", + "deadline", + "inspectionExpiresAt", + "idempotencyExpiresAt", + "elapsedMs", + "lockState", + "inputDigest" + ], + "type": "object" + } +] - added
Output schema / properties / error / properties / detailsAdded value: +{ + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "execution": { + "enum": [ + "not_started", + "may_have_run" + ], + "type": "string" + }, + "operationId": { + "minLength": 1, + "type": "string" + }, + "reservationId": { + "minLength": 1, + "type": "string" + } + }, + "required": [ + "execution", + "operationId" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "execution": { + "const": "may_have_run", + "type": "string" + } + }, + "required": [ + "execution" + ], + "type": "object" + } + ] +}
1 tool update
- Changed
get_app3 fields changed- added
Output schema / properties / api / properties / operations / items / properties / idempotentAdded value: +{ + "description": "True when repeating the call with the same input has no further effect.", + "type": "boolean" +} - added
Output schema / properties / api / properties / operations / items / properties / openWorldAdded value: +{ + "description": "True when the route may reach beyond the app, such as the network. Default true.", + "type": "boolean" +} - changed
Output schema / properties / api / properties / operations / items / requiredPrevious value: -[ - "op", - "method", - "path", - "url", - "readOnly", - "destructive", - "public", - "tool", - "discoveredFrom" -]New value: +[ + "op", + "method", + "path", + "url", + "readOnly", + "destructive", + "idempotent", + "openWorld", + "public", + "tool", + "discoveredFrom" +]
33 tool updates
- Added
acknowledge_feedback_responses - Added
cancel_app_build - Changed
create_app41 fields changed- added
Input schema / properties / expected_revisionAdded value: +{ + "description": "Required when ESM source reuses an existing manifest.id. Pass the desired revision from get_app_source.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - added
Input schema / properties / idempotency_keyAdded value: +{ + "description": "Required for ESM builds: 8–128 visible ASCII characters. Retry the exact request with the same key to recover its build; use a new key for changed source.", + "type": "string" +} - added
Input schema / properties / migrate_contractAdded value: +{ + "description": "Set true to migrate an existing legacy manifest.id to ESM, together with expected_revision. Source submissions do not roll back contracts. History can explicitly restore a retained validated existing-contract revision.", + "type": "boolean" +} - changed
Input schema / properties / module / descriptionPrevious value: -"ES module source for the app backend. Export a `manifest`; to persist any state its `capabilities.imports` must include \"buildy:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). All persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"buildy:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export `routes` (recommended) or a default `fetch` handler serving `/api/<opName>`, each returning `{ ok: true, value }` or `{ ok: false, error: { kind, message } }`. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"buildy:browser/microphone@1.0\" (getUserMedia audio), \"buildy:browser/camera@1.0\" (getUserMedia video), \"buildy:browser/geolocation@1.0\", \"buildy:browser/clipboard-read@1.0\" (reading the clipboard), \"buildy:browser/display-capture@1.0\" (getDisplayMedia screen share), \"buildy:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"buildy:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"buildy:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"buildy:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"buildy:network/fetch@1.0\" — backend `fetch` is blocked by default and this enables it (public-only: private/loopback/cloud-metadata addresses stay blocked; claim-gated). Restrict it to the hosts the app needs with `manifest.capabilities.fetchHosts` (concrete https hosts, like imageHosts) — default-deny, any non-listed host is blocked; omit to allow any public host. For an endpoint that needs an API key, declare \"buildy:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values host-side, so the key never enters app source or the sandbox; the app OWNER sets the value in the dashboard at `/app/<id>/secrets` and the agent only references the NAME. Never embed API keys in source. To render remote images, list each https host in `manifest.capabilities.imageHosts`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.buildy.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.buildy.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the imageHosts allowlist; neither bypasses it."New value: +"Eligible ESM authors may instead select `$schema: \"https://charm.ing/schema/app-manifest/2026-09-05.json\"`, declare target-specific `dependencies.server` and `dependencies.client`, and use ordinary package imports plus exact versioned platform imports. For ESM persistence, use `import { kv } from 'charming:storage/kv@1.0'` and call `kv.get`/`kv.put` inside route handlers; omit `capabilities`. ESM creation takes its name from `manifest.meta.name`; omit `display_name`. For the existing contract, export a strict canonical `manifest` with `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"`, `id`, and `meta: { name, icon? }`. The server may insert the exact schema URL on create when the rest of the source is canonical. Unknown manifest keys are rejected. To persist state in the existing contract, `capabilities.imports` must include \"charming:storage/kv@1.0\" (without it `env.storage` is undefined and every read/write throws `storage capability not granted`). A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; it adds no discoverable route metadata. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). For the existing contract, persistence goes through `env.storage` using Workers KV semantics — `get(key)`, `put(key, value)`, `delete(key)`, `list()`; `.set`/`.add`/`.write`/`.setItem`/`.removeItem` do not exist and throw `TypeError: env.storage.<x> is not a function`. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Use env.storage for ALL persistence — it is the only storage that survives inside Claude/ChatGPT and syncs across devices. Do NOT keep app data or user state in localStorage/sessionStorage/IndexedDB: those APIs are empty inside chat hosts, so their data silently vanishes there (the most common cause of an app that appears not to save). The \"charming:browser/storage@1.0\" capability (claim-gated) unlocks them but only for throwaway, web-only caching; anything the user expects to keep belongs in env.storage. Export a `routes` array with unique `op` values and `handler` functions. Canonical route fields are `inputSchema`, `outputSchema`, and `annotations`; `method` defaults to `POST`, `path` defaults to `/api/<op>`, input defaults to a closed empty-object schema, and `public` defaults to true. Set all four MCP annotation hints when their defaults do not fit; Charming does not infer them from the HTTP method. A default `fetch` handler is an unmatched-request fallback only and is not discoverable. The following capability declarations apply only to the existing contract. Apps that use a sensitive browser capability must declare its import in `capabilities.imports` — \"charming:browser/microphone@1.0\" (getUserMedia audio), \"charming:browser/camera@1.0\" (getUserMedia video), \"charming:browser/geolocation@1.0\", \"charming:browser/clipboard-read@1.0\" (reading the clipboard), \"charming:browser/display-capture@1.0\" (getDisplayMedia screen share), \"charming:browser/midi@1.0\" (Web MIDI, navigator.requestMIDIAccess), \"charming:browser/device-motion@1.0\" (device orientation/motion: DeviceOrientationEvent/DeviceMotionEvent + iOS requestPermission), \"charming:browser/ambient-light@1.0\" (ambient light, new AmbientLightSensor), or \"charming:browser/storage@1.0\" (native client storage — localStorage/sessionStorage/IndexedDB — web-only); access is granted only after the app is claimed/authenticated. To call external HTTPS APIs from backend code, declare \"charming:network/fetch@1.0\" and list each exact origin in `manifest.permissions.server.fetch`; both are required and public-only. For an endpoint that needs an API key, declare \"charming:secrets/fetch@1.0\" to get `env.fetch` (claimed apps only) — a sealed outbound fetch that substitutes `{{secret:NAME}}` references in request HEADER values or query-parameter VALUES host-side (never a parameter name, the host, path, fragment, or body), so the key never enters app source or the sandbox; write the placeholder literally in the URL string — `URLSearchParams.set(...)` or `encodeURIComponent(...)` percent-encodes it first and it will NOT resolve; the app OWNER opens App settings, then Secrets, at `/<owner-handle>/~/apps/<app-name>/settings/secrets`, while `/app/<id>/secrets` remains the machine HTTP API. The agent only references the NAME. Never embed API keys in source. To render remote images, list each exact https origin in `manifest.permissions.browser[\"img-src\"]`. To make an image render in ANY host — standalone, ChatGPT, AND Claude inline (their injected CSP blocks a cross-origin `<img src>`) — set the src from `const src = await window.charming.images.load(remoteUrl)` (it fetches through Charming and returns a `data:` URL every embed CSP allows). `window.charming.images.proxy(remoteUrl)` returns a same-origin proxy URL that works standalone/ChatGPT but NOT in Claude inline; prefer `images.load(...)` when the app may be embedded. Both enforce the declared origins; neither bypasses them." - added
Input schema / properties / team_idAdded value: +{ + "description": "Optional destination team id. Only a team owner or admin can create an App there. Omit it to create a personal App.", + "type": "string" +} - changed
Input schema / properties / ui / descriptionPrevious value: -"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example."New value: +"Under the explicit ESM contract, this is an ES module: import declared client packages and import { api, onStateChange } from \"charming:ui/app@1.0\" to call this app and subscribe to its state changes. Under the existing contract, follow the classic JavaScript rules below. Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.charming.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.charming.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.charming.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example." - added
Output schema / anyOfAdded value: +[ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "advisories": { + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "appName": { + "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", + "type": [ + "string", + "null" + ] + }, + "icon": { + "additionalProperties": false, + "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", + "properties": { + "bg": { + "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", + "type": "string" + }, + "emoji": { + "description": "The single emoji rendered on the icon.", + "type": "string" + } + }, + "required": [ + "emoji", + "bg" + ], + "type": "object" + }, + "id": { + "description": "UUID of the created or updated app.", + "type": "string" + }, + "ok": { + "const": true, + "description": "Indicates success. Errors arrive as content with isError:true.", + "type": "boolean" + }, + "revision": { + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "shareUrl": { + "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", + "type": "string" + }, + "url": { + "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", + "type": "string" + }, + "warnings": { + "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "ok", + "id", + "url", + "shareUrl", + "revision", + "icon" + ], + "type": "object" + }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "acceptedAt": { + "type": "string" + }, + "activeRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "appId": { + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" + }, + "attempts": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "buildId": { + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" + }, + "deadline": { + "type": "string" + }, + "desiredRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "elapsedMs": { + "minimum": 0, + "type": "number" + }, + "error": { + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" + }, + "finishedAt": { + "type": [ + "string", + "null" + ] + }, + "idempotencyExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "inputDigest": { + "type": "string" + }, + "inspectionExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "intent": { + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" + }, + "lockDigest": { + "type": "string" + }, + "lockState": { + "enum": [ + "locked", + "unresolved" + ], + "type": "string" + }, + "ok": { + "const": true, + "type": "boolean" + }, + "queueDeadline": { + "type": "string" + }, + "resolvedDependencies": { + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" + }, + "retryAfterSeconds": { + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "revision": { + "description": "Published app source revision.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "source": { + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" + }, + "sourceEtag": { + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" + }, + "state": { + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" + }, + "statusUrl": { + "description": "Authenticated HTTP status URL for this build.", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "url": { + "description": "App URL. Present only after successful publication.", + "type": "string" + } + }, + "required": [ + "ok", + "buildId", + "intent", + "state", + "sourceEtag", + "statusUrl", + "attempts", + "acceptedAt", + "updatedAt", + "finishedAt", + "queueDeadline", + "deadline", + "inspectionExpiresAt", + "idempotencyExpiresAt", + "elapsedMs", + "lockState", + "inputDigest" + ], + "type": "object" + } +] - added
Output schema / properties / acceptedAtAdded value: +{ + "type": "string" +} - added
Output schema / properties / activeRevisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / advisories / descriptionPrevious value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path." - added
Output schema / properties / appIdAdded value: +{ + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" +} - removed
Output schema / properties / appName / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / appName / typeAdded value: +[ + "string", + "null" +] - added
Output schema / properties / attemptsAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / buildIdAdded value: +{ + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" +} - added
Output schema / properties / deadlineAdded value: +{ + "type": "string" +} - added
Output schema / properties / desiredRevisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / elapsedMsAdded value: +{ + "minimum": 0, + "type": "number" +} - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" +} - added
Output schema / properties / finishedAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / icon / descriptionPrevious value: -"The effective home-screen icon stored for the app, after normalization. Read this back to confirm what stuck: if you sent a `manifest.icon` and this is the default `{ emoji: \"🧱\", bg: \"#3b82f6\" }`, your icon was invalid and rejected — see `warnings`."New value: +"The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`." - added
Output schema / properties / idempotencyExpiresAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / inputDigestAdded value: +{ + "type": "string" +} - added
Output schema / properties / inspectionExpiresAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / intentAdded value: +{ + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" +} - added
Output schema / properties / lockDigestAdded value: +{ + "type": "string" +} - added
Output schema / properties / lockStateAdded value: +{ + "enum": [ + "locked", + "unresolved" + ], + "type": "string" +} - removed
Output schema / properties / ok / descriptionRemoved value: -"Indicates success. Errors arrive as content with isError:true." - added
Output schema / properties / queueDeadlineAdded value: +{ + "type": "string" +} - added
Output schema / properties / resolvedDependenciesAdded value: +{ + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" +} - added
Output schema / properties / retryAfterSecondsAdded value: +{ + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" +} - added
Output schema / properties / revisionAdded value: +{ + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / sourceAdded value: +{ + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" +} - added
Output schema / properties / sourceEtagAdded value: +{ + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" +} - added
Output schema / properties / stateAdded value: +{ + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" +} - added
Output schema / properties / statusUrlAdded value: +{ + "description": "Authenticated HTTP status URL for this build.", + "type": "string" +} - added
Output schema / properties / updatedAtAdded value: +{ + "type": "string" +} - changed
Output schema / properties / url / descriptionPrevious value: -"Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead."New value: +"App URL. Present only after successful publication." - removed
Output schema / properties / versionRemoved value: -{ - "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" -} - changed
Output schema / properties / warnings / descriptionPrevious value: -"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches, or when a provided `manifest.icon` was invalid and coerced to the default. The write succeeded; fix by adding the backend op, renaming the UI call, or correcting the icon `{ emoji, bg }`."New value: +"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field." - changed
Output schema / requiredPrevious value: -[ - "ok", - "id", - "url", - "shareUrl", - "version", - "icon" -]New value: +[ + "ok" +]
- Added
create_routine - Changed
delete_app1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Added
delete_routine - Changed
get_app25 fields changed- added
Output schema / properties / $schemaAdded value: +{ + "description": "Exact dated canonical manifest schema URL. Omitted for legacy apps.", + "enum": [ + "https://charm.ing/schema/app-manifest/2026-07-31.json", + "https://charm.ing/schema/app-manifest/2026-09-05.json" + ], + "type": "string" +} - added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / api / descriptionPrevious value: -"Full API surface — same shape as `_meta.buildy.api`, but model-facing."New value: +"Full API surface — same shape as `_meta.charming.api`, but model-facing." - changed
Output schema / properties / api / properties / operations / items / properties / input / descriptionPrevious value: -"JSON Schema for the field. Same shape passed to `route.input`/`route.output`."New value: +"JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`." - removed
Output schema / properties / api / properties / operations / items / properties / nameRemoved value: -{ - "description": "Back-compat alias of `op`. Read either; prefer `op` for new consumers.", - "type": "string" -} - changed
Output schema / properties / api / properties / operations / items / properties / output / descriptionPrevious value: -"JSON Schema for the field. Same shape passed to `route.input`/`route.output`."New value: +"JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`." - removed
Output schema / properties / appName / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / appName / typeAdded value: +[ + "string", + "null" +] - changed
Output schema / properties / appVersion / descriptionPrevious value: -"Author-declared version string for the app (whatever the manifest source set as `manifest.version`, e.g. \"0.0.1\"). Distinct from the concurrency `version` int and from `manifestVersion` (Charming contract date)."New value: +"Canonical apps return decimal String(revision). Legacy apps return their stored effective SemVer." - removed
Output schema / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / description / typeAdded value: +[ + "string", + "null" +] - changed
Output schema / properties / manifestVersion / descriptionPrevious value: -"Charming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour."New value: +"Deprecated public contract marker. Canonical apps return null; legacy apps return their stored contract date." - changed
Output schema / properties / manifestVersion / typePrevious value: -"string"New value: +[ + "string", + "null" +] - changed
Output schema / properties / recentIssues / descriptionPrevious value: -"Runtime failures recorded against the current app version since it was published (#1133): contract misses, runtime JS errors, CSP violations, and failed API calls. Present only when the current version has at least one such event — absence means a clean render. The same summary is appended to the text content. Fetch full detail with GET /app/:id/activity."New value: +"Runtime failures recorded against the current app revision since it was published (#1133): contract misses, runtime JS errors, CSP violations, and failed API calls. Present only when the current revision has at least one such event — absence means a clean render. The same summary is appended to the text content. Fetch full detail with GET /app/:id/activity." - added
Output schema / properties / recentIssues / properties / counts / properties / externalResourceFailuresAdded value: +{ + "description": "Failed external image requests, including failures caught by app code.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - changed
Output schema / properties / recentIssues / properties / counts / requiredPrevious value: -[ - "contractMisses", - "runtimeErrors", - "cspViolations", - "apiFailures", - "appLoadErrors" -]New value: +[ + "contractMisses", + "runtimeErrors", + "cspViolations", + "apiFailures", + "externalResourceFailures", + "appLoadErrors" +] - changed
Output schema / properties / recentIssues / properties / examples / items / properties / category / enumPrevious value: -[ - "contractMisses", - "runtimeErrors", - "cspViolations", - "apiFailures", - "appLoadErrors" -]New value: +[ + "contractMisses", + "runtimeErrors", + "cspViolations", + "apiFailures", + "appLoadErrors", + "externalResourceFailures" +] - changed
Output schema / properties / recentIssues / properties / examples / items / properties / kind / descriptionPrevious value: -"Underlying durable event kind: `diag_report` (runtime errors and CSP violations, distinguished by category), `contract_validation` (contract misses), `api_proxy_result` (API failures), or `app_load_error` (caught load failures)."New value: +"Underlying durable event kind: `diag_report` (runtime errors and CSP violations, distinguished by category), `contract_validation` (contract misses), `api_proxy_result` (API failures), `app_load_error` (caught load failures), or `image_proxy_result` (external image failures)." - added
Output schema / properties / recentIssues / properties / sinceRevisionAdded value: +{ + "description": "The app revision the issues are attributed to (the current revision at call time). Legacy nulls normalize to 0.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - removed
Output schema / properties / recentIssues / properties / sinceVersionRemoved value: -{ - "anyOf": [ - { - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" - }, - { - "type": "null" - } - ], - "description": "The app version the issues are attributed to (the current version at call time). Null on legacy rows that predate versioning." -} - changed
Output schema / properties / recentIssues / properties / total / descriptionPrevious value: -"Issue events counted for the current version, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list."New value: +"Issue events counted for the current revision, capped at 500 — a value of 500 means 500 or more. Use GET /app/:id/activity for the exact, paginated list." - changed
Output schema / properties / recentIssues / requiredPrevious value: -[ - "sinceVersion", - "total", - "counts", - "examples" -]New value: +[ + "sinceRevision", + "total", + "counts", + "examples" +] - added
Output schema / properties / revisionAdded value: +{ + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - removed
Output schema / properties / versionRemoved value: -{ - "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" -} - changed
Output schema / requiredPrevious value: -[ - "ok", - "id", - "url", - "shareUrl", - "displayName", - "description", - "manifestId", - "version", - "appVersion", - "manifestVersion", - "api" -]New value: +[ + "ok", + "id", + "url", + "shareUrl", + "displayName", + "description", + "manifestId", + "revision", + "appVersion", + "manifestVersion", + "api" +]
- Added
get_app_build - Changed
get_app_source17 fields changed- added
Output schema / properties / $schemaAdded value: +{ + "description": "Exact dated canonical manifest schema URL. Omitted for legacy apps.", + "enum": [ + "https://charm.ing/schema/app-manifest/2026-07-31.json", + "https://charm.ing/schema/app-manifest/2026-09-05.json" + ], + "type": "string" +} - changed
Output schema / properties / advisories / descriptionPrevious value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path." - changed
Output schema / properties / appVersion / descriptionPrevious value: -"Author-declared version string for the app (whatever the manifest source set as `manifest.version`, e.g. \"0.0.1\"). Distinct from the concurrency `version` int and from `manifestVersion` (Charming contract date)."New value: +"Canonical apps return decimal String(revision). Legacy apps return their stored effective SemVer." - changed
Output schema / properties / capabilities / properties / imports / descriptionPrevious value: -"WIT-style capability ids the app requests (e.g. \"buildy:storage/kv@1.0\"). Empty if the app declares none."New value: +"WIT-style capability ids the app requests (e.g. \"charming:storage/kv@1.0\"). Empty if the app declares none." - removed
Output schema / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / description / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / expiresAt / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / expiresAt / typeAdded value: +[ + "string", + "null" +] - changed
Output schema / properties / manifestVersion / descriptionPrevious value: -"Charming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour."New value: +"Deprecated public contract marker. Canonical apps return null; legacy apps return their stored contract date." - changed
Output schema / properties / manifestVersion / typePrevious value: -"string"New value: +[ + "string", + "null" +] - added
Output schema / properties / revisionAdded value: +{ + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - removed
Output schema / properties / source / properties / styles / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / source / properties / styles / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / source / properties / ui / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / source / properties / ui / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / versionRemoved value: -{ - "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" -} - changed
Output schema / requiredPrevious value: -[ - "ok", - "id", - "url", - "manifestId", - "sourceManifestId", - "displayName", - "description", - "version", - "appVersion", - "manifestVersion", - "capabilities", - "claimed", - "expiresAt", - "source" -]New value: +[ + "ok", + "id", + "url", + "manifestId", + "sourceManifestId", + "displayName", + "description", + "revision", + "appVersion", + "manifestVersion", + "capabilities", + "claimed", + "expiresAt", + "source" +]
- Changed
list_app_shares3 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - removed
Output schema / properties / shares / items / properties / accepted_at / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / shares / items / properties / accepted_at / typeAdded value: +[ + "string", + "null" +]
- Changed
list_apps9 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - removed
Output schema / properties / apps / items / properties / appName / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / apps / items / properties / appName / typeAdded value: +[ + "string", + "null" +] - changed
Output schema / properties / apps / items / properties / capabilities / properties / exports / descriptionPrevious value: -"Operations this app exposes to other apps via `window.buildy.api(<id>).<export>()`. Use to plan cross-app integrations without round-tripping through get_app_source."New value: +"Operations this app exposes to other apps via `window.charming.api(<id>).<export>()`. Use to plan cross-app integrations without round-tripping through get_app_source." - changed
Output schema / properties / apps / items / properties / capabilities / properties / imports / descriptionPrevious value: -"Capability tokens the app depends on (e.g. \"buildy:storage/kv@1.0\", \"buildy:browser/microphone@1.0\")."New value: +"Capability tokens the app depends on (e.g. \"charming:storage/kv@1.0\", \"charming:browser/microphone@1.0\")." - removed
Output schema / properties / apps / items / properties / description / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / apps / items / properties / description / typeAdded value: +[ + "string", + "null" +] - added
Output schema / properties / apps / items / properties / revisionAdded value: +{ + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / apps / items / requiredPrevious value: -[ - "id", - "role", - "displayName", - "description", - "url", - "shareUrl", - "lastUpdatedAt", - "claimed", - "capabilities" -]New value: +[ + "id", + "role", + "displayName", + "revision", + "description", + "url", + "shareUrl", + "lastUpdatedAt", + "claimed", + "capabilities" +]
- Changed
list_feedback8 fields changed- changed
Input schema / properties / since / patternPrevious value: -"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"New value: +"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z))$" - added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - removed
Output schema / properties / cursor / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / cursor / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / items / items / properties / text / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / items / items / properties / text / typeAdded value: +[ + "string", + "null" +] - removed
Output schema / properties / items / items / properties / user_id / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / items / items / properties / user_id / typeAdded value: +[ + "string", + "null" +]
- Added
list_feedback_responses - Added
list_routines - Changed
mutate_app1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Changed
query_app1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Added
read_docs - Changed
rename_app1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Added
search_templates - Changed
set_handle1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Changed
set_public3 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / message / descriptionPrevious value: -"Consequence copy the agent should surface verbatim to the user. WARNS that anyone with the URL can read and overwrite (or wipe) the shared data, with no login and no per-visitor isolation."New value: +"Consequence copy the agent should surface verbatim to the user. It states that anyone with the URL can view the live App with no login but cannot change its data or source." - changed
Output schema / properties / public_url / descriptionPrevious value: -"Public URL for the now-public app. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Anyone can open this URL with no login and read AND write the app's SHARED data. Free of write-capable `?t=` tokens."New value: +"Public URL for the now-Public App. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Anyone can open this URL with no login and view the live App and its data, but cannot change data or source. Free of write-capable `?t=` tokens."
- Changed
set_remixable2 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / public_url / descriptionPrevious value: -"Public share URL for the now-remixable app. Friendly `/<handle>/<app-name>` form when available, `/app/<uuid>` otherwise. Visitors opening this URL get their own brand-new editable copy; the original is never mutated. Free of write-capable `?t=` tokens."New value: +"Canonical `/templates/<handle>/<app-name>` Template page when the owner and App have public names. A person who can already read the source App can choose to create an editable copy after signing in; the original is never mutated. Free of write-capable `?t=` tokens."
- Changed
set_starter_prompt3 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - removed
Output schema / properties / starter_prompt / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / starter_prompt / typeAdded value: +[ + "string", + "null" +]
- Added
set_template - Changed
share_app3 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / message / descriptionPrevious value: -"Consequence copy the agent should surface verbatim: the invitee has no access until they accept, and what they will be able to do once they do."New value: +"Consequence copy the agent should surface verbatim: the invitee has no access until they choose Open app, and what their role permits after the durable grant succeeds." - changed
Output schema / properties / status / descriptionPrevious value: -"Sharing creates an invitation, not access. `pending` = the grantee has a Charming account and must accept (dashboard or invite email). `invited` = the email has no account yet; it becomes a pending share once they register and verify that address. `updated` = the grantee already had a share and re-sharing with a `role` changed it in place (no new invitation, no second email)."New value: +"Sharing creates an invitation, not access. `pending` = the grantee has a Charming account and gets access only when that account chooses Open app. `invited` = the email has no account yet; it becomes a pending share once they register and verify that address. `updated` = the grantee already had a share and re-sharing with a `role` changed it in place (no new invitation, no second email)."
- Changed
submit_feedback1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Changed
unset_public1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Changed
unset_remixable1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Added
unset_template - Changed
unshare_app1 field changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +}
- Changed
update_app42 fields changed- changed
Input schema / properties / edits / descriptionPrevious value: -"Edits path. Array of exact-string find/replace operations applied atomically. Pass `expected_version` alongside to gate optimistic-concurrency. Mutually exclusive with full-source fields (`module` / `ui` / `styles`)."New value: +"Edits path. Array of exact-string find/replace operations applied atomically. Pass the last-read revision through `expected_revision` to gate optimistic concurrency. Mutually exclusive with full-source fields (`module` / `ui` / `styles`)." - added
Input schema / properties / expected_revisionAdded value: +{ + "description": "Revision precondition. Required for every ESM save and for existing-contract edits[]. Pass revision from your last get_app_source response. A new request against a stale desired revision fails with revision_mismatch; an identical idempotent retry returns its original build.", + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" +} - changed
Input schema / properties / expected_version / descriptionPrevious value: -"Required when `edits[]` is present. Pass the `version` from your last get_app_source or update_app response. If the stored version has advanced, the edit is rejected with `version_mismatch` and the current version is surfaced so you can re-read and retry."New value: +"Deprecated compatibility input. Use `expected_revision`; while legacy hosts remain active, expected_version maps to the same revision precondition." - added
Input schema / properties / idempotency_keyAdded value: +{ + "description": "Required for ESM saves. Retry the exact request with the same key; use a new key and current expected_revision for a new save.", + "type": "string" +} - added
Input schema / properties / migrate_contractAdded value: +{ + "description": "Set true only when replacing a legacy app with a complete valid dated manifest and routes contract. Source submissions do not roll back contracts. History can explicitly restore a retained validated existing-contract revision.", + "type": "boolean" +} - changed
Input schema / properties / module / descriptionPrevious value: -"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus route handlers that use env.storage.get/put. default.fetch is optional; Charming supplies a generic 404 handler when it is absent. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement ES module source. Same selected contract as create_app. For the existing contract, declare capabilities.imports including \"charming:storage/kv@1.0\" for persistence. For ESM, keep the exact ESM schema and import { kv } from \"charming:storage/kv@1.0\"; omit capabilities. A route handler in `export const routes = [...]` receives `(input, { env, ctx, request })` and returns exactly the value declared by `outputSchema`; for an array schema, use `handler: async (_input, { env }) => (await env.storage.get(\"key\")) ?? []`. Charming creates the transport envelope. Do not add a `{ ok, value }` or `{ value }` envelope unless those fields belong to `outputSchema` itself. A named context reads storage as `context.env.storage`. The optional unmatched-request fallback has the separate signature `export default { fetch(request, env, ctx) { ... } }`, where the second argument is the environment itself; Charming supplies a generic 404 handler when it is absent. `env.user` is always present, not gated by any import: the caller's public identity (`{ id, handle?, name?, image? }`) or `null`. It lives only on `env` — read `env.user` (or `context.env.user`); there is no `ctx.user`. Full reference: call read_docs with path `llms-full.txt` (https://charm.ing/docs/llms-full.txt). Keep persisted state in backend storage (env.storage for the existing contract, imported kv for ESM); do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`. Migrating a legacy app to the existing dated contract requires the complete canonical manifest with the exact dated `$schema: \"https://charm.ing/schema/app-manifest/2026-07-31.json\"` plus `migrate_contract: true`; on this full-source path only, an omitted `$schema` is inserted automatically, but a wrong one still fails. ESM migration instead selects `https://charm.ing/schema/app-manifest/2026-09-05.json` through full-source or edits and requires `migrate_contract: true`, `expected_revision`, and `idempotency_key`." - changed
Input schema / properties / ui / descriptionPrevious value: -"Full-source path only. Optional replacement frontend JavaScript. Same contract as create_app: must (a) populate #app innerHTML BEFORE attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — NOT `api.operation(name, params)` and NOT raw fetch(). The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors. Cap the reading measure on an INNER wrapper only for text-heavy views, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement frontend JavaScript. Follow the create_app rules for the selected contract. Existing-contract UI must (a) populate #app innerHTML BEFORE attaching event listeners, and (b) call operations as `window.charming.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — NOT `api.operation(name, params)` and NOT raw fetch(). The signed-in caller is exposed synchronously as `window.charming.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors. Cap the reading measure on an INNER wrapper only for text-heavy views, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Mutually exclusive with `edits`." - added
Output schema / anyOfAdded value: +[ + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "advisories": { + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" + }, + "appName": { + "description": "URL-safe slug for the app, unique per owner. Distinct from manifestId and displayName, and stable across edits — use rename_app to change it (the title changing does NOT change the slug).", + "type": [ + "string", + "null" + ] + }, + "icon": { + "additionalProperties": false, + "description": "The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`.", + "properties": { + "bg": { + "description": "The icon background as a hex color (e.g. \"#1d8a4e\").", + "type": "string" + }, + "emoji": { + "description": "The single emoji rendered on the icon.", + "type": "string" + } + }, + "required": [ + "emoji", + "bg" + ], + "type": "object" + }, + "id": { + "description": "UUID of the created or updated app.", + "type": "string" + }, + "ok": { + "const": true, + "description": "Indicates success. Errors arrive as content with isError:true.", + "type": "boolean" + }, + "revision": { + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "shareUrl": { + "description": "The link to give humans whenever the user wants to open or share the app. Friendly /<handle>/<app-name> form when the OWNER has a live handle and the app a slug, /app/<uuid> otherwise. Always token-free — safe to show, paste, and send. Not an API base: appending /api/<op> to the friendly form 404s; use `url` for machine calls.", + "type": "string" + }, + "url": { + "description": "Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead.", + "type": "string" + }, + "warnings": { + "description": "Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field.", + "items": { + "type": "string" + }, + "type": "array" + } + }, + "required": [ + "ok", + "id", + "url", + "shareUrl", + "revision", + "icon" + ], + "type": "object" + }, + { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "additionalProperties": false, + "properties": { + "acceptedAt": { + "type": "string" + }, + "activeRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "appId": { + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" + }, + "attempts": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "buildId": { + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" + }, + "deadline": { + "type": "string" + }, + "desiredRevision": { + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" + }, + "elapsedMs": { + "minimum": 0, + "type": "number" + }, + "error": { + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" + }, + "finishedAt": { + "type": [ + "string", + "null" + ] + }, + "idempotencyExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "inputDigest": { + "type": "string" + }, + "inspectionExpiresAt": { + "type": [ + "string", + "null" + ] + }, + "intent": { + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" + }, + "lockDigest": { + "type": "string" + }, + "lockState": { + "enum": [ + "locked", + "unresolved" + ], + "type": "string" + }, + "ok": { + "const": true, + "type": "boolean" + }, + "queueDeadline": { + "type": "string" + }, + "resolvedDependencies": { + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" + }, + "retryAfterSeconds": { + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "revision": { + "description": "Published app source revision.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" + }, + "source": { + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" + }, + "sourceEtag": { + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" + }, + "state": { + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" + }, + "statusUrl": { + "description": "Authenticated HTTP status URL for this build.", + "type": "string" + }, + "updatedAt": { + "type": "string" + }, + "url": { + "description": "App URL. Present only after successful publication.", + "type": "string" + } + }, + "required": [ + "ok", + "buildId", + "intent", + "state", + "sourceEtag", + "statusUrl", + "attempts", + "acceptedAt", + "updatedAt", + "finishedAt", + "queueDeadline", + "deadline", + "inspectionExpiresAt", + "idempotencyExpiresAt", + "elapsedMs", + "lockState", + "inputDigest" + ], + "type": "object" + } +] - added
Output schema / properties / acceptedAtAdded value: +{ + "type": "string" +} - added
Output schema / properties / activeRevisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - changed
Output schema / properties / advisories / descriptionPrevious value: -"Structured advisories attached when the tool detected a non-fatal authoring issue (e.g. legacy bridge usage). Each advisory.summary is also appended to the text content for the LLM path."New value: +"Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path." - added
Output schema / properties / appIdAdded value: +{ + "description": "Existing target app ID, or the created app ID after publication.", + "type": "string" +} - removed
Output schema / properties / appName / anyOfRemoved value: -[ - { - "type": "string" - }, - { - "type": "null" - } -] - added
Output schema / properties / appName / typeAdded value: +[ + "string", + "null" +] - added
Output schema / properties / attemptsAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / buildIdAdded value: +{ + "description": "Durable build ID. Use get_app_build to inspect progress or source.", + "type": "string" +} - added
Output schema / properties / deadlineAdded value: +{ + "type": "string" +} - added
Output schema / properties / desiredRevisionAdded value: +{ + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / elapsedMsAdded value: +{ + "minimum": 0, + "type": "number" +} - added
Output schema / properties / errorAdded value: +{ + "additionalProperties": false, + "properties": { + "column": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "kind": { + "type": "string" + }, + "line": { + "maximum": 9007199254740991, + "minimum": -9007199254740991, + "type": "integer" + }, + "message": { + "type": "string" + }, + "retryable": { + "type": "boolean" + }, + "specifier": { + "type": "string" + }, + "target": { + "type": "string" + } + }, + "required": [ + "kind", + "message", + "retryable" + ], + "type": "object" +} - added
Output schema / properties / finishedAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - changed
Output schema / properties / icon / descriptionPrevious value: -"The effective home-screen icon stored for the app, after normalization. Read this back to confirm what stuck: if you sent a `manifest.icon` and this is the default `{ emoji: \"🧱\", bg: \"#3b82f6\" }`, your icon was invalid and rejected — see `warnings`."New value: +"The effective home-screen icon stored for the app. Canonical source declares it at `manifest.meta.icon`." - added
Output schema / properties / idempotencyExpiresAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / inputDigestAdded value: +{ + "type": "string" +} - added
Output schema / properties / inspectionExpiresAtAdded value: +{ + "type": [ + "string", + "null" + ] +} - added
Output schema / properties / intentAdded value: +{ + "description": "The accepted operation: create, update, migrate, restore, or copy.", + "type": "string" +} - added
Output schema / properties / lockDigestAdded value: +{ + "type": "string" +} - added
Output schema / properties / lockStateAdded value: +{ + "enum": [ + "locked", + "unresolved" + ], + "type": "string" +} - removed
Output schema / properties / ok / descriptionRemoved value: -"Indicates success. Errors arrive as content with isError:true." - added
Output schema / properties / queueDeadlineAdded value: +{ + "type": "string" +} - added
Output schema / properties / resolvedDependenciesAdded value: +{ + "additionalProperties": false, + "properties": { + "client": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "server": { + "additionalProperties": { + "type": "string" + }, + "propertyNames": { + "type": "string" + }, + "type": "object" + } + }, + "required": [ + "server", + "client" + ], + "type": "object" +} - added
Output schema / properties / retryAfterSecondsAdded value: +{ + "description": "Wait at least this many seconds before polling again.", + "exclusiveMinimum": 0, + "maximum": 9007199254740991, + "type": "integer" +} - added
Output schema / properties / revisionAdded value: +{ + "description": "Server-owned app source revision. Historical null counters read as 0; new apps start at 1; each successful source write advances it once. Pass this value through `expected_revision` when guarding update_app.", + "maximum": 9007199254740991, + "minimum": 0, + "type": "integer" +} - added
Output schema / properties / sourceAdded value: +{ + "additionalProperties": false, + "description": "Exact accepted source, returned only when include_source is true.", + "properties": { + "description": { + "type": [ + "string", + "null" + ] + }, + "module": { + "type": "string" + }, + "styles": { + "type": [ + "string", + "null" + ] + }, + "ui": { + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "module", + "ui", + "styles", + "description" + ], + "type": "object" +} - added
Output schema / properties / sourceEtagAdded value: +{ + "description": "ETag identifying the immutable input accepted for this build.", + "type": "string" +} - added
Output schema / properties / stateAdded value: +{ + "enum": [ + "queued", + "resolving", + "building", + "validating", + "published", + "failed", + "superseded", + "canceled", + "expired" + ], + "type": "string" +} - added
Output schema / properties / statusUrlAdded value: +{ + "description": "Authenticated HTTP status URL for this build.", + "type": "string" +} - added
Output schema / properties / updatedAtAdded value: +{ + "type": "string" +} - changed
Output schema / properties / url / descriptionPrevious value: -"Machine/API URL for the app (stable /app/<uuid> form). Embeds a write-capable ?t= access token — NEVER show, paste, or send it to the user. Append /api/<op> to its path for out-of-band operation calls. For anything user-facing, use shareUrl instead."New value: +"App URL. Present only after successful publication." - removed
Output schema / properties / versionRemoved value: -{ - "description": "Monotonic int version of the app. 0 on truly-legacy rows that predate versioning (still editable — pass `expected_version: 0`); otherwise a positive int bumped on every successful update_app/PUT. Pass back as `expected_version` on edits-aware update_app and as `If-Match: \"v<N>\"` on PATCH /app/:id/source.", - "maximum": 9007199254740991, - "minimum": -9007199254740991, - "type": "integer" -} - changed
Output schema / properties / warnings / descriptionPrevious value: -"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches, or when a provided `manifest.icon` was invalid and coerced to the default. The write succeeded; fix by adding the backend op, renaming the UI call, or correcting the icon `{ emoji, bg }`."New value: +"Non-blocking publish feedback (#1126): present when static validation found UI/backend contract mismatches or legacy icon input needed a fallback. The write succeeded; fix the named source field." - changed
Output schema / requiredPrevious value: -[ - "ok", - "id", - "url", - "shareUrl", - "version", - "icon" -]New value: +[ + "ok" +]
- Added
update_routine - Changed
upload_asset2 fields changed- added
Output schema / properties / advisoriesAdded value: +{ + "description": "Structured non-fatal advisories, including authoring issues and unread staff feedback responses. Each advisory.summary is also appended to the text content for the LLM path.", + "items": { + "additionalProperties": false, + "properties": { + "data": { + "additionalProperties": {}, + "description": "Kind-specific structured payload. Shape varies per advisory kind.", + "propertyNames": { + "type": "string" + }, + "type": "object" + }, + "doc_url": { + "description": "Optional docs pointer for this advisory kind.", + "type": "string" + }, + "kind": { + "description": "Stable advisory identifier (e.g. \"legacy-bridge\").", + "type": "string" + }, + "severity": { + "description": "Severity; omitted advisories are treated as 'info'.", + "enum": [ + "info", + "warn" + ], + "type": "string" + }, + "summary": { + "description": "Agent-facing summary. Self-sufficient; no extra context required.", + "type": "string" + }, + "userSummary": { + "description": "End-user-facing summary. Set when the advisory should render in-app.", + "type": "string" + } + }, + "required": [ + "kind", + "summary" + ], + "type": "object" + }, + "type": "array" +} - changed
Output schema / properties / url / descriptionPrevious value: -"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.buildy.assets.getUrl(key)."New value: +"Same-origin URL serving the asset. Use in <img src>/<a href>/fetch, or read in the backend via env.assets.get(key). Equivalent to window.charming.assets.getUrl(key)."
1 tool update
- Changed
update_app1 field changed- changed
Input schema / properties / module / descriptionPrevious value: -"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus a default.fetch handler that routes /api/<opName> requests using env.storage.get/put. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."New value: +"Full-source path only. Optional replacement ES module source. Same contract as create_app: must export a `manifest` with capabilities.imports including \"buildy:storage/kv@1.0\" for any app that persists state, plus route handlers that use env.storage.get/put. default.fetch is optional; Charming supplies a generic 404 handler when it is absent. Keep all persisted state in env.storage — do not move it into localStorage/sessionStorage/IndexedDB, which are empty inside Claude/ChatGPT and lose the data. env.storage stores JSON-compatible values directly; do not JSON.stringify before put or JSON.parse after get. Mutually exclusive with `edits`."
1 tool update
- Changed
create_app1 field changed- changed
Input schema / properties / ui / descriptionPrevious value: -"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the buildy:app-guide prompt for a canonical example."New value: +"Frontend JavaScript rendered into #app. The #app mount point starts empty, so (a) populate its innerHTML before attaching event listeners, and (b) call operations as `window.buildy.api('<manifest-id>').<opName>(input)` (operation name = method name, strips the { ok, value } envelope — you receive the value only, never ok) — not `api.operation(name, params)` and not raw fetch(), which fails in the null-origin srcdoc iframe. The signed-in caller is exposed synchronously as `window.buildy.user` (`{ id, handle?, name?, image? }`, or `null` for an anonymous visitor) — read `user.name` to greet, attribute, or personalize, instead of asking the user to type their name. PUBLIC fields only (never email); it is a convenience signal, not enforcement. The outermost container MUST fill the viewport — use `<main class=\"min-h-screen\">` (or a grid/flex layout that spans width) as the root shell. Do NOT wrap the root in `max-w-md`, `max-w-2xl`, or `container mx-auto`: those cap the entire app to a narrow central column with wide empty margins on 2K+ monitors — the loudest \"AI-generated app\" tell. If the view is text-heavy (a note, an article, a form with long prose), cap the reading measure on an INNER wrapper only, e.g. `<main class=\"min-h-screen\"><div class=\"mx-auto max-w-2xl\">…</div></main>`. Dashboards, kanban, tables, canvases, galleries, and split views should use the full width. For live updates when an agent mutates state from another session, register `window.buildy.onStateChange((e) => { ... })` and update the DOM surgically rather than wiping #app. See the charming:app-guide prompt for a canonical example."
21 tool updates
- First observed
create_app - First observed
delete_app - First observed
get_app - First observed
get_app_source - First observed
list_app_shares - First observed
list_apps - First observed
list_feedback - First observed
mutate_app - First observed
query_app - First observed
rename_app - First observed
set_handle - First observed
set_public - First observed
set_remixable - First observed
set_starter_prompt - First observed
share_app - First observed
submit_feedback - First observed
unset_public - First observed
unset_remixable - First observed
unshare_app - First observed
update_app - First observed
upload_asset
Related MCP Connectors
Publish AND operate micro-apps from your AI. No account, no API key. Stable URL, EU-hosted.
Build and publish web apps from your AI client: live preview, Postgres, storage, public URL.
Host apps built with AI: deploy to a live HTTPS URL, custom domains, secrets and backups.
Host AI-generated single-file HTML apps with JSON persistence. No signup.
Related MCP Servers
AlicenseNot gradedqualityAmaintenanceInstant secure Full Stack Apps and AI Agents1,198MIT- AlicenseAqualityCmaintenancePublish live web pages from AI coding agents. Instant shareable URLs for dashboards, landing pages, and reports with password protection.41MIT
- AlicenseAqualityBmaintenanceEnables building and shipping real apps directly from Claude or ChatGPT by scaffolding projects, editing code, running live previews with public share URLs, storing data, sending email and push notifications, deploying to hosting, and exporting finished repos.22MIT
- AlicenseBqualityCmaintenanceEnables AI assistants to scaffold, edit, live-preview, and deploy full-stack apps with built-in database, email, and push notification capabilities through natural language.19MIT
Glama MCP Gateway
Add one secure layer between your agents and this server.