Plane MCP Server CE
[!IMPORTANT]
Community Edition and self-hosted first
This fork exists to provide the broadest possible MCP compatibility with the free, self-hosted Plane Community Edition. It is not intended for upstream contribution: its focus is making every capability that CE actually exposes usable by AI agents, while keeping Cloud-only and paid features out of their tool list.
Issues and pull requests that improve Plane CE or self-hosted compatibility are warmly welcome. Contributions authored with AI coding agents are welcome too, provided they are clean, reviewed, and remain aligned with this CE and self-hosted focus.
A Model Context Protocol (MCP) server for Plane integration. This package is
published on PyPI as plane-community-mcp and provides tools and resources for
interacting with self-hosted Plane CE through AI agents. The distribution name
is intentionally different from the executable: install
plane-community-mcp, then run plane-mcp-server-ce.
This repository is a fork of plane-mcp-server-ce. It publishes under its own
distribution name because the PyPI project plane-mcp-server-ce belongs to the
upstream project; the GitHub repository and the CLI command keep the original
name so existing agent configurations keep working.
Features
- 🏠 CE-first: hides API surfaces that self-hosted Community Edition cannot serve.
- 🔐 Two credential paths: an API key (PAT) for the public API; a browser session for the CE app-API features (pages, archive).
- 📄 Useful Pages support: CE project pages support create, retrieve, rename, HTML content updates, archive, unarchive, and archived-page deletion.
- 🔌 Two transports: stdio and PAT-header streamable HTTP. OAuth transports were removed — Plane CE has no OAuth provider endpoints (
/auth/o/…returns 404), so they could never work self-hosted.
Usage
The server supports two transport methods. We recommend using uvx as it doesn't require installation.
Install name vs. run command
The PyPI distribution is plane-community-mcp, while the executable remains
plane-mcp-server-ce. Use both names when starting it with uvx:
uvx --from plane-community-mcp plane-mcp-server-ce --help
Do not use uvx plane-community-mcp: that is the installable distribution, not
the executable name. If you prefer a persistent installation instead:
python -m pip install plane-community-mcp
plane-mcp-server-ce stdio
Requirements:
- Python 3.10+ (for stdio transport, via
uvx) - Node.js 22+ (for remote transports, via
npx)
1. Stdio transport against self-hosted Plane CE (recommended)
This is the standard setup for a self-hosted Community Edition instance. Set the environment variables before launching the server:
export PLANE_BASE_URL="https://your-plane.example" # your CE instance origin
export PLANE_API_KEY="your-api-key" # created in CE workspace settings → API
export PLANE_WORKSPACE_SLUG="your-workspace"
export PLANE_MCP_EDITION="community"
# Session credentials — required for the CE-only tools this fork exists for
# (project pages, work-item archive/unarchive). Everything else works with
# the API key alone; without these, pages and archive tools stay hidden.
# export PLANE_SESSION_COOKIE="<session-id cookie value>" # preferred
# … or email + password instead of a cookie:
# export PLANE_SESSION_EMAIL="you@example.com"
# export PLANE_SESSION_PASSWORD="your-password"
uvx --from plane-community-mcp plane-mcp-server-ce stdio
Project pages and work-item archiving are the reason to run this fork instead
of upstream — and they require session credentials: without PLANE_SESSION_*
those tools stay hidden, while the rest of the server works with the API key
alone. See Session-only capabilities
for how to obtain the cookie.
MCP Client Configuration (using uvx - recommended):
{
"mcpServers": {
"plane": {
"command": "uvx",
"args": ["--from", "plane-community-mcp", "plane-mcp-server-ce", "stdio"],
"env": {
"PLANE_API_KEY": "<your-api-key>",
"PLANE_WORKSPACE_SLUG": "<your-workspace-slug>",
"PLANE_BASE_URL": "https://<your-self-hosted-plane-url>",
"PLANE_MCP_EDITION": "community",
"PLANE_SESSION_COOKIE": "<your-session-id-cookie>"
}
}
}
}
The PLANE_SESSION_COOKIE entry (or PLANE_SESSION_EMAIL +
PLANE_SESSION_PASSWORD) is what turns on the pages and archive tools —
the CE features this fork exists for. Omit it and those tools stay hidden.
2. Self-hosted HTTP transport (PAT headers)
Run the server on your own network when several clients need to reach it over HTTP, or when your client only speaks URL-based transports. The server listens on port 8211 and serves a single endpoint:
| Endpoint | Transport | Authentication |
|---|---|---|
/http/api-key/mcp |
Streamable HTTP | Authorization: Bearer <api-key> + x-workspace-slug headers |
The server only needs to know where your Plane instance lives; each client authenticates with its own API key:
export PLANE_BASE_URL="https://your-plane.example"
export PLANE_MCP_EDITION="community"
uvx --from plane-community-mcp plane-mcp-server-ce http
Or with Docker (the image defaults to the http transport):
docker build -t plane-mcp-server-ce .
docker run -p 8211:8211 \
-e PLANE_BASE_URL="https://your-plane.example" \
-e PLANE_MCP_EDITION="community" \
plane-mcp-server-ce
Client configuration (mcp-remote forwards the headers; ${VAR} is expanded
from the client's environment):
{
"mcpServers": {
"plane": {
"command": "npx",
"args": [
"mcp-remote@latest",
"http://your-server:8211/http/api-key/mcp",
"--header", "Authorization: Bearer ${PLANE_API_KEY}",
"--header", "x-workspace-slug: ${PLANE_WORKSPACE_SLUG}"
]
}
}
}
The API key must travel in the Authorization: Bearer header — that is the
only header the token middleware inspects — and x-workspace-slug names the
workspace. To use the session-only tools (pages, archive) over HTTP, also set
PLANE_SESSION_* on the server, as in section 1.
About Plane Cloud: this server targets self-hosted CE and authenticates with API keys only. Plane Cloud users should connect to Plane's hosted MCP at
https://mcp.plane.so(OAuth or PAT) instead of running this fork.
Configuration
Authentication
The server requires authentication via environment variables:
PLANE_BASE_URL: Base URL for Plane API (default:https://api.plane.so). For self-hosted CE, set this to your instance origin, e.g.https://your-plane.example.PLANE_API_KEY: API key for authentication (required for stdio transport)PLANE_WORKSPACE_SLUG: Workspace slug identifier (required for stdio transport)PLANE_INTERNAL_BASE_URL: Internal URL preferred overPLANE_BASE_URLfor server-to-server calls (useful when the MCP server runs inside the same network as Plane). Also consulted byPLANE_MCP_EDITION=autowhen detecting a self-hosted instance.PLANE_MCP_EDITION: Tool discovery mode:community(orce) exposes only tools verified against Plane CE;cloud(orall) exposes the complete SDK surface;autois the default and treats a configured non-*.plane.soAPI URL as self-hosted. Setcommunityexplicitly for predictable self-hosted deployments, especially if you use a custom Cloud domain.PLANE_SESSION_EMAIL/PLANE_SESSION_PASSWORD, orPLANE_SESSION_COOKIE: CE-only app-session credentials — required for the tools this fork exists for (work-item archive/unarchive and project pages); without them those tools are hidden from discovery. See Session-only capabilities.
Example (self-hosted CE, stdio transport):
export PLANE_BASE_URL="https://your-plane.example"
export PLANE_API_KEY="your-api-key"
export PLANE_WORKSPACE_SLUG="your-workspace-slug"
export PLANE_MCP_EDITION="community"
Note: For the self-hosted HTTP transport (section 2), set PLANE_BASE_URL (and PLANE_MCP_EDITION) on the server; each client then authenticates with an Authorization: Bearer <api-key> header plus x-workspace-slug.
Logging
The server emits structured JSON logs. Each tool call is logged with its tool name, duration, status, and workspace slug.
LOG_LEVEL: Python log level; defaults toINFO. Set toWARNINGin a high-volume production deployment orDEBUGwhile troubleshooting.- Tool arguments and other request payloads are never logged by default.
LOG_USER_INFO: Whentrue, include user info (PII such as the display name) in logs alongside the opaque user id. Defaults tofalseso PII is never logged unless explicitly opted in. Only the PAT (header) HTTP transport carries request-level auth context; stdio is unaffected.
export LOG_USER_INFO="true"
Available Tools
The server provides comprehensive tools for interacting with Plane. All tools use Pydantic models from the Plane SDK for type safety and validation.
Community Edition availability
Set PLANE_MCP_EDITION=community to prevent unavailable tools from being
advertised to an agent. This keeps the MCP tool list focused on functionality
that exists on the free, self-hosted edition instead of returning cryptic 404
errors. The detailed endpoint evidence is maintained in CE_COMPAT.md.
| Capability group | Available in CE mode | Notes |
|---|---|---|
| Projects, members, cycles, modules, labels, states, intake items | Yes | CE-compatible endpoints, including the CE fallback for *-lite lists. |
| Work items, search, activities, comments, links, attachments | Yes | Detail reads automatically expand assignees and labels. list_work_items deliberately does not expose pql in CE mode: the CE API silently ignores it. |
| Work item relations | Partial | Listing and creating the eight built-in relation types work; CE stable exposes no deletion route. |
| Work item property definitions and options | Partial | Definition tools remain exposed; per-item property values are not available. |
| Feature flags, roles, initiatives, milestones | No | Cloud-only / paid API surface. |
| Work logs, estimates | No | Endpoints are absent from the tested CE API. |
| Work item archive/unarchive, archived work items | Session | Absent from the public API; reachable through the app API when app-session credentials are configured (see below). |
| Project pages | Session | Root-project pages can create, retrieve, rename, update HTML, archive, unarchive, and delete archived pages through the app API. Workspace pages and work-item↔page links have no CE route. |
| Work item types, custom relation definitions | No | Endpoints are absent from the tested CE API. |
The category tables below describe the full SDK surface. Rows marked No or Partial above are deliberately omitted from MCP discovery in Community Edition mode. Rows marked Session are hidden by default and exposed only when app-session credentials are set.
Session-only capabilities (Community Edition)
A few things exist on a self-hosted CE instance but are served only by the
internal app API (/api/…, no /v1), which uses a browser session and
rejects a personal access token with 401: work-item archive/unarchive
(and listing archived items) and project pages.
Provide app-session credentials to unlock them. The MCP then logs in like the
web app (CSRF + /auth/sign-in/), reuses the session cookie, and routes only
these tools through the app API; everything else keeps using your PAT. On Plane
Cloud these variables are ignored.
# either email + password …
export PLANE_SESSION_EMAIL="you@example.com"
export PLANE_SESSION_PASSWORD="your-password"
# … or a pre-obtained session cookie (keeps the password out of the environment)
export PLANE_SESSION_COOKIE="<session-id cookie value>"
To get the cookie: log into your CE instance in the browser, then copy the
session-id value from DevTools → Application → Cookies. It expires when you
log out or the session is invalidated — when the pages and archive tools start
returning 401, copy a fresh one. Email + password avoids expiry but places
your full account credentials in the environment; prefer the cookie.
Pages available with a session are deliberately small and predictable:
| Tool | CE behavior |
|---|---|
create_page |
Creates a project page, writes description_html, then reads it back. |
update_page / update_page_content |
Rename a root-project page or replace its HTML content. |
archive_page / unarchive_page |
Archive or restore a root-project page and return the read-back page. |
delete_page |
Deletes an already archived project page. Archive first; CE rejects deletion of active pages. |
Notes:
- These credentials are your full user login (the app API is more privileged
than a scoped PAT). Prefer
PLANE_SESSION_COOKIEwhere possible. - Only project pages are available; workspace-level pages and work-item↔page links have no CE endpoint and stay hidden.
- Page writes are conservative: they are never automatically replayed. A 4xx means the request was rejected; a 5xx or transport failure may be ambiguous, so retrieve the page before retrying.
- These four mutations are CE-only and intentionally do not appear in Cloud
discovery:
update_page,update_page_content,archive_page, andunarchive_page. Cloud retainsdelete_pagethrough the SDK. - Without these variables, the affected tools stay hidden in CE mode (no cryptic 404s). The endpoint evidence is in CE_COMPAT.md.
Projects
| Tool Name | Description |
|---|---|
list_projects |
List all projects in a workspace with optional pagination and filtering |
create_project |
Create a new project with name, identifier, and optional configuration |
retrieve_project |
Retrieve a project by ID |
update_project |
Update a project with partial data |
delete_project |
Delete a project by ID |
get_project_worklog_summary |
Get work log summary for a project |
get_project_members |
Get all members of a project |
update_project_features |
Update features configuration of a project |
Work Items
| Tool Name | Description |
|---|---|
list_work_items |
List all work items in a project with pagination. In Community Edition mode, server-side PQL filtering is unavailable and is not exposed to agents. |
create_work_item |
Create a new work item with name, assignees, labels, and other attributes |
retrieve_work_item |
Retrieve a work item by ID with optional field expansion |
retrieve_work_item_by_identifier |
Retrieve a work item by project identifier and issue sequence number |
update_work_item |
Update a work item with partial data |
delete_work_item |
Delete a work item by ID |
search_work_items |
Search work items across a workspace with query string |
Cycles
| Tool Name | Description |
|---|---|
list_cycles |
List cycles in a project (set archived=true for archived) |
create_cycle |
Create a new cycle with name, dates, and owner |
retrieve_cycle |
Retrieve a cycle by ID |
update_cycle |
Update a cycle with partial data |
delete_cycle |
Delete a cycle by ID |
manage_cycle_work_items |
Add and/or remove work items on a cycle |
list_cycle_work_items |
List work items in a cycle |
transfer_cycle_work_items |
Transfer work items from one cycle to another |
manage_cycle_archive |
Archive or unarchive a cycle |
Modules
| Tool Name | Description |
|---|---|
list_modules |
List modules in a project (set archived=true for archived) |
create_module |
Create a new module with name, dates, status, and members |
retrieve_module |
Retrieve a module by ID |
update_module |
Update a module with partial data |
delete_module |
Delete a module by ID |
manage_module_work_items |
Add and/or remove work items on a module |
list_module_work_items |
List work items in a module |
manage_module_archive |
Archive or unarchive a module |
Initiatives
| Tool Name | Description |
|---|---|
list_initiatives |
List all initiatives in a workspace |
create_initiative |
Create a new initiative with name, dates, state, and lead |
retrieve_initiative |
Retrieve an initiative by ID |
update_initiative |
Update an initiative with partial data |
delete_initiative |
Delete an initiative by ID |
Intake Work Items
| Tool Name | Description |
|---|---|
list_intake_work_items |
List all intake work items in a project with optional pagination |
create_intake_work_item |
Create a new intake work item in a project |
retrieve_intake_work_item |
Retrieve an intake work item by work item ID with optional field expansion |
update_intake_work_item |
Update an intake work item with partial data |
delete_intake_work_item |
Delete an intake work item by work item ID |
Work Item Properties
| Tool Name | Description |
|---|---|
list_work_item_properties |
List work item properties for a work item type |
create_work_item_property |
Create a new work item property with type, settings, and validation rules |
retrieve_work_item_property |
Retrieve a work item property by ID |
update_work_item_property |
Update a work item property with partial data |
delete_work_item_property |
Delete a work item property by ID |
Milestones
| Tool Name | Description |
|---|---|
list_milestones |
List all milestones in a project |
create_milestone |
Create a new milestone |
retrieve_milestone |
Retrieve a milestone by ID |
update_milestone |
Update a milestone by ID |
delete_milestone |
Delete a milestone by ID |
manage_milestone_work_items |
Add and/or remove work items on a milestone |
list_milestone_work_items |
List work items in a milestone |
Labels
| Tool Name | Description |
|---|---|
list_labels |
List all labels in a project |
create_label |
Create a new label |
retrieve_label |
Retrieve a label by ID |
update_label |
Update a label by ID |
delete_label |
Delete a label by ID |
States
| Tool Name | Description |
|---|---|
list_states |
List all states in a project |
create_state |
Create a new state |
retrieve_state |
Retrieve a state by ID |
update_state |
Update a state by ID |
delete_state |
Delete a state by ID |
Work Item Comments
| Tool Name | Description |
|---|---|
list_work_item_comments |
List comments for a work item |
retrieve_work_item_comment |
Retrieve a specific comment for a work item |
create_work_item_comment |
Create a comment for a work item |
update_work_item_comment |
Update a comment for a work item |
delete_work_item_comment |
Delete a comment for a work item |
Work Item Links
| Tool Name | Description |
|---|---|
list_work_item_links |
List links for a work item |
retrieve_work_item_link |
Retrieve a specific link for a work item |
create_work_item_link |
Create a link for a work item |
update_work_item_link |
Update a link for a work item |
delete_work_item_link |
Delete a link for a work item |
Work Item Types
| Tool Name | Description |
|---|---|
list_work_item_types |
List all work item types in a project |
create_work_item_type |
Create a new work item type |
retrieve_work_item_type |
Retrieve a work item type by ID |
update_work_item_type |
Update a work item type by ID |
delete_work_item_type |
Delete a work item type by ID |
import_work_item_types_to_project |
Bulk-link workspace-level work item types to a project |
resolve_work_item_type |
Find or create a named type for a project, auto-handling workspace vs project scope and import |
Work Item Relations
| Tool Name | Description |
|---|---|
list_work_item_relations |
List relations for a work item |
create_work_item_relation |
Create relations for a work item |
remove_work_item_relation |
Remove a relation from a work item |
Work Item Relation Definitions
| Tool Name | Description |
|---|---|
list_work_item_relation_definitions |
List workspace custom relation definitions |
create_work_item_relation_definition |
Create a workspace relation definition |
update_work_item_relation_definition |
Update a relation definition |
delete_work_item_relation_definition |
Delete a relation definition |
Work Item Activities
| Tool Name | Description |
|---|---|
list_work_item_activities |
List activities for a work item |
retrieve_work_item_activity |
Retrieve a specific activity for a work item |
Work Logs
| Tool Name | Description |
|---|---|
list_work_logs |
List work logs for a work item |
create_work_log |
Create a work log for a work item |
update_work_log |
Update a work log for a work item |
delete_work_log |
Delete a work log for a work item |
Pages
| Tool Name | Description |
|---|---|
list_pages |
List pages (workspace, or a project's if project_id given) |
retrieve_page |
Retrieve a page by ID (workspace, or project's if project_id given) |
create_page |
Create a workspace or project page |
Workspaces
| Tool Name | Description |
|---|---|
get_workspace_members |
Get all members of the current workspace |
get_features |
Get feature flags (workspace, or a project's if project_id given) |
update_workspace_features |
Update features of the current workspace |
Users
| Tool Name | Description |
|---|---|
get_me |
Get current authenticated user information |
Total Tools: 100+ tools across 20 categories
Development
Running Tests
pytest
Code Formatting
black plane_mcp/
ruff check plane_mcp/
License
MIT License - see LICENSE for details.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
Deprecation Notice
⚠️ The Node.js-based plane-mcp-server is deprecated and no longer maintained.
This repository represents the new Python+FastMCP based implementation of the Plane MCP server. If you were using the previous Node.js version, please migrate to this Python-based version for continued support and updates.
The new implementation offers:
- Better type safety with Pydantic models
- Improved performance with FastMCP
- Enhanced tool coverage
- Active maintenance and development
For migration assistance, please refer to the configuration examples in this README or open an issue for support.
Old Node.js Configuration (Deprecated):
If you were using the previous Node.js-based @makeplane/plane-mcp-server, your configuration looked like this:
{
"mcpServers": {
"plane": {
"command": "npx",
"args": [
"-y",
"@makeplane/plane-mcp-server"
],
"env": {
"PLANE_API_KEY": "<YOUR_API_KEY>",
"PLANE_API_HOST_URL": "<HOST_URL_FOR_SELF_HOSTED>",
"PLANE_WORKSPACE_SLUG": "<YOUR_WORKSPACE_SLUG>"
}
}
}
}
Please migrate to the new Python-based configuration shown in the Usage section above.
Releasing plane-community-mcp
Maintainers should follow RELEASING.md. The PyPI distribution
is plane-community-mcp; the executable remains plane-mcp-server-ce.
Publishing uses PyPI Trusted Publishing, so no PyPI token is stored in this
repository.
Release files for plane-community-mcp 0.6.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| plane_community_mcp-0.6.0.tar.gz | 67.5 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| plane_community_mcp-0.6.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 143.3 kB
Release files / plane_community_mcp-0.6.0.tar.gz
| Download URL | plane_community_mcp-0.6.0.tar.gz |
|---|---|
| Size | 67.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
9e988b459f4e2b92be25d0f44006a0154fc17b8d0553895c096b3c1e01256180
|
|
BLAKE2b-256 checksum How to use checksums |
6ee24824c6b461970c198f49b1be7b4af659be9d6b6c5e8aadbe7d0f6f037da0
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency logRelease files / plane_community_mcp-0.6.0-py3-none-any.whl
| Download URL | plane_community_mcp-0.6.0-py3-none-any.whl |
|---|---|
| Size | 75.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
e405d500262820cd439f8cdbb3e3a87f395761334ad3d8f0f2d3360a271f7057
|
|
BLAKE2b-256 checksum How to use checksums |
38d3198b0755cdafc624fe221a00d294d4c6d6e121417060191f276675cc5e1b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 4, 2026.
Transparency log