Ya Planka
БесплатноНе проверенA Model Context Protocol (MCP) server that enables AI clients to read and manage your Planka boards using the Planka REST API.
Описание
A Model Context Protocol (MCP) server that enables AI clients to read and manage your Planka boards using the Planka REST API.
README
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-mcp - Install 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:
Full walkthrough: Obtaining API Credentials.cp .env.example .env # edit .env: set PLANKA_BASE_URL and PLANKA_API_KEY - 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.
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) or
pip+venv - Access 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-mcp
2. Install dependencies
With uv (recommended — creates .venv/ and resolves the lockfile):
uv sync
This 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 test
Or 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 .env
Then fill in the variables below.
Environment variables
| Variable | Required? | Purpose |
|---|---|---|
PLANKA_BASE_URL |
Yes | Base URL of your Planka instance (e.g. https://planka.example.com, no trailing slash) |
PLANKA_API_KEY |
Option 1 | Recommended. The admin-generated API key from Planka's user administration screen — see Obtaining API Credentials. Checked second, only if PLANKA_API_TOKEN is unset. |
PLANKA_API_TOKEN |
Option 2 | JWT access token from the legacy /api/access-tokens exchange — see Fallback: JWT access-token exchange. Checked first (takes priority over PLANKA_API_KEY if both are set). |
PLANKA_EMAIL + PLANKA_PASSWORD |
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": "[email protected]",
"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:
[email protected]
PLANKA_PASSWORD=your-password
This 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.py
claude 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 |
|---|---|
planka_get_workspace |
Workspace structure (projects, boards, lists, labels, users). Pass board_name/project_name to scope the response — a scoped call is a fraction of the full dump |
planka_get_me |
Authenticated user identity (id, username, role) |
planka_get_labels |
All labels on a board (fast targeted refresh) |
planka_list_cards |
Filter and list cards with detail levels (preview/summary/detailed) and pagination |
planka_find_and_get_card |
Search and fetch a specific card |
planka_get_card |
Fetch a card with full checklist detail (real task IDs, progress counts) |
planka_get_comments |
List a card's comments, newest first, with optional prefix filter (e.g. Blocked:) |
Write
| Tool | Purpose |
|---|---|
planka_create_board |
Scaffold a board with canonical kanban lists and lifecycle labels in one call |
planka_create_list / planka_update_list |
Create, rename, and reorder board lists |
planka_create_card / planka_update_card / planka_delete_card |
Card CRUD |
planka_move_cards |
Bulk-move 1–50 cards to a list (by id or name), order-preserving, per-card results |
planka_create_task_list / planka_add_task / planka_update_task / planka_delete_task |
Checklist management |
planka_create_label / planka_update_label / planka_delete_label |
Label CRUD (create is idempotent by name) |
planka_add_card_label / planka_remove_card_label |
Assign/remove board labels on cards |
planka_add_card_member / planka_remove_card_member |
Assign/remove card members |
planka_add_comment |
Write a comment to a card |
Composite workflow
| Tool | Purpose |
|---|---|
planka_next_card |
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 |
planka_card_ready_check |
Mechanical readiness validation (labels, description sections, checklist shape) |
planka_board_status |
One-call board report: per-list counts, in-progress ages, blocked cards with latest Blocked: comment, unsatisfied gates, done-window points |
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 (planka_list_cards) |
Works | Not exercised by the board member live smoke (it never calls this tool) | tests/test_live_smoke.py::test_non_owner_live_smoke_permissions |
| Create a card, read fresh card detail, delete the card | Works | Works | test_non_owner_live_smoke_permissions; test_board_member_live_smoke_permissions |
| Create a task list, add/update/delete a task | Works | Not exercised by the board member live smoke | test_non_owner_live_smoke_permissions |
| Add / remove a card label | Works | Not exercised by the board member live smoke | test_non_owner_live_smoke_permissions |
Read cardMemberships on a card detail |
Works (implied) | Works — asserted explicitly (cardMemberships key must be present) |
test_board_member_live_smoke_permissions (docstring: "PERM-01 evidence") |
| 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) | test_non_owner_live_smoke_permissions (include_member_mutations=True) |
| 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 | test_board_member_live_smoke_permissions |
planka_get_workspace users list |
Populated | Empty. Planka returns 403 on /api/users for board member tokens; the server catches it and degrades gracefully (returns {} plus _users_hidden_due_to_permissions: true in JSON) instead of raising |
Source: fetch_workspace_data in src/planka_mcp/handlers/workspace.py (tagged PERM-03); unit tests test_fetch_workspace_data_users_403_returns_empty_map and test_get_workspace_permission_hint_when_users_empty in tests/test_workspace.py (mocked 403, not part of the live smoke suite) |
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 -v
Opt-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_URL- One 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-cov
Safety contract:
- Creates a disposable card and checklist task, then removes them
- Label add/remove uses a reusable board label
- Cleanup runs in
finallyeven on failure - Fresh-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 smoke- Optional 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-cov
Test with MCP Inspector
npx @modelcontextprotocol/inspector uv run python mcp_server.py
Contributing
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 tests
Before 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=80 - If 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:
This is not part of CI (it requires live credentials) — it is a pre-PR check for the author, not a merge gate.set -a; source .env; set +a PLANKA_RUN_PERMISSION_SMOKE=1 uv run pytest -m live tests/test_live_smoke.py -q --no-cov - 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.
Установка Ya Planka
У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.
▸ github.com/andrejberg/ya-planka-mcpFAQ
Ya Planka MCP бесплатный?
Да, Ya Planka MCP бесплатный — установка в пару кликов через Unyly без оплаты.
Нужен ли API-ключ для Ya Planka?
Нет, Ya Planka работает без API-ключей и переменных окружения.
Ya Planka — hosted или self-hosted?
Доступен hosted-вариант: Unyly запускает сервер в облаке, локальная установка не обязательна.
Как установить Ya Planka в Claude Desktop, Claude Code или Cursor?
Открой Ya Planka на unyly.org, выбери вкладку своего клиента (Claude Desktop, Claude Code, Cursor) и нажми Install — конфиг сгенерируется автоматически, без правки JSON.
Похожие MCP
Fetch
Web content fetching and conversion for efficient LLM usage.
AWS KB Retrieval
Retrieval from AWS Knowledge Base using Bedrock Agent Runtime.
автор: modelcontextprotocolSpring AI MCP Server
Provides auto-configuration for setting up an MCP server in Spring Boot applications.
llm-analysis-assistant
A very streamlined mcp client that supports calling and monitoring stdio/sse/streamableHttp, and can also view request responses through the /logs page. It also
автор: xuzexin-hzCompare Ya Planka with
Не уверен что выбрать?
Найди свой стек за 60 секунд
Автор?
Embed-бейдж для README
Похожее
Все в категории ai
