PlaneIO MCP Server for backlog usage with Claude
plane-io-mcp — MCP server for Plane + markdown backlog
plane-io-mcp (npm package name: mcp-plane-sync) is a Model Context Protocol (MCP) stdio server that connects Plane (open-source project management and issue tracking) with a markdown backlog inside a Git repository. Use it from Cursor, Claude Desktop, or any MCP-capable client to sync issues, create tasks, move Kanban sections, comment, and probe API auth — without leaving your editor.
If you searched for Plane MCP, Plane.io MCP, Plane issue sync, markdown backlog Plane, Cursor Plane integration, PAT Plane API, or self-hosted Plane automation, this tool is aimed at that workflow.
Features
| Area | What it does |
|------|----------------|
| Bidirectional sync | Aligns Plane issues with - [ ] tasks in markdown files; stores <!-- plane:issueId=... --> markers |
| Dry-run | plane_sync_status plans changes without writing |
| Workflow | Create issues, take tasks (assign + move section), set status, add comments |
| Config | Per-repo .plane-sync.json + optional global ~/.config/plane-sync/config.json |
| Secrets | PLANE_TOKEN / credentials file — never commit tokens |
MCP tools (stdio)
plane_probe— verify token and API (/users/me)plane_sync_status— dry-run sync planplane_sync— apply sync (markdown ↔ Plane)plane_issue_new— create Plane issue + append backlog lineplane_issue_take— move to Doing (or custom section), assign self, optional commentplane_issue_set_status— move markdown section + update Planestate_idwhen mappedplane_issue_comment— comment in Plane + optional details file update
All tools accept optional repoPath. If omitted, the server uses its current working directory and walks up to find .git.
Requirements
- Node.js 18+
- A Git repo containing
.plane-sync.jsonand markdown files matchingbacklogFiles - Plane instance with API access (cloud or self-hosted)
- Personal access token (PAT) or API key with appropriate scopes
Install
git clone git@github.com:iampelixm/plane-io-mcp.git
cd plane-io-mcp
npm install
Guided install for Cursor (interactive)
The repository includes install-cursor-mcp.sh (Russian prompts). It will:
- Ask for your Git project root, Plane API token, API base URL, workspace slug, project id (or project slug if id is empty), and backlog file path (default
docs/todo/backlog.md). - Write
~/.config/plane-mcp.env(PLANE_TOKEN, mode600) and merge~/.config/plane-sync/config.json(baseUrl/apiBaseUrl, no token). - Create or update
.plane-sync.jsonin the project, create the backlog file with default Inbox / Ready / Doing / Done headings if missing, and append.plane-sync.state.jsonand.envto the project.gitignore. - Merge the
plane-syncentry into~/.cursor/mcp.jsonusing the absolute path to this clone (src/index.mjs),cwd:${workspaceFolder}, andenvFilepointing at~/.config/plane-mcp.env. - Optionally run
npm installin the clone.
chmod +x install-cursor-mcp.sh
./install-cursor-mcp.sh
After it finishes, restart Cursor (or toggle MCP) and run plane_probe from a chat with the target workspace open.
NVM-only machines: if node is not on PATH yet, the script tries to source $NVM_DIR/nvm.sh (default ~/.nvm/nvm.sh), then falls back to the newest directory under ~/.nvm/versions/node/*/bin/node. The generated mcp.json always stores the absolute path to node, because Cursor’s MCP process usually does not load NVM.
Configuration
1. Token (do not commit)
The server reads .env in this order (standard dotenv rules: an already-set variable is not overwritten by a later file):
<current working directory>/.env— whatever directory the MCP process was started with ascwd.- In Cursor, if you set
"cwd": "${workspaceFolder}", this is the root of the open project. PutPLANE_TOKENthere if the token should be per repository.
- In Cursor, if you set
<plane-io-mcp clone>/.env— next to this package’spackage.json(parent ofsrc/).- Use this for a single shared token on the machine, or when you run
node src/index.mjsfrom inside the clone.
- Use this for a single shared token on the machine, or when you run
You can keep only one of these files, or both (workspace .env wins for keys present in both).
Example next to the clone:
cd /path/to/plane-io-mcp
cp .env.example .env
# edit .env — set PLANE_TOKEN=...
Example for a per-project token: create .env in the app repo root (and add .env to that repo’s .gitignore).
You do not have to use .env at all if the token is already in the environment (e.g. env / envFile in the MCP client config) or in ~/.config/plane-sync/credentials.json / global config.json (see below).
2. Global defaults (optional)
~/.config/plane-sync/config.json example:
{
"baseUrl": "https://your-plane.example.com",
"apiBaseUrl": "https://your-plane.example.com/api/v1/"
}
Notes:
- Plane’s REST API is typically under
/api/v1/. Trailing slashes on URLs matter on some deployments. - For tokens shaped like
plane_api_…, Plane expects theX-API-Keyheader — notAuthorization: Bearer …. - If this file defines an
authblock that forces Bearer (or any scheme other than the key header), it overrides the automatic API-key behaviour. Requests then go out with the wrong header and the API often returns 401 (Authentication credentials were not provided). Either omitauthforplane_api_…keys, or document clearly that Bearer must not be forced for those keys.
3. Repository config (.plane-sync.json)
In the root of the Git project (not necessarily this package), add .plane-sync.json. Start from the example in this repo:
cp .plane-sync.example.json /path/to/your/repo/.plane-sync.json
Edit workspaceSlug, projectId (recommended) or projectSlug, backlogFiles, and optional mapping.sectionToStateId so markdown headings map to Plane workflow states.
projectId must be the project UUID from Plane’s API (e.g. from the projects list). Issue URLs use …/projects/{id}/issues/… with that UUID. A short human-readable identifier (e.g. GOVADMIN) is not the same value — putting it in projectId leads to 404 on issue routes. You may set projectSlug instead of projectId; the server resolves it via listProjects (see Integrator notes).
Optional — Kanban / status sync: if mapping.sectionToStateId is empty or wrong, markdown sections and Plane columns may diverge. For full Kanban ↔ Plane alignment, fill the map using state ids from your workspace’s workflow in Plane (API or UI), keyed by the exact section heading strings you use in markdown.
State file
The sync writes .plane-sync.state.json in the repo for conflict detection. Add it to .gitignore in your application repository.
Integrator notes (package / MCP consumers)
listProjectsresponse shape: Plane often returns a paginated object (results,total_count, …), not a bare array.pickProjectIdincore.mjsaccepts both an array and{ results }soprojectSlugresolution works. If you fork the client, normalize the same way before calling.findon the list.
Run (stdio)
From this package directory:
node src/index.mjs
Or after npm link / global install, run the mcp-plane-sync binary defined in package.json.
Cursor / MCP client setup
Configure an MCP server with command node and args pointing to src/index.mjs (absolute path recommended). Set cwd to your application repository root so tools resolve .plane-sync.json and backlog files by default.
Example (conceptual — adjust paths):
{
"mcpServers": {
"plane-sync": {
"command": "node",
"args": ["/absolute/path/to/plane-io-mcp/src/index.mjs"],
"cwd": "/absolute/path/to/your/git/repo"
}
}
}
Ensure PLANE_TOKEN is available to that process (env file next to the server, shell profile, or client-specific env).
How tasks link to Plane
Markdown checklist lines get an HTML comment marker:
- [ ] Example task title <!-- plane:issueId=abc123 -->
The server parses headings as sections (Inbox / Ready / Doing / Done by default, configurable).
Debugging
Set PLANE_SYNC_DEBUG=1 to log sanitized request metadata to stderr (see core.mjs).
Issue summary (for tickets / handoff)
- 401 with API key: global
~/.config/plane-sync/config.jsonforces Bearer viaauth, soX-API-Keyis not used. - 404 on issues:
projectIdmust be the UUID, not a short identifier (e.g.GOVADMIN). - Crash with
projectSlugonly (older builds): paginatedlistProjects+pickProjectIdcalling.findon the raw object — fixed in this repo by normalizing toresultsinsidepickProjectId.
Keywords / discovery (search)
Useful search terms for this project: MCP, Model Context Protocol, stdio MCP server, Plane, Plane.so, Plane app, Plane REST API, issue sync, backlog sync, markdown tasks, Git workflow, Cursor MCP, AI coding assistant, project management API, Kanban, PAT, personal access token, self-hosted Plane, two-way sync, developer tooling, Node.js ESM.
License
See repository root if a LICENSE file is added; until then, usage is governed by your team’s policy for this fork.
Related
- Plane — plane.so
- MCP — modelcontextprotocol.io
- @modelcontextprotocol/sdk — official MCP SDK for Node