List Apps
List the caller's Charming apps — owned ones plus apps shared with them (accepted invites, marked `[shared with you]`; a read-only share also reads `(view-only)`).
MCP name: list_apps
Tool contract
{
"annotations": {
"destructiveHint": false,
"openWorldHint": false,
"readOnlyHint": true,
"title": "List Apps"
},
"description": "List the caller's Charming apps — owned ones plus apps shared with them (accepted invites, marked `[shared with you]`; a read-only share also reads `(view-only)`). Use this to find an app's id before fetching, editing, or calling it. Returns per app: id, revision, role (owner | collaborator | end-user | viewer | team-admin | team-member), displayName, description (a search-friendly summary), url (machine API base), shareUrl (the link to give the user), lastUpdatedAt (ISO-8601 of the last write), claimed (always true for now — exposed for forward-compat), and capabilities (imports + exports). A `collaborator` can edit and run a shared app; an `end-user` can run it and write its data but cannot edit the app source; a `viewer` can only open and read it. The description disambiguates apps with similar display names; capabilities.exports lists each app's callable operations, exposing the cross-app integration surface without N+1 get_app_source calls. Paginate with `cursor` from a prior call's `nextCursor` line. Apps with `description: null` predate descriptions and have not yet been backfilled. When telling the user where to open or share an app, always give them `shareUrl` — never construct links for humans from the `url` field.",
"execution": {
"taskSupport": "forbidden"
},
"inputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"properties": {
"cursor": {
"description": "Opaque cursor from a prior call's `nextCursor` to fetch the next page.",
"type": "string"
},
"limit": {
"description": "Max apps to return (1-100, default 50).",
"maximum": 100,
"minimum": 1,
"type": "integer"
}
},
"type": "object"
},
"name": "list_apps",
"outputSchema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"additionalProperties": false,
"properties": {
"apps": {
"description": "Apps on this page, ordered by creation time newest-first.",
"items": {
"additionalProperties": false,
"properties": {
"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)."
},
"capabilities": {
"additionalProperties": false,
"description": "Declared capability surface from the app manifest. The `exports` array is the discoverability hook for cross-app calls.",
"properties": {
"exports": {
"description": "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.",
"items": {
"type": "string"
},
"type": "array"
},
"imageHosts": {
"description": "External https image hosts injected into the app CSP img-src (e.g. [\"covers.openlibrary.org\"]). Omitted when the app declares none.",
"items": {
"type": "string"
},
"type": "array"
},
"imports": {
"description": "Capability tokens the app depends on (e.g. \"charming:storage/kv@1.0\", \"charming:browser/microphone@1.0\").",
"items": {
"type": "string"
},
"type": "array"
}
},
"required": [
"imports",
"exports"
],
"type": "object"
},
"claimed": {
"description": "True if the app is owned by an authenticated user (i.e. has been claimed). list_apps only ever returns apps owned by the caller, so this is always true today; exposed for forward-compatibility with shared/discoverable listings.",
"type": "boolean"
},
"description": {
"anyOf": [
{
"type": "string"
},
{
"type": "null"
}
],
"description": "Search-friendly summary written by the creating agent. Match user intent (\"open my protein tracker\", \"log food\") against this rather than display name alone. Null on apps created before descriptions existed and not yet backfilled."
},
"displayName": {
"description": "Human-readable name.",
"type": "string"
},
"id": {
"description": "App UUID. Pass to get_app to render or get_app_source to read.",
"type": "string"
},
"lastUpdatedAt": {
"description": "ISO-8601 timestamp of the last write to this app's row (create, update_app, set_remixable, unset_remixable, claim, version pointer edits, etc.). Use for recency cues and \"what did I work on most recently\" surfaces. Not the sort key — apps are ordered by creation time, so sort client-side by this field if you need recency order.",
"type": "string"
},
"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"
},
"role": {
"description": "`owner` = your personal app. `collaborator` = shared with you via an accepted invite (edit + run, but not share/delete/transfer). `end-user` = shared use-and-write-data (run the app and write its data, but cannot edit the app source). `viewer` = shared read-only (open and read, but no edits or mutating ops). `team-admin` / `team-member` = owned by a team you belong to; admins get full control, members can edit + run.",
"enum": [
"owner",
"collaborator",
"end-user",
"viewer",
"team-admin",
"team-member"
],
"type": "string"
},
"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 base URL (stable /app/<uuid> form, token-free). Append /api/<op> to its path for out-of-band operation calls; mint a per-app token via get_app for write access. When giving the user a link, use shareUrl instead.",
"type": "string"
}
},
"required": [
"id",
"role",
"displayName",
"revision",
"description",
"url",
"shareUrl",
"lastUpdatedAt",
"claimed",
"capabilities"
],
"type": "object"
},
"type": "array"
},
"nextCursor": {
"description": "Opaque cursor for the next page. Pass back as `cursor` on the next list_apps call. Absent on the final page.",
"type": "string"
},
"ok": {
"const": true,
"description": "Indicates success. Errors arrive as content with isError:true.",
"type": "boolean"
}
},
"required": [
"ok",
"apps"
],
"type": "object"
}
}