@calca/mcp
v0.9.0
Published
calca CLI — MCP playground server for AI agents
Readme
@calca/mcp
The calca CLI — Layer 2 of the Calca stack: an MCP playground that lets AI agents read and edit a canvas board over the Model Context Protocol.
The pure tool surface (session, commands, leases, proposals, idempotency) lives in @calca/mcp-core and is runtime-neutral; this package is the Node-facing binding: stdio transport, board-file persistence, host config installers.
Quick start
Requires Bun or Node >= 20.
# Install as a dev dependency of your project
bun add -D @calca/mcp
# ...or install globally
npm i -g @calca/mcpRun the MCP server over stdio, bound to a board file:
calca mcp --file ./board.jsonInstall into an agent host (supported hosts: claude-code, codex, cursor, gemini-cli, opencode):
calca mcp install claude-codeVerify the board is readable:
calca open ./board.jsonThe 5-minute loop
- Propose. The agent calls
canvas.proposewith a title, rationale, and a batch of commands. Nothing is mutated yet; the call returns a proposal id. - Review. Read the proposal with
canvas.read(scopesummaryshows counts and pending proposals). Leave feedback withcanvas.comment. - Apply. Land the proposal with
canvas.applyand itsproposalId. Commands run atomically and idempotently (a repeatedrequestIdis a no-op).
If you don't have a board yet, point --file at a path that doesn't exist: the server starts empty and writes the file on first save. A minimal board is {"shapes":[],"bindings":[]} (note: shapes/bindings, not records; records is what calca open reports).
Commands
calca mcp— serve the canvas tool contract over stdio (see the Tools section below).--fileloads/saves a JSON snapshot with autosave on change;--agentsets the principal id used for command origins and leases;--formats <dir>loads format manifests from a specific directory.calca mcp install <host>— mergecalcainto the host's MCP config. Hosts:claude-code,codex,cursor,gemini-cli,opencode. Prints the config instead of writing with--print.calca open <file>— board summary (record counts by type). Full visual open lands with the web build (Phase 3).calca skill— print the path of the bundled agent skill (calca-design-exploration).calca skill --copy <dir>copies the skill folder into<dir>instead.
Tools
All tools are namespaced canvas.*. Names and semantics come from the contract in @calca/mcp-core:
| Tool | Description |
| ------------------------ | ----------------------------------------------------------------------------------------- |
| canvas.read | Read canvas state (scope: summary, viewport, selection, or full). |
| canvas.apply | Apply canvas commands immediately; can land a pending proposal via proposalId. |
| canvas.propose | Default mutation mode: record a proposal (title + rationale + commands) without mutating. |
| canvas.lease | Take exclusive soft leases on record ids (TTL clamped to 30000 ms). |
| canvas.release | Release this principal's leases on the given record ids early. |
| canvas.comment | Attach a comment to a record (creates a comment shape record). |
| canvas.arrange | Lay out shapes as a row, column, or grid with an optional gap. |
| canvas.show_variations | Create a titled group of design variations laid out side by side (max 8). |
| canvas.formats | List the output formats available to the session. |
Custom formats
Output formats are declarative JSON manifests describing how an artifact is framed (scripts, styles, theme attributes) and which exporters it supports. They are discovered from .calca/formats directories.
Discovery rules
Verified against packages/format/src/discovery.ts:
- Starting at the working directory, every ancestor directory is checked for
<dir>/.calca/formats. The walk never stops at repository boundaries (.gitis irrelevant) and terminates at the filesystem root and at the user's home directory. <home>/.calca/formatsis always appended as the last (lowest-priority) source.- Directories are merged nearest-first: when the same format id appears in several directories, the deepest (nearest) definition wins.
- A manifest may
extendsanother format id. When that id is present in the loaded chain, the frame env is resolved parent-first (defaults applied last). - Setting
CALCA_FORMATS=<dir>disables discovery and loads that single directory verbatim. calca mcp --formats <dir>loads that directory as the single source for the session, overriding discovery.
Malformed manifests are skipped with a warning; they never abort the session.
canvas.formats tool
Read-only tool listing the formats available to the session:
{
"formats": [
{
"id": "daisy",
"extends": "html-tailwind",
"exporters": ["html"],
"frameEnv": { "styles": ["daisyui.css"], "attrs": { "data-theme": "light" } },
"promptSnippets": { "layout": "use daisyUI component classes" },
"sourcePath": "/path/to/.calca/formats/daisy.json"
}
],
"warnings": []
}Example: daisyUI manifest
.calca/formats/daisy.json:
{
"id": "daisy",
"extends": "html-tailwind",
"exporters": ["html"],
"frameEnv": {
"styles": ["https://unpkg.com/daisyui@5/daisyui.css"],
"attrs": { "data-theme": "light" },
"customCssPassthrough": true
},
"promptSnippets": {
"layout": "Build the UI with daisyUI component classes (btn, card, navbar, modal)."
}
}With a local copy of the stylesheet instead of the CDN URL, daisyui.css sits next to the manifest:
/* .calca/formats/daisyui.css */
@import "https://cdn.jsdelivr.net/npm/daisyui@5/themes.css";
:root {
--btn-border: 0px;
}Load it with calca mcp --formats ./.calca/formats, or drop it into ~/.calca/formats to make it available everywhere.
Agent skill
The package ships a skill that teaches an agent how to work a board: skills/calca-design-exploration/SKILL.md. Copy it into your host's skill directory:
calca skill --copy ~/.claude/skills/License
Apache-2.0
