Skip to content
Charming Docs
Esc
navigateopen⌘Jpreview
On this page

Get App

Fetch an existing app by ID and render it inline.

MCP name: get_app

Tool contract

{
  "_meta": {
    "ui": {
      "resourceUri": "ui://charming/app"
    },
    "ui/resourceUri": "ui://charming/app"
  },
  "annotations": {
    "destructiveHint": false,
    "openWorldHint": false,
    "readOnlyHint": true,
    "title": "Get App"
  },
  "description": "Fetch an existing app by ID and render it inline. Use this to open, re-render, or continue working with an app the caller already has. Returns the live embedded UI plus its callable API operations, which another agent can invoke with query_app (read-only) or mutate_app (writes) to query or update saved app data. Unlike list_apps, which returns metadata including IDs and URLs, get_app renders the app; call list_apps first to find the ID. When telling the user where to open or share the app, always give them `shareUrl` from the result — never the `url` field, which is machine-only and embeds a write-capable access token.",
  "execution": {
    "taskSupport": "forbidden"
  },
  "inputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "properties": {
      "app_id": {
        "description": "The app ID (UUID)",
        "format": "uuid",
        "pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$",
        "type": "string"
      }
    },
    "required": [
      "app_id"
    ],
    "type": "object"
  },
  "name": "get_app",
  "outputSchema": {
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "additionalProperties": false,
    "properties": {
      "$schema": {
        "const": "https://charm.ing/schema/app-manifest/2026-07-31.json",
        "description": "Exact dated canonical manifest schema URL. Omitted for legacy apps.",
        "type": "string"
      },
      "advisories": {
        "description": "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.",
        "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"
      },
      "api": {
        "additionalProperties": false,
        "description": "Full API surface — same shape as `_meta.charming.api`, but model-facing.",
        "properties": {
          "baseUrl": {
            "description": "Origin + app prefix the operations live under.",
            "type": "string"
          },
          "operations": {
            "description": "Discovered routes in author order.",
            "items": {
              "additionalProperties": false,
              "properties": {
                "description": {
                  "description": "Author-supplied prose description.",
                  "type": "string"
                },
                "destructive": {
                  "description": "True when the route destroys data. Default false unless derived as such.",
                  "type": "boolean"
                },
                "discoveredFrom": {
                  "description": "Sources that contributed this operation (precedence order).",
                  "items": {
                    "enum": [
                      "routes_export",
                      "manifest_export",
                      "module_route"
                    ],
                    "type": "string"
                  },
                  "type": "array"
                },
                "examples": {
                  "description": "Author-supplied calling examples that flow into the query_app/mutate_app snippet.",
                  "items": {
                    "additionalProperties": false,
                    "properties": {
                      "description": {
                        "type": "string"
                      },
                      "input": {},
                      "output": {}
                    },
                    "type": "object"
                  },
                  "type": "array"
                },
                "input": {
                  "description": "JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`."
                },
                "manifestExport": {
                  "description": "Original capability-export string when discovered via `manifest_export`.",
                  "type": "string"
                },
                "method": {
                  "description": "HTTP method the route accepts.",
                  "enum": [
                    "GET",
                    "POST",
                    "PUT",
                    "PATCH",
                    "DELETE"
                  ],
                  "type": "string"
                },
                "op": {
                  "description": "Operation name. Matches the `op` field on the corresponding Route.",
                  "type": "string"
                },
                "output": {
                  "description": "JSON Schema for the field. Canonical source declares it as `route.inputSchema` or `route.outputSchema`."
                },
                "path": {
                  "description": "Path under the app, e.g. `/api/increment`.",
                  "type": "string"
                },
                "public": {
                  "description": "True when the route is visible to discovery. Default true.",
                  "type": "boolean"
                },
                "readOnly": {
                  "description": "True when the route is a safe read (resolved from author intent + derivation).",
                  "type": "boolean"
                },
                "title": {
                  "description": "Short author-supplied title for the operation.",
                  "type": "string"
                },
                "tool": {
                  "description": "MCP tool to invoke this op: `query_app` for read-only, `mutate_app` otherwise.",
                  "enum": [
                    "query_app",
                    "mutate_app"
                  ],
                  "type": "string"
                },
                "url": {
                  "description": "Full URL (origin + app prefix + path).",
                  "type": "string"
                }
              },
              "required": [
                "op",
                "method",
                "path",
                "url",
                "readOnly",
                "destructive",
                "public",
                "tool",
                "discoveredFrom"
              ],
              "type": "object"
            },
            "type": "array"
          }
        },
        "required": [
          "baseUrl",
          "operations"
        ],
        "type": "object"
      },
      "appName": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ],
        "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)."
      },
      "appVersion": {
        "description": "Canonical apps return decimal String(revision). Legacy apps return their stored effective SemVer.",
        "type": "string"
      },
      "description": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ],
        "description": "Search-friendly summary of what the app does. Null on apps created before descriptions existed; agents are nudged to backfill on the next update_app."
      },
      "displayName": {
        "description": "Human-readable name shown in app listings and headers.",
        "type": "string"
      },
      "id": {
        "description": "UUID of the opened app.",
        "type": "string"
      },
      "manifestId": {
        "description": "Stable manifest identifier declared by the app module. Distinct from `id` (DB primary key) — surface this when discussing the app with the user.",
        "type": "string"
      },
      "manifestVersion": {
        "anyOf": [
          {
            "type": "string"
          },
          {
            "type": "null"
          }
        ],
        "description": "Deprecated public contract marker. Canonical apps return null; legacy apps return their stored contract date."
      },
      "ok": {
        "const": true,
        "description": "Indicates success. Errors arrive as content with isError:true.",
        "type": "boolean"
      },
      "recentIssues": {
        "additionalProperties": false,
        "description": "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.",
        "properties": {
          "counts": {
            "additionalProperties": false,
            "description": "Issue counts per category.",
            "properties": {
              "apiFailures": {
                "description": "Failed calls to the app API proxy.",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              "appLoadErrors": {
                "description": "Caught manifest-resolve / app load failures the bridge swallowed before they became an unhandled rejection.",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              "contractMisses": {
                "description": "Publish-time UI/backend contract validation failures.",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              "cspViolations": {
                "description": "Content-Security-Policy violations (e.g. an external image blocked by img-src).",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              },
              "runtimeErrors": {
                "description": "Runtime JS errors and unhandled rejections reported by the rendered page.",
                "maximum": 9007199254740991,
                "minimum": -9007199254740991,
                "type": "integer"
              }
            },
            "required": [
              "contractMisses",
              "runtimeErrors",
              "cspViolations",
              "apiFailures",
              "appLoadErrors"
            ],
            "type": "object"
          },
          "examples": {
            "description": "Most recent example per non-empty category, newest first.",
            "items": {
              "additionalProperties": false,
              "properties": {
                "category": {
                  "description": "Which `counts` bucket this example illustrates.",
                  "enum": [
                    "contractMisses",
                    "runtimeErrors",
                    "cspViolations",
                    "apiFailures",
                    "appLoadErrors"
                  ],
                  "type": "string"
                },
                "kind": {
                  "description": "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).",
                  "type": "string"
                },
                "summary": {
                  "description": "Compact one-line description.",
                  "type": "string"
                },
                "ts": {
                  "description": "ISO-8601 timestamp of the event.",
                  "type": "string"
                }
              },
              "required": [
                "ts",
                "category",
                "kind",
                "summary"
              ],
              "type": "object"
            },
            "type": "array"
          },
          "sinceRevision": {
            "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"
          },
          "total": {
            "description": "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.",
            "maximum": 9007199254740991,
            "minimum": -9007199254740991,
            "type": "integer"
          }
        },
        "required": [
          "sinceRevision",
          "total",
          "counts",
          "examples"
        ],
        "type": "object"
      },
      "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"
      }
    },
    "required": [
      "ok",
      "id",
      "url",
      "shareUrl",
      "displayName",
      "description",
      "manifestId",
      "revision",
      "appVersion",
      "manifestVersion",
      "api"
    ],
    "type": "object"
  }
}

ChatGPT metadata

ChatGPT adds or replaces these fields for progress messages and inline app rendering.

{
  "_meta": {
    "openai/outputTemplate": "ui://charming/chatgpt/app-v1",
    "openai/toolInvocation/invoked": "App ready",
    "openai/toolInvocation/invoking": "Opening app…",
    "ui": {
      "resourceUri": "ui://charming/chatgpt/app-v1"
    },
    "ui/resourceUri": "ui://charming/chatgpt/app-v1"
  }
}

Was this page helpful?