Skip to main content
Glama
bhflm

plane-mcp

by bhflm

plane-mcp

Local MCP server for a self-hosted Plane instance. Exposes tickets (work items), cycles, modules, labels, and states as MCP tools, plus a small set of mutation tools (label add/remove, state changes, ticket create/update, module attach).

The Plane API key is read only from the PLANE_API_KEY environment variable. It is never logged, never printed, and never included in tool output — errors are redacted before being returned.

Setup

npm install
npm run build

export PLANE_BASE_URL="https://your-plane-instance.example.com"
export PLANE_API_KEY="..."
export PLANE_DEFAULT_WORKSPACE="..."          # optional
export PLANE_DEFAULT_PROJECT_ID="..."         # optional
export PLANE_DEFAULT_PROJECT_IDENTIFIER="..." # optional
export PLANE_ENABLE_WRITES="false"            # optional; must be true for mutations

Copy .env.example to .env for reference (placeholders only — never commit a real .env).

Related MCP server: plane-mcp-server

Run

npm start
# or during development:
npm run dev

The server speaks MCP over stdio.

MCP client config (stdio)

{
  "mcpServers": {
    "plane": {
      "command": "node",
      "args": ["/absolute/path/to/plane-mcp/dist/src/index.js"],
      "env": {
        "PLANE_BASE_URL": "https://your-plane-instance.example.com",
        "PLANE_API_KEY": "${PLANE_API_KEY}",
        "PLANE_DEFAULT_WORKSPACE": "${PLANE_DEFAULT_WORKSPACE}",
        "PLANE_DEFAULT_PROJECT_ID": "${PLANE_DEFAULT_PROJECT_ID}",
        "PLANE_ENABLE_WRITES": "false"
      }
    }
  }
}

Exposed tools

Tool

Purpose

plane_list_workspaces

List accessible workspaces

plane_list_projects

List projects in a workspace

plane_resolve_project

Resolve a project identifier (e.g. SDK) to its UUID

plane_search_tickets

Search work items by query/key

plane_get_ticket

Fetch a full ticket by UUID or key (e.g. SDK-250)

plane_list_cycles

List cycles (sprints/milestones)

plane_get_current_cycle

Fetch the current active cycle

plane_list_cycle_tickets

List tickets in a cycle

plane_list_current_cycle_tickets

One-shot "what's in the current cycle"; link summaries by default

plane_list_modules

List modules (epics/milestones)

plane_list_module_tickets

List tickets in a module

plane_list_labels

List labels for a project

plane_add_labels_to_ticket

Add labels without clobbering existing ones

plane_remove_labels_from_ticket

Remove labels from a ticket

plane_update_ticket

Patch basic ticket fields

plane_add_comment

Add a comment to a ticket/work item

plane_list_states

List states/statuses

plane_set_ticket_state

Move a ticket to a state by name or id

plane_create_ticket

Create a ticket, optionally attach to cycle/module

plane_add_ticket_to_module

Attach an existing ticket to a module

plane_get_ticket_children

List child tickets by filtering on parent

Tools return normalized, allowlisted summaries rather than raw Plane API records. Mutating tools accept dry_run: boolean for previews. Real writes are disabled unless PLANE_ENABLE_WRITES=true is set, and each mutating call must also pass confirm: true; successful ticket updates are verified by re-fetching the record afterward, while comment creation returns the created comment from Plane.

plane_add_comment accepts either comment_text or comment_html. comment_text is escaped and converted to simple paragraph HTML before it is sent to Plane. Comments default to access: "INTERNAL" unless supplied.

Testing

npm test

Unit tests mock fetch — no real Plane API key is required. Coverage includes: auth header presence without leaking the key, redaction of secrets from errors and result payloads, safe path construction, bounded cursor pagination, schema limits, ticket-key normalization, and label-union (non-clobbering) behavior.

Smoke test

With real credentials exported (see Setup), you can drive the server directly with the MCP inspector, or manually via any MCP-compatible client pointed at node dist/src/index.js. A minimal manual check:

node --input-type=module -e "
import { PlaneClient } from './dist/src/planeClient.js';
const client = new PlaneClient({
  baseUrl: process.env.PLANE_BASE_URL,
  apiKey: process.env.PLANE_API_KEY,
  defaultWorkspace: process.env.PLANE_DEFAULT_WORKSPACE,
});
console.log(await client.paginate('/api/v1/workspaces/'));
"

Known quirks (self-hosted Plane)

  • GET /api/v1/workspaces/ may 404 (no cross-workspace listing endpoint on some self-hosted deployments). Set PLANE_DEFAULT_WORKSPACE and use workspace-scoped tools directly instead of relying on plane_list_workspaces.

  • Advanced search may return no results when project_id is included; the client retries workspace-wide and filters client-side.

  • Cycle-issue and module-issue list endpoints may return link objects ({ issue: <uuid> }) rather than full ticket records. Current-cycle tools keep link summaries by default; pass include_full_tickets: true to join normalized ticket summaries.

Security

  • Credentials are read only from environment variables (PLANE_API_KEY, PLANE_BASE_URL).

  • The API key is never printed, logged, or embedded in responses.

  • Errors (HTTP failures, network failures, JSON parse failures) are passed through a redactor before being surfaced to the MCP client.

  • Tool arguments used in Plane URL paths are validated and encoded before request construction.

  • Tool outputs are allowlisted and redacted; raw Plane API records are not returned to MCP clients.

  • Writes are off by default and require both PLANE_ENABLE_WRITES=true and confirm: true on each mutating call.

  • .env is gitignored; only .env.example with placeholders is committed.

Related MCP Connectors

Related MCP Servers

  • A
    license
    B
    quality
    D
    maintenance
    An MCP server that enables LLMs to fully manage a Plane workspace, including projects, work items, states, labels, cycles, modules, comments, and members.
    38
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Unofficial MCP server for self-hosted Plane Community Edition, enabling project management tasks like managing work items, cycles, modules, and initiatives via natural language.
    100
    2
    MIT