| name | artifact-capabilities |
| description | Runtime capabilities a published Artifact page can be granted — behavior static HTML cannot provide on its own, such as the page reading live or connected data, remembering what people do on it (a poll, a sign-up sheet, a checklist, a document edited in place — it saves new versions of itself), keeping state shared across viewers, knowing who is viewing, asking Claude a question of its own, storing files people add, or handing the viewer a file to save. Serves this user's live capability roster and the typed call definitions. Load it whenever the user asks for an artifact needing any such runtime behavior. |
Artifact runtime capabilities
A published Artifact page can declare runtime capabilities — abilities the claude.ai viewer grants the page at open time — by passing capabilities: {name: config} to the Artifact tool. The control plane is the authority on valid names and config shapes. Declaration gestures: omitting capabilities on a redeploy carries the stored declaration forward unchanged (and preserves the artifact's stored contract pin); an empty object {} is the explicit clear-all; a non-empty object is a full-set declaration (anything stored but not restated is revoked). Moving a republished artifact's runtime version is a deliberate gesture — pass contract: 'latest' to upgrade, or a specific version to pin or roll back — never a side effect of editing.
Available capabilities: artifact, downloads, mcp, self — the complete set of capability names you may declare. Anything not listed is unavailable to this user.
Runtime contract 0.2.21
Capability namespaces live behind claude.use(name): const db = await claude.use("db") resolves the capability's namespace, or null when this view cannot run it (not served, not granted, or failed to load — indistinguishable by design). Branch on null and design for absence. window.claude carries only use: no window.claude.db, .room, or .artifact member is ever promised, so never read one — render the page without them and light features up when the promise resolves (later, never within your script's first run, and unordered with DOMContentLoaded; null after 10 s when no viewer answers). The resolved namespace is frozen and platform-owned: call its functions and keep the reference; never assign to it, defineProperty on it, or replace a member (wrap it for your own helpers). Permission stays on the calls: a consent prompt, rate limit, or policy refusal arrives on the first call, never from use(). Awaiting use("db") again is free (memoized); an unknown name resolves null.
--- capability: artifact ---
Use artifact for pages that should remember what people do with them: polls, sign-up sheets, checklists, trackers, boards — the page is the record. Declare capabilities: {artifact: {}}; const artifact = await claude.use("artifact"), then await artifact.publish(html) saves html (a complete document, doctype first) as the new version, and every open view, this one included, reloads to it. Nothing a viewer types, ticks or drags is kept unless the page publishes it. So embed the shared state as data in the HTML you publish and render the page from it; when an interaction completes, update the state, regenerate the document and publish it — never serialize the live DOM; batch rapid edits into one publish; publish only after a viewer acts, never on load. conflict is routine (someone published first; every view reloads to the winner, dropping this edit): no retry. Owner and editors publish as themselves; for read-only viewers publish rejects not_granted/not_writer — render a read-only view.
--- capability: downloads ---
The downloads capability lets a published page offer a generated file to the viewer: declare capabilities: {downloads: true}, then const downloads = await claude.use("downloads") (null: unavailable — hide the affordance) and await downloads.save({filename, data}). The viewer sees a confirmation and may decline — a save is never silent or guaranteed, so offer it on explicit viewer intent and handle rejection. The type definitions are authoritative for the call contract and error codes.
--- capability: mcp ---
mcp lets a published page call the viewer's claude.ai connectors: const mcp = await claude.use("mcp") (null: unavailable); calls run with the viewer's credentials, never exposing tokens. Declare capabilities: {mcp: {servers: [{server, tools}]}} — server is a connector's display name. Keep the manifest minimal: it is a viewer-consented grant; a declaring page cannot be shared publicly. Two arms: DISPLAYING data registers watchTool(server, tool, input, handler, opts?) — replays cache, refreshes when stale, polls only via refetchInterval, returns a sync unsubscribe; an ACTION calls callTool once and reads result.payload. Tool failures REJECT (tool_error); watch failures arrive as handler error events. Type definitions first: branch UX per error code, retry only retryable errors, drop data on authz denials, drive freshness UI from result.cache.storedAt. They omit argument names and result encoding: observe a real request/response pair per tool, or say so at publish — never guess.
--- capability: self ---
self is the former name of the artifact capability (renamed). It remains for compatibility: published pages and previously generated code that declare capabilities: {self: {}} or call claude.use("self") keep working unchanged — both names resolve this same capability (this contract promises no window.claude.self member to feature-check; use() is the check). Do not use it in new pages: declare capabilities: {artifact: {}} and obtain the namespace with await claude.use("artifact"); see the artifact section for how to use it.
Your connectors this session. Connector tools appear in your tool list as mcp__<connector>__<toolName>. Set server to the <connector> segment — everything between mcp__ and the next __ (for mcp__claude_ai_Slack_beta__search, the server is claude_ai_Slack_beta). Copy the segment exactly, case included; when publishing, it is resolved to the connector's display name automatically. Only claude.ai connectors are valid — locally-configured MCP servers are not. The manifest's tools array takes the connector's upstream tool names (as returned by listTools() / /v1/mcp_servers), which can differ from the normalized <toolName> segment when an upstream name contains . or spaces. Every servers[] entry needs a non-empty tools array naming the tools the page calls — an empty or omitted tools list is refused and never means "all tools"; to publish without connector access, leave mcp out of capabilities (pass capabilities: {} to clear a stored declaration) rather than declaring an empty servers list. In hermetic/CI sessions where connectors aren't loaded but $CLAUDE_CODE_OAUTH_TOKEN is set, fetch the list via Bash: curl -H 'anthropic-version: 2023-06-01' -H 'anthropic-beta: mcp-servers-2025-12-04' -H "Authorization: Bearer $CLAUDE_CODE_OAUTH_TOKEN" https://api.anthropic.com/v1/mcp_servers?limit=1000; in that case use each entry's display_name as the server value (exact display names are always accepted alongside tool-prefix segments).
Call contract (runtime contract 0.2.21). The platform-served window.claude type definitions for this contract are extracted under <skill-dir>: 0.2.21/artifact.d.ts, 0.2.21/claude.d.ts, 0.2.21/downloads.d.ts, 0.2.21/mcp.d.ts, 0.2.21/self.d.ts. Read <skill-dir>/0.2.21/claude.d.ts (how a page reaches any capability on this contract) and <skill-dir>/0.2.21/mcp.d.ts before writing any code that calls the mcp capability — they are authoritative for this contract version over any remembered API shape. The type definitions cover only the call envelope — they do not tell you a connector tool's argument names or its result encoding. Never publish a page that calls a connector tool without having observed one real request/response pair for that tool in this session; if you cannot safely observe one (for example, the connector is unauthenticated here, or calling the tool would have side effects), say that explicitly to the user at publish time — in your reply, not as a note inside the published page — instead of shipping a guessed shape. Observed response payloads are the user's real data: learn the shape from them, but never embed the observed values in the published page as sample or placeholder data.