Skip to content
Agentic Control Plane

Plane MCP server: setup, tools, auth and read-only use

David Crowe David Crowe · · Updated · 13 min read
plane mcp mcp-controls reference
Share X HN LinkedIn

The Plane MCP server is the official Model Context Protocol server for Plane, the open-source project-management tool. It lets an agent read and change projects, work items, cycles, modules, pages and more in your Plane workspace. Plane publishes it as makeplane/plane-mcp-server and also runs it hosted at https://mcp.plane.so/http/mcp.

Below: endpoints, auth, config for Claude Code, Codex, Cursor and ChatGPT, what the tools can change, and how to stop it changing more than you want. Details are as of 2026-11-07 and come from Plane’s docs and repo.

Official or community

The official server is the Python package plane-mcp-server in the makeplane GitHub org, MIT licensed, built on FastMCP and Plane’s plane-sdk. It needs Python 3.10+ and uv when you run it locally.

The older Node package @makeplane/plane-mcp-server is, in the repo’s words, deprecated and unmaintained. If an old blog post tells you to npx @makeplane/plane-mcp-server, use the Python server instead. If you migrate, rename PLANE_API_HOST_URL to PLANE_BASE_URL.

Endpoints

From Plane’s MCP server docs:

Transport Endpoint Auth
Streamable HTTP (recommended) https://mcp.plane.so/http/mcp OAuth
Streamable HTTP https://mcp.plane.so/http/api-key/mcp Personal or workspace access token
Local stdio uvx plane-mcp-server stdio PLANE_API_KEY + PLANE_WORKSPACE_SLUG
SSE https://mcp.plane.so/sse Deprecated

Auth: API key and workspace slug

OAuth. Your client sends you to Plane, you sign in and pick a workspace, and the connection is bound to that workspace. OAuth requests read and write scopes.

Access token. Create one under Profile Settings → Personal Access Tokens, or Workspace Settings → Access Tokens for automations. Every request carries two headers:

Authorization: Bearer <PAT>
x-workspace-slug: <workspace-slug>

The workspace slug is the path segment after app.plane.so/. Plane’s docs flag that the server now reads the standard Authorization: Bearer header, so configs that sent the token another way need updating.

Local stdio. Two required environment variables and one optional:

Variable Required Meaning
PLANE_API_KEY yes Your access token
PLANE_WORKSPACE_SLUG yes The workspace to act in
PLANE_BASE_URL no Defaults to https://api.plane.so; set it for self-hosted Plane

Whatever the method, the server acts as the authenticated user. Plane’s docs: “Plane enforces workspace and project roles, so a Guest cannot do more through MCP.”

Connect it to Claude Code

OAuth, then sign in from inside Claude Code with /mcp (or claude mcp login plane):

claude mcp add --transport http plane https://mcp.plane.so/http/mcp

Access token. The --header flags go after the URL:

claude mcp add --transport http plane https://mcp.plane.so/http/api-key/mcp \
  --header "Authorization: Bearer <PAT>" \
  --header "x-workspace-slug: <workspace-slug>"

Local stdio:

claude mcp add --transport stdio plane \
  --env PLANE_API_KEY=<your-api-key> \
  --env PLANE_WORKSPACE_SLUG=<your-workspace-slug> \
  -- uvx plane-mcp-server stdio

Add --scope local, project or user to choose where the entry is saved. Check it with claude mcp list.

Connect it to Codex

OAuth:

codex mcp add plane --url https://mcp.plane.so/http/mcp
codex mcp login plane
codex mcp list

Access token, in ~/.codex/config.toml. Codex sends Authorization: Bearer $PLANE_PAT; other headers are config-file only:

[mcp_servers.plane]
url = "https://mcp.plane.so/http/api-key/mcp"
bearer_token_env_var = "PLANE_PAT"
http_headers = { "x-workspace-slug" = "<workspace-slug>" }

Connect it to Cursor

In ~/.cursor/mcp.json. Remote entries use url and must not include a type key.

{
  "mcpServers": {
    "plane": {
      "url": "https://mcp.plane.so/http/mcp"
    }
  }
}

Access token:

{
  "mcpServers": {
    "plane": {
      "url": "https://mcp.plane.so/http/api-key/mcp",
      "headers": {
        "Authorization": "Bearer ${env:PLANE_PAT}",
        "x-workspace-slug": "<workspace-slug>"
      }
    }
  }
}

Connect it to ChatGPT

Turn on Developer mode, then add a connector at chatgpt.com/plugins with the OAuth URL https://mcp.plane.so/http/mcp. Plane’s docs: “ChatGPT does not accept custom headers, so use OAuth.”

Any other client

The generic stdio entry, from the repo README:

{
  "mcpServers": {
    "plane": {
      "command": "uvx",
      "args": ["plane-mcp-server", "stdio"],
      "env": {
        "PLANE_API_KEY": "<your-api-key>",
        "PLANE_WORKSPACE_SLUG": "<your-workspace-slug>"
      }
    }
  }
}

A stdio-only client can reach the hosted server through mcp-remote (Node.js 22+):

{
  "mcpServers": {
    "plane": {
      "command": "npx",
      "args": ["mcp-remote@latest", "https://mcp.plane.so/http/mcp"]
    }
  }
}

Windsurf and Antigravity use serverUrl instead of url. VS Code uses .vscode/mcp.json with a servers key and "type": "http".

The tools it exposes

Since 0.3 the server exposes 30 tools, one per Plane resource, covering 207 operations. Each tool takes an action parameter. Creating a work item looks like workitem(action="create", project_id=..., name="Fix login").

The tool names, from the tools README:

Area Tools
Work items workitem, workitem_comment, workitem_link, workitem_relation, workitem_attachment, workitem_activity, workitem_property, workitem_type, work_log, label, state, intake
Planning cycle, module, milestone, initiative, project_estimate
Releases release, release_label, release_tag
Projects and workspace project, workspace, member, template
Docs page, collection
Customers customer, customer_property, customer_request
Query help get_pql_reference

There are no epic tools. Epics are work items of type “Epic”: resolve the type with workitem_type, then create or list with that type id.

If your config or prompts use the 0.2.x per-operation names (create_work_item, list_cycles and so on), 169 of the 177 old names still resolve as aliases. The other seven return a message naming their replacement.

What it can change versus read

Almost every tool can write. The workitem tool alone has list, retrieve, search and count, and also create, update, delete and archive. project can delete and archive projects. cycle can complete and transfer_workitems. page, module, release and the customer tools all have delete.

Three tools are read-only by their action list: get_pql_reference, workitem_activity (list, retrieve) and member (me, list_workspace, list_project, list_roles, retrieve_role).

Each action is declared with flags such as read=True or destructive=True, and the server derives its MCP annotations from them. Plane’s docs say read-only tools carry the readOnlyHint annotation and destructive ones carry destructiveHint.

Run it read-only or scoped to one project

Plane’s docs say it outright: “There is no separate read-only endpoint.” Your options, strongest first:

1. Use a role-limited Plane account. The server can do only what the authenticated user can do. A dedicated account with a Guest role, or with membership in only one project, caps what any agent can reach. Plane recommends a workspace access token “with the minimum role needed for automations.” This is also the only way to scope to one project: there is no per-project setting on the connection. OAuth binds one workspace, and a token connection is scoped by its x-workspace-slug.

2. Filter tools in the client. This works at tool level, and since one tool holds both reads and deletes, denying workitem removes work items entirely.

Claude Code accepts a deny or ask rule for a whole server or one tool. To be asked before any Plane call:

{
  "permissions": {
    "ask": ["mcp__plane__*"]
  }
}

To block one action rather than the whole tool, Claude Code’s permissions docs say parameter rules on MCP tools must be passed with --disallowedTools; settings files skip any mcp__ rule that has parentheses:

claude --disallowedTools "mcp__plane__workitem(action:delete)"

Codex has an allow list, a deny list and approval modes per server (Codex MCP docs):

[mcp_servers.plane]
url = "https://mcp.plane.so/http/mcp"
enabled_tools = ["workitem", "cycle", "get_pql_reference", "member"]
disabled_tools = ["project"]
default_tools_approval_mode = "writes"

writes prompts only for tools not marked read-only. With Plane’s mixed tools, expect that to mean most calls prompt.

3. Turn the server off when you are not using it. enabled = false in Codex, or remove the entry.

Self-hosted Plane

The hosted server cannot reach a private instance. Run stdio with PLANE_BASE_URL pointing at your API, or deploy the server yourself. Check your key first:

curl -H "x-api-key: $PLANE_API_KEY" "https://plane.yourcompany.com/api/v1/users/me/"

A 200 means the key works. Plane’s docs say OAuth self-hosting needs Plane Cloud or Commercial Edition; Community Edition should use stdio.

Common errors

Symptom Cause Fix
401 on a token connection Wrong or revoked token, or old header Send Authorization: Bearer <PAT>
401 on OAuth Session expired Re-authenticate (/mcp in Claude Code, codex mcp login plane)
“workspace slug missing” Header left out Add x-workspace-slug
404 Wrong slug or id Check the segment after app.plane.so/
403 Your Plane role is too low Ask for the needed workspace or project role
402 Plan-gated feature The message names the feature
400 Bad argument Check the action’s required fields
mcp-remote won’t start Old Node Node.js 22+ and npx -y mcp-remote@latest
Server not listed Bad JSON or wrong schema Trailing commas; url vs serverUrl; no type in Cursor
Only the first page of projects Pagination Follow next_cursor or pass per_page

For a stuck OAuth session through mcp-remote, rm -rf ~/.mcp-auth clears it, along with every other mcp-remote cache. Set MCP_REMOTE_CONFIG_DIR to keep Plane’s separate. To debug, claude --debug and claude mcp list show what Claude Code loaded.

What this does not cover

Client-side tool filters live in each agent’s own config. A filter written for Claude Code does nothing in Cursor, and Plane’s role model is the only limit that holds across every client. If you run ACP, its rules can allow, ask or deny an MCP tool by name, with the same rule on every harness whose hook sees MCP calls and one log of each call. See the coverage table for which harnesses those are. That is still tool-level, so it has the same limit as above: workitem is one tool, reads and deletes together. For how Plane’s controls compare with other MCP servers, see /mcp-controls.

Frequently asked questions

plane mcp server: is there an official one?

Yes. Plane publishes it as makeplane/plane-mcp-server on GitHub, a Python server run with uvx or used hosted at https://mcp.plane.so/http/mcp. The older Node package @makeplane/plane-mcp-server is deprecated and unmaintained.

plane mcp claude code: what is the command?

For OAuth: claude mcp add –transport http plane https://mcp.plane.so/http/mcp, then run /mcp in Claude Code to sign in. For a personal access token, point the same command at https://mcp.plane.so/http/api-key/mcp and add –header “Authorization: Bearer " and --header "x-workspace-slug: " after the URL.

Can I run the Plane MCP server read-only?

There is no read-only endpoint. Plane’s docs point you to your client’s tool allow-list or deny-list. Since 0.3 each tool bundles reads and writes behind an action parameter, so a tool-level deny removes a whole resource; a role-limited Plane account is the cleaner way to cap writes.

mcp plane: why do I get 401 or 'workspace slug missing'?

A 401 on a token connection means a wrong or revoked token, or the old header: send Authorization: Bearer . A 401 on OAuth means the session expired, so re-authenticate. 'Workspace slug missing' means you left out the x-workspace-slug header.

Where to read more

Running coding agents? ACP records each tool call its hook sees and makes the dangerous shell commands (a force-push, destructive SQL, curl | sh) wait for you. One command, free up to 5 agents:

macOS · Linux · WSL
curl -fsSL https://agenticcontrolplane.com/install.sh | bash
Windows · PowerShell
irm https://agenticcontrolplane.com/install.ps1 | iex

What the installer writes  ·  Getting started

Share X HN LinkedIn
Get the next data drop
What agents actually cost, new tool-surface captures, and the occasional incident post-mortem — sent when we publish something worth your inbox, not on a schedule. Unsubscribe anytime.
Share: Twitter LinkedIn
Related posts

← back to blog