Skip to main content
Glama
Ownership verified

Server Details

Build personal interactive apps with real URLs and persistent storage, using any AI.

Status
Healthy
Last Tested
Transport
Streamable HTTP
URL

Glama MCP Gateway

Connect through Glama MCP Gateway for full control over tool access and complete visibility into every call.

MCP client
Glama
MCP server

Full call logging

Every tool call is logged with complete inputs and outputs, so you can debug issues and audit what your agents are doing.

Tool access control

Enable or disable individual tools per connector, so you decide what your agents can and cannot do.

Managed credentials

Glama handles OAuth flows, token storage, and automatic rotation, so credentials never expire on your clients.

Usage analytics

See which tools your agents call, how often, and when, so you can understand usage patterns and catch anomalies.

100% free. Your data is private.
Tool DescriptionsA

Average 4.5/5 across 21 of 21 tools scored. Lowest: 3.9/5.

Server CoherenceA
Disambiguation5/5

Every tool has a clearly distinct purpose: create, read, update, delete, share, list, query, mutate, etc. No two tools overlap in what they do, and descriptions clearly differentiate actions like query_app (read-only) vs mutate_app (writes).

Naming Consistency5/5

All 21 tools follow a consistent verb_noun pattern in lowercase with underscores (e.g., create_app, set_public, list_feedback). No mixing of conventions or vague verbs.

Tool Count5/5

21 tools is well-scoped for a full-featured app platform. Each tool covers a specific operation without being unnecessarily granular or overly broad.

Completeness4/5

Core CRUD, sharing, feedback, assets, and settings are covered. Minor gap: no explicit 'claim_app' tool for anonymous apps, though ownership transfer and deletion are present. Overall, a strong surface for managing apps.

Available Tools

21 tools
create_appA
Destructive
Inspect

Create a new interactive web app and render it inline. Use this to build a new app from a request. This tool call is synchronous: when it returns, the app is already live at the URL in the response. There is no Charming process to wait for, no deployment queue, and no polling step — success means the app is immediately accessible. If module reuses a manifest.id the caller already owns, the new app replaces the existing app module, UI, and styles in place; use update_app to edit a known app ID by UUID. Apps persist state through a backend env.storage (Workers KV) binding and call backend operations from the frontend via window.buildy.api. The module, ui, and description parameter docs carry the authoring rules — including the fill-viewport outer-container rule on ui; the buildy:app-guide prompt has the full guide and a canonical example. If a request needs something Charming can't do yet (AI calls, external integrations, a native app, scheduled jobs, SQL, notifications, view-only sharing), don't fake it — build the closest local-state version and log the gap with submit_feedback; the buildy:app-guide prompt lists each case and what to build instead. The buildy:design-guide prompt documents Charming's default visual style for generated ui (single accent, warm neutrals, real type hierarchy; no gradients or decorative emoji) — a default that yields to any user-requested aesthetic. 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uiNoFrontend 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.
moduleYesES 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.
stylesNoOptional CSS for the rendered app
descriptionYesSearch-friendly summary of what this app does, surfaced by list_apps so a future session can match user intent (e.g. "open my protein tracker", "log food") to this app even when display_name is ambiguous. Write 1-2 sentences covering: (a) what the app tracks/does, (b) the key actions it supports, and (c) synonyms or alternative phrasings the user might say. Example: "Tracks daily protein intake. Log meals, view weekly totals, set a daily goal. Synonyms: meals, food log, nutrition tracker, calorie counter." Limit 500 characters.
display_nameNoOptional display name override

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the created or updated app.
okYesIndicates success. Errors arrive as content with isError:true.
urlYesMachine/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.
iconYesThe 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`.
appNameNoURL-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).
versionYesMonotonic 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.
shareUrlYesThe 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.
warningsNoNon-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 }`.
advisoriesNoStructured 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.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate destructiveHint=true and readOnlyHint=false, so the write/destructive nature is known. The description adds critical behavioral context: synchronous execution ('when it returns, the app is already live'), replacement semantics for same manifest.id, and the immediate accessibility of the result. These go beyond annotations to clarify the tool's operational behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is lengthy but every sentence earns its place. It is front-loaded with the core purpose and synchronous behavior, then flows into replacement semantics, parameter guidance, and fallback policy. While it could be trimmed slightly, the structure is logical and the density of useful information justifies the length.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 parameters, destructive behavior, replacement semantics, and integration with other features like storage and fallback), the description covers all critical aspects. It explains when creation is safe, how state persists, and how to handle unsupported requests. The presence of an output schema reduces the need to describe return values, but the description still provides necessary behavioral context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

All five parameters have schema descriptions (100% coverage), so the baseline is 3. The tool description does not repeat parameter definitions but does add context for some parameters indirectly (e.g., mentioning fill-viewport rule for ui, storage semantics for module). However, the added value is marginal because the schema already provides detailed parameter explanations.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description begins with 'Create a new interactive web app and render it inline.' It clearly identifies the verb (create) and resource (interactive web app). It distinguishes from sibling tool update_app by noting that create_app uses manifest.id ownership to replace, while update_app edits by UUID. This differentiation makes the purpose unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states 'Use this to build a new app from a request.' It provides explicit guidance on when to use this tool versus update_app, and includes a detailed fallback policy for tasks Charming cannot handle: 'don't fake it — build the closest local-state version and log the gap with submit_feedback.' This covers both appropriate use and alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

delete_appA
Destructive
Inspect

Permanently delete a Charming app the caller owns, optionally also purging its stored data. Use this to remove an app the caller no longer wants. Deletion is irreversible and requires confirmation: the host is asked to show a confirmation prompt, and when it cannot, the call fails closed until re-invoked with confirm: true.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to delete
confirmNoExplicit confirmation that the caller intends to permanently delete this app. Fallback for hosts that cannot show a confirmation prompt: set true only after the deletion has been confirmed with the user through another channel. On hosts that do support a prompt, the prompt is authoritative and this field is ignored.
purge_storageNoAlso delete stored app data

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the targeted app.
okYesIndicates success. Errors arrive as content with isError:true.
deletedYesTrue if the app was deleted, false if deletion was cancelled by the user.
cancelledNoSet to true when the user declined the elicitation confirmation prompt.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true), the description adds context: permanent deletion, optional purge, irreversibility, and detailed confirmation mechanism with fallback behavior for hosts that cannot show a prompt.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, front-loaded with the core action, followed by usage guidance and important behavioral notes. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (deletion with confirmation and optional purge), the description fully covers the behavior, including host-dependent confirmation logic and irreversibility warning.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents parameters. The description adds value by explaining the confirm parameter's role and fallback behavior, and mentioning purge_storage option, but does not add extensive new detail.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the verb 'delete', the resource 'Charming app', and the scope 'the caller owns'. It also mentions optional data purging. This clearly distinguishes it from sibling tools like update_app or rename_app.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description says 'use this to remove an app the caller no longer wants' and provides critical guidance on irreversibility and confirmation requirements. However, it does not explicitly state when not to use this tool or list alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_appA
Read-only
Inspect

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.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID)

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the opened app.
okYesIndicates success. Errors arrive as content with isError:true.
apiYesFull API surface — same shape as `_meta.buildy.api`, but model-facing.
urlYesMachine/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.
appNameNoURL-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).
versionYesMonotonic 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.
shareUrlYesThe 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.
appVersionYesAuthor-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).
manifestIdYesStable manifest identifier declared by the app module. Distinct from `id` (DB primary key) — surface this when discussing the app with the user.
descriptionYesSearch-friendly summary of what the app does. Null on apps created before descriptions existed; agents are nudged to backfill on the next update_app.
displayNameYesHuman-readable name shown in app listings and headers.
recentIssuesNoRuntime 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.
manifestVersionYesCharming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true; description adds that it returns 'live embedded UI' and 'callable API operations', and warns about the url field embedding a write-capable token. This provides useful behavioral context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, each adding value; front-loaded with core purpose. Could be slightly more concise but well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Complete description covering purpose, usage flow, output composition, and important distinction between shareUrl and url. No gaps given annotations and output schema existence.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description and pattern for app_id. Description adds minimal value beyond schema (implies ID comes from list_apps). Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the verb 'Fetch' and resource 'app by ID', and distinguishes from sibling tool list_apps by explicitly contrasting metadata vs rendering.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides clear when-to-use instructions (open, re-render, continue working) and advises to call list_apps first to find the ID. Includes a specific warning about using shareUrl instead of url, but no explicit when-not-to-use beyond that.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_app_sourceA
Read-only
Inspect

Return an app's raw persisted source (module, frontend ui script, and styles) plus its current version for optimistic-concurrency edits. Use this when you need the source to inspect, debug, or edit an app the caller owns.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID)

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the inspected app.
okYesIndicates success. Errors arrive as content with isError:true.
urlYesPublic app URL without an access token, built from the OWNER's handle when available (friendly form) and the UUID form otherwise. Safe to show the user. Browsers open via session cookie; agents should call get_app to mint a per-app token for write access.
sourceYesPersisted source bundle. The same fields accepted by create_app/update_app.
claimedYesTrue if the app is owned by an authenticated account. False for anonymous apps still in the unclaimed grace window.
versionYesMonotonic 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.
expiresAtYesISO timestamp when an unclaimed app will be hard-deleted. Null for claimed apps.
advisoriesNoStructured 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.
appVersionYesAuthor-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).
manifestIdYesEffective manifest id. May differ from `sourceManifestId` when a conflicting id was rewritten on save.
descriptionYesSearch-friendly summary set by the creating agent. Null on apps created before descriptions existed.
displayNameYesHuman-readable name from the manifest.
capabilitiesYesCapability declarations parsed from the app manifest.
manifestVersionYesCharming manifest contract date (`YYYY-MM-DD`) the app is pinned to. The runtime branches on this value to pick contract-specific behaviour.
sourceManifestIdYesManifest id as authored in the persisted module source.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and destructiveHint=false. Description adds optimism-concurrency version detail, aligning with safe read behavior. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, front-loaded with purpose and content summary, no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Low complexity tool with one parameter and output schema; description covers purpose, usage, and return content completely.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema has 100% coverage with detailed format description for app_id. Description adds no additional meaning beyond schema, meeting baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it returns app source (module, UI script, styles) and version, distinguishing it from siblings like get_app (metadata) or mutate_app (modification).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says use for inspecting, debugging, or editing owned apps, providing clear context. Lacks explicit when-not-to-use or alternatives, but sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_appsA
Read-only
Inspect

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, 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax apps to return (1-100, default 50).
cursorNoOpaque cursor from a prior call's `nextCursor` to fetch the next page.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
appsYesApps on this page, ordered by creation time newest-first.
nextCursorNoOpaque cursor for the next page. Pass back as `cursor` on the next list_apps call. Absent on the final page.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations declare readOnlyHint=true, and the description adds extensive behavioral context: details of returned fields (id, role, displayName, etc.), role explanations, pagination mechanics, and notes about null descriptions. This goes well beyond annotations, offering rich transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is front-loaded with the main purpose and well-structured, but it is somewhat verbose with detailed role explanations. However, every sentence contributes useful information; no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (paginated list with multiple roles and fields), the description is highly complete. It explains output semantics, pagination, null descriptions, and usage of shareUrl. The presence of an output schema does not diminish the value of this clarity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents both parameters (limit, cursor) with descriptions. The description adds value by explaining pagination flow ('Paginate with cursor from a prior call's nextCursor line'), which is not present in schema descriptions. This provides helpful usage context.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool lists the caller's Charming apps including owned and shared ones, with a specific verb ('List') and resource ('apps'). It distinguishes from siblings like 'get_app' by noting this is for finding an app's ID before fetching, editing, or calling it.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use this to find an app's id before fetching, editing, or calling it,' providing clear context for when to use this tool. It also explains pagination and how to use returned data (e.g., using shareUrl). However, it does not explicitly state when not to use it compared to alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_app_sharesA
Read-only
Inspect

Use this to see who an app is shared with: lists every outstanding invitation and active grant, labeled by status (pending = invited, no access yet; accepted = active grantee; invited = email-only invite, no Charming account yet) and by role (collaborator = read + write; end-user = run + write data, not edit source; viewer = read only).

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to list shares for

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
sharesYesEvery outstanding invitation and active grant on the app.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true, so description's behavioral disclosure is less critical. Yet description adds value by explaining the meaning of status and role fields in output, providing context beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Single sentence packs significant detail about output labeling. Though lengthy, it is efficiently structured. Minor improvement could be splitting roles/statuses for easier parsing.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With output schema present and one well-documented parameter, description covers core purpose and output. Could mention lack of pagination or ordering, but not critical for simple listing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Only one parameter (app_id), fully covered by schema description. Tool description does not add additional parameter semantics beyond what schema provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

Description clearly states the tool lists who an app is shared with, and provides specific details about output (status and role labels). Distinguishes from sibling tools like share_app and unshare_app which modify shares.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States 'Use this to see who an app is shared with', which is clear. However, no explicit when-not-to-use or comparisons to siblings like list_apps or list_feedback. Implied but not direct.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_feedbackA
Read-only
Inspect

List feedback rows for the caller's apps. Use this to review feedback previously recorded for an app. When app_id is set, returns rows for that one app (owner-checked); when omitted, returns rows across every app the caller owns. Paginate with cursor from a prior call's cursor field. Newest rows come first.

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMax rows to return (1-50, default 20).
sinceNoOptional inclusive lower bound on `created_at` as an ISO-8601 timestamp.
app_idNoOptional app ID (UUID) to restrict to. When omitted, returns feedback across every app the caller owns.
cursorNoOpaque cursor from a prior call's `cursor` to fetch the next page.
categoryNoOptional category filter. One of: bug, crash, enhancement, praise, other.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
itemsYesFeedback rows ordered by `created_at DESC, id DESC` (newest-first).
cursorYesOpaque cursor for the next page. Null when this page is the last. Pass back as `cursor` on the next list_feedback call.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds key behavioral details beyond annotations: owner-checked, pagination with cursor, newest-first ordering. Annotations already indicate read-only and non-destructive, which the description does not contradict.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences, no fluff. The first sentence states the purpose, followed by usage guidance and key behavioral notes. Efficient and well-structured.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers core functionality: listing feedback, filtering by app, pagination, ordering. Output schema exists for return values, so description is sufficient. Minor omission: no mention of error handling or rate limits, but acceptable for a read-only list tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with descriptions for all parameters. The description rephrases behavior for app_id but does not add new meaning beyond the schema. Baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (list) and resource (feedback rows for caller's apps). It distinguishes from sibling tools like submit_feedback (write) and list_apps (different resource). The phrase 'owner-checked' adds specificity.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use this to review feedback previously recorded for an app,' providing clear context. It explains behavior with and without app_id, but doesn't explicitly mention when not to use or alternatives beyond the implied alternative of submit_feedback.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

mutate_appA
Destructive
Inspect

Run a mutating backend operation on a Charming app and return its result, without editing code. Use this for operations that change state — including operations whose read/write safety can't be determined. For read-only operations, use query_app. If you don't know an operation's name or which tool it needs, call get_app — each operation lists its tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
opYesOperation name, routed to /api/:op inside the app module
app_idYesThe app ID (UUID)
paramsNoOptional JSON params

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue if the operation handler returned a successful envelope. False when the app reported an operation error — distinct from a transport/protocol error.
errorNoSet when ok=false. Always inspect kind before retrying.
valueNoOperation return value when ok=true. Shape depends on the app and op called.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false. Description adds that operations change state and that read/write safety may be uncertain. No contradictions, but could elaborate on what gets destroyed.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences directly stating purpose, usage guidelines, and fallback. No redundant words, front-loaded with key information.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Covers what the tool does, when to use it, and how to discover operations. Mentions returning a result. Output schema exists, so return details are not needed. Missing explicit mention of parameter passing but schema addresses it.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameters with descriptions. Description adds no extra param details beyond what schema provides, so baseline score of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool runs a mutating backend operation on a Charming app, distinguishing it from read-only query_app. It specifies 'without editing code' to avoid confusion with code editing tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says use for operations that change state, for read-only use query_app, and if operation name is unknown call get_app. Provides clear when-to-use and when-not-to-use guidance with named alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

query_appA
Read-only
Inspect

Run a read-only backend operation on a Charming app and return its result, without editing code. Use this for operations that only read state. For operations that change state, use mutate_app. If you don't know an operation's name or which tool it needs, call get_app — each operation lists its tool.

ParametersJSON Schema
NameRequiredDescriptionDefault
opYesOperation name, routed to /api/:op inside the app module
app_idYesThe app ID (UUID)
paramsNoOptional JSON params

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesTrue if the operation handler returned a successful envelope. False when the app reported an operation error — distinct from a transport/protocol error.
errorNoSet when ok=false. Always inspect kind before retrying.
valueNoOperation return value when ok=true. Shape depends on the app and op called.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint=true and destructiveHint=false. The description adds that it returns results and does not edit code, but lacks detail on error handling or behavior if op is invalid.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no wasted words, sufficiently detailed without being verbose.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 3 parameters and an output schema, the description provides complete context: purpose, usage, and sibling differentiation. No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description does not add any additional meaning beyond the schema's parameter descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'run' and resource 'backend operation on a Charming app', and explicitly distinguishes from mutate_app by noting it is read-only and does not edit code.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says when to use (read-only operations) and when not (state changes, use mutate_app). It also advises calling get_app if unsure which operation or tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

rename_appAInspect

Change a Charming app's URL slug — the human-readable, URL-safe name, distinct from its title/displayName and from its machine manifest id. Use this to give an app a different public URL. Titles and slugs are independent: editing the title with update_app does not change the slug; this tool does. Renaming changes the public URL, and the old URL keeps working by redirecting to the new one. Slug rules: lowercase letters, digits, and hyphens; 2-48 chars; may start with a letter or digit; no leading, trailing, or consecutive hyphens. When telling the user where to open or share the renamed app, always give them shareUrl from the result — never the url field, which is machine-only and embeds a write-capable access token.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to rename.
app_nameYesThe new URL slug. Lowercase letters, digits, and hyphens; 2-48 chars; may start with a letter or digit; no leading/trailing or consecutive hyphens. Input is lowercased and trimmed.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the renamed app.
okYesIndicates success. Errors arrive as content with isError:true.
urlYesMachine/API URL for the app (stable /app/<uuid> form). Reflects the new slug.. 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.
appNameYesThe new live slug for the app.
shareUrlYesThe 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.
previousAppNameYesThe slug the app had before this rename. Retained as an alias so old URLs keep resolving (a redirect to the new slug).
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds critical behaviors: old URL redirects, shareUrl vs url distinction. Annotations only hint at mutability; description fill gaps with no contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Five purposeful sentences with no fluff. Key action and constraints front-loaded; every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given output schema exists, description covers purpose, behavior, parameter rules, and result guidance (shareUrl). Complete for a mutation tool with moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema already describes both parameters (100% coverage). Description adds processing details ('lowercased and trimmed') and validates slug format, exceeding schema baseline.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool changes an app's URL slug, distinct from title/machine id, and differentiates from update_app and other sibling tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says when to use (give app a different public URL) and contrasts with update_app. Lacks explicit 'when not to use' but context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_handleAInspect

Change the signed-in user's handle (their username) — the first segment of their friendly app URLs (https://charm.ing/<handle>/<app-name>), so changing it changes the prefix of every app URL they share. Use this to give the current user a different handle. The old handle keeps working by redirecting to the new one, so links already shared stay valid. Acts on the current signed-in user only and takes no user id. Handle rules: lowercase letters, digits, and hyphens; 3-32 chars; must start with a letter; no leading, trailing, or consecutive hyphens; some words are reserved. Rate-limited to 3 changes per rolling 30 days.

ParametersJSON Schema
NameRequiredDescriptionDefault
handleYesThe desired new handle. Lowercase letters, digits, and hyphens; 3-32 chars; must start with a letter; no leading/trailing or consecutive hyphens. Input is lowercased and trimmed.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
handleYesThe new live handle for the signed-in user.
previousHandleYesThe handle the user had before this change. Retained as an alias so old friendly URLs (`/<previousHandle>/<app>`) keep resolving (a redirect to the new handle). Empty string when the user had no prior handle.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds significant behavioral context beyond annotations: it explains that changing the handle changes app URL prefixes, old handles redirect, and it is rate-limited. Annotations indicate it is not read-only and not destructive, which aligns with the description. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single block of text that is informative yet concise, with no wasted words. It front-loads the core purpose and then adds important details. Slightly better structuring (e.g., bullet points for rules) could improve readability, but it is adequate.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple mutation tool with one parameter, the description covers all essential aspects: purpose, effect on URLs, scope (current user), handle rules, rate limits, and that old handles redirect. An output schema exists (though not detailed in the input), so return value explanation is not needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% coverage for the single 'handle' parameter, with description covering rules. The tool description adds value by reiterating these rules in context and mentioning that input is lowercased and trimmed, providing extra clarity beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it changes the handle (username) of the signed-in user, explains what a handle is (first segment of URLs), and specifies it acts on the current user only. No sibling tools have similar functionality, so it stands out.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use the tool (to change handle) and provides context such as old handle redirecting and rate limiting (3 per 30 days). It does not explicitly state when not to use it, but given the tool's specificity and no similar siblings, this is sufficient.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_publicAInspect

Make a Charming app PUBLIC: anyone who opens its URL can use it with no login and read AND write its SHARED data. Use this for a totally-open surface (a poll, an RSVP list, a guestbook) where requiring sign-in or per-person invites is not worth it. WARNING — this is a shared, unauthenticated write surface: every anonymous visitor reads and writes the SAME data pool with no per-visitor isolation, so anyone with the URL can overwrite or wipe the data. Surface the returned message verbatim so the user understands that before sharing. For per-person access that keeps an audit trail and write control, share with the end-user role instead (it requires login). Idempotent: calling on an already-public app returns the same URL without re-firing analytics. Owner-only; anonymous apps must be claimed first.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to make public

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
messageYesConsequence 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.
public_urlYesPublic 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.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Adds critical warnings beyond annotations: shared unauthenticated write surface, risk of data overwrite/wipe, requirement to surface the message. Annotations already indicate openWorldHint and non-read-only; description enriches with real-world implications.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Well-structured with front-loaded purpose, then usage, warning, alternative, and idempotency. Every sentence adds value; slightly verbose but acceptable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Single-parameter tool with output schema. Description covers all aspects: purpose, usage, warnings, ownership, idempotency, and alternative. No gaps given context.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema covers 100% of parameter description with app_id as UUID. Description adds no additional parameter semantics beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the verb 'Make... PUBLIC' and the resource 'Charming app' with scope: anyone can read AND write shared data. It distinguishes from siblings like unset_public (reverse) and share_app (per-person access).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly provides when to use (totally-open surfaces like polls, RSVP lists) and when not (per-person access requires share with end-user role). Also notes idempotency and owner-only restriction.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_remixableAInspect

Mark a Charming app as remixable. Use this to let anyone who opens the app's URL get their own brand-new editable copy, while the original is never mutated by visitors. Each remix is an independent app the visitor can keep and later claim by signing up. Idempotent: calling on an already-remixable app returns the same URL without re-firing analytics. Anonymous apps cannot be made remixable; the app must be claimed first.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to share as remixable

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
messageYesConsequence copy the agent should surface verbatim to the user when reporting that the share was created. Spells out that other people will get their own remix — the user's data is untouched.
public_urlYesPublic 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.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=false, destructiveHint=false, openWorldHint=true), the description adds idempotency, that it returns the same URL without re-firing analytics when already remixable, and that anonymous apps cannot be made remixable. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise (4 sentences), front-loaded with the main action, and every sentence adds value. No unnecessary words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given one parameter, high schema coverage, and presence of an output schema, the description covers idempotency, prerequisites, and the core effect, making it complete for an agent to decide usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with a clear description for 'app_id'. The tool description does not add additional parameter-level details beyond the schema, so baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly states the action ('Mark a Charming app as remixable') and clarifies the effect: anyone opening the URL gets their own editable copy without mutating the original. This distinguishes it from siblings like 'unset_remixable' and 'share_app'.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description mentions a prerequisite (app must be claimed) and idempotency, but does not explicitly compare to alternatives like 'share_app' or 'set_public'. It gives context but lacks explicit when/not-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

set_starter_promptA
Destructive
Inspect

Set or clear an app's authored starter prompt — a short getting-started instruction prefilled in the chat host when a visitor clicks "Open in Claude" or "Open in ChatGPT" on the app, replacing the generic "I'm using a Charming app" body. Use this to frame a shared/remixable app's intended first action for visitors. Write a generic instruction — do NOT embed the app's URL: the app name, description, and URL (and, for unclaimed apps, an access token) are appended automatically at render time, so a hardcoded URL would point every remixer at the template instead of their own copy. Pass starter_prompt: null (or an empty string) to clear and revert to the generic default. Owner-only; anonymous apps must be claimed first. Idempotent (re-setting the same value is a no-op). Length cap: 2000 characters.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) whose starter prompt should change.
starter_promptYesGetting-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.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
messageYesConsequence 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.
starter_promptYesThe current starter prompt on the app row after this call. Null when the prompt was cleared (or normalized away from whitespace-only input). Otherwise the verbatim authored string.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true, readOnlyHint=false), the description details idempotency, length cap (2000 chars), automatic context appending, and the pitfall of hardcoded URLs pointing to the template. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficient and front-loaded, with every sentence adding unique value. It is slightly long but justified by the complexity; no redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a mutation tool with destructive potential and specific rendering behavior, the description covers ownership, idempotency, length limits, clearing mechanism, and the automatic appending of app context. No gaps remain for an agent to infer.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Even with 100% schema coverage, the description adds substantial value: explains the proper format for starter_prompt (generic instruction, not self-contained prompt), why not to embed URL, and how null/empty clears. This goes well beyond the schema's basic type info.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action ('Set or clear an app's authored starter prompt') and the specific resource (the app's starter prompt). It distinguishes this tool from general app mutation by focusing on the starter prompt, and the sibling tools include no direct competitor.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit when-to-use ('frame a shared/remixable app's intended first action'), what-not-to-do ('do NOT embed the app's URL'), how to clear ('pass null or empty string'), ownership constraints ('owner-only; anonymous apps must be claimed first'), and idempotency. This covers all key usage decisions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

share_appA
Destructive
Inspect

Invite someone (by Charming handle or email) to one of your apps, OR change the role of someone you already invited. Use this when the user wants to give a specific person access to an app, or to change what an existing collaborator/end-user/viewer can do. Creates a PENDING invitation: the invitee gets no access and sees nothing in their workspace until they accept. Pick a role: collaborator (default) can open, edit, and run the app (shared state, same data); end-user can open the app and write its data (record entries, save state) but cannot edit the app source; viewer can only open and use the read-only surface — viewers cannot edit, run mutating ops, or change anything. If the grantee already has a share, calling this again WITH a role changes their role in place (status updated, no new invitation, no second email) — this is how you flip a collaborator to an end-user and back; re-sharing WITHOUT a role leaves the existing role untouched. No share role can ever share, delete, or transfer the app. The invitee does NOT need a Charming account first — inviting an email with no account stores a pending invitation and emails them a sign-up link; it activates once they register and verify that email (an unknown handle still errors, since there is no address to reach). Revoke anytime with unshare_app.

ParametersJSON Schema
NameRequiredDescriptionDefault
roleNoThe access level: `collaborator` (default — edit and run), `end-user` (run + write data, not edit source), or `viewer` (read-only)
app_idYesThe app ID (UUID) to share
granteeYesThe invitee's Charming handle (e.g. `ada` or `@ada`) or account email

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
statusYesSharing 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).
granteeYesThe resolved grantee (handle when set, else email) the invitation was sent to.
messageYesConsequence 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.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that the tool creates a PENDING invitation, describes each role's capabilities, clarifies that re-sharing without role leaves existing role untouched, and notes that no share role can share/delete/transfer the app. No annotations contradict; destructiveHint=true is consistent with role changes.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-structured: starts with the main purpose, then details roles, invitation flow, and edge cases. Every sentence adds value, though could be slightly tighter. Front-loaded effectively.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given three parameters, a rich output schema (implied), and many sibling tools, the description covers all relevant scenarios: pending invitations, role change behavior, account registration, and revocation. No gaps apparent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% (all parameters have descriptions). The description adds nuance: default role is 'collaborator', re-sharing without role leaves untouched, and invitee does not need a Charming account beforehand—adding value beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description starts with a clear verb ('Invite someone... OR change the role') and identifies the exact resource ('one of your apps'). It distinguishes from its sibling 'unshare_app' by mentioning revocation explicitly.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

States when to use: 'Use this when the user wants to give a specific person access to an app, or to change what an existing collaborator/end-user/viewer can do.' Also explains when NOT to send a new invitation (re-sharing with role) and directs to 'unshare_app' for revocation.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

submit_feedbackAInspect

Record agent-authored feedback about a Charming app. Use this to log observed bugs, suggested enhancements, caught crash reports, or qualitative notes. Source is server-enforced to "agent" — agents cannot impersonate user or auto-crash sources. The caller must own the app.

ParametersJSON Schema
NameRequiredDescriptionDefault
textNoFree-form feedback body (up to 16384 chars). Optional, but at least one of text / structured_data / crash_data should usually be set so the row is actionable.
app_idYesThe app ID (UUID) the feedback is attached to.
categoryYesFeedback category. One of: bug, crash, enhancement, praise, other. Pass "crash" only when crash_data carries the captured error.
crash_dataNoRequired when category=crash. Optional otherwise.
structured_dataNoOptional JSON object with caller-supplied structured context (e.g. route, repro inputs).

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the newly-inserted feedback row.
okYesIndicates success. Errors arrive as content with isError:true.
app_idYesUUID of the app the feedback was attached to.
created_atYesISO-8601 timestamp when the row was inserted.
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate a mutation (readOnlyHint=false) and non-destructive nature. The description adds valuable behavioral context: source is server-enforced to 'agent', agents cannot impersonate, and ownership requirement, which are beyond annotation capabilities.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, no filler, front-loaded with purpose, then constraints. Every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (5 params, nested objects, enum, output schema), the description covers purpose, usage, constraints, and parameter relationships sufficiently. The output schema exists, so return value details are not needed.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. The description adds meaning by linking category 'crash' to crash_data requirement, and stating that at least one of text/structured_data/crash_data should be set. This goes beyond the schema's individual descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb 'Record' and resource 'feedback about a Charming app', listing concrete use cases (bugs, enhancements, crashes, notes). It clearly distinguishes from sibling tools like list_feedback and other app mutation tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description states when to use (logging feedback) and provides constraints (source enforced to 'agent', caller must own app). It does not explicitly state when not to use or name alternatives, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unset_publicA
Destructive
Inspect

Make a public Charming app PRIVATE again. Use this to close anonymous access: visitors can no longer open the app without logging in (the URL requires login). Data already written by anonymous visitors is retained. Idempotent: calling on an already-private app is a no-op.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to make private

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
messageYesConsequence copy the agent should surface verbatim. Tells the user the app now requires login again; data already written by anonymous visitors is retained.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (readOnlyHint=false, destructiveHint=true, openWorldHint=true), the description adds context: data retention, idempotency, and the requirement for login. No contradiction with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise with three sentences. The first sentence immediately states the action, making it front-loaded. Every sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description explains the tool's behavior, side effects (data retention), idempotency, and the effect on access. With an output schema present, this is complete for the tool's purpose.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The schema covers the single parameter 100% with a clear description. The tool description does not add new parameter semantics, so a baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool makes a public Charming app private, specifying the action and resource. It distinguishes from the sibling `set_public` by explicitly reversing its effect.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description tells when to use the tool ('to close anonymous access') and describes the effect (visitors must log in). It also notes idempotency but does not explicitly mention when not to use it or alternatives.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unset_remixableA
Destructive
Inspect

Stop allowing remixes of a Charming app. Use this to turn off auto-forking for new visitors; existing remixes survive untouched. Idempotent: calling on an already-non-remixable app is a no-op.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to stop sharing as remixable

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
messageYesConsequence copy the agent should surface verbatim. Tells the user new visitors can no longer remix, while existing remixes are unaffected.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond annotations (destructiveHint=true), description reveals that existing remixes survive untouched and operation is idempotent. This adds critical behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three concise sentences, no wasted words. Key information front-loaded ('Stop allowing remixes'). Each sentence adds value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given single parameter, clear annotations, and output schema, the description fully covers what the tool does, its side effects, idempotency, and scope. No gaps.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with description 'The app ID (UUID) to stop sharing as remixable'. Tool description adds no additional parameter semantics beyond schema, earning baseline 3.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action ('Stop allowing remixes') and resource ('Charming app'). It distinguishes from sibling set_remixable by specifying the inverse operation and noting idempotency.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly says 'Use this to turn off auto-forking for new visitors', providing context for when to use. Idempotency guidance encourages safe repeated calls. Sibling tool names give alternative for opposite action.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

unshare_appA
Destructive
Inspect

Revoke another user's access to one of your apps — removes a pending invitation or an accepted collaborator grant. Use this when the user wants to withdraw an invitation or remove a collaborator. Takes effect immediately for new requests. Idempotent: revoking a grant that does not exist is a no-op.

ParametersJSON Schema
NameRequiredDescriptionDefault
app_idYesThe app ID (UUID) to revoke access on
granteeYesThe grantee's Charming handle or account email

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
removedYesTrue when a pending invitation or active grant was removed; false when there was nothing to remove (idempotent no-op).
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description discloses that the tool is destructive (consistent with annotation), idempotent, and takes effect immediately, adding beyond annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two concise sentences, front-loaded with the main action, no wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the presence of an output schema and annotations, the description fully covers behavior, idempotency, and effect timing, making it complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% so baseline is 3. The description does not add significant meaning beyond the schema's parameter descriptions, though it clarifies idempotency.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action (revoke another user's access) and the resource (one of your apps), and distinguishes it from sibling tools like share_app and delete_app.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains when to use this tool ('withdraw an invitation or remove a collaborator') but does not explicitly list when not to use it or name alternative tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

update_appA
Destructive
Inspect

Update an existing Charming app and render the fresh version inline. Use this to edit an app the caller already owns, identified by UUID. This tool call is synchronous: when it returns, the updated app is already live — no process to wait for, no deployment queue. Two mutually exclusive input shapes: (A) full-source — pass module/ui/styles to replace those buckets, following the same authoring rules as create_app (documented on those parameters and in the buildy:app-guide prompt); (B) edits[] — exact-string find/replace operations plus the expected_version from your last read, much cheaper for small changes. If the app's behavior changed materially (new operation, new data tracked, new use-case), also pass an updated description so list_apps stays accurate; backfill one if an older app has none. 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.

ParametersJSON Schema
NameRequiredDescriptionDefault
uiNoFull-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`.
editsNoEdits 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`).
app_idYesThe app ID (UUID) to update
moduleNoFull-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`.
stylesNoFull-source path only. Optional replacement CSS. Mutually exclusive with `edits`.
descriptionNoOptional replacement description. Omit to preserve the existing description, pass `null` to clear, pass a string to replace. Same shape and intent as create_app.description (1-2 sentences covering purpose + key actions + synonyms). Limit 500 characters.
expected_versionNoRequired 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.

Output Schema

ParametersJSON Schema
NameRequiredDescription
idYesUUID of the created or updated app.
okYesIndicates success. Errors arrive as content with isError:true.
urlYesMachine/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.
iconYesThe 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`.
appNameNoURL-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).
versionYesMonotonic 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.
shareUrlYesThe 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.
warningsNoNon-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 }`.
advisoriesNoStructured 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.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations indicate destructiveHint=true and readOnlyHint=false, which the description matches by stating the tool updates an app. It adds key behavioral details: synchronous execution (app is live on return), atomic edits with expected_version for concurrency control, and instruction to use shareUrl not url for sharing. No contradictions with annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with front-loaded purpose, clear sections for input shapes, and important notes at the end. While fairly long, every sentence adds value. Minor opportunity to trim redundant phrasing (e.g., 'Mutually exclusive' repeated).

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (7 parameters, two input shapes, concurrency), the description covers all key aspects: synchronous behavior, atomic edits, concurrency control, output field guidance (shareUrl vs url), and when to update description. It is fully actionable for an AI agent.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, but the description goes far beyond by explaining the two input shapes in detail, including authoring rules for ui and module, the behavior of edits (exact string matching, replace_all), and the purpose of expected_version. This adds significant meaning beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'Update an existing Charming app and render the fresh version inline.' It identifies the resource (Charming app), action (update), and ownership requirement (caller's own app, identified by UUID). It distinguishes from sibling tools like create_app and delete_app.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit guidance on two mutually exclusive input shapes (full-source vs edits) and when to update the description. It contrasts with create_app by referencing its authoring rules. However, it does not explicitly list when not to use this tool versus alternatives like rename_app or set_public.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

upload_assetA
Destructive
Inspect

UPLOAD A STATIC ASSET TO AN APP so app code stays small and the app reads it back same-origin. Use this when an app needs a large or static file — an image, PDF, audio clip, or a dataset bigger than a few KB — that would otherwise be inlined into module/ui and blow the 256 KiB source cap. Provide EXACTLY ONE of: sourceUrl (PREFERRED for any binary — the SERVER fetches the remote file, follows redirects, and the bytes never transit this tool call), text (UTF-8 dataset/JSON/CSV — no encoding needed), or dataBase64 (LAST RESORT, tiny binaries only: large base64 arguments can stall inside some MCP clients before ever reaching the server, so keep it under ~16 KB and use sourceUrl for anything bigger). The app reads the asset via window.buildy.assets.getUrl(key) (for /) or env.assets.get(key) in its backend (the app must declare buildy:storage/blob@1.0 in manifest.capabilities.imports to use env.assets). Caps: 10 MiB/asset, 50 assets/app, 100 MiB/app.

ParametersJSON Schema
NameRequiredDescriptionDefault
keyYesAsset name, e.g. "dataset_v1.json". URL-safe [a-zA-Z0-9._-], <=128 chars, no leading dot.
textNoUTF-8 text payload (datasets, JSON, CSV). No base64.
appIdYesThe app id (app_modules.id) to attach the asset to. Must be an app you own.
sourceUrlNohttps URL the server fetches and stores. Bytes never pass through this tool call.
dataBase64NoBase64 of a SMALL binary. Last resort — prefer sourceUrl: large base64 tool arguments can stall in some MCP clients before reaching the server. Keep the encoded string under ~16 KB; the server-side hard cap is 64 KiB decoded.
contentTypeNoMIME type. Defaults: text/plain for text, sniffed for sourceUrl, application/octet-stream otherwise.

Output Schema

ParametersJSON Schema
NameRequiredDescription
okYesIndicates success. Errors arrive as content with isError:true.
keyYesThe asset key it was stored under. Same value passed in.
urlYesSame-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).
appIdYesUUID of the asset-owning app.
bytesYesStored byte length of the asset payload after decode/fetch.
contentTypeYesEffective MIME type stored with the asset (supplied, sniffed from sourceUrl, or defaulted).
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Discloses that server fetches remote file without bytes transiting through tool call, warns about MCP client stalls with large base64, and provides caps (10 MiB/asset, 50 assets/app, 100 MiB/app). Annotations are consistent (destructiveHint=true, readOnlyHint=false).

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Four sentences packed with information, front-loaded with purpose, then usage, then parameter details. No redundant or vague phrases.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Fully covers all aspects: purpose, parameter selection, caps, how app reads asset, and capability requirement. Output schema exists, so return value explanation unnecessary.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Despite 100% schema coverage, description adds critical meaning: parameter selection guidance (sourceUrl preferred over text/dataBase64), size limitations (sourceUrl docs, base64 <16KB), and default MIME type logic.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states 'UPLOAD A STATIC ASSET TO AN APP' with specific verb and resource. It distinguishes from sibling tools which all operate on apps rather than assets.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly states when to use ('when an app needs a large or static file') and provides clear parameter preference order (sourceUrl preferred, dataBase64 last resort) with warnings about stalls.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Discussions

No comments yet. Be the first to start the discussion!

Try in Browser

Your Connectors

Sign in to create a connector for this server.

Resources