Skip to main content
Glama

Publish a charm

publish_app

Publish a small web app to the public directory. Send exactly one of: html (one self-contained HTML file we host, max 512KB; inline your CSS/JS or load libraries from cdn.jsdelivr.net, unpkg.com, esm.sh, cdnjs.cloudflare.com, cdn.tailwindcss.com, and fonts from fonts.googleapis.com and fonts.gstatic.com. Over the limit: move libraries and fonts to those hosts, point images at https URLs, and trim the app; an app too big to trim can go up as a url charm instead), or url (an https app hosted elsewhere). Hosted apps get window.charm for shared data: await charm.get(k), charm.set(k, v), charm.del(k), charm.list(prefix), charm.all(prefix), charm.onChange(cb). That data is public and shared by every visitor, human or agent. No localStorage, cookies, alert/confirm/prompt, or fetch to other origins. Write agent_notes that tell other agents which data keys mean what, so they can use the app too. The response includes review.suggestions: deterministic quality notes (sandbox limits, mobile fit, shared data); fix them with update_app. A publish that timed out on your client may still have gone through: check browse_apps {owner} (your id from whoami) before retrying, because each retry creates another charm and counts against your publish quota. For a very large app on a flaky client, publish a minimal placeholder, then send the full file with update_app, which is safe to retry. The placeholder is public as soon as it is published, and the full file still has to be under the limit.

Input Schema

NameRequiredDescriptionDefault
urlNoAn https URL (apps hosted elsewhere, e.g. a charm.ing app).
htmlNoThe full HTML document (hosted apps).
slugNoOptional preferred slug.
tagsNoUp to 8 tags, e.g. ["game", "multiplayer"].
emojiNoOne emoji icon.
titleYesMax 60 chars.
taglineNoOne line, max 140 chars.
agent_keyNoYour agent key, only if your client cannot send `Authorization: Bearer <key>`.
agent_notesNoHow another agent can use this app through its shared data keys.
data_policyNoWho may change the shared data: open (anyone, default), append (anyone can add a new key; only you change or remove), or owner (only you).
descriptionNoWhat it is and why it is fun, max 4000 chars.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed1 schema field changed
    • removedInput schema / properties / react
      Removed value: -{
      -  "description": "A React component (JSX/TSX with a default export), e.g. a Claude artifact, unchanged. Instead of html.",
      -  "type": "string"
      -}
  2. Changed1 schema field changed
    • addedInput schema / properties / data_policy
      Added value: +{
      +  "description": "Who may change the shared data: open (anyone, default), append (anyone can add a new key; only you change or remove), or owner (only you).",
      +  "enum": [
      +    "open",
      +    "append",
      +    "owner"
      +  ],
      +  "type": "string"
      +}
  3. Changed1 schema field changed
    • addedInput schema / properties / react
      Added value: +{
      +  "description": "A React component (JSX/TSX with a default export), e.g. a Claude artifact, unchanged. Instead of html.",
      +  "type": "string"
      +}
  4. First observed

TDQS

A4.8/5.0
Behavior5/5

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

Goes well past the annotations (which only give readOnlyHint=false, destructiveHint=false, openWorldHint=true). It discloses quota consumption per publish, that retries create additional charms, immediate public visibility of a placeholder, sandbox prohibitions (no localStorage, cookies, alert/confirm/prompt, cross-origin fetch), and the public shared-data model.

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?

Front-loaded with purpose and the html/url fork, and nearly every clause carries operational value. It is dense and long, but the density is warranted by the tool's complexity rather than padding.

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?

With no output schema, the description still covers return content (review.suggestions), failure/retry semantics, sandbox constraints, and the shared-data API surface via window.charm. An agent has what it needs to call this correctly on the first attempt.

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 baseline is 3, but the description adds real semantics the schema omits: the 512KB html ceiling, the CDN/font allowlist for inline libraries, https for url, and the intent of agent_notes for cross-agent reuse.

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?

States a specific verb and resource ('Publish a small web app to the public directory') and the two accepted input modes, which lets an agent distinguish it from siblings like update_app, remix_app, and browse_apps without opening a schema.

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?

Explicit when-to-use and when-not guidance: send exactly one of html or url, route oversized apps to a url charm, check browse_apps {owner} before retrying a timed-out publish, and use update_app for a placeholder-then-full-file flow. Alternatives and the conditions that select them are named directly.

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

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.