ya-planka-mcp
Click on "Install 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., "@ya-planka-mcpList all cards in the TODO column"
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.
ya-planka-mcp
A Model Context Protocol (MCP) server that enables AI clients to read and manage your Planka boards using the Planka REST API.
Getting Started
New here? Four steps to a running, registered server — minimal detail, each one links to the full section below if you need it.
Clone the repo:
git clone https://github.com/andrejberg/ya-planka-mcp cd ya-planka-mcpInstall dependencies:
uv sync(see Installation for thepipalternative).Get an API key and fill in
.env: log in to Planka as an admin, generate an API key, then:cp .env.example .env # edit .env: set PLANKA_BASE_URL and PLANKA_API_KEYFull walkthrough: Obtaining API Credentials.
Register the server with your MCP client — Claude Desktop, Claude Code, or any generic client: see MCP Client Configuration.
That's the whole path. For dependency details, alternate install methods, credential fallbacks, troubleshooting, and everything else, keep scrolling.
Related MCP server: Plane MCP Server
Overview
ya-planka-mcp provides a lightweight bridge between MCP clients and your self‑hosted Planka instance. It exposes projects, boards, lists, cards, tasks, and labels through MCP tools, allowing agents to use planka for the full project management and execution live cycle.
Features
List projects, boards, lists, labels, and members — full dump or scoped to one board
Search and retrieve cards with multiple detail levels
Read card checklists with real task IDs and accurate progress counts
Create, update, delete, and bulk-move cards
Create, update, and delete checklist tasks and task lists
Manage labels (create idempotently, assign, remove) and card members
Read and write card comments
Scaffold complete boards (canonical kanban lists + lifecycle labels) in one call
Composite workflow tools: next workable card, mechanical readiness checks, and a computed one-call board status report
Token-optimized: detail levels, scoped responses, slimmed schemas — measured by a committed audit script
Works with any MCP‑compatible client
Example use cases:
"Show all 'In Progress' cards across my workspace."
"Create a new card in
<Board> / TODOwith subtasks…""Find the 'Login bug' card and list all tasks."
"Mark the 'Write tests' task as complete."
"Add the 'Urgent' label to the 'Deploy' card."
Prerequisites
Python 3.10+
uv(recommended) orpip+venvAccess to a Planka instance
A Planka account you're comfortable letting the MCP server act as (see Obtaining API Credentials below — the account's role determines what the server can do; see Roles & Permissions)
Installation
1. Clone the repository
git clone https://github.com/andrejberg/ya-planka-mcp
cd ya-planka-mcp2. Install dependencies
With uv (recommended — creates .venv/ and resolves the lockfile):
uv syncThis installs runtime dependencies only. If you also want to run the test
suite (see Running Tests below), install the test extra instead:
uv sync --extra testOr with pip in a manually created virtualenv (the last two lines below —
installing requirements.txt then an editable install — are exactly what CI
runs in .github/workflows/test.yml, just without a venv there):
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
pip install -e .Note the venv directory name differs between the two paths: uv sync creates
.venv/; the pip walkthrough above creates venv/. This matters for the
run_server.sh helper script and the MCP client config below — pick one path
and stay consistent with it.
3. Create your .env file
cp .env.example .envThen fill in the variables below.
Environment variables
Variable | Required? | Purpose |
| Yes | Base URL of your Planka instance (e.g. |
| Option 1 | Recommended. The admin-generated API key from Planka's user administration screen — see Obtaining API Credentials. Checked second, only if |
| Option 2 | JWT access token from the legacy |
| Option 3 | Login credentials. The server exchanges them for a token automatically at startup. Checked last, only if neither token variable is set. |
Precedence is fixed in src/planka_mcp/api_client.py::initialize_auth:
PLANKA_API_TOKEN > PLANKA_API_KEY > PLANKA_EMAIL+PLANKA_PASSWORD — this
only matters if you set more than one. For a fresh setup, set just
PLANKA_API_KEY (the admin-generated key); see Obtaining API Credentials
below for how to get it.
.env.example also documents role-scoped variables
(PLANKA_API_TOKEN_BOARD_MANAGER, PLANKA_API_TOKEN_BOARD_MEMBER,
PLANKA_SMOKE_LIST_ID, PLANKA_SMOKE_LABEL_ID) — these are only read by the
opt-in test suite (see Opt-in permission smoke under Running Tests), not
by the server itself.
Obtaining API Credentials
This server was developed and tested against Planka Community v2.0.3. In that version, generating an API key requires admin access — there is no self-service "generate my key" option for a regular board member.
Log in to your Planka instance as an admin user.
Open User Administration (the admin-only user management screen).
Generate an API key for the account you want the MCP server to act as — this can be the admin account itself or any other account. The key carries exactly that account's Planka permissions; see Roles & Permissions below for what a given account can and can't do through this server before picking which one to use.
Copy the generated key into
.env:PLANKA_API_KEY=your-generated-api-key
That's the whole flow. If your Planka instance predates v2.0.3 or otherwise has no admin-generated API key screen, use one of the fallback methods below instead.
Fallback: JWT access-token exchange
Older Planka versions (and any instance without an admin-generated API key
screen) expose a JWT token via the /api/access-tokens endpoint — the same
exchange the Planka web client performs internally on login:
curl -X POST https://your-planka-instance.com/api/access-tokens \
-H "Content-Type: application/json" \
-d '{
"emailOrUsername": "your-email@example.com",
"password": "your-password"
}'Response:
{
"item": {
"accessToken": "..."
}
}Copy the accessToken value into .env as PLANKA_API_TOKEN.
Note: JWT tokens may expire. If you get authentication errors later, repeat the exchange to mint a new one.
Fallback: Email/Password
If you'd rather not mint a token up front, set PLANKA_EMAIL and
PLANKA_PASSWORD directly — the server performs the same JWT exchange
automatically at startup:
PLANKA_EMAIL=your-email@example.com
PLANKA_PASSWORD=your-passwordThis is only used if PLANKA_API_TOKEN and PLANKA_API_KEY are both unset.
MCP Client Configuration
The server is a stdio MCP server; the actual entry point every config below
runs is mcp_server.py (main.py exists only as a legacy wrapper that
subprocesses into mcp_server.py). Replace /path/to/ya-planka-mcp with
your clone's absolute path.
Claude Desktop
Edit claude_desktop_config.json (macOS:
~/Library/Application Support/Claude/claude_desktop_config.json; Windows:
%APPDATA%\Claude\claude_desktop_config.json).
If you installed with uv sync (step 2 above):
{
"mcpServers": {
"ya-planka-mcp": {
"command": "uv",
"args": ["--directory", "/path/to/ya-planka-mcp", "run", "python", "mcp_server.py"],
"env": {
"PLANKA_BASE_URL": "https://your.domain",
"PLANKA_API_KEY": "<token>"
}
}
}
}If you installed with pip into venv/ (step 2 above), point directly at
that interpreter — use absolute paths for both command and the script
argument, since the client's working directory when it spawns the process is
not guaranteed to be this repo:
{
"mcpServers": {
"ya-planka-mcp": {
"command": "/path/to/ya-planka-mcp/venv/bin/python",
"args": ["/path/to/ya-planka-mcp/mcp_server.py"],
"env": {
"PLANKA_BASE_URL": "https://your.domain",
"PLANKA_API_KEY": "<token>"
}
}
}
}Claude Code
Either add a project-scoped .mcp.json at the root of the project you're
working in (not inside ya-planka-mcp itself):
{
"mcpServers": {
"ya-planka-mcp": {
"type": "stdio",
"command": "uv",
"args": ["--directory", "/path/to/ya-planka-mcp", "run", "python", "mcp_server.py"],
"env": {
"PLANKA_BASE_URL": "https://your.domain",
"PLANKA_API_KEY": "<token>"
}
}
}
}or register it with the CLI:
claude mcp add ya-planka-mcp \
--env PLANKA_BASE_URL=https://your.domain \
--env PLANKA_API_KEY=<token> \
-- uv --directory /path/to/ya-planka-mcp run python mcp_server.pyclaude mcp add defaults to --scope local (visible only to you, in this
project); pass --scope project to commit .mcp.json for teammates, or
--scope user to make the server available across all your projects.
Generic MCP client
Any client that can spawn a stdio subprocess needs only the same three pieces of information as the configs above:
command/args:
uv --directory /path/to/ya-planka-mcp run python mcp_server.py(or the direct venv-interpreter form if you installed withpip)env:
PLANKA_BASE_URLand one auth variable (see Environment variables above)
run_server.sh is an alternative launcher some clients may prefer over a raw
uv/python command — it activates ./venv (not .venv) if present and runs
mcp_server.py, or falls back to the system python3 running main.py
otherwise. It only auto-detects a venv literally named venv/, so it is
compatible with the pip install path above but not with uv sync's
.venv/; the explicit uv --directory ... / venv-interpreter forms above
work regardless of install method and are recommended.
Tools & Capabilities
29 tools, grouped by kind:
Read
Tool | Purpose |
| Workspace structure (projects, boards, lists, labels, users). Pass |
| Authenticated user identity (id, username, role) |
| All labels on a board (fast targeted refresh) |
| Filter and list cards with detail levels ( |
| Search and fetch a specific card |
| Fetch a card with full checklist detail (real task IDs, progress counts) |
| List a card's comments, newest first, with optional prefix filter (e.g. |
Write
Tool | Purpose |
| Scaffold a board with canonical kanban lists and lifecycle labels in one call |
| Create, rename, and reorder board lists |
| Card CRUD |
| Bulk-move 1–50 cards to a list (by id or name), order-preserving, per-card results |
| Checklist management |
| Label CRUD (create is idempotent by name) |
| Assign/remove board labels on cards |
| Assign/remove card members |
| Write a comment to a card |
Composite workflow
Tool | Purpose |
| Top card of a list (default TODO) with everything needed to execute it — description, tasks with ids, labels, members, latest comments — in one round-trip |
| Mechanical readiness validation (labels, description sections, checklist shape) |
| One-call board report: per-list counts, in-progress ages, blocked cards with latest |
Token efficiency
Responses support response_format (markdown/json) and, where reads can be
large, detail_level and scope filters. scripts/token_audit.py measures the
per-session tool-definition cost and live response sizes against your instance:
uv pip install tiktoken # optional, for exact o200k_base counts
.venv/bin/python scripts/token_audit.py [--board <name>] [--skip-live]Usage Examples
Ask your assistant:
"List all my boards."
"Search for cards mentioning 'invoice'."
"Create a card named 'App release checklist' with these subtasks…"
"Move the 'Integrate payment API' card to 'Done'."
"Mark the 'Write tests' task on the 'Backend sprint' card as complete."
"Add the 'Urgent' label to the 'Deploy hotfix' card."
Roles & Permissions
The MCP server does no role handling of its own. It acts as whatever
Planka user the configured API key (or email/password) belongs to — whatever
that account can do in Planka, the server can do through its tools; whatever
it can't, the server can't either. You control what the agent is capable of
entirely by which account's key you put in .env, and by adjusting that
account's rights inside Planka itself.
Planka distinguishes two kinds of board access, and this section uses Planka's own terms throughout:
Board manager — a user in the board's managers list. Only accounts with at least Project Owner or Admin role can be added as a board manager. Board managers get full card/task access plus board-level management (settings, members, labels).
Board member — a user added to a board with either edit or view-only rights. Edit rights allow card/task mutations; view-only is read-only. Board members — even with edit rights — cannot manage the board's members list or most board-level settings.
Role capability matrix
Capability | Board manager token | Board member token | Evidence |
List cards on a board list ( | Works | Not exercised by the board member live smoke (it never calls this tool) |
|
Create a card, read fresh card detail, delete the card | Works | Works |
|
Create a task list, add/update/delete a task | Works | Not exercised by the board member live smoke |
|
Add / remove a card label | Works | Not exercised by the board member live smoke |
|
Read | Works (implied) | Works — asserted explicitly ( |
|
Assign / remove another board member as a card member | Works | Not exercised — the board member smoke only self-assigns, consistent with board member tokens being unable to enumerate other users (see next row) |
|
Assign / remove yourself as a card member | Works (not the focus of this test) | Works — self-assign then self-remove is the entire point of the test |
|
| Populated | Empty. Planka returns | Source: |
Rows marked "not exercised" are not asserted anywhere in this repo's tests — they are not claimed to fail, only that the board member live smoke does not cover them. Only claim behavior beyond this table after adding a test that proves it.
Gotchas
A 403 on
/api/usersis invisible by design. Ifplanka_get_workspacecomes back with no users, check the account's board role (planka_get_me) before assuming a bug — a board member token gets an empty users map on purpose, not an error.Non-admin tokens silently see less, not an error. This is a Planka platform characteristic (not asserted by this repo's own test suite): a Planka user — and therefore a token scoped to that user — only sees projects/boards/lists/cards it is a member of. A wrong or under-scoped token does not raise;
planka_get_workspaceandplanka_list_cardsjust return fewer boards/cards than you expect. If something you know exists is missing, check board membership for that token's user first.
Security recommendations
The MCP server accesses only what the authenticated Planka user can access.
API token recommended over email/password.
Use HTTPS when exposing Planka externally.
Consider using a dedicated Planka service user with restricted permissions.
Troubleshooting & FAQ
401 Unauthorized
Check token validity and .env configuration.
Client cannot connect to server Verify the correct Python/uv path, firewall rules, and execution permissions.
No boards or cards returned Confirm the Planka user has workspace access.
Task creation fails
Ensure you are passing a valid task_list_id. Use planka_get_card to retrieve real task list IDs from the card's checklist.
Development
This project uses an editable install so the src/ directory is automatically on the Python path.
# Install in editable mode
uv sync
# or: pip install -e .Running Tests
Test dependencies (pytest and friends) live behind the test extra, not
the base install — run this once before the commands below:
uv sync --extra test# Run all offline tests
uv run pytest --cov=src/planka_mcp --cov-report=term-missing
# Run a specific test file
uv run pytest tests/test_cards.py -vOpt-in live smoke test
The repo includes an opt-in live smoke path that creates a card, task, and label on a real Planka board, then cleans up. It is skipped unless you opt in.
Required environment variables:
PLANKA_RUN_LIVE_SMOKE=1PLANKA_BASE_URLOne auth method:
PLANKA_API_KEY,PLANKA_API_TOKEN, orPLANKA_EMAIL+PLANKA_PASSWORD
The smoke test targets any writable list on your Planka instance — no disposable list or label IDs are required. Point it at a safe test board (e.g. "Test Project").
pytest does not auto-load .env — source it into the shell first:
set -a; source .env; set +a
uv run pytest -m live tests/test_live_smoke.py -q --no-covSafety contract:
Creates a disposable card and checklist task, then removes them
Label add/remove uses a reusable board label
Cleanup runs in
finallyeven on failureFresh-state assertions after task mutation use a new API client (not cached reads)
Card state and cache behavior
planka_get_card caches per-card detail payloads for up to 60 seconds. Card mutation tools
that can affect detail output invalidate that card cache: comments, task lists/tasks, labels,
members, custom field values, card updates, moves, and deletes.
planka_list_cards reads the board view live for every call. Preview and summary output use
state present in that board response, including commentsTotal when comment bodies are not
loaded. Detailed list output fetches fresh detail for each paginated card before rendering so
tasks and comments reflect live Planka state instead of a stale detail cache.
Opt-in permission smoke (role tokens)
For board-permission verification, run the gated permission smoke with role-scoped tokens. Tests are role-dependent:
test_non_owner_live_smoke_permissionsusesPLANKA_API_TOKEN_BOARD_MANAGERtest_board_member_live_smoke_permissionsusesPLANKA_API_TOKEN_BOARD_MEMBER
Required environment variables:
PLANKA_RUN_PERMISSION_SMOKE=1PLANKA_BASE_URL(orPLANKA_PERM_BASE_URL)PLANKA_API_TOKEN_BOARD_MANAGERfor board manager-role smokePLANKA_API_TOKEN_BOARD_MEMBERfor board member-role smokeOptional explicit disposable targets:
PLANKA_SMOKE_LIST_IDandPLANKA_SMOKE_LABEL_ID(orPLANKA_PERM_SMOKE_*)
set -a; source .env; set +a
PLANKA_RUN_PERMISSION_SMOKE=1 uv run pytest -m live tests/test_live_smoke.py -q --no-covTest with MCP Inspector
npx @modelcontextprotocol/inspector uv run python mcp_server.pyContributing
Dev environment setup
git clone https://github.com/andrejberg/ya-planka-mcp
cd ya-planka-mcp
uv sync # editable install, src/ on the Python path
cp .env.example .env # fill in PLANKA_BASE_URL + a token before touching live testsBefore opening a PR
Run the offline suite with coverage — CI (
.github/workflows/test.yml) runspytest --cov=src/planka_mcp --cov-report=xml --cov-fail-under=80on every push/PR tomain; match that locally:uv run pytest --cov=src/planka_mcp --cov-report=term-missing --cov-fail-under=80If the change touches role/permission behavior (anything in
src/planka_mcp/handlers/workspace.py, card membership, or label handling), run the opt-in permission smoke locally against a real Planka instance with both role tokens before describing the change as verified — see "Opt-in permission smoke (role tokens)" above:set -a; source .env; set +a PLANKA_RUN_PERMISSION_SMOKE=1 uv run pytest -m live tests/test_live_smoke.py -q --no-covThis is not part of CI (it requires live credentials) — it is a pre-PR check for the author, not a merge gate.
Keep the Roles & Permissions matrix above honest: if a PR changes what a board manager or board member token can do, update the matrix and its test in the same PR — don't let the docs drift from
tests/test_live_smoke.py.New tools/handlers follow the existing layout: Pydantic models in
src/planka_mcp/models.py, handler functions insrc/planka_mcp/handlers/, matching tests intests/.
PR expectations
Offline tests pass and coverage stays at or above 80% (CI enforces this).
No secrets (
.env, tokens) committed.README/docs updated when behavior, tools, or setup steps change.
Acknowledgements
Planka project: https://github.com/plankanban/planka
Model Context Protocol: https://modelcontextprotocol.io/
Credits & Attribution
This project is a fork of another-planka-mcp by Roel van der Ven, adapted and substantially extended as ya-planka-mcp. The original implementation provided the foundation for Planka MCP integration; this fork introduces significant enhancements, new features, and production-oriented improvements.
License
MIT License. See LICENSE.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/andrejberg/ya-planka-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server