MCP server for Planka - enables AI agents to interact with Planka kanban, supports multi-client SSE
2.6K
MCP server for Planka (real-time Kanban), tuned for AI coding agents:
Claude Code, Codex, opencode and any MCP client. Works with Planka v2 and v1 (≤ 1.26.x).
No build step, no Docker required — npx runs the prebuilt package over stdio.
Two auth modes: username/password works on every Planka version (the server logs in
automatically, caches the token, and silently re-logins on expiry); API key is Planka v2
only — generate one in your Planka user settings → API keys (v1.26.x has no API keys; verified:
X-Api-Key returns 401 there).
Planka v1 (≤ 1.26.x) — username/password:
claude mcp add planka \
--env PLANKA_BASE_URL=http://localhost:3000 \
--env PLANKA_USERNAME=your-email-or-username \
--env PLANKA_PASSWORD=your-password \
-- npx -y @denisixnpm/planka-mcp
Planka v2 — API key (username/password above works too):
claude mcp add planka \
--env PLANKA_BASE_URL=http://localhost:3000 \
--env PLANKA_API_KEY=your-api-key \
-- npx -y @denisixnpm/planka-mcp
Or in claude_desktop_config.json / .mcp.json (username/password form — works on both versions):
{
"mcpServers": {
"planka": {
"command": "npx",
"args": ["-y", "@denisixnpm/planka-mcp"],
"env": { "PLANKA_BASE_URL": "http://localhost:3000", "PLANKA_USERNAME": "your-email-or-username", "PLANKA_PASSWORD": "your-password" }
}
}
}
~/.codex/config.toml)Planka v1 (≤ 1.26.x):
[mcp_servers.planka]
command = "npx"
args = ["-y", "@denisixnpm/planka-mcp"]
env = { PLANKA_BASE_URL = "http://localhost:3000", PLANKA_USERNAME = "your-email-or-username", PLANKA_PASSWORD = "your-password" }
Planka v2 (API key):
[mcp_servers.planka]
command = "npx"
args = ["-y", "@denisixnpm/planka-mcp"]
env = { PLANKA_BASE_URL = "http://localhost:3000", PLANKA_API_KEY = "your-api-key" }
opencode.json)Planka v1 (≤ 1.26.x):
{
"mcp": {
"planka": {
"type": "local",
"command": ["npx", "-y", "@denisixnpm/planka-mcp"],
"environment": { "PLANKA_BASE_URL": "http://localhost:3000", "PLANKA_USERNAME": "your-email-or-username", "PLANKA_PASSWORD": "your-password" }
}
}
}
Planka v2 (API key):
{
"mcp": {
"planka": {
"type": "local",
"command": ["npx", "-y", "@denisixnpm/planka-mcp"],
"environment": { "PLANKA_BASE_URL": "http://localhost:3000", "PLANKA_API_KEY": "your-api-key" }
}
}
}
Requires Node.js ≥ 22.19 (or run the same command with Bun ≥ 1.3). Debug: npx -y @denisixnpm/planka-mcp 2>&1 | tee debug.log.
| Variable | Default | Description |
|---|---|---|
PLANKA_BASE_URL | http://localhost:3000 | Planka instance URL |
PLANKA_USERNAME / PLANKA_PASSWORD | — | Login auth — all Planka versions; token is fetched, cached, and refreshed automatically |
PLANKA_API_KEY | — | API key auth — Planka v2 only (user settings → API keys); wins if both are set |
PLANKA_HTTP_TIMEOUT_MS | 30000 | Per-request timeout (aborts, then retries) |
PLANKA_HTTP_MAX_RETRIES | 2 | Retries for 408/429/5xx and network errors |
PLANKA_HTTP_RETRY_BASE_DELAY_MS | 250 | Exponential backoff base (base * 2^attempt) |
PLANKA_CONDENSED_OUTPUT | true | Condensed agent output; false = raw payloads |
ENABLE_ALL_TOOLS | false | Enable all 28 tools (otherwise 11 core) |
ENABLE_ADMIN_TOOLS / ENABLE_OPTIONAL_TOOLS | false | Enable one extra category |
MCP_TRANSPORT | stdio | stdio (single client) or sse (multi-client) |
MCP_PORT / MCP_HOST | 3001 / 127.0.0.1 | SSE mode bind; 0.0.0.0 in Docker |
MCP_AUTH_TOKEN | — | If set, SSE endpoints require Authorization: Bearer <token> |
MCP_CORS_ORIGIN | — | If set, emitted as Access-Control-Allow-Origin (no CORS by default) |
MCP_HEARTBEAT_INTERVAL_MS | 30000 | SSE keep-alive interval for strict proxies |
Note: Bun auto-loads .env from the working directory (real env vars win); the Node/npx path does not.
Scoped context — select a project/board/list/card once, then omit ids:
{"name": "context", "arguments": {"action": "set", "data": {"boardId": "..."}}}
{"name": "cards", "arguments": {"action": "create", "data": {"name": "Ship it", "type": "project", "position": 1}}}
context.set returns an overview of what you opened (boards of the project, lists/cards of the board). Setting a higher level resets deeper ones. Scope is per SSE session; process-wide for stdio.
Condensed output — responses keep only agent-relevant fields (ids, names, positions, states); timestamps, password hashes and audit metadata are stripped, long text truncated, included sidecars reduced per entity. Escape hatches: per-call raw: true or PLANKA_CONDENSED_OUTPUT=false.
Every tool takes action, optional id/data/query, and optional raw: true.
| Category | Tools |
|---|---|
| Core (11, always on) | auth, bootstrap, context, projects, boards, lists, cards, comments, tasks, labels, cardMembers |
| Admin (4) | config, users, webhooks, projectManagers |
| Optional (13) | attachments, backgroundImages, boardMembers, cardExtras, cardMemberExtras, commentExtras, customFields, labelExtras, listExtras, notifications, taskExtras, userInfo, actions |
Actions per tool are enumerated in the MCP tools/list response. Live-verified semantics worth knowing: project managers exist only on shared projects; notification services are self-only; Planka v2 JSON link attachments HTTP 500 (multipart required); v1.26.2 has no REST comments/task-lists/custom-fields/webhooks (clean 404s), and renamed v1 membership/label routes are retried automatically.
To serve several clients over HTTP instead of stdio, run the same package in SSE mode:
MCP_TRANSPORT=sse MCP_HOST=127.0.0.1 MCP_PORT=3001 MCP_AUTH_TOKEN=change-me \
PLANKA_BASE_URL=http://localhost:3000 PLANKA_API_KEY=your-api-key \
npx -y @denisixnpm/planka-mcp
Connect MCP clients to http://127.0.0.1:3001/sse. Set MCP_AUTH_TOKEN whenever binding beyond
loopback (MCP_HOST=0.0.0.0) — without it, anyone who can reach the port has full tool access.
A --healthcheck mode is built in for orchestrators.
Prefer a container? The image is published on Docker Hub:
hub.docker.com/r/denisix/planka-mcp
docker run -d -p 3001:3001 \
-e MCP_TRANSPORT=sse -e MCP_HOST=0.0.0.0 -e MCP_AUTH_TOKEN=change-me \
-e PLANKA_BASE_URL=http://host.docker.internal:3000 \
-e PLANKA_API_KEY=your-api-key \
denisix/planka-mcp:latest
Compiled Bun binary on distroless (171 MB, no shell, no node_modules).
bun install && bun test # build + full hermetic suite
bun run dev # run from source (stdio)
End-to-end tests run against real Planka stacks (docker compose --profile e2e up -d, then E2E_PLANKA_URL=... bun test). See CONTRIBUTING.md.
Fork of planka-mcp by Christopher Maldonado — credit for the original server goes to him. Maintained by denisix, published as @denisixnpm/planka-mcp.
What this fork improves
npm audit findings; loopback-only SSE by default, timing-safe bearer auth, no wildcard CORS, validated login responses (no Bearer undefined), single-flight login, per-request timeouts.context tool for scoped, id-free workflows.fetch, compiled distroless image.MIT — see LICENSE. Issues: github.com/denisix/planka-mcp/issues.
Content type
Image
Digest
sha256:13f3e011c…
Size
45 MB
Last updated
15 days ago
docker pull denisix/planka-mcp