Command Palette

Search for a command to run...

UnylyUnyly
Весь каталог

Ya Planka

БесплатноНе проверен

A Model Context Protocol (MCP) server that enables AI clients to read and manage your Planka boards using the Planka REST API.

GitHubEmbed

Описание

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.

Tests

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.

  1. Clone the repo:
    git clone https://github.com/andrejberg/ya-planka-mcp
    cd ya-planka-mcp
    
  2. Install dependencies: uv sync (see Installation for the pip alternative).
  3. 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_KEY
    
    Full walkthrough: Obtaining API Credentials.
  4. 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> / TODO with 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.

  1. Log in to your Planka instance as an admin user.
  2. Open User Administration (the admin-only user management screen).
  3. 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.
  4. 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 with pip)
  • env: PLANKA_BASE_URL and 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/users is invisible by design. If planka_get_workspace comes 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_workspace and planka_list_cards just 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=1
  • PLANKA_BASE_URL
  • One auth method: PLANKA_API_KEY, PLANKA_API_TOKEN, or PLANKA_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 finally even 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_permissions uses PLANKA_API_TOKEN_BOARD_MANAGER
  • test_board_member_live_smoke_permissions uses PLANKA_API_TOKEN_BOARD_MEMBER

Required environment variables:

  • PLANKA_RUN_PERMISSION_SMOKE=1
  • PLANKA_BASE_URL (or PLANKA_PERM_BASE_URL)
  • PLANKA_API_TOKEN_BOARD_MANAGER for board manager-role smoke
  • PLANKA_API_TOKEN_BOARD_MEMBER for board member-role smoke
  • Optional explicit disposable targets: PLANKA_SMOKE_LIST_ID and PLANKA_SMOKE_LABEL_ID (or PLANKA_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

  1. Run the offline suite with coverage — CI (.github/workflows/test.yml) runs pytest --cov=src/planka_mcp --cov-report=xml --cov-fail-under=80 on every push/PR to main; match that locally:
    uv run pytest --cov=src/planka_mcp --cov-report=term-missing --cov-fail-under=80
    
  2. 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:
    set -a; source .env; set +a
    PLANKA_RUN_PERMISSION_SMOKE=1 uv run pytest -m live tests/test_live_smoke.py -q --no-cov
    
    This is not part of CI (it requires live credentials) — it is a pre-PR check for the author, not a merge gate.
  3. 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.
  4. New tools/handlers follow the existing layout: Pydantic models in src/planka_mcp/models.py, handler functions in src/planka_mcp/handlers/, matching tests in tests/.

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

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.

from github.com/andrejberg/ya-planka-mcp

Установка Ya Planka

У этого сервера нет опубликованного пакета — он собирается из исходников. Открой репозиторий и следуй инструкции в README.

▸ github.com/andrejberg/ya-planka-mcp

FAQ

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

Compare Ya Planka with

Не уверен что выбрать?

Найди свой стек за 60 секунд

Автор?

Embed-бейдж для README

Похожее

Все в категории ai