craaft
io.craaftPublished by craaft.ioOfficial publisherv1.0.2Updated Oct 24, 2026
Read and update your craaft kanban boards: add and move cards, comment, and tick off checklists.
Overview
Remote MCP server for craaft Kanban boards, letting an assistant read, create, move, comment on and archive cards, columns and projects.
- What you can do
- List and inspect projects, boards, cards, card details, activity logs, focus overview and notifications
- Create, update, move, archive, restore and delete cards, including bulk create/update/move and column rebalancing
- Manage checklists, comments, tags, milestones, followers and attachments on cards
- Create, update, export, import and delete boards and columns, with templates and Trello/Jira/Asana/CSV import preview
- Administer workspace members, invitations, board access, webhooks, email-to-card intake and public sharing links
- When to use it
- Useful when a team keeps its work on craaft boards and wants an assistant to triage cards, draft or move work items, summarise board activity, or bulk-edit and import boards without leaving the chat.
- Requirements
- A remote HTTP endpoint; no local package. Requires a craaft account and OAuth sign-in through the connector flow (choosing read-only or read-and-write, and optionally specific boards), or a cra_ personal access token sent as an Authorization Bearer header.
Installation
In SourceWeft
- Open craaft in the dashboard and add it to a workspace.
- Connect the required credentials. They are stored privately and never shown on public pages.
- Enable the server for the chats that should use its tools.
Web executable via Streamable HTTP. Remote servers run from the web runtime once configured in a workspace.
Use with an agent
Paste this prompt into Claude Code, Codex, Cursor or another agent — or into SourceWeft chat. The agent reads this server's install guide, shows you its publisher, endpoint and sign-in, and adds it to your client once you agree. Keys never go into a command.
Read https://sourceweft.com/mcp/io.craaft%2Fmcp/install.md and connect the MCP server it describes to my client. Before changing any config, show me its publisher, endpoint and sign-in method and wait for my OK. Never put an API key in a command or in a file I would commit; ask me where it should come from.Other MCP clients
Add this to your client's mcpServers config. The client completes OAuth sign-in on first connect.
{
"mcpServers": {
"craaft": {
"type": "http",
"url": "https://ai.craaft.io/mcp"
}
}
}README
Craaft MCP Server
Model Context Protocol server for Craaft - lets AI assistants read and write your Kanban boards.
Deployed as an HTTP service. Each request authenticates via the caller's Authorization: Bearer header - either a cra_* personal access token (same ones used by the Craaft REST API) or a cro_* OAuth access token minted by signing in through the connector flow below.
Two-factor sign-in on a craaft account doesn't affect either kind of token. Account security settings (password, two-factor, API keys) are browser-only on the platform, so no tool changes them.
Deploy
The PORT env var is set automatically by Cloud Run.
Connect from Claude (OAuth)
With MCP_PUBLIC_URL set, the server is an OAuth 2.1 protected resource: no
token needs to be copied by hand.
craaft is in the Claude directory: connect it from there and skip to step 3. Or add it as a custom connector:
- In Claude Desktop or claude.ai, go to Settings > Connectors > Add custom connector.
- Paste
https://ai.craaft.io/mcp. - Sign in to craaft, choose Read and write or Read only, and approve the connection.
With read-only access, tools that only read (list_projects, get_board,
search_cards and the like) work, and every tool that changes something
fails with this token is read-only; this request needs a token with read and write access. The same goes for a cra_ key created as read only.
You can also connect it to Chosen boards only. Tools then see just those
boards: other boards are not found, and list_projects and search_cards
leave them out. create_project, import_board, list_members,
list_invitations and the other member tools fail with this token is limited to some boards; this request needs a token for all boards. To change an app's
access or boards, connect it again and choose again.
To revoke access later, go to Craaft Settings > Connected apps.
Configure (Claude Desktop, cra_ token)
- Sign in to Craaft → Settings → API keys → create a token
- Add to
~/.config/claude/claude_desktop_config.json:
MCP registry
craaft is listed in the official MCP registry
as io.craaft/mcp, described by server.json. craaft.io proves it owns the
io.craaft namespace by serving a public key at
https://craaft.io/.well-known/mcp-registry-auth (platform repo,
internal/server/mcpregistry.go). The matching private key is not in this repo.
To publish a change, raise version in server.json (a published version
can't be changed or republished), then:
Install mcp-publisher from the registry's
releases.
Tools
The three bulk_* tools are all-or-nothing: one bad item rolls the whole
batch back and the error names the offending index, so a failed call never
leaves a partially applied board. They send no notification emails (activity
events and realtime updates still fire), and each call spends one rate-limit
token against a 60-burst budget - which is why they should be preferred over
looping the single-card tools.
Endpoints
Env vars
Attachments
This server runs remotely, so it cannot read the caller's filesystem:
upload_attachment takes the contents inline (content_text for text,
content_base64 for binary), not a path.
download_attachment returns text-ish content types as readable text and
everything else base64-encoded. Attachments can be up to 25 MiB, which no
conversation wants inline, so it refuses anything over max_bytes
(default 256 KiB) and reports the real size instead. Text is truncated
rather than refused, since truncated text is still readable; truncated
base64 is not, so binary over the limit is skipped entirely.
Attachments are a paid feature. On a Free workspace the upload returns 402
and the error names the current plan. Check canUploadAttachments on the
project first - it reflects the board's workspace plan, not the caller's.
Import
preview_import and import_board take the same arguments: filename,
the file inline (content_text or content_base64), and optionally
source (trello, jira, asana, csv or craaft; detected when left
out), name for the new board, and a CSV mapping from craaft fields to
headers. Preview first: it writes nothing and, for a CSV, returns the
headers, the suggested mapping and sample rows. A mapping replaces the
suggestion, so send every field you want. import_board always creates a
new private board and counts toward the workspace's board limit (402 when
full). Limits: 5 MB, 2,000 cards, 200 columns; attachments aren't imported.
Known platform quirk: archive then delete
archive_column only archives cards in a column flagged isDone, and
returns 200 with archived: 0 (and an empty id list) on any other column
rather than erroring - check the count. Its returned ids let you undo the
sweep with restore_card on each one.
delete_column is blocked by live cards only. Archived cards no longer
block it - they are reassigned to the board's first column and the delete
proceeds, so they keep existing and stay archived. (This used to fail: the
cards_project_column_fk constraint still saw the archived rows, so the
delete returned 409 forever. Fixed on the platform side.)
Archive and restore
archive_card takes a card off its board without deleting it; it stays
searchable and shows up in list_archived_cards until restore_card puts it
back in the exact column and position it was archived from. Archiving an
already-archived card, or restoring one that isn't archived, is an error.
list_archived_cards uses the same lean board projection as get_board
(description omitted), plus archivedAt, capped at 200 rows (newest first) -
older archived cards stay reachable through search_cards.
Board templates
list_board_templates is the same fixed catalogue for every caller, no plan
gate. Pass a template's key as create_project's template argument to
start a board with that column layout. create_project's response never
includes columns at all, template or not - that field is only populated by
get_project / get_board. Only the default kanban template seeds the
historical todo / doing / done column keys anyway, every other template
generates its own, so call get_project on the new board before creating
cards on it.
Webhooks and email-to-card (board admin, Pro)
Both surfaces are gated the same way: board not visible → not found; visible
but you're not a board admin → forbidden; Free workspace → a 402 naming
"integrations" as the limit. delete_webhook and disable_inbound_email
are not plan-gated, so a workspace that downgraded after setting either
up can still turn them off.
A webhook subscription's secret is returned in full on every read (list,
create, update) - it is never redacted after creation. It signs craaft
format deliveries via the X-Craaft-Signature header; slack and discord
deliveries are unsigned chat messages, authenticated only by the receiving
service's secret URL. update_webhook's subscription_id argument is the
subscription id, not the workspace-level endpoint_id the response also
carries.
Email-to-card mints one intake address per board
(<token>@<inbound-domain>). Mail becomes a card only when the sender is a
workspace member and SPF/DKIM pass; everything else is dropped silently, no
error surfaces to the sender. update_inbound_email's rotate flag mints a
new token and invalidates the old address immediately - there's no grace
period.
Not exposed, and why
GET /projects/{id}/events is the board's SSE realtime stream, not an
activity log - a long-lived text/event-stream that doesn't fit a
request/response tool. For a board's history use get_board_activity
(/projects/{id}/activity), and for one card's history get_card_activity
(/cards/{id}/events).
Also absent: POST /projects/{id}/cards/rebalance (internal position
maintenance), the board background-image endpoints, and the unauthenticated
/public/projects/{token} read - a token-holding agent should just use
get_board.
Source: README.md at commit fb4158b
Tools
0Version history
1- v1.0.2LatestOct 11, 2026
Score
75% of the applicable checks met
How complete this listing is, computed from the registry entry, the endpoint and public sources. Not a rating of the server and not a statement that it is safe or working today: reachability is a dated check, and no installs or reviews go into the score.
- Reached in the last 30 daysRequired25 pts
- Auth declaredRequired10 pts
- Tools listed15 pts
Answer tools/list without a credential, or ship a package that starts in a sandbox without one.
- DescriptionRequired15 pts
- Logo10 pts
- Documentation15 pts
- License10 pts
Declare a license in the repository or the registry entry.