Homespun
This server provides a human-in-the-loop platform called Pane, enabling AI agents to present interactive UIs (forms, dashboards, approvals, pickers) to humans via URL and receive structured data back — designed for headless or out-of-band agent environments.
Create & Manage Panes: Deploy interactive web UIs from inline HTML or reusable templates, with shareable URLs. Update live panes (title, data, TTL), swap HTML in-place, list, or delete them.
Human ↔ Agent Communication: Poll the append-only event log (get_events) to receive structured human responses (form submissions, approvals, selections), with long-polling support. Push updates into a live UI (send_to_pane) for real-time progress or status changes.
Mutable Record Collections: Manage per-pane structured data (todos, kanban cards, comments) with full CRUD, optimistic locking, and cursor-based polling.
Reusable Templates: Create, version, publish, and discover UI templates — define once, instantiate many times with per-pane data.
Participants & Sharing: Mint multiple participant URLs, invite users by email, and set access modes (invite-only, link, or public).
Attachments: Upload/download binary files (images, PDFs, audio, video) scoped to agent, pane, or template, with secure temporary download tokens.
SQL Queries: Run read-only DuckDB SQL over your panes, records, and events for reporting or analysis.
Agent Management: Inspect/revoke API keys, claim agent identity, manage soft-deleted panes/templates (trash), submit feedback, and store UI style preferences (taste notes).
Self-Documentation: Fetch the live skill guide (get_skill) for up-to-date usage instructions, schema grammars, and polling patterns.
Allows CrewAI agents to incorporate human feedback by presenting UIs and retrieving structured data asynchronously.
Integrates with LangGraph agents to pause execution, present a UI to a human, and resume with structured input.
Enables agents built with the OpenAI Agents SDK to request human input via a URL-based UI and process the structured response.
Allows distribution of UI URLs to humans via Slack, enabling human-in-the-loop workflows from Slack bots.
Allows delivery of interactive UIs to humans via Telegram, enabling human-in-the-loop workflows from Telegram bots.
Homespun
Human-in-the-loop for AI agents. Your agent hands a human a real UI — a form, a picker, a dashboard, a diff to review — by URL, and gets the answer back as structured data. No GUI host app, no public address on the agent's side. Works from a cron job, a Slack bot, CI, or any headless server.
Your agent can do anything except ask a human a real question. Homespun fixes that.

Works with any agent that can run a shell command or call HTTP — Claude Code & the Claude Agent SDK, LangGraph / CrewAI / OpenAI Agents SDK, or your own cron / CI / bot.
Quickstart
Register once, claim your agent, then deploy:
npx @homespunapps/cli agent register --name "my-agent" # one-time, hosted relayA freshly registered agent is unclaimed and cannot deploy yet. Claim it so it is bound to you: open https://homespun.dev/get-started, generate a claim code, then run:
npx @homespunapps/cli agent claim <code>
npx @homespunapps/cli deploy ./my-app # Node 20+, reads ./my-app/index.html + manifest.jsonNew apps are private by default: only you and the people you invite can open them. Pass --visibility link or --visibility public to share wider.
Related MCP server: mcp-interactive-ui-server
Reach for Homespun when a text reply is the wrong shape
Approvals — deploy gate, refund, PR merge: agent pauses, human clicks approve/reject, agent continues.
Forms & pickers — collect structured input instead of parsing prose.
Doc / diff review — human marks up a diff; agent gets per-line comments back.
Dashboards & status — view-only apps the human just reads.
Lists & boards — todo lists, checklists, kanban (records), mutated live.
Try it in 60 seconds ↓ · How it works · Agent reference
The problem
Apps are built for everyone; apps are built for you. Agents can already emit rich output (the "ask Claude for HTML, not Markdown" pattern). But the human's reply is still prose. The agent → human channel is rich, the human → agent channel is a text box. Homespun closes the loop: agent renders a UI (form, picker, doc-review view, dashboard, sketchboard), human manipulates it, every interaction emits structured data, the agent retrieves it (or pushes its own updates back into the same UI). The human "answers" by using a UI, not by typing.
This matters most for agents that live outside a GUI host app: cron agents, Slack/Telegram bots, CI agents, headless servers, personal-agent setups. None of them can use MCP Apps (which needs a host app to render the UI). Homespun needs neither a host app nor a public address on the agent's side; the agent only makes outbound calls to the relay.
Templates and apps — the model
Two nouns carry the whole system:
A template is a reusable UI definition: the HTML, an optional event schema, and an optional input schema. Author it once.
A app is one use of a template — one context, one (or more) humans, one event log, one TTL. Many apps per template.
The intended flow is author-once, instance-many: register a template with homespun template create, then spin up an app each time you need it with homespun create --template-id <slug> — no HTML re-sent, no regeneration. Per-instance data (the "which PR is this?" data that makes one PR-review template render this PR) rides in --input-data, which the page reads as window.homespun.inputData. For a genuine one-off you can inline the HTML on homespun create --template '<...>' and skip the named template entirely.
A template with no event schema is view-only — a report, dashboard, or chart the human only reads. Give it an event schema when you need an answer back.
How it works
Agent authors (or reuses) a template — an HTML page, optionally with an event schema declaring what the page and the agent may emit.
Agent →
POST /v1/appswith{template_id | template, input_data, ttl}→ gets{app_id, urls, tokens, expires_at}.Agent delivers
urls.humans[0]to the human over whatever channel it already has.Human opens the URL. The relay serves a small shell page that loads the template in a sandboxed iframe (locked-down CSP), plus a tiny app runtime exposing
window.homespun—homespun.emit(type, data),homespun.on(type, handler),homespun.state,homespun.records,homespun.inputData.Human interacts → each
homespun.emit(...)is POSTed to/v1/apps/{id}/events→ appended to that app's event log (validated against the schema; a wrong shape or wrong author is rejected).Agent retrieves: stream over the WebSocket (
homespun watch), long-poll (GET /v1/apps/{id}/events?since=<cursor>&wait=<s>/homespun show --wait), or register a webhook. The "ask the human" call blocks until the awaited event or a timeout.Homespun expires after
ttl.
Event ordering. A client connected over the WebSocket may receive an event via the broadcast stream before the
ackfor its own write of that same event. Clients de-duplicate on the eventid— treat theid, not arrival order, as the source of truth.
More than the round trip
The core round trip is the foundation; the relay also carries the pieces you need to build real, durable agent↔human surfaces:
Reusable templates + a marketplace.
homespun template create / list / search / show / versionmanage named, versioned templates. A human can mark one public in the relay's web UI, giving it a listing other humans can browse and install into their own account.Records — per-app mutable collections (posts, comments, kanban cards, line items) keyed by stable
record_key, with optimistic locking and soft-delete. Use records when the current value matters and history doesn't; use events when history is the point. Declared with arecord_schema(JSON Schema 2020-12 + thex-homespun-collectionsextension).Attachments — upload images/PDFs/audio/video (
homespun attachment …), reference them by id in events, and let the page fetch them lazily or accept uploads back from the human. Capability-URL (/b/<token>) downloads, MIME sniffing, and EXIF stripping included.SQL query —
homespun query "<SQL>"runs read-only DuckDB SQL (a PostgreSQL-compatible dialect) scoped to your own apps, records, and events.Multi-participant apps — beyond the single auto-minted human URL, an owner can add identity-bound (email-invite) or public/anonymous participants.
homespun participant list / new / revokemanage URLs on a live app.Taste & feedback —
homespun tasteremembers a human's presentation preferences across runs so authored UIs stay consistent;homespun feedbackreports issues about app itself.
See skills/homespun/SKILL.md — the agent-facing reference — for the authoritative, version-matched description of all of the above.
How Homespun compares
Homespun is not a competitor to in-chat UI extensions — it owns a different quadrant. MCP Apps (SEP-1865), MCP elicitation, and AG-UI / CopilotKit all render UI inside a live host or chat session: a host app (Claude Desktop, ChatGPT, VS Code) or your own front-end is present, the human is looking at it, and the UI is torn down when the turn ends. Homespun is for the agents those approaches can't serve — the ones with no session at all: a cron job, a CI pipeline, a Slack or Telegram bot, a headless server, or any case where the human is on a different device than the agent. Agents that live outside a GUI need a callback URL, not a chat window.
Homespun | MCP Apps (SEP-1865) | MCP elicitation | AG-UI / CopilotKit | |
Where the UI renders | Standalone URL, any browser/device | Sandboxed iframe inside the MCP host app | Inside the MCP client (form/URL prompt) | Inside your front-end app |
Needs a host app / live session | No — agent makes outbound HTTP only | Yes — an MCP host renders it | Yes — an MCP client must be connected | Yes — a running front-end + SSE session |
Out-of-band delivery (URL to another device/channel) | Yes — hand the URL over Slack, Telegram, email, SMS | No — bound to the host UI | No — the client drives the prompt in-session | No — bound to the app the user is in |
Survives the agent turn ending | Yes — app lives until its TTL; the human can answer later | No — tied to the conversation turn | No — request is resolved within the call | No — tied to the live session |
Persistent / mutable state | Yes — durable event log + mutable records per app | Per-render component state | Single request/response | Session state (STATE_DELTA), app-managed |
Self-hostable | Yes — one container, MIT | Spec only; depends on host | Spec only; depends on client | Open-source; you host the app + agent |
The rows app wins on are exactly the headless/out-of-band ones: no host app, URL-on-another-device delivery, an answer that can arrive minutes or hours later, and state that outlives a single turn. If you do have a live host or front-end session, MCP Apps / elicitation / AG-UI are the natural fit — render the UI right where the human already is. Homespun is the tool for everywhere else.
Examples
Runnable, copy-pasteable examples live in examples/:
claude-code-approval/— a CLI agent (Claude Code or any shell agent) hands a human an "approve this plan?" app and reads the decision back fromhomespun watch.ci-deploy-gate/— a GitHub Actions deploy gate: the pipeline posts an app URL, a human approves/rejects with a reason, and a script polls the result and exits0/1.
Install
No build step, no host app. Pick your audience — paste the agent block into your AI agent's chat, or run the human block yourself.
Paste to your AI agent
Paste the block below into your AI agent's chat. It will install the CLI, register against the hosted relay, and install the Homespun skill into its own skill directory.
Install Homespun for me. Homespun lets you (the agent) build me (the human) an app: a rich interactive UI hosted by URL, built for the moment I need it. If it captures input, you get my response back as structured data. Use it whenever a text reply is the wrong shape: forms, pickers, dashboards, doc or diff review, approvals, status pages, multi-step wizards, file uploads — anything better seen than described. Input is optional; a read-only dashboard or status view is a valid Homespun.
Install everything at GLOBAL / USER scope, not in the current workspace. Homespun is a personal capability I want available in every project, not a per-repo dependency. Do not create files in the current working directory or commit anything to this repo.
Do the following:
1. Install the CLI globally: `npm i -g @homespunapps/cli` (needs Node 20+). The binary is `homespun`. Do not add it to the current project's package.json.
2. Install the Homespun skill into your agent's GLOBAL / USER skill directory, not a project-local one. For example:
- Claude Code: ~/.claude/skills/homespun/SKILL.md (NOT .claude/skills/ in the current repo)
- Cursor: user-level rules, NOT .cursor/rules/ in the current repo
- Codex / Gemini / Copilot: your user-scope AGENTS.md / GEMINI.md / instructions file, NOT the project root
Run `homespun skill show` to fetch the skill from the relay you're targeting — it prints the raw markdown to stdout, version-matched to that relay. Capture that output and save it in the appropriate format for your runtime (Claude Code keeps the markdown as-is; Cursor wants `.mdc` rules; Codex / Gemini compose it into the user-scope AGENTS.md / GEMINI.md).
3. Register against the hosted relay: `homespun agent register --name "<short-descriptive-agent-name>"`. Pick a name that identifies your agent (e.g. `claude-code-lalit-macbook`, `cursor-work-laptop`) — the default is unhelpful. One-time, writes a key to ~/.config/homespun/config.json (already user-scope).
4. Confirm install with `homespun key list`. This round-trips your key against the relay and prints { agent_id, name, key_prefix, ... } — proves the CLI is installed AND registration succeeded.
5. Now exercise the round-trip end-to-end so I can see it work:
- Create a simple two-way app — a small inline HTML template with a text input and a submit button that emits an event back to you with `homespun.emit("hello", {msg})` (use whatever shape `homespun create --help` and the SKILL.md describe; the simplest "hello" form is fine).
- Print the resulting app URL (`urls.humans[0]`) and ask me to open it.
- Start watching for the submit event (e.g. `homespun watch <homespun-id> --type hello`).
- When I submit, show me the structured event payload you received. That's the "aha" moment — confirms the full round-trip works.
After this, reach for `homespun create / show / send / watch` (and `homespun template …` to reuse UIs) whenever a UI would communicate better than text. Run `homespun <command> --help` for authoritative options.Run yourself (human)
Six commands. Needs Node 20+.
# 1. Install the CLI (Node 20+)
npm i -g @homespunapps/cli
# 2. Register with the hosted relay, pick a short, descriptive agent name
homespun agent register --name "<short-descriptive-agent-name>"
# 3. Confirm, round-trips your key against the relay
homespun key list
# 4. Install the skill into your agent. `homespun skill show` prints the relay's
# current, version-matched skill markdown to stdout, save it where your
# runtime keeps skills (e.g. ~/.claude/skills/homespun/SKILL.md for Claude Code).
homespun skill show > ~/.claude/skills/homespun/SKILL.md
# 5. Claim your agent so it can deploy. Open https://homespun.dev/get-started,
# generate a claim code, then run:
homespun agent claim <code>
# 6. Deploy your first app (reads ./my-app/index.html + manifest.json).
# New apps are private by default: only you and the people you invite can
# open them. Pass --visibility link or --visibility public to share wider.
homespun deploy ./my-appUse from an AI chat (remote connector — no install)
No terminal? Add Homespun to Claude (web, desktop, mobile), ChatGPT, or any chat app that supports remote MCP connectors — nothing to install. Add a custom connector pointing at:
https://homespun.dev/mcpLog in with your email (magic link), approve the consent screen once, and Homespun's tools show up in the chat — then ask it to "build me an app for …" and it hands back a URL. This is the only way to drive Homespun from a phone or a pure chat app.
Full walkthrough (Claude web/desktop/mobile, Claude Code's claude mcp add,
ChatGPT, and others) → docs/CONNECT-AI-CHAT.md.
Distribution
The repo is an npm-workspaces monorepo with four packages:
@homespunapps/core— the relay client: a pure, framework-free HTTP + WebSocket library (HomespunClient+openStream). Build any client on it.@homespunapps/relay— the relay server. Use the hosted instance, or self-host it withdocker compose up(bundled Postgres) — see Self-hosting.@homespunapps/cli— thehomespuncommand-line tool. The agent's entry point: emits JSON on stdout, so it's harness-agnostic — works for an MCP host, a cron agent, a shell pipeline, a CI job, or a process supervisor.homespun watch <id> --type <event>streams an app as JSON-lines and exits when the awaited event lands. A LangChain tool wrapper may come later.@homespunapps/mcp— a thin stdio MCP server (binaryhomespun-mcp) with full parity with the CLI. Point Claude Desktop, Cursor, or any MCP client atnpx @homespunapps/mcpand Homespun shows up as tools: the hot-path discrete tools (create_app,get_events,send_to_app,update_app,upgrade_app,list_apps,delete_app, the record CRUD tools) plus consolidatedaction-based tools for templates, sharing, attachments, taste, keys, trash, feedback, agent identity, andrun_query/get_skill. See the package README for the full tool list and client config snippets.
The CLI is homespun <command> [options] — create, show, send, watch, list, delete, and participant operate on an app; template, attachment, records, query, taste, feedback, key, agent, config, and skill are the other command groups. Run homespun --help for the full list.
Use from an MCP client (local stdio server)
Run Homespun as a local stdio MCP server inside any MCP host (Claude Desktop, Cursor, …) — no global install needed. (For a chat app with no terminal, or your phone, use the remote connector instead — nothing to run locally.)
{
"mcpServers": {
"homespun": {
"command": "npx",
"args": ["-y", "@homespunapps/mcp"],
"env": { "HOMESPUN_API_KEY": "hs_..." }
}
}
}Omit env to let the server auto-register an agent on first use. Full setup, the tool list, and the poll-for-events pattern are in the @homespunapps/mcp README.
Stack
TypeScript. Runtime: Node 20+ (Bun fine too). Web: Hono (tiny, fast, container/edge-friendly). ORM: Prisma. PostgreSQL, self-host and hosted alike. npm workspaces for the monorepo. See docs/SPEC.md.
Self-hosting
You don't have to run a relay — point the CLI at the hosted instance and you're done. But Homespun is open-core (MIT) and self-hosts with no paid dependencies:
docs/SELF-HOSTING.md — run your own relay with
docker compose up(relay + bundled Postgres). Set three env vars, done.docs/DEPLOY.md — the operator guide: managed Postgres, multi-replica scaling, observability, and the Azure Container Apps reference deployment.
The relay is configured entirely through environment variables —
packages/relay/.env.example is the full
reference.
Contributing
Issues, fixes, and design feedback are welcome. See
CONTRIBUTING.md for dev setup, the test suites, and PR
conventions, and CODE_OF_CONDUCT.md for community
expectations. Security vulnerabilities: please report them privately — see
SECURITY.md.
See also
skills/homespun/SKILL.md: the agent-facing reference — every command, the template/app model, schemas, records, attachments, query (authoritative, version-matched to the relay)docs/CONNECT-AI-CHAT.md: add Homespun to Claude / ChatGPT / any chat app as a remote connector — no installdocs/SPEC.md: technical design (architecture, API, data model, bridge, auth, open/closed split)docs/SELF-HOSTING.md: run your own relay withdocker compose up(relay + bundled Postgres)docs/DEPLOY.md: operator deployment — managed Postgres, scaling, observability, Azuredocs/ROADMAP.md: scope, later phases, strategy notesdocs/architecture/: per-phase implementation docs (Prisma models, endpoints, the app runtime, the CLI)Prior art / landscape: MCP Apps (
blog.modelcontextprotocol.io/posts/2026-01-26-mcp-apps/), mcp-ui (github.com/MCP-UI-Org/mcp-ui), AG-UI (copilotkit.ai), A2UI (Google), Thesys C1Motivating read: Thariq, "Using Claude Code: The Unreasonable Effectiveness of HTML" (
simonwillison.net/2026/May/8/unreasonable-effectiveness-of-html/)
Available Tools
26 toolsagentManage Agent IdentityADestructive
Agent identity + binding. ONE tool with an action enum: whoami (the resolved relay URL, active profile, whether a key is configured — no network, no secrets) | claim (bind this agent to a human via a one-shot claim code from their Settings UI; one-way) | logout (clear the locally-saved key/profile; does NOT revoke it on the relay — use the key tool's revoke for that).
| Name | Required | Description | Default |
|---|---|---|---|
| code | No | The one-shot claim code (required for claim). | |
| action | Yes | Agent identity. whoami: show the resolved relay URL, active profile, and whether a key is configured (no network, no secrets). claim: bind this agent to a human via a one-shot claim code the human generated in their Settings UI (one-way). logout: clear the locally-saved key/profile (does NOT revoke it on the relay — use the key tool's revoke for that). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behavioral traits beyond annotations: whoami is 'no network, no secrets', claim is 'one-way', and logout has a side-effect (clear local key but no relay revocation). Annotations only say destructiveHint=true; the description enriches with specific constraints and non-obvious behaviors.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single sentence that efficiently packs all actions and key details. While dense, it front-loads the core concept and uses clear separators (pipe). Minor conciseness could be improved by splitting into bullet points, but it remains effective.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (three actions, no output schema, but with annotations), the description covers all necessary behavioral aspects: each action's purpose, constraints (one-way, no network), side effects, and cross-tool reference for revocation. It is sufficiently complete for safe invocation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with good descriptions, but the description adds behavioral context (e.g., 'one-way' for claim, 'does NOT revoke' for logout) that goes beyond the schema's parameter descriptions. This enhances understanding without being redundant.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool's purpose: 'Agent identity + binding', and explicitly enumerates three distinct actions (whoami, claim, logout) with specific behaviors. It distinguishes from siblings by referencing the 'key' tool for revocation, ensuring the agent understands this tool's unique role.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use each action and, crucially, when not to: 'logout does NOT revoke it on the relay — use the key tool's revoke for that'. This direct alternative usage instruction is highly actionable for an AI agent.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
attachmentsManage AttachmentsADestructive
Binary attachments (images, PDFs, audio, video) referenced from event payloads / input_data via format: pane-attachment-id. ONE tool with an action enum: upload | download | show | list | delete | mint_token | revoke_token | list_tokens. upload reads an ABSOLUTE file_path; download writes to an ABSOLUTE out_path (or returns base64). Scope an upload to agent (default, reusable), pane, or template. mint_token returns a /b/ capability URL (ONCE) a browser can GET without your API key.
| Name | Required | Description | Default |
|---|---|---|---|
| mime | No | upload: advisory Content-Type (the relay sniffs the bytes regardless). | |
| once | No | mint_token: token self-deletes on first GET. | |
| limit | No | list page size (1..100). | |
| scope | No | upload scope (default agent). | |
| action | Yes | Binary attachment operations. upload: read a local file (file_path) and upload it; scope agent|pane|template. download: fetch bytes by attachment_id to out_path (absolute) or return base64. show: metadata only. list: the agent's attachments. delete: soft-delete. mint_token: mint a /b/<token> capability URL (returned ONCE). revoke_token / list_tokens: manage those tokens. | |
| cursor | No | list pagination cursor. | |
| pane_id | No | Required when scope=pane. | |
| filename | No | upload: display filename (defaults to the file's basename). | |
| out_path | No | download: ABSOLUTE path to write the bytes to. If omitted, the bytes are returned base64-encoded in the result. | |
| token_id | No | revoke_token: the token id to revoke. | |
| file_path | No | upload: ABSOLUTE path to the local file to upload. | |
| template_id | No | Required when scope=template. | |
| ttl_seconds | No | mint_token: per-token TTL (clamped by scope default). | |
| attachment_id | No | Attachment id. Required for download/show/delete/mint_token/revoke_token/list_tokens. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses behaviors such as absolute paths for upload/download, base64 fallback, soft-delete, and token self-deletion on first GET. Annotations indicate destructiveHint=true, which aligns with delete actions. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a single paragraph that efficiently packs details without fluff. It front-loads the core purpose and action list. Could be broken into bullet points but is still concise.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 14 parameters, conditional requirements, and no output schema, the description covers all actions, parameter roles, and return behavior (base64 for download, token for mint_token). It is thorough.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description adds meaningful context for each action and parameter (e.g., scope defaults to agent, token behavior). It significantly enhances understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly identifies the tool as managing binary attachments (images, PDFs, etc.) referenced from event payloads, and lists all actions. It is distinctive from sibling tools which focus on different entities like panes, records, or events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description specifies when to use the tool (for binary attachment operations) and explains each action's context. It lacks explicit comparisons to alternatives but the purpose is narrow enough that usage is clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
create_paneCreate PaneADestructive
Hand the human a rich interactive UI by URL and (optionally) get structured data back. Build the UI as inline HTML (pass name + html) OR reuse a saved template (pass template_id). The relay hosts it and returns a URL. ALWAYS give the returned url to the human — paste it into the conversation and ask them to open it. Reach for this whenever a text reply is the wrong shape: forms, approvals, pickers, surveys, dashboards, diff/doc review, wizards. If the page captures input it emits events back to you (poll them with get_events) or mutates record collections (the record tools). BEFORE authoring: call get_skill for the events-vs-records decision + schema grammar, and the taste tool (action: get) for the human's house style — both shape the HTML you write. Returns { pane_id, url, urls, title, expires_at }.
| Name | Required | Description | Default |
|---|---|---|---|
| html | No | The pane's UI as a complete inline HTML document. To send data back to you, the page calls window.pane.emit(eventType, payload) — every emitted eventType MUST be declared in event_schema with 'page' in its emittedBy. Read window.pane.inputData for seed data. Pass EITHER `html` (+`name`) for a one-off, OR `template_id` to reuse a saved template — not both. | |
| name | No | Short human-readable label for the auto-created template (e.g. 'Deploy approval'). REQUIRED when you pass `html` (inline form); omit when reusing an existing template via `template_id` (it inherits the template's name). | |
| tags | No | Optional per-pane filter tags (merged with the template's tags). ≤20 tags, ≤50 chars each; 'favorite'/'favorites' are reserved. | |
| title | No | Optional browser tab title for the human (≤80 chars). Defaults to `name`. | |
| callback | No | Optional webhook callback config so the relay POSTs new events to your endpoint. Shape per the relay's callback schema (e.g. { url, secret? }). Most MCP agents poll with get_events instead. | |
| metadata | No | Optional opaque JSON you can attach to the pane for your own bookkeeping (never shown to the human, queryable via run_query). | |
| preamble | No | Optional one/two-line context shown above the UI — 'who is asking, and why'. | |
| icon_emoji | No | Optional single-emoji icon override for this pane. | |
| input_data | No | Optional seed data for this pane instance, readable in the page as window.pane.inputData (e.g. the diff to review, the options to pick from). | |
| context_key | No | Optional natural key (e.g. 'pr-42'). Repeated create_pane calls with the same (template, key) return the SAME pane — makes retries idempotent. | |
| template_id | No | Reuse an existing named template (id or slug) instead of inline HTML. The template's pinned version supplies the HTML + event/input/record schemas. Mutually exclusive with `html`/`name`/`event_schema`/`input_schema`. Create templates with the `template` tool. | |
| ttl_seconds | No | Optional pane lifetime in seconds. The relay clamps to its max; the returned expires_at is authoritative. | |
| event_schema | No | Inline form only. Declares which events the page (and you) may emit and validates each payload. Shape: { events: { '<type>': { emittedBy: ['page'|'agent'...], payload: <JSON Schema> } } }. OMIT for a read-only pane. | |
| input_schema | No | Inline form only. Optional JSON Schema validating input_data. Needed if input_data references uploaded attachment ids the page must download. | |
| participants | No | Optional number of distinct human participant URLs to mint (default 1). Each gets its own URL in the returned `urls` array. | |
| record_schema | No | Inline form only. JSON Schema 2020-12 doc with an `x-pane-collections` extension declaring this pane's mutable record collections (todos, comments…). OMIT for an event-only pane. | |
| template_version | No | With `template_id`: pin this pane to a specific template version. Defaults to the template head's latest version. | |
| icon_attachment_id | No | Optional per-pane icon as a ready raster-image attachment id (png/jpeg/webp/gif). Upload it first via the `attachments` tool (scope: pane or agent). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses key behaviors: it creates a pane (destructive), returns a URL, expires after a time, and can be idempotent with context_key. It does not contradict the annotations (readOnlyHint=false, destructiveHint=true, idempotentHint=false). However, it does not mention rate limits or cost, missing a bit of transparency. Overall, it adds substantial context beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is appropriately detailed without being verbose. It starts with the core purpose and an actionable instruction ('ALWAYS give the returned url to the human'), then logically flows through usage, prerequisites, and technical details. Every sentence serves a purpose, making it efficient and well-structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's high complexity (18 parameters, no output schema), the description is remarkably complete. It explains the return object shape, pre-requisites (get_skill, taste), edge cases (idempotency, event schema for read-only), and how it relates to sibling tools. No essential information is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. However, the description adds extensive context for each parameter: mutual exclusivity of html/template_id, required name when html provided, reserved tags, callback opt-in, seed data usage, and more. This goes well beyond the schema definitions, earning top marks.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool creates a rich interactive UI by URL, with options for inline HTML or saved template. It distinguishes from siblings by listing specific use cases and instructing the agent to always return the URL to the human. The description also references related tools like get_events, making its role clear.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance on when to use this tool ('Reach for this whenever a text reply is the wrong shape'), lists many use cases, and advises when not to use it by mentioning alternatives (poll events with get_events or use record tools). It also instructs to call get_skill and taste before authoring, which is valuable context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_paneDelete PaneADestructiveIdempotent
Close/delete a pane (idempotent — an already-closed pane still succeeds). The human's URL stops working. To merely edit a pane keep it alive with update_pane; to recover a soft-deleted pane use the trash tool (action: restore).
| Name | Required | Description | Default |
|---|---|---|---|
| pane_id | Yes | The pane id to close/delete (idempotent). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already cover idempotent and destructive behaviors. Description adds valuable context: 'The human's URL stops working.' Extends transparency 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no wasted words. Every sentence adds unique information: idempotency, URL effect, and sibling tool guidance.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given single param, annotations, and no output schema, description fully covers behavior, consequences, and related tools. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers 100% of parameters. Description adds idempotent context for pane_id, clarifying that it's safe to resend. Adds value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the action (close/delete) and resource (pane). Distinguishes from siblings like update_pane and trash, ensuring no ambiguity.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly provides when-to-use and alternatives: edit uses update_pane, recovery uses trash. No ambiguity about appropriate context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_recordDelete RecordADestructiveIdempotent
Soft-delete a row from a pane's record collection. The page sees the deletion live (the row becomes a tombstone in list_records). Pass if_match for an optimistic-locked delete. Returns { deleted: true }.
| Name | Required | Description | Default |
|---|---|---|---|
| pane_id | Yes | The pane id. | |
| if_match | No | Optional optimistic-lock version. | |
| collection | Yes | The record collection name. | |
| record_key | Yes | The key of the record to delete. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (destructiveHint=true), describes soft-delete behavior, tombstone in list_records, and return value. No major gaps.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences, front-loaded with key action, no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers return value and behavioral aspects adequately for a simple delete tool; no output schema needed.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline 3. Description adds meaning to if_match parameter ('optimistic-locked delete'), enhancing clarity.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Soft-delete a row from a pane's record collection' with specific verb and resource, distinguishes from sibling tools like delete_pane and delete_record_collection.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides guidance on when to use if_match for optimistic locking, but does not explicitly state when not to use this tool or compare to alternatives like update_record.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
delete_record_collectionDelete Record CollectionADestructiveIdempotent
Drop a WHOLE per-pane record collection at once: every row plus the collection row itself. Use this to reset or remove a collection (todo list, comment thread, board) rather than deleting rows one by one with delete_record. Owner-only and destructive, so it requires confirm:true. Collection names are immutable, so to rename a collection drop the old one and write under the new name. Returns { deleted: true, collection }.
| Name | Required | Description | Default |
|---|---|---|---|
| confirm | Yes | Required (true) to drop the whole collection. This removes every row plus the collection row itself and cannot be undone. | |
| pane_id | Yes | The pane id. | |
| collection | Yes | The record collection to drop in its entirety. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate destructiveHint=true and readOnlyHint=false; description adds owner-only constraint, confirm:true requirement, and return format { deleted: true, collection }, providing full 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences, front-loaded with the core action, followed by usage guidance, behavioral notes, and return format. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a tool with 3 required parameters, no output schema, and clear annotations, the description covers purpose, usage, constraints, and return value, leaving no ambiguity for an agent.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description does not add new parameter-level detail beyond what the schema already provides, but it reinforces the confirm parameter's role in the context of the tool's destructive nature.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the verb (drop/delete) and resource (whole per-pane record collection), and explicitly distinguishes from sibling 'delete_record' by noting it removes the entire collection at once rather than rows one by one.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use (reset/remove a collection) and when not to (instead of delete_record), provides rename workaround, and notes owner-only and confirm requirement.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
feedbackManage FeedbackADestructive
Send or list feedback to the relay operator. ONE tool with an action enum: create (a bug|feature|note with a message, optional pane_id) | list (the agent's own submissions, newest first, paginated by before).
| Name | Required | Description | Default |
|---|---|---|---|
| type | No | Feedback category (required for create). | |
| limit | No | list page size (default 50, max 100). | |
| action | Yes | Feedback to the relay operator. create: submit a bug|feature|note with a message (optional pane_id). list: the agent's own submissions, newest first. | |
| before | No | list cursor from a prior page's next_before. | |
| message | No | Message body (required for create). | |
| pane_id | No | Optional pane this feedback relates to (create). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds behavioral context beyond annotations: it notes that list returns the agent's own submissions (newest first) and is paginated by 'before'. Annotations include destructiveHint=true, which might be interpreted broadly, but the description does not contradict annotations and provides useful operation-specific details.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the core action, and efficiently packs details about sub-actions, parameters, and pagination. Every sentence serves a purpose without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
The description lacks explicit return value information for both create and list. For list, it says 'newest first, paginated by before' but does not state the structure of the return payload. For create, no mention of a confirmation or result. Since no output schema is provided, the description should compensate but partially fails to do so.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 groups parameters by action (e.g., mentioning that type is required for create) but largely repeats schema descriptions. It adds minimal new meaning beyond the schema, such as clarifying that list pagination uses 'before' from a prior response.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool sends or lists feedback, with a specific action enum distinguishing create and list. It identifies the resource (feedback) and the verbs (send/list), and the detail about categories (bug, feature, note) further clarifies the purpose. No sibling tool duplicates this functionality, so differentiation is not needed.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explains when to use create (for submitting feedback) and list (for viewing own submissions), including pagination details. It does not explicitly state when not to use the tool or provide alternatives, but the context is sufficient for an agent to decide based on the action enum.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_eventsGet EventsARead-only
Poll a pane's append-only event log for what the human did (form submissions, approvals, picks). This is how you receive the round-trip result — there is no push/streaming in MCP. Poll loop: call with no since first; process the returned events; remember next_cursor; call again passing it as since to get only newer events. To WAIT for a human who hasn't acted yet, pass wait_seconds (~25) so the relay holds the request open until an event arrives or it times out, then call again with the same cursor. Returns { events, next_cursor }.
| Name | Required | Description | Default |
|---|---|---|---|
| since | No | Opaque cursor from a previous get_events call's next_cursor. Omit on the first call to read from the beginning. | |
| pane_id | Yes | The pane id to read events from. | |
| wait_seconds | No | Optional long-poll: how long the relay holds the request open waiting for a new event (0–30s). Use ~25 when waiting for a human to act, then call again with the same cursor. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses append-only nature, polling behavior, absence of push/streaming, long-poll mechanism with wait_seconds, and response format { events, next_cursor }. No contradiction with annotations (readOnlyHint: true, openWorldHint: false).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is moderately sized and well-structured, with each sentence providing essential guidance. Slightly verbose but every part adds value. Could be tightened slightly.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given complexity (polling loop, cursor, long-poll) and lack of output schema, description covers core usage, response structure, and intent well. Minor gaps: no error handling or rate limits, but still highly complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% with parameter descriptions, but the description adds crucial context: explains 'since' as a cursor from previous call, 'wait_seconds' for waiting on human action, and the overall polling pattern that ties parameters together.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool polls a pane's append-only event log for human actions like form submissions, approvals, and picks. Distinguishes from sibling tool 'get_pane_state' which deals with state, not events.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes the poll loop with and without 'since' parameter, and how to use 'wait_seconds' for long-polling. Also notes there is no push/streaming in MCP, so this is the only way to get round-trip results.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_pane_stateGet Pane StateARead-only
Fetch a pane's current metadata (status, title, template version, timestamps, expires_at) WITHOUT its event log. Use it to check whether a pane is still open or has expired. To read what the human did, use get_events.
| Name | Required | Description | Default |
|---|---|---|---|
| pane_id | Yes | The pane id returned by create_pane. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and openWorldHint=false. The description adds value by specifying exact metadata fields and explicitly stating that the event log is excluded, which is not in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, no redundancy. Front-loaded with purpose and immediately provides usage context. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity (one parameter, no output schema, clear annotations), the description adequately covers purpose, usage, return content, and exclusions. No gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100% and the schema description fully documents the single parameter 'pane_id'. The description does not add extra semantic info 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.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the verb 'Fetch', the resource 'pane's current metadata', and specifies the items included (status, title, template version, timestamps, expires_at). It distinguishes from the sibling tool 'get_events' by noting the exclusion of the event log.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use: 'to check whether a pane is still open or has expired', and when not to use: 'To read what the human did, use get_events'. Provides a clear alternative.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_recordGet RecordARead-only
Fetch a single record row by its key from a pane collection (scans the collection — fine for a one-off lookup, not a hot loop). Returns { record } or an isError record_not_found.
| Name | Required | Description | Default |
|---|---|---|---|
| pane_id | Yes | The pane id. | |
| collection | Yes | The record collection name. | |
| record_key | Yes | The key of the record to fetch. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description adds that it 'scans the collection' and specifies the return format ({ record } or isError), going beyond the readOnlyHint annotation. No contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, each serving a purpose: first states the action, second adds behavioral context and return value. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple fetch tool with three required parameters, the description covers the return format and scanning behavior. No output schema exists, but the description compensates adequately.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all three parameters with descriptions (100% coverage). The description does not add meaningful detail beyond the schema, so baseline score applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states 'Fetch a single record row by its key', which distinguishes it from list_records and other siblings. The verb+resource is specific and unambiguous.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly says 'fine for a one-off lookup, not a hot loop', providing clear usage constraints. Does not name alternative tools but the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
get_skillGet Skill GuideARead-only
Fetch the relay's auto-updating SKILL.md (the full Pane usage guide) — UNAUTHENTICATED, needs no API key. Call this to self-teach the Pane workflow (events vs records, schema grammars, the poll loop) before driving the other tools. Pass version_only:true to get just the relay's skill version string (to check if a cached copy is stale).
| Name | Required | Description | Default |
|---|---|---|---|
| version_only | No | If true, return only the relay's current skill version string instead of the full SKILL.md markdown. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint true, and the description adds that the tool is unauthenticated, which is valuable context beyond the annotations. It also explains the behavior difference when version_only is passed.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences, front-loaded with the most important information. Every sentence provides distinct value with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a simple read-only tool with one optional parameter and no output schema, the description covers what it returns and when to use it comprehensively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, and the description adds practical context for the version_only parameter, explaining its use case (checking if a cached copy is stale), which goes beyond the schema description.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it fetches the SKILL.md guide, is unauthenticated, and is intended for self-teaching before using other tools. It distinguishes itself from siblings by explaining its role as a learning resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly advises calling this tool to learn the workflow before driving other tools, and provides specific guidance for the version_only parameter to check cache staleness. It does not explicitly mention when not to use it, 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.
keyManage API KeyADestructive
Inspect or revoke the calling agent's API key. ONE tool with an action enum: list (key info — agent_id, key_prefix, timestamps) | revoke (self-destruct the agent's OWN key; it stops working immediately and is irreversible — pass confirm:true). The relay scopes keys to the caller, so both act only on your own key.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | The calling agent's API key. list: key info (agent_id, key_prefix, timestamps). revoke: self-destruct the agent's OWN key — it stops working immediately and is irreversible (requires confirm:true). | |
| confirm | No | Required (true) for revoke. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Description discloses all behavioral traits: destructive hint is confirmed with 'self-destruct' and 'irreversible'; scoping to caller is added context not in annotations. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences, front-loaded with purpose, and includes essential details without extraneous text. Efficient and clear.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description adequately covers return info for list and effect of revoke. Completeness is high for a simple 2-parameter tool.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds value by explaining the conditional requirement of 'confirm' for revoke and listing the output of 'list', going beyond schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description explicitly states 'Inspect or revoke the calling agent's API key' with specific actions (list and revoke). Clearly distinguishes from sibling tools which do not involve key management.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Provides context for when to use each action, including that revoke is irreversible and requires confirm:true. Lacks explicit mention of when not to use, but given no direct sibling overlap, the guidance is sufficient.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_panesList PanesARead-only
Enumerate YOUR agent's panes (newest first). Use it to find a pane_id you lost, audit what's open, or get a cursor for pagination. No secrets in the response (participant tokens are unrecoverable — mint a fresh URL with the participant tool). Filter by status (open|closed|all) or template_id. Returns { items, next_cursor }.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Page size (default 50, max 200). | |
| cursor | No | Opaque cursor from a previous page's next_cursor. | |
| status | No | Filter by effective status. Default: open. | |
| template_id | No | Filter to panes instantiated from a specific named template (head id, not version id). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already indicate readOnlyHint=true. Description adds important behavior: participant tokens are not returned and how to obtain them (via participant tool). Also states return shape is { items, next_cursor }. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two sentences: first states core purpose and ordering, second adds use cases, behavioral note, filters, and return shape. No redundant words, front-loaded with essential info.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers purpose, ordering, return shape, pagination cursor, security note about secrets, and filter options. For a list tool with well-described schema, this description is complete and self-contained.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema provides 100% coverage for all 4 parameters. Description only summarizes filters by status and template_id, adding minimal extra value beyond 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.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the action ('enumerate') and resource ('panes'), with ordering ('newest first'). It lists specific use cases (find pane_id, audit, get pagination cursor), distinguishing the tool from siblings like get_pane_state (single pane) and create_pane.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Describes when to use: to find lost pane IDs, audit open panes, get pagination cursor. Includes a caution about secrets and direction to use the participant tool for tokens. Could be more explicit about not using for single-pane details, but context with siblings makes it clear.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
list_recordsList RecordsARead-only
List rows in a pane's mutable record collection (todo list, shopping list, kanban board, comment thread). Records are the right primitive when the page shows several mutable items and the CURRENT state matters more than the history. This also doubles as the POLL/watch for records (no streaming in MCP): pass the prior next_since to fetch only newer/changed rows. include_tombstones:true surfaces deletions. Returns { records, next_since, has_more }.
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Optional page size (max 200). | |
| since | No | Optional cursor (next_since from a prior call). Also the POLL handle: to watch a collection (no streaming in MCP), call repeatedly passing the previous next_since to fetch only newer/changed rows. | |
| pane_id | Yes | The pane id. | |
| collection | Yes | The record collection name declared in the pane's record schema. | |
| include_tombstones | No | Include soft-deleted rows (deleted_at set) so you can observe deletions. Default false. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations declare readOnlyHint=true. The description adds return value details (records, next_since, has_more), explains include_tombstones for deletions, and clarifies polling behavior. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise, front-loaded with main purpose, and efficiently adds polling and return info. No unnecessary sentences, though could be slightly more structured.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given 5 parameters and no output schema, the description adequately covers return format, polling, and deletions. It is complete enough for an agent to use the tool correctly, though examples or edge cases could enhance.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all 5 parameters with descriptions (100% coverage). The description adds context for the 'since' parameter as a polling handle and for 'include_tombstones' as surfacing deletions, adding value beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool lists rows in a pane's mutable record collection. It differentiates from sibling tools like get_record by focusing on listing all records, and adds the polling/watch aspect.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides guidance on when to use records (when page shows mutable items and current state matters) and how to poll via the since parameter. It implicitly excludes uses where history matters more, but does not explicitly contrast with alternatives like get_record.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
participantManage ParticipantsADestructive
Manage a pane's participant URLs (recovery + leak-containment). ONE tool with an action enum: list | new | revoke. Use new when you lost the original URL (the plaintext token is returned ONCE — save it). Token URLs are stored hashed and cannot be recovered.
| Name | Required | Description | Default |
|---|---|---|---|
| action | Yes | Manage a pane's participant URLs. list: every participant (active + revoked) — use it to find a participant_id. new: mint a FRESH human URL on an existing pane (the plaintext token is returned ONCE — save it before delivering). revoke: invalidate one participant URL. | |
| pane_id | Yes | The pane id. | |
| participant_id | No | The participant id to revoke (required for revoke). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds significant behavioral details beyond annotations: the plaintext token is returned once and must be saved, tokens are hashed and unrecoverable, and the tool is used for leak containment. This aligns with the destructiveHint annotation without contradiction.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, front-loads the purpose, and provides essential behavioral context without any redundancy or fluff. Every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description could be more complete about return values for list and revoke. However, it adequately covers the three actions and their critical behavioral nuance (token returned once). Missing output details slightly reduce completeness.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 value by explaining the enum actions' meanings (list for finding ID, new for minting with token warning, revoke for invalidation). However, pane_id and participant_id descriptions are not enhanced beyond schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it manages a pane's participant URLs for recovery and leak-containment. It distinguishes three actions via an enum (list, new, revoke) with specific purposes. No sibling tool serves this exact function, making it uniquely identifiable.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides explicit guidance for each action, such as using 'new' when the original URL is lost. It implies usage contexts (e.g., 'list' to find participant_id) but does not explicitly state when not to use the tool or compare to alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
run_queryRun SQL QueryARead-only
Run read-only SQL over YOUR scoped data (panes, records, events) — the relay scopes every row to panes you own. Use it to summarise activity, find panes/records by content, or build a report. Tables + columns and JSON projection operators are documented on the sql parameter. Default output is { columns, rows, truncated, scope, elapsed_ms } (format:json); csv/tsv/table render the rows as text. Capped at 10,000 rows; 10s timeout.
| Name | Required | Description | Default |
|---|---|---|---|
| sql | Yes | Read-only SQL (SELECT/WITH/SHOW/DESCRIBE/EXPLAIN/PRAGMA) over your scoped data. Tables: panes(id,title,template_id,template_version,status,created_at,expires_at,deleted_at,metadata,input_data), records(id,pane_id,collection,key,data,version,seq,author_kind,author_id,created_at,updated_at,deleted_at), events(id,pane_id,type,ts,author_kind,author_id,data,template_version_id). `data` is JSON — project with ->> / ->. Capped at 10k rows; 10s timeout. | |
| format | No | Output format. Default json (columns+rows+meta). csv/tsv/table render the rows as text. | |
| pane_id | No | Scope the query to a single pane (resolves a view_conflict when two of your panes share a collection name with different schemas). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, but the description adds important behavioral details: scoping to user's data, 10,000 row cap, 10-second timeout, and output format details. This goes 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (three sentences) and front-loaded with the key verb 'Run read-only SQL'. Every sentence adds essential information with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (SQL query with multiple options), the description fully covers purpose, parameters, limits, scoping, and output format. With complete schema coverage and annotations, no gaps remain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Despite 100% schema coverage, the description adds significant value for each parameter: sql parameter lists available tables and columns, explains JSON operators; format parameter describes output behavior; pane_id explains conflict resolution. All three are well explained.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it runs read-only SQL over scoped data, with explicit use cases (summarise activity, find panes/records, build a report). It distinguishes itself from sibling tools as the only SQL query tool.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear context on when to use (summarising, finding, reporting) and implies read-only nature. However, it does not explicitly state when not to use or point to alternatives, though no alternatives exist among siblings.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
send_to_paneSend to PaneADestructive
Push an event INTO an open pane — update the live UI the human is looking at (progress, a new message, a status change, fresh data). The event type must be declared in the pane's event_schema with 'agent' in its emittedBy. For mutable collections (todos, line items, comment threads) prefer the record tools instead. Returns { event, deduped }.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | Event payload — any JSON value valid against the type's payload schema. Use {} or null for a no-payload event. | |
| type | Yes | Event type. Must be declared in the pane's event_schema with 'agent' in its emittedBy list. | |
| pane_id | Yes | The pane id to push the event into. | |
| idempotency_key | No | Optional dedup key — a repeat send with the same key is a no-op. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Adds context beyond annotations: explains it updates live UI, requires event type constraints, and mentions return value { event, deduped }. Idempotency_key dedup behavior is noted. No contradiction with annotations (readOnlyHint=false, destructiveHint=true).
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, each essential: first states action, second gives constraint, third provides usage guidance and return format. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Covers main behavior, constraints, dedup, and return. For a tool with 4 params and no output schema, this is sufficient. Could mention error cases but not necessary for typical use.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so baseline is 3. Description adds meaning: explains data as payload valid against schema, idempotency_key for dedup, and type must match pane's event_schema. This adds value beyond schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses specific verb ('push an event INTO') and resource ('open pane'), clearly stating it updates live UI. It distinguishes from sibling tools by mentioning preference for record tools on mutable collections.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly states when to use (push events into pane for live UI updates) and when not (prefer record tools for mutable collections). Also provides constraint on event type: must be declared in pane's event_schema with 'agent' in emittedBy.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
tasteManage UI Taste NotesADestructive
Read / write / clear the agent's freeform UI taste notes (a small markdown document of presentation preferences learned from human feedback — 'denser layout', 'no rounded corners'). ONE tool with an action enum: get | set | clear. Call get BEFORE generating a pane so prior feedback shapes the output; set does a whole-document replace (not append). Keep entries about UI/presentation only.
| Name | Required | Description | Default |
|---|---|---|---|
| taste | No | The full markdown notes (required for set; whole-document replace, not append). | |
| action | Yes | The agent's freeform UI taste notes (markdown) — presentation preferences learned from human feedback. get: read them before generating a pane. set: whole-document replace (taste, non-empty). clear: delete them. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description provides detailed behavioral context: it is a read/write/clear tool, `set` replaces the entire document, and entries should be UI-only. The annotations only indicate destructiveHint=true, so the description adds significant value beyond the structured data.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is concise (two sentences plus a short instruction) and front-loaded with the purpose. Every sentence adds necessary information without redundancy or waste.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the absence of an output schema, the description covers the behavior of all actions (get, set, clear) and provides usage guidance. It could have explicitly stated that `get` returns the markdown string, but the context implies it. Overall, it is sufficiently complete.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 explaining that `taste` is required for `set` and that `set` does a whole-document replace, which goes beyond the schema's property descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Read / write / clear the agent's freeform UI taste notes', specifying the verb and resource. It distinguishes from siblings by focusing on UI/presentation preferences only, and the action enum (get/set/clear) further clarifies the scope.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It explicitly instructs to 'Call `get` BEFORE generating a pane' and explains that `set` does whole-document replace, not append. It also advises to 'Keep entries about UI/presentation only.' However, it does not explicitly mention when to use this tool versus alternative tools like 'feedback'.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
templateManage TemplatesADestructive
Manage reusable, versioned UI templates (author once, instance many times via create_pane's template_id). ONE tool with an action enum: create | version | update | search | list | show | get_version | delete | publish | unpublish | search_public | set_icon. Required fields per action are documented on the action parameter. A template is HTML + an event schema (+ optional input/record/template-record schemas); a pane is one use of one version of it.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Template id or slug. Required for version/update/show/get_version/delete/publish/unpublish/set_icon. | |
| html | No | HTML template body / source (required for create + version). | |
| name | No | Template display name (required for create). | |
| slug | No | Stable agent-chosen handle (create/update). | |
| tags | No | Search keywords (create/update). | |
| clear | No | set_icon: clear both the emoji and image icon. | |
| limit | No | search_public page size (1..50). | |
| query | No | Free-text search (for search / search_public). | |
| action | Yes | Which template operation to run. create: a new named template (needs name+html). version: append a new immutable version to an existing template (id+html). update: patch head metadata (name/slug/description/tags). search/list: find the agent's templates (search takes an optional query). show: full template + version list (id). get_version: one version's content (id+version). delete: remove the template + all versions (id, requires confirm:true). publish/unpublish: public catalog (id). search_public: the public catalog across all agents (optional query). set_icon: set/clear a template's icon (id + one of emoji / icon_attachment_id / clear). | |
| offset | No | search_public offset. | |
| scopes | No | verb:noun permission scopes for publish (e.g. ['read:agent']). Empty array clears them. | |
| confirm | No | Required (true) for the destructive `delete` action. | |
| version | No | Version number (required for get_version). | |
| icon_emoji | No | set_icon: a single-emoji icon. | |
| description | No | Prose description (create/update). | |
| event_schema | No | Event schema (create/version). Omit for a view-only template. | |
| input_schema | No | Per-pane input_data JSON Schema (create/version). | |
| record_schema | No | Per-pane record collections schema (create/version). | |
| template_type | No | Source kind. Default html-inline; html-ref treats html as a URL. | |
| icon_attachment_id | No | set_icon: a ready template-scoped raster-image attachment id. | |
| template_record_schema | No | Template-level (shared) record collections schema (create/version). Set this before using the template_records tool. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description discloses behavioral traits such as the destructive nature of delete (requiring confirm:true) and the concept of versioning, going beyond annotations which only indicate destructiveHint=true.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose and is structured with a clear action enum. It is slightly verbose but acceptable for the complexity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (21 params, multiple actions, no output schema), the description explains the conceptual model and defers to action parameter for details. It is fairly complete for an AI agent to understand the tool's domain.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema already documents each parameter. The description adds overarching context and references the action parameter's documentation but does not add per-parameter meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states 'Manage reusable, versioned UI templates' and explains the relationship to panes via create_pane's template_id, distinguishing it from pane creation tools. It provides a specific verb and resource.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implicitly guides usage by stating templates are authored once and instantiated via create_pane, but does not explicitly state when not to use this tool. It leverages sibling context.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
template_recordsManage Template RecordsADestructive
CRUD for TEMPLATE-level record collections — owner-curated content anchored to a template head and visible to every pane derived from any of its versions (vs per-pane records, which are the discrete record tools). ONE tool with an action enum: list | get | upsert | update | delete | delete_collection. The template version must declare the collection via template_record_schema (set it with the template tool first).
| Name | Required | Description | Default |
|---|---|---|---|
| data | No | Record body. Required for upsert/update. | |
| limit | No | List page size. | |
| since | No | List cursor (and poll handle). | |
| action | Yes | Operation on a TEMPLATE-level (owner-curated, shared across every pane of the template) record collection. Same grammar as the per-pane record tools but scoped to a template head. The template version must declare the collection via template_record_schema (set it with the `template` tool). | |
| confirm | No | Required (true) for delete_collection (drops the whole collection). | |
| if_match | No | Optimistic-lock version for update/delete. | |
| collection | Yes | The template-level collection name. | |
| record_key | No | Record key. Required for get/update/delete; optional for upsert. | |
| template_id | Yes | Template id or slug. | |
| include_tombstones | No | Include soft-deleted rows in list. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the destructive hint annotation, the description explains that delete_collection requires a confirm parameter, and notes that the tool is owner-curated. This adds valuable behavioral context not present in annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is relatively concise, packing essential information into two sentences. However, the second sentence is lengthy and could be split for better readability. It avoids unnecessary words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the complexity of the tool (10 parameters, no output schema), the description provides key context: purpose, distinction from sibling tools, prerequisite, and action set. It could mention return behavior or error conditions, but overall it is sufficient for an experienced user.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the schema fully documents each parameter. The description adds context about the action enum and that the tool has the same grammar as per-pane tools, but does not significantly enhance parameter understanding beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states that the tool performs CRUD operations on template-level record collections, distinguishing it from per-pane records. It specifies the resource (template-level records) and the action via an enum, providing a precise purpose.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description indicates when to use this tool (for template-level records) versus per-pane records, and notes a prerequisite (collection must be declared via the template tool). However, it does not explicitly list when not to use it or provide alternative tools.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
trashManage TrashADestructive
Manage soft-deleted panes + templates. ONE tool with an action enum: list | restore (pane id) | restore_template (template id|slug) | purge (pane id) | purge_template (template id|slug). purge bypasses the retention window and is permanent. Soft-deleted rows live in trash until the sweeper reclaims them.
| Name | Required | Description | Default |
|---|---|---|---|
| id | No | Pane id (restore/purge) or template id|slug (restore_template/purge_template). | |
| action | Yes | Soft-delete trash. list: trashed panes + templates. restore/purge: un-trash or hard-delete a pane (id). restore_template/purge_template: same for a template (id|slug). purge bypasses the retention window (permanent). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark destructiveHint=true, and the description adds critical nuance: 'purge bypasses the retention window and is permanent' and explains the lifecycle (soft-deleted rows live in trash until sweeper reclaims them). 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is four sentences, front-loaded with purpose, and every sentence adds unique value: overall function, action enum breakdown, special behavior of purge, and lifecycle note. No wasted words.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's complexity (5 actions, 2 params, no output schema), the description covers actions and id semantics well. However, it lacks explanation of what the 'list' action returns (e.g., format or structure), which would be helpful for an agent. Minor gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, giving a baseline of 3. The description adds significant meaning by explaining the action enum values in context (e.g., 'restore: un-trash a pane (id)') and clarifying that id is used specifically with restore/purge for panes or templates. This goes beyond the schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states 'Manage soft-deleted panes + templates' with a specific verb and resource. It distinguishes itself from sibling tools by being the single entry point for all trash operations via an action enum, unlike other tools like delete_pane which likely handle direct deletion.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Description implies usage context by listing actions and noting purge is permanent, but does not explicitly state when to use this tool over alternatives like delete_pane or other sibling tools. No direct comparison or when-not guidance is provided.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_paneUpdate PaneADestructiveIdempotent
Edit instance-level fields on a LIVE pane in place (PATCH) without minting a new one — the pane keeps its id, URL, event log, and template pin. Settable: ttl_seconds OR expires_at (mutually exclusive), title, preamble, input_data (replaced wholesale + revalidated), metadata, tags, icon_emoji / icon_attachment_id (or clear_* to drop the override). Pass at least one field. Returns the full new pane state + an updated_fields array. To swap the HTML/schemas, use upgrade_pane instead.
| Name | Required | Description | Default |
|---|---|---|---|
| tags | No | Replace the per-pane tags. | |
| title | No | New tab title. | |
| pane_id | Yes | The pane id to edit. | |
| metadata | No | Replace the pane's metadata wholesale. | |
| preamble | No | New preamble (context band above the UI). | |
| expires_at | No | Set expires_at to a specific future ISO-8601 timestamp. Mutually exclusive with ttl_seconds. | |
| icon_emoji | No | Set the per-pane emoji icon. | |
| input_data | No | Replace the pane's input_data wholesale (revalidated against the pinned template version's input_schema). | |
| ttl_seconds | No | Reset the pane's lifetime to now + this many seconds. Mutually exclusive with expires_at. | |
| clear_icon_emoji | No | Clear the emoji override (fall back to the template's icon). | |
| icon_attachment_id | No | Set the per-pane icon to a ready raster-image attachment id. | |
| clear_icon_attachment_id | No | Clear the attachment icon override (fall back to the template's icon). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations provide destructiveHint and idempotentHint; description adds concrete behavior: pane keeps id, URL, event log, template pin; returns full state + updated_fields array, 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Description is concise and front-loaded: core action first, then settable fields with constraints, return info, and alternative tool – every sentence adds value.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, description mentions return format; covers all constraints (mutual exclusions, at least one field) and provides clear instructions, fully compensating for structured gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
100% schema coverage is already strong; description adds mutual exclusion (ttl_seconds vs expires_at), explains input_data revalidation, and clarifies clear_* fields for dropping overrides, exceeding baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Description clearly states it edits a live pane in place via PATCH, listing specific fields that can be set, and explicitly distinguishes from upgrade_pane for swapping HTML/schemas.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly tells when to use this tool (edit instance-level fields) and when to use upgrade_pane instead (for swapping HTML/schemas), plus instructs to pass at least one field.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
update_recordUpdate RecordADestructiveIdempotent
Update an existing row in a pane's record collection (replaces its data). Pass if_match with the row's current version for an optimistic-locked update — on a version mismatch the relay returns the current row so you can retry. Returns { record }.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The new record body (replaces the row's data). | |
| pane_id | Yes | The pane id. | |
| if_match | No | Optional optimistic-lock version. On mismatch the update is rejected with the current row in details.current. | |
| collection | Yes | The record collection name. | |
| record_key | Yes | The key of the record to update. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
The description adds context beyond annotations: replaces data, optimistic locking behavior, and return value on mismatch. Annotations already indicate destructive and idempotent traits. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences with no wasted words, front-loading the core action and then explaining the locking mechanism concisely.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a 5-parameter tool with no output schema, the description covers primary behavior, versioning, and return value. It lacks error handling details beyond version mismatch, but is sufficient for most use cases.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 value by explaining if_match's role in optimistic locking and the replacement behavior of data, providing meaning beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool updates an existing row in a pane's record collection, using specific verbs and resource. It differentiates from create/delete but does not explicitly contrast with the sibling tool upsert_record.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description provides guidance on using if_match for optimistic locking and retry behavior, but lacks explicit instructions on when to use this tool versus alternative tools like upsert_record or delete_record.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upgrade_paneUpgrade PaneADestructive
Re-pin a LIVE pane to swap its HTML (design) + event/input/record schemas in place — same URL, no new pane. Two ways: (1) pass html to EDIT AN INLINE PANE'S HTML in one call — the relay appends a fresh version with that HTML and re-pins (schemas you omit are inherited from the current version, so to change only the HTML pass only html); inline panes only. (2) pass template_version to re-pin to a version you already appended with the template tool (action: version) — for named/reusable templates. By default a strict schema-compat gate refuses an upgrade that would narrow the schema (returns schema_incompatible_upgrade + details.breaks); pass force:true to apply anyway. Returns { pane_id, template_version, upgraded, breaks, compat }.
| Name | Required | Description | Default |
|---|---|---|---|
| html | No | INLINE EDIT: the new HTML. The relay appends a fresh template version with this HTML and re-pins the pane to it in one call — editing an INLINE pane's HTML in place (same id/URL), no separate version step needed. Any schema you don't pass below is inherited from the pane's current version, so to change only the HTML pass only `html`. Inline panes only; a named/reusable template must go through the `template` tool (action: version) + `template_version`. Mutually exclusive with `template_version`. | |
| force | No | Override the strict schema-compat gate (compat=force). Without it, an upgrade that would narrow the schema is refused with schema_incompatible_upgrade + details.breaks. | |
| pane_id | Yes | The pane id to re-pin. | |
| event_schema | No | New event schema for the `html` version. Omit to inherit. | |
| input_schema | No | New input schema for the `html` version. Omit to inherit. | |
| record_schema | No | New record schema for the `html` version. Omit to inherit. | |
| template_type | No | Type for the `html` version. Default: html-inline. | |
| template_version | No | Target version of the SAME template. Defaults to the template head's latest version. Mutually exclusive with `html`. | |
| template_record_schema | No | New template-level record schema for the `html` version. Omit to inherit. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Discloses key behaviors: schema-compatibility gate with optional force override, return value structure, and the relay appending a version. Consistent with annotations (destructiveHint=true) and adds significant context beyond them.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Well-structured and front-loaded, with clear separation of usage modes. Each sentence adds value, though slightly verbose in places. Efficient for the complexity of the tool.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Comprehensive for a tool with 9 parameters, no output schema, and nested objects. Covers return value, error case (schema_incompatible_upgrade), and force option. No missing critical information.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
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 meaningful context for multiple parameters (e.g., html inline edit behavior, schema inheritance, mutual exclusivity, force override). Enhances understanding beyond schema names alone.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Clearly states the tool re-pins a LIVE pane to swap HTML and schemas in place. Specifically distinguishes two usage modes and contrasts with sibling tools like create_pane and template.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly describes two ways to use the tool (html for inline edit, template_version for reusable templates) with mutual exclusivity. Provides clear guidance on when to use each and when not to, mentioning that named/reusable templates must go through the template tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
upsert_recordUpsert RecordADestructiveIdempotent
Create a row in a pane's record collection, or return the existing row if record_key is already present (deduped:true). Use to add a todo, a line item, a comment, etc. The collection must be declared in the pane's record schema with 'agent' allowed to write. If you're still designing the pane, call get_skill first for the records-vs-events decision and the x-pane-collections schema grammar. Returns { record, deduped }.
| Name | Required | Description | Default |
|---|---|---|---|
| data | Yes | The record body — any JSON value valid against the collection schema. | |
| pane_id | Yes | The pane id. | |
| collection | Yes | The record collection name. | |
| record_key | No | Optional stable key. Reusing an existing key returns the existing row (deduped:true). |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond annotations (idempotent, destructive), the description reveals the deduped return flag, the prerequisite of collection write permission, and the exact return shape { record, deduped }. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four sentences with no superfluous words. First sentence states core behavior, second lists use cases, third gives prerequisite call, fourth specifies return value. Front-loaded and efficient.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description fully covers input requirements, dedup logic, preconditions (get_skill, collection write permission), and return shape. Siblings are many, but the description sufficiently differentiates the upsert behavior.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema covers all parameters (100% coverage), so baseline is 3. The description adds value by explaining record_key's deduplication role and the data parameter as 'record body', providing context not explicit in schema descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly defines the tool as an upsert operation: create a row or return existing if record_key is present (deduped:true). This distinguishes it from sibling tools like create_record (plain insert) and delete_record (removal).
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description advises when to use (add a todo, line item, comment) and when not to (if still designing, call get_skill first for records-vs-events decisions). It could explicitly contrast with create_record or delete_record, but the guidance is clear and helpful.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
26 tool updates
v0.1.0- First observed
agent - First observed
attachments - First observed
create_pane - First observed
delete_pane - First observed
delete_record - First observed
delete_record_collection - First observed
feedback - First observed
get_events - First observed
get_pane_state - First observed
get_record - First observed
get_skill - First observed
key - First observed
list_panes - First observed
list_records - First observed
participant - First observed
run_query - First observed
send_to_pane - First observed
share - First observed
taste - First observed
template - First observed
template_records - First observed
trash - First observed
update_pane - First observed
update_record - First observed
upgrade_pane - First observed
upsert_record
TDQS
Scored across 26 tools
Tools cover distinct aspects of the Pane system: identity, attachments, pane lifecycle, records, templates, etc. Some overlap exists between update_record and upsert_record, and between delete_pane and trash, but descriptions clarify the differences. Overall, an agent can reasonably distinguish between tools.
Mixed naming conventions: some tools use verb_noun (create_pane, delete_pane, list_records), while others are single-word nouns (agent, attachments, feedback, key, trash, taste) with action enums inside. This inconsistency could cause confusion, though each tool's purpose is clear.
26 tools is on the higher side but not unreasonable for the server's scope covering panes, records, templates, attachments, identity, and more. Some tools could potentially be consolidated (e.g., trash could be part of pane/template operations), but the count is still manageable.
The tool surface covers CRUD for panes, records, templates, and attachments, plus identity management, event polling, and feedback. Minor gaps exist (e.g., no explicit tool to list all templates requires using template's search action), but core workflows are well-supported.
Maintenance
Related MCP Connectors
An AI concierge that turns static forms into adaptive AI conversations. From any MCP client.
Human-in-the-loop for AI agents over MCP: durable approvals with a hosted review page & audit trail
Human-in-the-loop review and approval for AI agents. Audit trail, approval policies, native MCP.
Human-input bridge for AI agents with voice-first answer links, MCP tools, and HTTP APIs.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables AI clients to create multi-field forms, send approval requests via email, and retrieve structured human responses. It facilitates human-in-the-loop workflows by allowing agents to collect data and check form completion status.681 npmMIT
- AlicenseAqualityDmaintenanceEnables AI agents to render interactive user interfaces such as forms, dashboards, charts, tables, and wizards directly in MCP-compatible clients. Supports structured data collection and richer interactions beyond text responses.6MIT

Datashift MCP Serverofficial
AlicenseNot gradedqualityDmaintenanceEnables AI agents to submit tasks for human or AI review and receive decisions via MCP tools, adding human review checkpoints to workflows.MIT- AlicenseNot gradedqualityDmaintenanceEnables AI agents to ask clarification questions and receive structured user input through a Human-in-the-Loop interface.1MIT