planka-mcp
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@planka-mcp Work through my task queue"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
planka-mcp
An MCP server that lets an AI agent autonomously pick up and complete work on a Planka board.
It is not a wrapper around the Planka REST API. The tool surface is shaped around what an autonomous worker actually does — find ready work, claim it, report on it — and the guardrails are enforced in code, not in prompt text.
Vocabulary
The tools speak your words, not Planka's schema:
You say | Planka calls it | What it is |
board | project | the container (a tab strip) |
project | board | the tab you actually work in: lists, cards, members |
task | card | one piece of work |
Related MCP server: kanban-mcp
What the agent sees
Doing work
Tool | Purpose |
| Pre-filtered queue of genuinely ready work, most urgent first |
| Search every project — other people's work included — by text, assignee, status, label or overdue. A person's results cover task assignment, checklist items and comment mentions |
| Atomic claim; |
| Full detail of a chosen task |
|
|
| Report output, context, deliverables |
Shaping work
Tool | Purpose |
| File and refine work: title, description, deadline, kind, target column |
| Add steps, tick, reopen, assign items to people, link dependencies |
| Change priority/size (both are labels in Planka) |
| Move to any list, including stages outside the status flow, or to another project |
Structure
Tool | Purpose |
| Discover containers, tabs, and your role on each |
| The container: create, rename, describe, hide, favourite |
| New tab with workflow lists (names, or |
| Clone a project's columns with their exact types, plus labels and members — never cards |
| Columns: name, type, colour, reorder; retire via |
| Create, rename, delete-if-unused |
People
Tool | Purpose |
| What this server may do, and under what ceiling |
| Project members with roles, or the whole directory |
| Put people on a task, adding them to the project first |
| Add, re-role ( |
| Work handed over in a comment but never actually assigned |
| Instance roles, board managers, API key minting and revocation — off unless enabled |
Plus one prompt, “Work through my task queue”, as a one-click entry point.
Roles
Planka 2.4.1 has two role axes, and the swagger documents neither correctly:
instance role (admin, projectOwner, boardUser, guestOnly) and board
membership role (editor, worker, guest). This server folds them into one
effective role per project:
Condition | Effective role | Can |
instance |
| everything, incl. membership |
board membership |
| work, author, assign, structure |
board membership |
| work on tasks; no structure, no assigning others |
|
| read only |
PLANKA_ACT_AS=worker|editor|admin lowers that ceiling but never raises it — one
admin credential can still run a deliberately limited agent. Every refusal names
the role, where it came from, and what was attempted.
How Planka concepts are mapped
Planka has no status, priority or effort field, so the server derives them:
Status = which list the card is in. List names are matched by heuristic (
backlog/todo/ready→todo,doing/in progress/wip→in_progress,review/qa→review,done/closed→done). Lists of typewaiting/inactive, and Planka's own system lists, are outside the flow; typeclosedcounts as done. Override the mapping withPLANKA_STATUS_LISTS(see.env.example).Priority comes from label conventions (
p0/urgent/critical→ urgent,p1/high,p2/medium,p3/low), defaulting to medium.Effort comes from size labels (
size: M,small,XL) or point labels (sp: 3), falling back to the subtask count.Dependencies come from checklist tasks that link to another card (
linkedCardId). Reported aswaiting_oninget_task; only used as a filter whenPLANKA_REQUIRE_DEPS_MET=true.
What counts as actionable
A card is returned by list_actionable_tasks when all of these hold:
it sits in a list mapped to
todo, and that list is of typeactive;the card is not closed;
it has no assignees, or the agent's own account is one of them;
it is on a
projectboard —libraryandcollectionboards hold documents, not work (PLANKA_BOARD_TYPES);its board is inside
PLANKA_BOARD_IDS, when that allowlist is set.
Two further filters exist but are off by default: PLANKA_BLOCKED_LABELS
(hide cards carrying e.g. a blocked label) and PLANKA_REQUIRE_DEPS_MET
(hide cards whose linked dependency cards are unfinished).
How claiming is made safe
Planka has no compare-and-swap on card fields, but card assignment is a unique
row (cardId + userId), and the API answers 409 when it already exists. So:
read the card fresh; if someone else is assigned →
already_taken;POSTthe assignment —200= claimed,409= you already held it (idempotent, so a retried call is harmless);re-read and compare assignment timestamps; if another worker's row is older, the server removes its own row and reports
already_taken.
Caveat, stated plainly: step 1→2 is a read-then-write. Two different
accounts writing inside the same few milliseconds are resolved by the step-3
reconcile, not prevented outright. Two runs of the same agent account cannot
double-claim — the 409 makes that path genuinely atomic.
Guardrails enforced in code
Nothing that holds work is deleted.
delete_listrefuses a list containing cards;manage_labelsrefuses a label still on a card; there is no tool to delete a task, comment, project or board. Retiring a stage is a type change toinactive, which is reversible.Credentials are handled explicitly. Minting an API key requires
PLANKA_ALLOW_USER_ADMIN=trueplus an instance-admin account, reports whether it replaced an existing key, and refuses to touch the key this server is itself authenticating with.Other people's work is untouchable. Editing, moving, relabelling or releasing a task claimed by someone else is refused.
Claims are only ever for yourself.
claim_task/release_tasktake no user parameter; assigning others is a separate, higher-privileged tool.Role is checked per project, per action, and a refusal explains why.
Escalation is blocked.
admin_manage_personis off unlessPLANKA_ALLOW_USER_ADMIN=true, and even then it will not change its own account's role, grant instanceadmin, or create an account (that needs a password, which this server never handles).set_project_memberswill not remove its own access.Status transitions are validated;
doneis terminal unlessPLANKA_ALLOW_REOPEN=true.add_resulttakes an idempotency key, so a retry cannot double-post.attach_linkacceptshttp/httpsonly.PLANKA_BOARD_IDShard-scopes every tool to specific projects.
Tests
.venv/bin/python -m pytest tests -q79 offline tests run against an in-memory fake that reproduces Planka's
semantics — assignment unique on card+user with 409 on re-insert, cards in a
closed list finished by the server, board role separate from instance role.
They cover: claim → idempotent re-claim → lost-race rollback; illegal
transitions and done terminality; ownership checks on status/result/release/
edit/move; the board allowlist; role folding across both axes and the
PLANKA_ACT_AS cap; worker-vs-editor-vs-admin gating; the assign-and-add-as-
worker flow with ambiguity refusal; refusal to delete non-empty lists or in-use
labels; refusal to self-remove or self-promote.
Setup
Nothing to install or clone. Add this to your MCP client config, fill in three values, restart:
{
"mcpServers": {
"planka": {
"command": "uvx",
"args": ["--refresh-package", "planka-mcp", "--from", "https://github.com/KT-SPARKS/planka-mcp/releases/latest/download/planka_mcp-latest.tar.gz", "planka-mcp"],
"env": {
"PLANKA_BASE_URL": "https://planka.example.com",
"PLANKA_EMAIL": "you@example.com",
"PLANKA_PASSWORD": "your-password"
}
}
}
}That URL always resolves to the newest release, and --refresh-package makes
uv check for a new build on every launch — so restarting your client is the
whole update process. Drop the flag and you stay on whatever version you first
downloaded, because uv caches by URL.
Prefer an API key over a password (Planka: user settings → API key):
"env": {
"PLANKA_BASE_URL": "https://planka.example.com",
"PLANKA_API_KEY": "your-api-key"
}Claude Code, one line:
claude mcp add planka --env PLANKA_BASE_URL=https://planka.example.com --env PLANKA_API_KEY=your-api-key -- uvx --refresh-package planka-mcp --from https://github.com/KT-SPARKS/planka-mcp/releases/latest/download/planka_mcp-latest.tar.gz planka-mcpTo pin a version instead, point at that release's wheel and drop the refresh flag:
"args": ["--from", "https://github.com/KT-SPARKS/planka-mcp/releases/download/v0.3.0/planka_mcp-0.3.0-py3-none-any.whl", "planka-mcp"]That is the whole setup. Everything below is optional.
Two things trip up the Windows desktop app:
uvxnot found — the app spawns the command directly, so give the full path, with doubled backslashes:"command": "C:\\Users\\You\\AppData\\Local\\hermes\\bin\\uvx.exe". Find it withwhere uvx.Git executable not found— anenvblock replaces the process environment, so agit+https://...source cannot run git. The release URLs above need no git and avoid this entirely. If you do want to install from source on Windows, add"PATH"to theenvblock.
Config lives at %APPDATA%\Claude\claude_desktop_config.json. Quit from the
tray icon and reopen — closing the window does not restart the app.
The setup above gives the agent whatever the account can do. To narrow it:
"env": {
"PLANKA_BASE_URL": "https://planka.example.com",
"PLANKA_API_KEY": "your-api-key",
"PLANKA_BOARD_IDS": "1234567890123456789",
"PLANKA_ACT_AS": "worker"
}PLANKA_BOARD_IDS— every tool refuses anything outside these projects.PLANKA_ACT_AS— ceiling ofguest,worker,editororadmin, applied on top of the account's real rights.
Better still, create a dedicated Planka user for the agent, add it to just the
boards it should touch as a worker, and use its API key — rather than pointing
this at an admin account.
From source (needs git available to the process):
uvx --from git+https://github.com/KT-SPARKS/planka-mcp planka-mcpFor development:
git clone https://github.com/KT-SPARKS/planka-mcp.git
cd planka-mcp
uv venv && uv pip install -e .
cp .env.example .env # only read in this mode
.venv/bin/planka-mcpFull configuration reference — every environment variable, status mapping, HTTP transport — is in docs/configuration.md. Coverage map — every Planka endpoint and field, exposed or not and why — is in docs/api-coverage.md.
Notes on the live API
Developed and verified against Planka 2.4.1, whose published swagger (2.0.1) lags the server in several places — different role names, different list types, undocumented routes. Everything learned from the live instance — spec drift, permission rules, the private→shared conversion, the claim/CAS semantics, the Cloudflare WAF gotcha — is written up in docs/planka-api-notes.md.
Errors from Planka are returned to the model as clean
{"ok": false, "error": "..."} results rather than raised as exceptions.
Available Tools
33 toolsadd_commentA
Leave a comment on a task - a question, a blocker, or progress context for
the humans watching the board. Use add_result for the actual deliverable.
Inputs: text (required), task_id (required). Returns: object
add_resultA
Attach your output to a task: what you did, what you produced, where it lives. Post this before moving the task to done, so the work is auditable. Requires that you hold the claim.
Inputs: note (required), task_id (required), idempotency_key. Returns: object
admin_manage_personA
Instance-level administration: change someone's instance role, make someone
a manager of a board, or mint and revoke API keys. Off unless the operator
sets PLANKA_ALLOW_USER_ADMIN, and this server will never raise its own
account's role or hand out admin.
create_api_key returns the key once - Planka cannot show it again, and
it replaces any key that account already had, breaking whatever was using it.
A key is a long-lived credential that acts as that person, and the value will
pass through this conversation and any transcript of it, so treat the output
as a secret and hand it over out of band. revoke_api_key clears one.
Inputs: action (required), name, email, person, +2 more. Returns: object
assign_peopleA
Assign people to a task, adding them to the project first if they are not members yet. Each name is resolved against the project's members and the user directory; an ambiguous name is reported rather than guessed. Granting project membership needs membership rights, so a worker can assign existing members but cannot pull new people onto the project.
Inputs: people (required), task_id (required), add_to_project_as. Returns: object
attach_linkA
Attach a link to a task - a pull request, document or dashboard you
produced. Use this alongside add_result when the output lives somewhere
else. Only tasks you hold, or unclaimed ones, can be changed.
Inputs: url (required), name (required), task_id (required). Returns: object
claim_taskAIdempotent
Claim a task for yourself before working on it. This is atomic: the claim
is a unique assignment row in Planka, so a second worker racing for the same
task gets already_taken back and should simply pick another task. Claiming
a task you already hold succeeds again without side effects. You can only
ever claim a task for yourself, never for another user.
Inputs: task_id (required). Returns: object
copy_project_structureA
Clone a project's layout: its columns with their exact types and order, and optionally its labels and members. No cards are copied - this produces an empty project shaped like the original.
Prefer this over create_project when an existing project is the template.
Naming a column 'Done' is not the same as copying it: a list's type decides
whether Planka marks cards dropped there as finished, and only a copy carries
that across.
Inputs: name (required), source_project_id (required), board_id, include_labels, +1 more. Returns: object
create_boardA
Create a board - the container that holds projects (tabs).
Needs an admin or projectOwner account; Planka refuses project creation
for anyone else. Create the board first, then fill it with create_project
or copy_project_structure.
Inputs: name (required), shared, description. Returns: object
create_listA
Add a workflow stage to a project. Note that Planka closes any card placed
in a closed list, so use that type only for a genuine done stage.
Inputs: name (required), project_id (required), after, color, +1 more. Returns: object
create_projectA
Create a new project (tab) inside a board, pre-populated with workflow lists so it is immediately usable. Requires admin rights on that board.
To reproduce an existing project's layout, use copy_project_structure
instead - it carries the exact list types across, which naming alone cannot.
Inputs: name (required), board_id (required), lists, default_view, +3 more. Returns: object
create_taskA
Create a new task in the todo stage of a board - follow-up work you discovered, or a task you were asked to file. It lands unclaimed, so claim it before working on it. Labels must already exist on the board; this tool never invents board structure.
Inputs: title (required), labels, board_id, due_date, +4 more. Returns: object
delete_listA
Delete an empty list. A list holding cards is never deleted - move the cards out first, or retire the stage with update_list(list_type='inactive').
Inputs: project_id (required), list_name_or_id (required). Returns: object
find_informal_assignmentsARead-only
Find work handed out in comments but never actually assigned.
Teams often hand off by writing "Assigned to: @Name" in a comment. In
Planka that is just text: the person is not a member of the task, so it never
reaches their queue, no board view shows them as owner, and it is invisible to
reporting. This reports every such comment where the mentioned person is not a
member of the task, and gives you the exact assign_people call that would
make it real. Read-only - it changes nothing on its own. Confirm with a human
before acting on findings; a mention is not always a hand-off.
Inputs: limit, board_id, project_id, include_done, +1 more. Returns: object
find_tasksARead-only
Search tasks across every project you can see - including other people's.
Unlike list_actionable_tasks, which is your own ready-to-work queue, this
answers questions about the whole workspace: what is Ada working on, what is
overdue, where did that card about the login bug go.
Searching for a person finds all three ways work reaches them: tasks they are
assigned to, tasks holding a checklist item assigned to them, and tasks where
they were mentioned in a comment. Each result says which, in matched_by,
and carries the specific checklist items and mentions. Results are read-only
context; claiming and editing still go through the usual tools, and other
people's tasks remain off limits to edit.
Inputs: text, label, limit, status, +6 more. Returns: object
get_projectARead-only
Full structure of one project: its lists and what status each maps to, its labels and how heavily they are used, its members and their roles, and your own role. Read this before changing structure or assigning people.
Inputs: project_id (required). Returns: object
get_taskARead-only
Full detail for one task: description, labels, subtasks, assignees, comments and anything it is waiting on. Use it after you claim a task, to understand what has to be done.
Inputs: task_id (required). Returns: object
list_actionable_tasksARead-only
List tasks that are genuinely ready to be worked on, most urgent first.
Call this first, before any other tool. The filtering happens on the server:
only cards sitting in a 'todo' stage of an active list, not closed, and
either unassigned or already assigned to you are returned. Each entry carries
what you need to choose: title, priority, due date, effort, labels, subtask
counts and a description excerpt. Pick one, then call claim_task.
Inputs: limit, search, board_id. Returns: object
list_boardsARead-only
List the boards you can reach - the containers that hold projects. Use it to find where a project lives, or before creating a new project.
Inputs: no named parameters. Returns: object
list_peopleARead-only
List people and their roles - members of one project, or the whole directory. Use it to resolve a partial name before assigning work.
Inputs: project_id. Returns: object
list_projectsARead-only
List the projects (tabs) you can work in, with the role you hold on each. Start here when you are asked to do something on a named project.
Inputs: board_id. Returns: object
manage_labelsA
Create, rename or remove the labels a project uses for priority, size and state. A label still applied to cards is never deleted.
Inputs: project_id (required), colors, create, rename, +1 more. Returns: object
move_taskA
Move a task to another list, or to a different project entirely. Use this for stages that are not part of the todo/in_progress/review/done flow - a 'Blocked' or 'Icebox' list, say - where update_status does not apply.
Inputs: task_id (required), to_list, to_project_id. Returns: object
release_taskAIdempotent
Give up your claim on a task so another worker can take it. Only your own claim is ever removed - other people's assignments are untouched. Nothing is deleted; the task and its history stay on the board.
Inputs: task_id (required), reason, move_back_to_todo. Returns: object
set_project_membersA
Add people to a project, change the role they hold, or remove them from it. Requires membership rights on that project. Removing a member does not delete anything they created, and never touches their account.
Inputs: people (required), project_id (required), role. Returns: object
set_task_labelsA
Apply or take labels off a task - how you change its priority or size, since Planka stores both as labels. Labels themselves are untouched; only their link to this task changes.
Inputs: task_id (required), add, remove. Returns: object
unassign_peopleA
Take people off a task. Their project membership is untouched - this only removes the assignment.
Inputs: people (required), task_id (required). Returns: object
update_boardA
Rename a board (container), describe it, hide it or favourite it. Requires managing that board - instance admin, or one of its managers.
Inputs: board_id (required), name, hidden, favorite, +1 more. Returns: object
update_checklistA
Break a task into checklist steps and tick them off as you go, so progress is visible on the board while you work. Only tasks you hold, or unclaimed ones, can be changed. Items are never deleted - reopen them instead.
Inputs: task_id (required), add_items, assign_items, reopen_items, +2 more. Returns: object
update_listA
Rename a list or change its type. Retiring a stage is a type change to
inactive, which keeps every card intact and reversible.
Inputs: project_id (required), list_name_or_id (required), name, after, +2 more. Returns: object
update_projectA
Rename a project (tab) or change how it behaves: default view, the kind of task it creates, whether checklists open expanded. Requires structure rights.
Inputs: project_id (required), name, default_view, default_card_type, +3 more. Returns: object
update_statusAIdempotent
Move a task you have claimed to a new status. Legal moves are todo -> in_progress -> review -> done (plus in_progress -> todo to hand work back). Illegal jumps are rejected. You must hold the claim on the task, and the board must have a list for the target status.
Inputs: status (required), task_id (required). Returns: object
update_task_detailsA
Refine a task's title, description, deadline or labels - for example after investigating and learning what the work actually involves. Only tasks you hold, or tasks nobody has claimed, can be edited; another worker's task is never touched.
Inputs: task_id (required), title, labels, due_date, +3 more. Returns: object
whoamiARead-only
Who this server is acting as, and what it is allowed to do. Call it when a request might exceed your rights, so you can say so instead of failing.
Inputs: no named parameters. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 33 tools
Tools generally map to distinct resource/action pairs (boards, projects, lists, tasks, labels, people), and the descriptions explicitly differentiate close pairs like move_task vs update_status and create_project vs copy_project_structure. A few genuine overlaps remain—update_task_details and set_task_labels both change labels, and attach_link vs add_result both attach output—but they are unlikely to cause frequent misselection.
Almost every tool follows a verb_noun snake_case pattern (list_boards, create_task, update_status, assign_people), which makes the set predictable. Minor deviations like whoami and admin_manage_person, plus compound names like find_informal_assignments, keep it from being perfectly uniform.
33 tools is beyond the 25-tool threshold and feels heavy for a single server, even for a rich project-management domain. Several tools bundle multiple operations (admin_manage_person) and label-related behavior is split across three tools, so the surface could be consolidated.
The lifecycle is well covered: boards/projects/lists can be created and updated, tasks have claim/status/assignment/result/comment flows, and search/audit tools expose informal assignments. Missing destructive or cleanup operations (delete/archive task, delete board/project, remove attachment/comment) are notable but mostly work-aroundable.
Maintenance
Related MCP Connectors
Task & board management for AI agents + humans. Kanban, comments, digests via MCP.
Task boards for teams and their AI agents: cards, checklists, sprints, plans and proposals.
One board for you and your AI: hand tasks to ChatGPT, Claude, Cursor or Codex and get a report back.
Kanban boards your AI agent can use: add, complete, move and recall tasks with your team.
Related MCP Servers
- AlicenseBqualityDmaintenanceEnables AI assistants to interact with Planka, a real-time Kanban board application, for managing projects, boards, lists, cards, and more.1057 npm6MIT
- AlicenseNot gradedqualityDmaintenanceEnables AI assistants to manage Planka kanban boards, including creating, updating, and organizing tasks, lists, and cards via MCP.15 npm65MIT
- AlicenseBqualityCmaintenanceEnables AI agents to manage tasks through a board with backlog, ready, in-progress, and done columns, plan daily work, track velocity, forecast backlog completion, and leverage rule-based or DeepSeek-powered recommendations.221MIT
- AlicenseNot gradedqualityBmaintenanceEnables AI agents to claim task cards from a self-hosted board, receive complete briefings, and submit handoffs with evidence and telemetry for human validation.MIT