Plane 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., "@Plane MCP List my projects in Plane."
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.
Plane MCP
A Model Context Protocol server for Plane (self-hosted or Cloud). It lets an LLM client — Claude Desktop, Claude Code, Cursor, etc. — fully drive your Plane workspace: discover projects, and create / read / update / delete / re-organize work items, states, labels, cycles, modules, and comments.
Verified against a self-hosted instance at
plane.nzminds.com(workspacenzmt).
What it can do
Resource | Tools |
Projects |
|
Work items |
|
States (statuses) |
|
Labels |
|
Cycles (sprints) |
|
Modules |
|
Comments |
|
Members |
|
Related MCP server: Plane MCP Server
How Plane's model works (quick mental model)
Workspace (slug, e.g. "nzmt")
└─ Project (UUID) ← discover with list_projects
├─ Work Items / Issues ← the tickets; have a UUID + human number (TRAVELXS-391)
├─ States ← the statuses (Backlog/Todo/In Progress/Done…), each a UUID
├─ Labels ← UUIDs
├─ Cycles ← time-boxed sprints
└─ Modules ← feature groupingsEverything in a request body is a UUID, not a name. So the normal flow is:
list_projects→ pick a project UUID.list_states→ map "In Progress" → its UUID.list_members/list_labelslikewise.Create/update the work item. To change status, set
stateto the target state UUID (or useset_work_item_status).
Most tools take an optional project_id; if omitted they fall back to PLANE_DEFAULT_PROJECT_ID from your .env.
Setup
1. Get an API key
See SETUP.md for step-by-step instructions (Profile Settings → Personal Access Tokens).
2. Configure
cp .env.example .env
# edit .env: PLANE_BASE_URL, PLANE_API_KEY, PLANE_WORKSPACE_SLUG3. Install
Requires Python ≥ 3.10.
python -m pip install -e .(or with uv: uv pip install -e .)
4. Run
plane-mcp # or: python -m plane_mcpIt speaks MCP over stdio, so you normally don't run it by hand — your MCP client launches it.
Connecting to a client
Claude Desktop / Claude Code
Add to your MCP config (claude_desktop_config.json, or via claude mcp add):
{
"mcpServers": {
"plane": {
"command": "plane-mcp",
"env": {
"PLANE_BASE_URL": "https://plane.nzminds.com",
"PLANE_API_KEY": "plane_api_xxxxxxxx",
"PLANE_WORKSPACE_SLUG": "nzmt"
}
}
}
}Or, if you'd rather rely on the .env file, drop the env block and use the absolute interpreter:
{
"mcpServers": {
"plane": {
"command": "python",
"args": ["-m", "plane_mcp"],
"cwd": "d:/Govind/Plane MCP"
}
}
}Claude Code one-liner:
claude mcp add plane -- python -m plane_mcpExample prompts once connected
"List my projects in Plane."
"In TravelXS, create a high-priority bug 'Login fails on Safari' and assign it to govind.kumar."
"Move TRAVELXS-391 to In Progress."
"Create a cycle 'Sprint 12' from 2026-07-01 to 2026-07-14 and add TRAVELXS-394 and -376 to it."
"Add a comment to TRAVELXS-308 saying the fix is deployed."
Notes & limits
Rate limit: 60 requests/min per key. The client auto-retries on
429with backoff.Pagination: list tools follow Plane's cursor pagination and return all results.
Destructive ops: the hard
delete_*tools (project, work item, state, label, cycle, module, comment) are disabled by default. SetPLANE_ALLOW_DELETE=truein.envto expose them. Relationship removals (remove_work_item_from_cycle/_module) are always available since they're reversible.Self-hosted path quirk: cycle/module work-item sub-resources are
/cycle-issues/and/module-issues/(the public docs saywork_items, which 404s on self-hosted). This server uses the verified paths.
Project layout
src/plane_mcp/
├── config.py # env loading & validation
├── client.py # async HTTP client: pagination, 429 retry, errors
├── server.py # FastMCP instance + tool registration
├── __main__.py # entry point (stdio)
└── tools/ # one module per resource
├── projects.py issues.py states.py labels.py
├── cycles.py modules.py comments.py members.pyLicense
MIT
Available Tools
38 toolsadd_commentB
Add a comment to a work item. comment_html accepts HTML, e.g. 'Looks good'. access: INTERNAL or EXTERNAL.
Inputs: issue_id (required), comment_html (required), access, project_id. Returns: object
add_work_items_to_cycleC
Add one or more work items (by UUID) to a cycle.
Inputs: cycle_id (required), issue_ids (required), project_id. Returns: object
add_work_items_to_moduleB
Add one or more work items (by UUID) to a module.
Inputs: issue_ids (required), module_id (required), project_id. Returns: object
create_cycleC
Create a cycle. Dates are 'YYYY-MM-DD'. owned_by is a member UUID.
Inputs: name (required), end_date, owned_by, project_id, +2 more. Returns: object
create_labelB
Create a label. color is a hex like '#FF0000'.
Inputs: name (required), color, project_id, description. Returns: object
create_moduleB
Create a module. status: backlog|planned|in-progress|paused|completed|cancelled. lead/members are member UUIDs.
Inputs: name (required), lead, status, members, +4 more. Returns: object
create_projectB
Create a project. identifier is the short code (e.g. 'WEB'),
uppercase and unique in the workspace. network: 0=secret, 2=public.
Inputs: name (required), identifier (required), network, description, +2 more. Returns: object
create_stateC
Create a state. color is a hex like '#60646C'. group must be one of: backlog, unstarted, started, completed, cancelled.
Inputs: name (required), color (required), group (required), project_id, +1 more. Returns: object
create_work_itemB
Create a work item. Only name is required.
priority: none|urgent|high|medium|low
state: a STATE UUID (use list_states to find it)
assignees/labels: lists of UUIDs (use list_members / list_labels)
dates: 'YYYY-MM-DD'
Inputs: name (required), state, labels, parent, +7 more. Returns: object
find_memberA
Find members whose email or display name contains query
(case-insensitive). Returns matches so you can pick the right UUID.
Inputs: query (required). Returns: result
find_projectA
Find projects whose name or identifier contains query
(case-insensitive). Handy when you only know the project name.
Inputs: query (required). Returns: result
find_stateA
Find a state by (case-insensitive) name and return it, or None.
Inputs: name (required), project_id. Returns: result
get_cycleB
Get a single cycle by UUID.
Inputs: cycle_id (required), project_id. Returns: object
get_moduleB
Get a single module by UUID.
Inputs: module_id (required), project_id. Returns: object
get_projectA
Get full details of a single project by its UUID.
Inputs: project_id (required). Returns: object
get_work_itemA
Get a single work item by its UUID.
Inputs: issue_id (required), expand, project_id. Returns: object
get_work_item_by_numberA
Look up a work item by its human number (e.g. 391 for TRAVELXS-391).
Inputs: sequence_id (required), project_id.
list_commentsA
List all comments on a work item.
Inputs: issue_id (required), project_id. Returns: result
list_cyclesA
List a project's cycles (sprints) with their UUIDs and dates.
Inputs: project_id. Returns: result
list_cycle_work_itemsB
List the work items assigned to a cycle.
Inputs: cycle_id (required), project_id. Returns: result
list_labelsA
List a project's labels with their UUIDs (needed to tag work items).
Inputs: project_id. Returns: result
list_membersA
List workspace members with their UUIDs, emails, and display names.
Use the returned member UUID for assignees, owned_by, lead, etc.
Inputs: no named parameters. Returns: result
list_modulesA
List a project's modules with their UUIDs.
Inputs: project_id. Returns: result
list_module_work_itemsB
List the work items assigned to a module.
Inputs: module_id (required), project_id. Returns: result
list_projectsA
List all projects in the workspace. Use this to discover project IDs, names, and identifiers (the short code like 'TRAVELXS').
Inputs: no named parameters. Returns: result
list_statesA
List a project's states (statuses) with their UUIDs, names, and groups. Call this first to map a status name like 'In Progress' to its UUID before creating/updating work items.
Inputs: project_id. Returns: result
list_work_itemsA
List all work items in a project (paginated automatically).
expand inlines related objects; default expands state/assignees/labels.
Omit project_id to use PLANE_DEFAULT_PROJECT_ID.
Inputs: expand, project_id. Returns: result
remove_work_item_from_cycleC
Remove a single work item from a cycle.
Inputs: cycle_id (required), issue_id (required), project_id. Returns: object
remove_work_item_from_moduleB
Remove a single work item from a module.
Inputs: issue_id (required), module_id (required), project_id. Returns: object
search_work_itemsB
Full-text search work items in a project by name/content.
Inputs: query (required), project_id.
set_work_item_statusA
Change a work item's status by setting its state UUID. Convenience wrapper around update_work_item. Use list_states to map a status name (Backlog/Todo/In Progress/Done...) to its UUID.
Inputs: state (required), issue_id (required), project_id. Returns: object
update_commentC
Edit an existing comment.
Inputs: issue_id (required), comment_id (required), comment_html (required), project_id. Returns: object
update_cycleC
Update a cycle. Only provided fields change.
Inputs: cycle_id (required), name, end_date, project_id, +2 more. Returns: object
update_labelA
Update a label. Only provided fields change.
Inputs: label_id (required), name, color, project_id, +1 more. Returns: object
update_moduleB
Update a module. Only provided fields change.
Inputs: module_id (required), lead, name, status, +5 more. Returns: object
update_projectB
Update a project's editable fields. Only provided fields change.
Inputs: project_id (required), name, description, project_lead, +1 more. Returns: object
update_stateB
Update a state. Only provided fields change.
Inputs: state_id (required), name, color, group, +2 more. Returns: object
update_work_itemB
Update any fields of a work item. Only provided fields change.
To change STATUS, pass state with the target state's UUID.
To clear assignees/labels, pass an empty list [].
Inputs: issue_id (required), name, state, labels, +8 more. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 38 tools
Tools are generally distinct, with clear separation via resource type (project, work item, cycle, module, comment, label, member, state) and action. The main overlap is set_work_item_status being a convenience wrapper around update_work_item, but descriptions clarify the purpose. Some pairs like list_projects/find_project could be confused but are well-defined.
Names follow a consistent verb_noun pattern (list_*, get_*, create_*, update_*, find_*, add_*, remove_*). Variations like get_work_item_by_number and set_work_item_status are logically extended forms, not inconsistent. The convention is uniform across all 38 tools.
With 38 tools, the server is well over the 25+ threshold that typically indicates too many. While the scope is broad (multiple project management entities), the set includes many similar list/get/update tools per resource, making it feel heavy. A more streamlined set could consolidate some operations.
The server covers create, read, and update for most resources, plus work item status changes and assignment to cycles/modules. However, there are no delete operations for any entity (projects, work items, labels, cycles, modules, comments, states), which is a notable gap in CRUD coverage. Also missing get_label and get_comment, but these are less critical.
Maintenance
Related MCP Connectors
MCP server for AI agents to plan, verify, and deploy Cloudflare-native apps.
Nifty's MCP server — exposes tasks, projects, messages, and files as tools for AI agents.
MCP server for your apps' tools and custom tools, plus hosted AI agents and approval-gated workflows
MCP server for generating rough-draft project plans from natural-language prompts.
Related MCP Servers
- AlicenseBqualityDmaintenanceA Model Context Protocol server that enables LLMs to interact with Plane.so, allowing them to manage projects and issues through Plane's API for streamlined project management workflows.640MIT
- AlicenseBqualityDmaintenanceA Model Context Protocol (MCP) server that enables LLMs to interact with Plane.so, allowing them to manage projects and issues through Plane's API. Using this server, LLMs like Claude can directly interact with your project management workflows while maintaining user control and security.7613 npm1MIT
- AlicenseNot gradedqualityDmaintenanceAn MCP server for the Plane project management platform that enables users to manage workspaces, projects, and work items. It supports full CRUD operations for issues while providing access to cycles, modules, labels, and workflow states.MIT
- AlicenseCqualityDmaintenanceMCP server for Plane integration, enabling AI agents to interact with Plane APIs and services for project management tasks.100MIT