Sign inSign up

denisix/planka-mcp

By denisix

Updated 15 days ago

MCP server for Planka - enables AI agents to interact with Planka kanban, supports multi-client SSE

Image
Integration & delivery
Machine learning & AI
Developer tools
0

2.6K

denisix/planka-mcp repository overview

Planka MCP Server

npm version GitHub release Docker License: MIT

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.

Install

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).

Claude Code

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 (~/.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 (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.

Configuration

VariableDefaultDescription
PLANKA_BASE_URLhttp://localhost:3000Planka instance URL
PLANKA_USERNAME / PLANKA_PASSWORDLogin auth — all Planka versions; token is fetched, cached, and refreshed automatically
PLANKA_API_KEYAPI key auth — Planka v2 only (user settings → API keys); wins if both are set
PLANKA_HTTP_TIMEOUT_MS30000Per-request timeout (aborts, then retries)
PLANKA_HTTP_MAX_RETRIES2Retries for 408/429/5xx and network errors
PLANKA_HTTP_RETRY_BASE_DELAY_MS250Exponential backoff base (base * 2^attempt)
PLANKA_CONDENSED_OUTPUTtrueCondensed agent output; false = raw payloads
ENABLE_ALL_TOOLSfalseEnable all 28 tools (otherwise 11 core)
ENABLE_ADMIN_TOOLS / ENABLE_OPTIONAL_TOOLSfalseEnable one extra category
MCP_TRANSPORTstdiostdio (single client) or sse (multi-client)
MCP_PORT / MCP_HOST3001 / 127.0.0.1SSE mode bind; 0.0.0.0 in Docker
MCP_AUTH_TOKENIf set, SSE endpoints require Authorization: Bearer <token>
MCP_CORS_ORIGINIf set, emitted as Access-Control-Allow-Origin (no CORS by default)
MCP_HEARTBEAT_INTERVAL_MS30000SSE 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.

Agent workflow

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.

Tools (28)

Every tool takes action, optional id/data/query, and optional raw: true.

CategoryTools
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.

Multi-client SSE mode (optional)

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).

Development

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.

Credits

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

  • Security: 0 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.
  • Planka v1 compatibility: renamed v1 routes retried transparently on 404 — one build serves v2 and v1.
  • Agent-optimized: condensed output + context tool for scoped, id-free workflows.
  • Lean: one production dependency (MCP SDK), built-in fetch, compiled distroless image.
  • Verified: 117 tests incl. live E2E against real Planka 2.0.3 and 1.26.2, SSE protocol round-trips, engine edge cases.

License

MIT — see LICENSE. Issues: github.com/denisix/planka-mcp/issues.

Tag summary

Content type

Image

Digest

sha256:13f3e011c

Size

45 MB

Last updated

15 days ago

docker pull denisix/planka-mcp