diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index 2b58f947..4b819c4c 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -1040,7 +1040,10 @@ export default extendConfig(
text: "MCP Server",
link: "/dev-tools/mcp-server",
collapsed: false,
- items: [{ text: "For Claude Code", link: "/dev-tools/mcp-server-claude-code" }],
+ items: [
+ { text: "Self-host MCP Server", link: "/dev-tools/mcp-server-self-host" },
+ { text: "Tool Reference", link: "/dev-tools/mcp-server-tools" },
+ ],
},
{ text: "Plane Compose", link: "/dev-tools/plane-compose" },
{ text: "OpenAPI Specification", link: "/dev-tools/openapi-specification" },
diff --git a/docs/dev-tools/mcp-server-claude-code.md b/docs/dev-tools/mcp-server-claude-code.md
deleted file mode 100644
index 8d1924b7..00000000
--- a/docs/dev-tools/mcp-server-claude-code.md
+++ /dev/null
@@ -1,284 +0,0 @@
----
-title: MCP Server for Claude Code
-description: Install and use the Plane MCP Server with Claude Code CLI. Manage work items, projects, cycles, and modules from your terminal with AI.
-keywords: plane, mcp server, claude code, cli, ai, project management, work items, developer tools
----
-
-# MCP Server for Claude Code
-
-[Claude Code](https://docs.anthropic.com/en/docs/claude-code) is Anthropic's CLI tool for agentic
-coding. By connecting the Plane MCP Server to Claude Code, you can manage your Plane workspace
-directly from the terminal — create work items, plan cycles, search across projects, and more,
-all through natural language.
-
-
-Beta
-The Plane MCP Server is currently in **Beta**. Some aspects of the API may change. Please send any
-issues to support@plane.so.
-
-
-## Prerequisites
-
-- **Claude Code**: [Install Claude Code](https://docs.anthropic.com/en/docs/claude-code/getting-started) if you haven't already.
-- **Node.js 22+**: Required for HTTP transports. Verify with `node --version`.
-- **Python 3.10+** and **uvx**: Required only for the local Stdio transport. Verify with `python --version` and `uvx --version`.
-- **Plane API Key**: For PAT or Stdio transports, generate one from **Workspace Settings > API Tokens** in Plane.
-
-## Setup methods
-
-Choose the transport method that fits your setup.
-
-| Method | Best for | Auth |
-| ------------------------------------- | ---------------------------- | --------------------- |
-| [HTTP with OAuth](#http-with-oauth) | Plane Cloud, interactive use | Browser-based OAuth |
-| [HTTP with PAT](#http-with-pat-token) | CI/CD, automated workflows | API key in headers |
-| [Local Stdio](#local-stdio) | Self-hosted Plane instances | Environment variables |
-
-## HTTP with OAuth
-
-The simplest way to connect to Plane Cloud. Run this in your terminal:
-
-```bash
-claude mcp add --transport http plane https://mcp.plane.so/http/mcp
-```
-
-After adding the server, start Claude Code and run `/mcp` to authenticate via your browser.
-
-## HTTP with PAT token
-
-For automated workflows or when you prefer token-based auth:
-
-```bash
-claude mcp add-json plane '{
- "type": "http",
- "url": "https://mcp.plane.so/http/api-key/mcp",
- "headers": {
- "Authorization": "Bearer ",
- "X-Workspace-slug": ""
- }
-}'
-```
-
-Replace `` and `` with your actual values.
-
-## Local Stdio
-
-For self-hosted Plane instances, use the Stdio transport which runs locally:
-
-```bash
-claude mcp add-json plane '{
- "type": "stdio",
- "command": "uvx",
- "args": ["plane-mcp-server", "stdio"],
- "env": {
- "PLANE_API_KEY": "",
- "PLANE_WORKSPACE_SLUG": "",
- "PLANE_BASE_URL": "https://your-plane-instance.com"
- }
-}'
-```
-
-### Environment variables
-
-| Variable | Required | Description |
-| ---------------------- | -------- | --------------------------------------------------------------------- |
-| `PLANE_API_KEY` | Yes | API key from your workspace settings |
-| `PLANE_WORKSPACE_SLUG` | Yes | Your workspace slug (found in your Plane URL) |
-| `PLANE_BASE_URL` | No | API URL for self-hosted instances. Defaults to `https://api.plane.so` |
-
-## Scope options
-
-Control where the MCP server configuration is stored by adding a `--scope` flag:
-
-```bash
-# Available only to you in the current project (default)
-claude mcp add --scope local --transport http plane https://mcp.plane.so/http/mcp
-
-# Shared via .mcp.json, committed to version control
-claude mcp add --scope project --transport http plane https://mcp.plane.so/http/mcp
-
-# Available across all your projects
-claude mcp add --scope user --transport http plane https://mcp.plane.so/http/mcp
-```
-
-## Verify the connection
-
-After setup, verify the Plane MCP Server is connected:
-
-```bash
-# List all configured MCP servers
-claude mcp list
-
-# Get details for the Plane server
-claude mcp get plane
-```
-
-Inside Claude Code, run `/mcp` to check the server status and see the available tools.
-
-## Available tools
-
-The Plane MCP Server exposes 55+ tools across these categories:
-
-| Category | Tools | Examples |
-| ------------------------ | ----- | --------------------------------------------------------------- |
-| **Projects** | 9 | List, create, update, delete projects; get members and features |
-| **Work Items** | 7 | Create, list, search, update, delete work items |
-| **Cycles** | 12 | Manage cycles, add/remove work items, transfer, archive |
-| **Modules** | 11 | Manage modules, add/remove work items, archive |
-| **Initiatives** | 5 | Create and manage workspace-level initiatives |
-| **Intake** | 5 | Manage intake work items for triage |
-| **Work Item Properties** | 5 | Manage custom properties on work items |
-| **Users** | 1 | Get current authenticated user info |
-
-## Examples
-
-Here are common tasks you can perform by chatting with Claude Code after connecting the Plane MCP Server.
-
-### List projects in your workspace
-
-**Prompt:**
-
-```
-List all projects in my workspace.
-```
-
-Claude Code calls `list_projects` and returns a summary of all projects including their identifiers, lead, and status.
-
-### Create a work item
-
-**Prompt:**
-
-```
-Create a bug in project WEB titled "Fix login redirect loop" and assign it to me.
-```
-
-Claude Code calls `get_me` to find your user ID, then `create_work_item` with the project ID, name, and assignee.
-
-### Search across work items
-
-**Prompt:**
-
-```
-Search for work items related to "authentication" across the workspace.
-```
-
-Claude Code calls `search_work_items` with the query string and returns matching results from all projects.
-
-### Plan a cycle
-
-**Prompt:**
-
-```
-Create a new cycle called "Sprint 24" in project WEB starting today and
-ending in 2 weeks. Add work items WEB-102, WEB-115, and WEB-118 to it.
-```
-
-Claude Code calls `create_cycle` with the name and dates, then `add_work_items_to_cycle` to attach the specified items.
-
-### Triage intake items
-
-**Prompt:**
-
-```
-Show me all intake items in project MOBILE and accept the ones related to
-crash reports.
-```
-
-Claude Code calls `list_intake_work_items` to retrieve pending items, then `update_intake_work_item` to accept the relevant ones.
-
-### Get a project overview
-
-**Prompt:**
-
-```
-Give me a summary of project BACKEND — what cycles are active, how many
-open work items are there, and who are the members?
-```
-
-Claude Code calls `retrieve_project`, `list_cycles`, `list_work_items`, and `get_project_members` to assemble a full overview.
-
-### Manage modules
-
-**Prompt:**
-
-```
-Create a module called "Auth Revamp" in project WEB and add all work items
-tagged with the "auth" label to it.
-```
-
-Claude Code calls `create_module`, then `list_work_items` with label filtering, and finally `add_work_items_to_module` to associate the items.
-
-### Move work items between cycles
-
-**Prompt:**
-
-```
-Transfer all incomplete work items from "Sprint 23" to "Sprint 24" in
-project WEB.
-```
-
-Claude Code calls `list_cycles` to find both cycle IDs, then `transfer_cycle_work_items` to move unfinished items.
-
-## Managing the server
-
-```bash
-# Remove the Plane MCP server
-claude mcp remove plane
-
-# Re-add with a different transport
-claude mcp add --transport http plane https://mcp.plane.so/http/mcp
-```
-
-## Troubleshooting
-
-### MCP server not connecting
-
-If the server fails to start, launch Claude Code with the debug flag:
-
-```bash
-claude --mcp-debug
-```
-
-This shows detailed logs during MCP server initialization.
-
-### Authentication errors (OAuth)
-
-Clear saved OAuth tokens and re-authenticate:
-
-```bash
-rm -rf ~/.mcp-auth
-```
-
-Then restart Claude Code and run `/mcp` to authenticate again.
-
-### Server timeout on startup
-
-If the MCP server times out during initialization, increase the timeout:
-
-```bash
-MCP_TIMEOUT=10000 claude
-```
-
-This sets a 10-second startup timeout (default is lower).
-
-### Python or Node.js not found
-
-Ensure the required runtime is installed and available on your `PATH`:
-
-```bash
-# For HTTP transports
-node --version # Should be 22+
-
-# For Stdio transport
-python --version # Should be 3.10+
-uvx --version
-```
-
-### Getting help
-
-If issues persist:
-
-1. Check your credentials and workspace slug
-2. Run `claude mcp list` to verify the configuration
-3. Contact support at support@plane.so for Plane-specific issues
-4. Visit the [Plane MCP Server repository](https://github.com/makeplane/plane-mcp-server) for known issues
diff --git a/docs/dev-tools/mcp-server-self-host.md b/docs/dev-tools/mcp-server-self-host.md
new file mode 100644
index 00000000..00134e8d
--- /dev/null
+++ b/docs/dev-tools/mcp-server-self-host.md
@@ -0,0 +1,301 @@
+---
+title: Self-host MCP Server
+description: Deploy your own Plane MCP Server with Docker Compose or Helm. Register an OAuth app, configure credentials, and point AI clients at your own instance.
+keywords: plane mcp server, self-hosted mcp, plane mcp deployment, docker compose mcp, helm mcp, plane oauth mcp, mcp server setup
+---
+
+# Self-host MCP Server
+
+This guide is for teams that want to run their own instance of the Plane MCP Server - either because they're on a self-hosted Plane installation that needs OAuth against their own domain, or because they want full control over the MCP infrastructure.
+
+If you're a Plane Cloud user connecting to `mcp.plane.so`, you don't need this. Use the [MCP Server setup guide](/dev-tools/mcp-server) instead.
+
+## Prerequisites
+
+- A running **Plane instance** (self-hosted or Cloud) with workspace admin access
+- **Docker** and Docker Compose v2+, _or_ **Kubernetes** v1.21+ with Helm v3+
+- A **public URL** for the MCP server (e.g. `https://mcp.yourdomain.com`) - OAuth callbacks must be able to reach it over HTTPS
+
+---
+
+## Register an OAuth app in Plane
+
+The MCP server authenticates users through Plane's OAuth 2.0 system. You need to register an app to get a Client ID and Client Secret.
+
+1. Go to **Workspace Settings → Integrations**:
+
+ ```
+ https:////settings/integrations/
+ ```
+
+2. Click **Build your own**.
+
+3. Fill in the application details:
+
+ | Field | Value |
+ | ---------------- | ---------------------------------------------------------------- |
+ | **App Name** | Anything descriptive (e.g. `Plane MCP Server`) |
+ | **Setup URL** | Your MCP server's public URL (e.g. `https://mcp.yourdomain.com`) |
+ | **Redirect URI** | All three URIs listed below, space-separated |
+ | **Webhook URL** | Leave empty unless you need webhook events |
+
+ ::: tip Add all three redirect URIs
+ The server exposes callbacks on three paths to support all transports and MCP clients:
+
+ | Transport | Redirect URI |
+ | --------------- | ------------------------------------- |
+ | OAuth callback | `/callback` |
+ | HTTP with OAuth | `/http/auth/callback` |
+ | SSE (legacy) | `/auth/callback` |
+
+ For `https://mcp.yourdomain.com`, paste this into the Redirect URI field:
+
+ ```
+ https://mcp.yourdomain.com/callback https://mcp.yourdomain.com/http/auth/callback https://mcp.yourdomain.com/auth/callback
+ ```
+
+ :::
+
+4. Under **Scopes & Permissions**, select both **read** and **write** scopes.
+
+5. Save. Copy the generated **Client ID** and **Client Secret** - you'll need them in the next step.
+
+::: warning
+Never expose the Client Secret in client-side code or commit it to version control.
+:::
+
+For more detail on OAuth app creation, see [Create an OAuth Application](/dev-tools/build-plane-app/create-oauth-application).
+
+---
+
+## Deploy
+
+### Option A: Docker Compose
+
+**1. Create a `docker-compose.yaml`:**
+
+```yaml
+name: plane-mcp
+
+services:
+ mcp:
+ image: makeplane/plane-mcp-server:${APP_RELEASE_VERSION:-latest}
+ restart: always
+ ports:
+ - "8211:8211"
+ env_file:
+ - variables.env
+ environment:
+ REDIS_HOST: valkey
+ REDIS_PORT: "6379"
+ depends_on:
+ valkey:
+ condition: service_healthy
+
+ valkey:
+ image: valkey/valkey:8-alpine
+ restart: always
+ volumes:
+ - valkey-data:/data
+ healthcheck:
+ test: ["CMD", "valkey-cli", "ping"]
+ interval: 5s
+ timeout: 3s
+ retries: 5
+
+volumes:
+ valkey-data:
+```
+
+**2. Create a `variables.env` with your OAuth credentials from Step 1:**
+
+```env
+# Image tag - pin to a specific version in production
+APP_RELEASE_VERSION=latest
+
+# Plane API URL - use your self-hosted instance URL or https://api.plane.so for Cloud
+PLANE_BASE_URL=https://api.plane.so
+
+# Optional: internal URL for server-to-server calls (same-network setups)
+# PLANE_INTERNAL_BASE_URL=
+
+# OAuth credentials from Step 1
+PLANE_OAUTH_PROVIDER_CLIENT_ID=your-client-id
+PLANE_OAUTH_PROVIDER_CLIENT_SECRET=your-client-secret
+
+# Public URL where MCP clients reach this server (must match what you registered in Step 1)
+PLANE_OAUTH_PROVIDER_BASE_URL=https://mcp.yourdomain.com
+```
+
+**3. Start:**
+
+```bash
+docker compose up -d
+```
+
+**4. Verify:**
+
+```bash
+docker compose logs -f mcp # follow startup logs
+curl http://localhost:8211/http/mcp # expect: 401 or MCP protocol response
+```
+
+::: warning Terminate TLS in front of this container
+The container listens on plain HTTP at `:8211`. Put it behind a reverse proxy (nginx, Caddy, Traefik, Cloudflare) that handles TLS. OAuth callbacks will fail without HTTPS, and `PLANE_OAUTH_PROVIDER_BASE_URL` must be the `https://` URL that proxy exposes.
+:::
+
+#### Environment variable reference
+
+| Variable | Required | Description |
+| ------------------------------------ | -------- | ------------------------------------------------------------------------------ |
+| `APP_RELEASE_VERSION` | No | Image tag to deploy. Defaults to `latest`. Pin in production. |
+| `PLANE_BASE_URL` | No | Plane API URL. Defaults to `https://api.plane.so`. |
+| `PLANE_INTERNAL_BASE_URL` | No | Internal Plane URL for server-to-server calls. Falls back to `PLANE_BASE_URL`. |
+| `PLANE_OAUTH_PROVIDER_CLIENT_ID` | Yes | OAuth Client ID from Step 1. |
+| `PLANE_OAUTH_PROVIDER_CLIENT_SECRET` | Yes | OAuth Client Secret from Step 1. |
+| `PLANE_OAUTH_PROVIDER_BASE_URL` | Yes | Public URL of **this MCP server** - not your Plane instance. |
+| `MCP_PATH_PREFIX` | No | Path prefix for all routes. Use when reverse-proxying alongside other apps. |
+
+#### Upgrading
+
+```bash
+docker compose pull
+docker compose up -d
+```
+
+---
+
+### Option B: Helm
+
+**1. Add the Plane Helm repo:**
+
+```bash
+helm repo add plane https://helm.plane.so
+helm repo update
+```
+
+**2. Create a `values.yaml`:**
+
+```yaml
+ingress:
+ enabled: true
+ host: mcp.yourdomain.com
+ ingressClass: nginx
+ ssl:
+ enabled: true
+ issuer: cloudflare # cloudflare | digitalocean | http
+ email: you@yourdomain.com
+
+services:
+ api:
+ plane_base_url: "https://api.plane.so"
+ plane_oauth:
+ enabled: true
+ client_id: ""
+ client_secret: ""
+ provider_base_url: "https://mcp.yourdomain.com"
+```
+
+**3. Install:**
+
+```bash
+helm install plane-mcp plane/plane-mcp-server \
+ --namespace plane-mcp \
+ --create-namespace \
+ -f values.yaml
+```
+
+#### Helm values reference
+
+| Value | Default | Description |
+| -------------------------------------------- | ----------------- | --------------------------------------------------- |
+| `dockerRegistry.default_tag` | `latest` | Image tag to deploy |
+| `ingress.enabled` | `true` | Enable ingress |
+| `ingress.host` | `mcp.example.com` | Public hostname |
+| `ingress.ingressClass` | `nginx` | Ingress class name |
+| `ingress.ssl.enabled` | `false` | Enable TLS via cert-manager |
+| `ingress.ssl.issuer` | `cloudflare` | ACME issuer (`cloudflare`, `digitalocean`, `http`) |
+| `services.api.replicas` | `1` | Number of MCP server replicas |
+| `services.api.plane_base_url` | `""` | Plane API URL |
+| `services.api.plane_oauth.enabled` | `false` | Enable OAuth endpoints |
+| `services.api.plane_oauth.client_id` | `""` | OAuth Client ID |
+| `services.api.plane_oauth.client_secret` | `""` | OAuth Client Secret |
+| `services.api.plane_oauth.provider_base_url` | `""` | Public URL this server is reachable on |
+| `services.redis.local_setup` | `true` | Deploy Valkey in-cluster |
+| `services.redis.external_redis_url` | `""` | External Valkey/Redis URL (if not using in-cluster) |
+
+#### Upgrading
+
+```bash
+helm upgrade plane-mcp plane/plane-mcp-server \
+ --namespace plane-mcp \
+ -f values.yaml
+```
+
+#### Uninstalling
+
+```bash
+helm uninstall plane-mcp --namespace plane-mcp
+```
+
+---
+
+## Connect AI clients
+
+Once the server is running, your available endpoints are:
+
+| Endpoint | Auth | Description |
+| --------------------------------------------- | ---------- | ----------------------------------- |
+| `https://mcp.yourdomain.com/http/mcp` | OAuth | Recommended for most clients |
+| `https://mcp.yourdomain.com/http/api-key/mcp` | PAT header | For CI/CD, scripts, headless setups |
+| `https://mcp.yourdomain.com/sse` | OAuth | Legacy SSE transport (deprecated) |
+
+Client configuration is identical to the [MCP Server setup guide](/dev-tools/mcp-server) - replace `https://mcp.plane.so` with your server's URL in every config snippet.
+
+---
+
+## Troubleshooting
+
+**Server not starting:**
+
+```bash
+docker compose logs mcp
+```
+
+**Valkey not reachable:**
+
+```bash
+docker compose exec valkey valkey-cli ping
+# Expect: PONG
+```
+
+If Valkey is unhealthy, tokens are stored in-memory and lost on restart. Verify `REDIS_HOST` and `REDIS_PORT` are set correctly in your environment.
+
+**OAuth errors:**
+
+- Confirm all three redirect URIs are registered in your Plane OAuth app: `/callback`, `/http/auth/callback`, `/auth/callback`.
+- Check that `PLANE_OAUTH_PROVIDER_CLIENT_ID` and `PLANE_OAUTH_PROVIDER_CLIENT_SECRET` match what Plane generated.
+- Check that `PLANE_OAUTH_PROVIDER_BASE_URL` is the publicly reachable `https://` URL of this MCP server - not your Plane instance URL.
+- Clear any cached auth tokens on the client side:
+
+ ```bash
+ rm -rf ~/.mcp-auth
+ ```
+
+**Reset Docker Compose** (deletes Valkey data):
+
+```bash
+docker compose down -v
+docker compose up -d
+```
+
+**Still stuck:**
+
+1. Double-check OAuth credentials and redirect URIs in Plane workspace settings.
+2. Check the [plane-mcp-server](https://github.com/makeplane/plane-mcp-server) repo for known issues.
+3. Contact support@plane.so.
+
+---
+
+→ For client configuration details, see the [MCP Server setup guide](/dev-tools/mcp-server).
+→ For the full list of available tools, see the [MCP Server Tool Reference](/dev-tools/mcp-server-tools).
diff --git a/docs/dev-tools/mcp-server-tools.md b/docs/dev-tools/mcp-server-tools.md
new file mode 100644
index 00000000..832b7b9d
--- /dev/null
+++ b/docs/dev-tools/mcp-server-tools.md
@@ -0,0 +1,763 @@
+---
+title: MCP Server Tool Reference
+description: Complete reference for all tools exposed by the Plane MCP Server — work items, projects, cycles, modules, worklogs, epics, milestones, and more.
+keywords: plane mcp server, mcp tools, plane api tools, work items mcp, projects mcp, cycles mcp, mcp tool reference
+---
+
+# MCP Server Tool Reference
+
+The Plane MCP Server exposes 100+ tools across 20 modules. All tools are available regardless of transport mode — stdio, HTTP/OAuth, HTTP/PAT, and SSE expose the same set.
+
+For setup and client configuration, see the [MCP Server setup guide](/dev-tools/mcp-server).
+
+---
+
+### Users
+
+#### `get_me`
+
+Returns the profile of the currently authenticated user. No parameters.
+
+---
+
+### Workspaces
+
+#### `get_workspace_members`
+
+Returns all members of the workspace.
+
+#### `get_workspace_features`
+
+Returns enabled features for the workspace.
+
+#### `update_workspace_features`
+
+Updates workspace-level feature flags.
+
+---
+
+### Projects
+
+#### `list_projects`
+
+Returns all projects the current user is a member of.
+
+#### `create_project`
+
+Creates a new project.
+
+| Parameter | Type | Required | Description |
+| ------------- | ------ | -------- | ------------------------------------------------ |
+| `name` | string | **Yes** | Project display name |
+| `identifier` | string | **Yes** | Short uppercase code, max 12 chars (e.g., `ENG`) |
+| `description` | string | No | Project description |
+| `network` | string | No | `0` (secret) or `2` (public) |
+
+#### `retrieve_project`
+
+Returns details of a single project.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `update_project`
+
+Updates project fields. All fields are optional.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| other fields | partial | No |
+
+#### `delete_project`
+
+Deletes a project.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `get_project_worklog_summary`
+
+Returns time-tracking summary for a project.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `get_project_members`
+
+Returns all members of a project.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `get_project_features`
+
+Returns the feature configuration for a project (modules, cycles, pages, etc.).
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `update_project_features`
+
+Updates which features are enabled on a project.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| feature fields | partial | No |
+
+---
+
+### Work Items
+
+#### `list_work_items`
+
+Lists work items in a project, or searches across the workspace when filters are provided.
+
+When any filter parameter is set, the tool uses Plane's advanced search endpoint (supports workspace-wide search). Without filters it uses the standard paginated list endpoint.
+
+| Parameter | Type | Required | Description |
+| ------------------ | ----------- | ----------- | --------------------------------------------------------------- |
+| `project_id` | UUID string | Conditional | Required when no filters are provided |
+| `query` | string | No | Free-text search across name and description |
+| `assignee_ids` | UUID[] | No | Filter by assignee |
+| `state_ids` | UUID[] | No | Filter by state |
+| `state_groups` | string[] | No | `backlog` · `unstarted` · `started` · `completed` · `cancelled` |
+| `priorities` | string[] | No | `urgent` · `high` · `medium` · `low` · `none` |
+| `label_ids` | UUID[] | No | Filter by label |
+| `type_ids` | UUID[] | No | Filter by work item type |
+| `cycle_ids` | UUID[] | No | Filter by cycle |
+| `module_ids` | UUID[] | No | Filter by module |
+| `is_archived` | boolean | No | Filter by archived status |
+| `created_by_ids` | UUID[] | No | Filter by creator |
+| `workspace_search` | boolean | No | Search across all projects (requires filters) |
+| `limit` | integer | No | Max results when using filters |
+| `cursor` | string | No | Pagination cursor (list mode) |
+| `per_page` | integer | No | Results per page, 1–100 (list mode) |
+| `expand` | string | No | Comma-separated fields to expand |
+| `fields` | string | No | Comma-separated fields to include |
+| `order_by` | string | No | Sort field |
+
+#### `create_work_item`
+
+Creates a new work item in a project.
+
+| Parameter | Type | Required | Description |
+| ------------------ | ----------- | -------- | --------------------------------------------- |
+| `project_id` | UUID string | **Yes** | Target project |
+| `name` | string | **Yes** | Work item title |
+| `description_html` | string | No | HTML body |
+| `state_id` | UUID string | No | Initial state |
+| `priority` | string | No | `urgent` · `high` · `medium` · `low` · `none` |
+| `assignee_ids` | UUID[] | No | Assigned members |
+| `label_ids` | UUID[] | No | Labels |
+| `type_id` | UUID string | No | Work item type |
+| `parent_id` | UUID string | No | Parent work item (sub-item) |
+| `start_date` | string | No | `YYYY-MM-DD` |
+| `due_date` | string | No | `YYYY-MM-DD` |
+
+#### `retrieve_work_item`
+
+Returns a single work item by UUID.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `retrieve_work_item_by_identifier`
+
+Returns a work item using its human-readable identifier (e.g., `ENG-42`).
+
+| Parameter | Type | Required | Description |
+| ---------------------- | ------ | -------- | --------------------------- |
+| `project_identifier` | string | **Yes** | Project prefix, e.g., `ENG` |
+| `work_item_identifier` | string | **Yes** | Issue number, e.g., `42` |
+
+#### `update_work_item`
+
+Updates one or more fields on a work item. Only supplied fields are changed.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| other fields | partial | No |
+
+#### `delete_work_item`
+
+Permanently deletes a work item.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `search_work_items`
+
+Searches work items by text query within a project.
+
+| Parameter | Type | Required | Description |
+| ------------ | ----------- | -------- | ----------- |
+| `project_id` | UUID string | **Yes** | |
+| `query` | string | **Yes** | Search text |
+
+---
+
+### Work Item Activities
+
+#### `list_work_item_activities`
+
+Returns the activity log (history of changes) for a work item.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `retrieve_work_item_activity`
+
+Returns a single activity entry.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `activity_id` | UUID string | **Yes** |
+
+---
+
+### Work Item Comments
+
+#### `list_work_item_comments`
+
+Returns all comments on a work item.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `retrieve_work_item_comment`
+
+Returns a single comment.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `comment_id` | UUID string | **Yes** |
+
+#### `create_work_item_comment`
+
+Adds a comment to a work item. Comments are stored as HTML.
+
+| Parameter | Type | Required | Description |
+| -------------- | ----------- | -------- | --------------------------------------------------- |
+| `project_id` | UUID string | **Yes** | |
+| `work_item_id` | UUID string | **Yes** | |
+| `comment_html` | string | **Yes** | HTML content, e.g., `Fixed in commit abc123
` |
+
+#### `update_work_item_comment`
+
+Updates a comment's content.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `comment_id` | UUID string | **Yes** |
+| `comment_html` | string | **Yes** |
+
+#### `delete_work_item_comment`
+
+Deletes a comment.
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `comment_id` | UUID string | **Yes** |
+
+---
+
+### Work Item Links
+
+External URLs attached to a work item (e.g., Figma designs, PRs, docs).
+
+#### `list_work_item_links`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `retrieve_work_item_link`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `link_id` | UUID string | **Yes** |
+
+#### `create_work_item_link`
+
+| Parameter | Type | Required | Description |
+| -------------- | ----------- | -------- | -------------------------- |
+| `project_id` | UUID string | **Yes** | |
+| `work_item_id` | UUID string | **Yes** | |
+| `url` | string | **Yes** | External URL |
+| `title` | string | No | Display title for the link |
+
+#### `update_work_item_link`
+
+| Parameter | Type | Required |
+| --------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `link_id` | UUID string | **Yes** |
+| `url` / `title` | string | No |
+
+#### `delete_work_item_link`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `link_id` | UUID string | **Yes** |
+
+---
+
+### Work Item Relations
+
+Relations between work items (e.g., "blocks", "is blocked by", "duplicate of").
+
+#### `list_work_item_relations`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `create_work_item_relation`
+
+| Parameter | Type | Required | Description |
+| ---------------------- | ----------- | -------- | ----------------------------------------------------------------------- |
+| `project_id` | UUID string | **Yes** | |
+| `work_item_id` | UUID string | **Yes** | Source work item |
+| `related_work_item_id` | UUID string | **Yes** | Target work item |
+| `relation_type` | string | **Yes** | `blocking` · `blocked_by` · `duplicate_of` · `duplicate` · `relates_to` |
+
+#### `remove_work_item_relation`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `relation_id` | UUID string | **Yes** |
+
+---
+
+### Work Item Properties
+
+Custom fields defined per project.
+
+#### `list_work_item_properties`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `create_work_item_property`
+
+| Parameter | Type | Required | Description |
+| --------------- | ----------- | -------- | ------------------------ |
+| `project_id` | UUID string | **Yes** | |
+| `name` | string | **Yes** | Property name |
+| `property_type` | string | **Yes** | Type of the custom field |
+
+#### `retrieve_work_item_property`
+
+| Parameter | Type | Required |
+| ------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `property_id` | UUID string | **Yes** |
+
+#### `update_work_item_property`
+
+| Parameter | Type | Required |
+| ------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `property_id` | UUID string | **Yes** |
+
+#### `delete_work_item_property`
+
+| Parameter | Type | Required |
+| ------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `property_id` | UUID string | **Yes** |
+
+---
+
+### Work Item Types
+
+Custom work item type definitions (e.g., Bug, Feature, Task, Epic).
+
+#### `list_work_item_types`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `create_work_item_type`
+
+| Parameter | Type | Required |
+| ------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `name` | string | **Yes** |
+| `description` | string | No |
+| `is_active` | boolean | No |
+
+#### `retrieve_work_item_type`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `type_id` | UUID string | **Yes** |
+
+#### `update_work_item_type`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `type_id` | UUID string | **Yes** |
+
+#### `delete_work_item_type`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `type_id` | UUID string | **Yes** |
+
+---
+
+### Worklogs
+
+Time tracking for work items. All durations are in **minutes**.
+
+#### `list_work_logs`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `create_work_log`
+
+| Parameter | Type | Required | Description |
+| -------------- | ----------- | -------- | -------------------- |
+| `project_id` | UUID string | **Yes** | |
+| `work_item_id` | UUID string | **Yes** | |
+| `duration` | integer | **Yes** | Minutes logged (≥ 0) |
+| `description` | string | No | What was done |
+
+#### `update_work_log`
+
+| Parameter | Type | Required |
+| -------------------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `work_log_id` | UUID string | **Yes** |
+| `duration` / `description` | - | No |
+
+#### `delete_work_log`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+| `work_log_id` | UUID string | **Yes** |
+
+---
+
+### States
+
+Workflow states for a project's work items.
+
+#### `list_states` / `create_state` / `retrieve_state` / `update_state` / `delete_state`
+
+All state tools accept `project_id`. Create and update accept:
+
+| Field | Type | Required | Description |
+| ------------- | ------ | ---------------- | --------------------------------------------------------------- |
+| `name` | string | **Yes** (create) | Display name |
+| `color` | string | **Yes** (create) | Hex color code, e.g., `#FF5733` |
+| `group` | string | **Yes** (create) | `backlog` · `unstarted` · `started` · `completed` · `cancelled` |
+| `description` | string | No | |
+
+---
+
+### Labels
+
+Tags for work items.
+
+#### `list_labels` / `create_label` / `retrieve_label` / `update_label` / `delete_label`
+
+All label tools accept `project_id`. Create and update accept:
+
+| Field | Type | Required |
+| -------- | ----------- | ---------------- |
+| `name` | string | **Yes** (create) |
+| `color` | string | **Yes** (create) |
+| `parent` | UUID string | No |
+
+---
+
+### Cycles
+
+Time-boxed iterations (sprints).
+
+#### `list_cycles`
+
+Returns all cycles in a project including upcoming, active, and completed.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `list_archived_cycles`
+
+Returns archived cycles only.
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `create_cycle`
+
+| Parameter | Type | Required | Description |
+| ------------- | ----------- | -------- | ------------ |
+| `project_id` | UUID string | **Yes** | |
+| `name` | string | **Yes** | Cycle name |
+| `start_date` | string | No | `YYYY-MM-DD` |
+| `end_date` | string | No | `YYYY-MM-DD` |
+| `description` | string | No | |
+
+#### `retrieve_cycle`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `cycle_id` | UUID string | **Yes** |
+
+#### `update_cycle` / `delete_cycle`
+
+Accept `project_id` and `cycle_id`.
+
+#### `add_work_items_to_cycle`
+
+| Parameter | Type | Required |
+| --------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `cycle_id` | UUID string | **Yes** |
+| `work_item_ids` | UUID[] | **Yes** |
+
+#### `remove_work_item_from_cycle`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `cycle_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `list_cycle_work_items`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `cycle_id` | UUID string | **Yes** |
+
+#### `transfer_cycle_work_items`
+
+Moves all incomplete work items from one cycle to another.
+
+| Parameter | Type | Required | Description |
+| -------------- | ----------- | -------- | ------------ |
+| `project_id` | UUID string | **Yes** | |
+| `cycle_id` | UUID string | **Yes** | Source cycle |
+| `new_cycle_id` | UUID string | **Yes** | Target cycle |
+
+---
+
+### Modules
+
+Feature groupings within a project.
+
+#### `list_modules` / `list_archived_modules`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `create_module`
+
+| Parameter | Type | Required |
+| ------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `name` | string | **Yes** |
+| `description` | string | No |
+| `start_date` | string | No |
+| `target_date` | string | No |
+| `lead` | UUID string | No |
+| `members` | UUID[] | No |
+
+#### `retrieve_module` / `update_module` / `delete_module` / `archive_module`
+
+Accept `project_id` and `module_id`.
+
+#### `add_work_items_to_module`
+
+| Parameter | Type | Required |
+| --------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `module_id` | UUID string | **Yes** |
+| `work_item_ids` | UUID[] | **Yes** |
+
+#### `remove_work_item_from_module`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `module_id` | UUID string | **Yes** |
+| `work_item_id` | UUID string | **Yes** |
+
+#### `list_module_work_items`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `module_id` | UUID string | **Yes** |
+
+---
+
+### Epics
+
+Large work items that group related items. The server resolves the Epic work item type automatically.
+
+#### `list_epics` / `create_epic` / `retrieve_epic` / `update_epic` / `delete_epic`
+
+| Parameter | Type | Required |
+| ----------------------- | ----------- | ------------------- |
+| `project_id` | UUID string | **Yes** |
+| `epic_id` | UUID string | Varies by operation |
+| name, description, etc. | - | Varies |
+
+---
+
+### Milestones
+
+Point-in-time goals within a project.
+
+#### `list_milestones` / `create_milestone` / `retrieve_milestone` / `update_milestone` / `delete_milestone`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | ---------------- |
+| `project_id` | UUID string | **Yes** |
+| `milestone_id` | UUID string | Varies |
+| `name` | string | **Yes** (create) |
+
+#### `add_work_items_to_milestone`
+
+| Parameter | Type | Required |
+| --------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `milestone_id` | UUID string | **Yes** |
+| `work_item_ids` | UUID[] | **Yes** |
+
+#### `remove_work_items_from_milestone`
+
+| Parameter | Type | Required |
+| --------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `milestone_id` | UUID string | **Yes** |
+| `work_item_ids` | UUID[] | **Yes** |
+
+#### `list_milestone_work_items`
+
+| Parameter | Type | Required |
+| -------------- | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `milestone_id` | UUID string | **Yes** |
+
+---
+
+### Initiatives
+
+Workspace-scoped strategic goals that span multiple projects.
+
+#### `list_initiatives` / `create_initiative` / `retrieve_initiative` / `update_initiative` / `delete_initiative`
+
+Initiatives are workspace-scoped - no `project_id` required. `retrieve_initiative`, `update_initiative`, and `delete_initiative` accept an `initiative_id` UUID.
+
+---
+
+### Intake
+
+Triage queue for incoming work items before they enter a project.
+
+#### `list_intake_work_items`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+
+#### `create_intake_work_item`
+
+| Parameter | Type | Required |
+| ------------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `name` | string | **Yes** |
+| `description_html` | string | No |
+
+#### `retrieve_intake_work_item` / `update_intake_work_item` / `delete_intake_work_item`
+
+Accept `project_id` and `work_item_id`.
+
+---
+
+### Pages
+
+Wiki-style documents. Pages can be workspace-scoped or project-scoped.
+
+#### `retrieve_workspace_page`
+
+| Parameter | Type | Required |
+| --------- | ----------- | -------- |
+| `page_id` | UUID string | **Yes** |
+
+#### `retrieve_project_page`
+
+| Parameter | Type | Required |
+| ------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `page_id` | UUID string | **Yes** |
+
+#### `create_workspace_page`
+
+| Parameter | Type | Required |
+| ------------------ | ------ | -------- |
+| `name` | string | **Yes** |
+| `description_html` | string | No |
+
+#### `create_project_page`
+
+| Parameter | Type | Required |
+| ------------------ | ----------- | -------- |
+| `project_id` | UUID string | **Yes** |
+| `name` | string | **Yes** |
+| `description_html` | string | No |
diff --git a/docs/dev-tools/mcp-server.md b/docs/dev-tools/mcp-server.md
index 7b18d427..6e9e55c6 100644
--- a/docs/dev-tools/mcp-server.md
+++ b/docs/dev-tools/mcp-server.md
@@ -1,6 +1,6 @@
---
title: MCP server
-description: Setup MCP Server for Plane. Integrate Plane with Model Context Protocol for AI-powered project management.
+description: Connect Cursor, VS Code, Claude, Windsurf, and Zed to your Plane workspace. Create work items, manage cycles, search across projects — all through natural language.
keywords: plane, developer tools, integrations, extensions, mcp server, protocol, integration
---
@@ -83,6 +83,12 @@ Plane hosts the MCP server for you at **`https://mcp.plane.so`**. If you run you
- Python 3.10+ installed (`python --version`)
- `uv` package manager (recommended). See [Installing uv](https://docs.astral.sh/uv/getting-started/installation/)
+| Variable | Required | Description |
+| ---------------------- | -------- | --------------------------------------------------------------------- |
+| `PLANE_API_KEY` | Yes | API key from your workspace settings |
+| `PLANE_WORKSPACE_SLUG` | Yes | Your workspace slug |
+| `PLANE_BASE_URL` | No | API URL for self-hosted instances. Defaults to `https://api.plane.so` |
+
#### Get your API key (required for stdio and PAT token modes)
1. Open Plane and go to your workspace.
@@ -102,9 +108,14 @@ https://app.plane.so/acme-corp/
the slug is `acme-corp`.
+::: info Clients that don't support custom headers
+**Claude Desktop** — use Stdio instead.
+**Claude.ai** — use OAuth instead (the UI doesn't expose arbitrary headers).
+:::
+
### Claude Desktop
-Config file: `/claude_desktop_config.json`.
+Config file: `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows).
Quit Claude Desktop before editing, then relaunch and click the hammer icon (🔨) to confirm Plane tools are listed.
@@ -128,21 +139,27 @@ Spawns the server as a local subprocess. Credentials come from environment varia
}
```
-#### HTTP with OAuth
+#### HTTP with OAuth (via mcp-remote)
-Connects to a remote MCP server. Claude Desktop opens a browser window for the Plane OAuth flow on first use.
+Claude Desktop doesn't support remote HTTP natively. Use `mcp-remote` — a local proxy that bridges Claude Desktop to Plane's cloud server. **Requires Node.js 18+.**
```json
{
"mcpServers": {
"plane": {
- "url": "https://mcp.plane.so/http/mcp",
- "type": "http"
+ "command": "npx",
+ "args": ["mcp-remote@latest", "https://mcp.plane.so/http/mcp"]
}
}
}
```
+On first launch, `mcp-remote` opens a browser for the Plane OAuth flow.
+
+::: tip No Node.js?
+Use the SSE fallback instead: `"url": "https://mcp.plane.so/sse", "type": "sse"`.
+:::
+
#### HTTP with PAT Token
Connects to the PAT endpoint using API key headers. No browser interaction required - suitable for shared team setups where users authenticate via their own API key.
@@ -181,7 +198,7 @@ For existing integrations already using the SSE transport.
### Claude Code (CLI)
-Claude Code manages MCP servers via `claude mcp add` or a settings file.
+Claude Code manages MCP servers via `claude mcp add` or `claude mcp add-json`. MCP configs are stored in `~/.claude.json` (user scope) or `.mcp.json` in your repo root (project scope) — **not** `.claude/settings.json`.
#### Stdio
@@ -193,69 +210,27 @@ claude mcp add plane \
-- uvx plane-mcp-server stdio
```
-Settings file (`.claude/settings.json` for project scope, `~/.claude/settings.json` for user scope):
-
-```json
-{
- "mcpServers": {
- "plane": {
- "command": "uvx",
- "args": ["plane-mcp-server", "stdio"],
- "env": {
- "PLANE_API_KEY": "your_api_key_here",
- "PLANE_WORKSPACE_SLUG": "your-workspace-slug"
- }
- }
- }
-}
-```
+Add `--scope project` to write to `.mcp.json` (shared via git with your team) instead of `~/.claude.json` (your local copy).
#### HTTP with OAuth
```bash
-claude mcp add plane \
- --transport http \
- --url https://mcp.plane.so/http/mcp
+claude mcp add --transport http plane https://mcp.plane.so/http/mcp
```
-Claude Code will open a browser for the Plane OAuth flow. Settings file equivalent:
-
-```json
-{
- "mcpServers": {
- "plane": {
- "url": "https://mcp.plane.so/http/mcp",
- "type": "http"
- }
- }
-}
-```
+Claude Code will open a browser for the Plane OAuth flow. Run `/mcp` inside a session to re-authenticate if needed.
#### HTTP with PAT Token
```bash
-claude mcp add plane \
- --transport http \
- --url https://mcp.plane.so/http/api-key/mcp \
- --header "x-api-key: your_api_key_here" \
- --header "x-workspace-slug: your-workspace-slug"
-```
-
-Settings file equivalent:
-
-```json
-{
- "mcpServers": {
- "plane": {
- "url": "https://mcp.plane.so/http/api-key/mcp",
- "type": "http",
- "headers": {
- "x-api-key": "your_api_key_here",
- "x-workspace-slug": "your-workspace-slug"
- }
- }
+claude mcp add-json plane '{
+ "type": "http",
+ "url": "https://mcp.plane.so/http/api-key/mcp",
+ "headers": {
+ "x-api-key": "your_api_key_here",
+ "x-workspace-slug": "your-workspace-slug"
}
-}
+}'
```
#### SSE (Legacy)
@@ -305,11 +280,15 @@ Claude.ai supports remote MCP servers for eligible plans. Because it runs in a b
#### HTTP with OAuth
-1. Go to **Customize → Connectors ** in Claude.ai.
+**Pro / Max:**
+
+1. Go to **Customize → Connectors** in Claude.ai.
2. Click **Add custom connector**.
3. Enter the server URL: `https://mcp.plane.so/http/mcp`
4. Claude.ai redirects you through the Plane OAuth flow.
+**Team / Enterprise** (admins only): Go to **Organization settings → Connectors → Add custom connector** and use the same URL.
+
#### HTTP with PAT Token
If your Claude.ai plan supports custom headers in integrations:
@@ -469,6 +448,10 @@ Config file: `~/.codeium/windsurf/mcp_config.json`
Restart Windsurf after saving, then open the Cascade panel. The `windsurf://` redirect URI is registered in the OAuth provider.
+::: warning
+Windsurf uses `"serverUrl"` (not `"url"`) for remote HTTP servers.
+:::
+
#### Stdio
```json
@@ -493,8 +476,7 @@ Restart Windsurf after saving, then open the Cascade panel. The `windsurf://` re
{
"mcpServers": {
"plane": {
- "url": "https://mcp.plane.so/http/mcp",
- "type": "http"
+ "serverUrl": "https://mcp.plane.so/http/mcp"
}
}
}
@@ -506,8 +488,7 @@ Restart Windsurf after saving, then open the Cascade panel. The `windsurf://` re
{
"mcpServers": {
"plane": {
- "url": "https://mcp.plane.so/http/api-key/mcp",
- "type": "http",
+ "serverUrl": "https://mcp.plane.so/http/api-key/mcp",
"headers": {
"x-api-key": "your_api_key_here",
"x-workspace-slug": "your-workspace-slug"
@@ -602,6 +583,19 @@ Config file: `~/.config/zed/settings.json` under `"context_servers"`. Zed uses a
Open the AI panel (`Cmd + Shift + A`) to use Plane tools in conversation.
+---
+
+### Other clients (mcp-remote bridge)
+
+Any MCP client that supports stdio but not remote HTTP can use `mcp-remote` as a proxy. It runs locally as a subprocess and forwards requests to `https://mcp.plane.so/http/mcp`, handling the OAuth flow on first run. **Requires Node.js 18+.**
+
+```json
+{
+ "command": "npx",
+ "args": ["mcp-remote@latest", "https://mcp.plane.so/http/mcp"]
+}
+```
+
## Self-hosted Plane deployments
Set `PLANE_BASE_URL` to the public URL of your Plane instance (e.g., https://plane.yourcompany.com). This is used for user-facing OAuth redirects and API calls in stdio mode.
@@ -619,761 +613,9 @@ curl -H "x-api-key: YOUR_API_KEY" \
A `200` response confirms the API key and URL are correct.
----
-
-## Tool reference
-
-The server exposes 100+ tools across 20 modules. All tools are registered identically regardless of transport mode. The same tools are available via stdio, HTTP/OAuth, HTTP/PAT, and SSE.
-
-### Users
-
-#### `get_me`
-
-Returns the profile of the currently authenticated user. No parameters.
-
----
-
-### Workspaces
-
-#### `get_workspace_members`
-
-Returns all members of the workspace.
-
-#### `get_workspace_features`
-
-Returns enabled features for the workspace.
-
-#### `update_workspace_features`
-
-Updates workspace-level feature flags.
-
----
-
-### Projects
-
-#### `list_projects`
-
-Returns all projects the current user is a member of.
-
-#### `create_project`
-
-Creates a new project.
-
-| Parameter | Type | Required | Description |
-| ------------- | ------ | -------- | ------------------------------------------------ |
-| `name` | string | **Yes** | Project display name |
-| `identifier` | string | **Yes** | Short uppercase code, max 12 chars (e.g., `ENG`) |
-| `description` | string | No | Project description |
-| `network` | string | No | `0` (secret) or `2` (public) |
-
-#### `retrieve_project`
-
-Returns details of a single project.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `update_project`
-
-Updates project fields. All fields are optional.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| other fields | partial | No |
-
-#### `delete_project`
-
-Deletes a project.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `get_project_worklog_summary`
-
-Returns time-tracking summary for a project.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `get_project_members`
-
-Returns all members of a project.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `get_project_features`
-
-Returns the feature configuration for a project (modules, cycles, pages, etc.).
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `update_project_features`
-
-Updates which features are enabled on a project.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| feature fields | partial | No |
-
----
-
-### Work Items
-
-#### `list_work_items`
-
-Lists work items in a project, or searches across the workspace when filters are provided.
-
-When any filter parameter is set, the tool uses Plane's advanced search endpoint (supports workspace-wide search). Without filters it uses the standard paginated list endpoint.
-
-| Parameter | Type | Required | Description |
-| ------------------ | ----------- | ----------- | --------------------------------------------------------------- |
-| `project_id` | UUID string | Conditional | Required when no filters are provided |
-| `query` | string | No | Free-text search across name and description |
-| `assignee_ids` | UUID[] | No | Filter by assignee |
-| `state_ids` | UUID[] | No | Filter by state |
-| `state_groups` | string[] | No | `backlog` · `unstarted` · `started` · `completed` · `cancelled` |
-| `priorities` | string[] | No | `urgent` · `high` · `medium` · `low` · `none` |
-| `label_ids` | UUID[] | No | Filter by label |
-| `type_ids` | UUID[] | No | Filter by work item type |
-| `cycle_ids` | UUID[] | No | Filter by cycle |
-| `module_ids` | UUID[] | No | Filter by module |
-| `is_archived` | boolean | No | Filter by archived status |
-| `created_by_ids` | UUID[] | No | Filter by creator |
-| `workspace_search` | boolean | No | Search across all projects (requires filters) |
-| `limit` | integer | No | Max results when using filters |
-| `cursor` | string | No | Pagination cursor (list mode) |
-| `per_page` | integer | No | Results per page, 1–100 (list mode) |
-| `expand` | string | No | Comma-separated fields to expand |
-| `fields` | string | No | Comma-separated fields to include |
-| `order_by` | string | No | Sort field |
-
-#### `create_work_item`
-
-Creates a new work item in a project.
-
-| Parameter | Type | Required | Description |
-| ------------------ | ----------- | -------- | --------------------------------------------- |
-| `project_id` | UUID string | **Yes** | Target project |
-| `name` | string | **Yes** | Work item title |
-| `description_html` | string | No | HTML body |
-| `state_id` | UUID string | No | Initial state |
-| `priority` | string | No | `urgent` · `high` · `medium` · `low` · `none` |
-| `assignee_ids` | UUID[] | No | Assigned members |
-| `label_ids` | UUID[] | No | Labels |
-| `type_id` | UUID string | No | Work item type |
-| `parent_id` | UUID string | No | Parent work item (sub-item) |
-| `start_date` | string | No | `YYYY-MM-DD` |
-| `due_date` | string | No | `YYYY-MM-DD` |
-
-#### `retrieve_work_item`
-
-Returns a single work item by UUID.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `retrieve_work_item_by_identifier`
-
-Returns a work item using its human-readable identifier (e.g., `ENG-42`).
-
-| Parameter | Type | Required | Description |
-| ---------------------- | ------ | -------- | --------------------------- |
-| `project_identifier` | string | **Yes** | Project prefix, e.g., `ENG` |
-| `work_item_identifier` | string | **Yes** | Issue number, e.g., `42` |
-
-#### `update_work_item`
-
-Updates one or more fields on a work item. Only supplied fields are changed.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| other fields | partial | No |
-
-#### `delete_work_item`
-
-Permanently deletes a work item.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `search_work_items`
-
-Searches work items by text query within a project.
-
-| Parameter | Type | Required | Description |
-| ------------ | ----------- | -------- | ----------- |
-| `project_id` | UUID string | **Yes** | |
-| `query` | string | **Yes** | Search text |
-
----
-
-### Work Item Activities
-
-#### `list_work_item_activities`
-
-Returns the activity log (history of changes) for a work item.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `retrieve_work_item_activity`
-
-Returns a single activity entry.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `activity_id` | UUID string | **Yes** |
-
----
-
-### Work Item Comments
-
-#### `list_work_item_comments`
-
-Returns all comments on a work item.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `retrieve_work_item_comment`
-
-Returns a single comment.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `comment_id` | UUID string | **Yes** |
-
-#### `create_work_item_comment`
-
-Adds a comment to a work item. Comments are stored as HTML.
-
-| Parameter | Type | Required | Description |
-| -------------- | ----------- | -------- | --------------------------------------------------- |
-| `project_id` | UUID string | **Yes** | |
-| `work_item_id` | UUID string | **Yes** | |
-| `comment_html` | string | **Yes** | HTML content, e.g., `Fixed in commit abc123
` |
-
-#### `update_work_item_comment`
-
-Updates a comment's content.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `comment_id` | UUID string | **Yes** |
-| `comment_html` | string | **Yes** |
-
-#### `delete_work_item_comment`
-
-Deletes a comment.
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `comment_id` | UUID string | **Yes** |
-
----
-
-### Work Item Links
-
-External URLs attached to a work item (e.g., Figma designs, PRs, docs).
-
-#### `list_work_item_links`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `retrieve_work_item_link`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `link_id` | UUID string | **Yes** |
-
-#### `create_work_item_link`
-
-| Parameter | Type | Required | Description |
-| -------------- | ----------- | -------- | -------------------------- |
-| `project_id` | UUID string | **Yes** | |
-| `work_item_id` | UUID string | **Yes** | |
-| `url` | string | **Yes** | External URL |
-| `title` | string | No | Display title for the link |
-
-#### `update_work_item_link`
-
-| Parameter | Type | Required |
-| --------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `link_id` | UUID string | **Yes** |
-| `url` / `title` | string | No |
-
-#### `delete_work_item_link`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `link_id` | UUID string | **Yes** |
-
----
-
-### Work Item Relations
-
-Relations between work items (e.g., "blocks", "is blocked by", "duplicate of").
-
-#### `list_work_item_relations`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `create_work_item_relation`
-
-| Parameter | Type | Required | Description |
-| ---------------------- | ----------- | -------- | ----------------------------------------------------------------------- |
-| `project_id` | UUID string | **Yes** | |
-| `work_item_id` | UUID string | **Yes** | Source work item |
-| `related_work_item_id` | UUID string | **Yes** | Target work item |
-| `relation_type` | string | **Yes** | `blocking` · `blocked_by` · `duplicate_of` · `duplicate` · `relates_to` |
-
-#### `remove_work_item_relation`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `relation_id` | UUID string | **Yes** |
-
----
-
-### Work Item Properties
-
-Custom fields defined per project.
-
-#### `list_work_item_properties`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `create_work_item_property`
-
-| Parameter | Type | Required | Description |
-| --------------- | ----------- | -------- | ------------------------ |
-| `project_id` | UUID string | **Yes** | |
-| `name` | string | **Yes** | Property name |
-| `property_type` | string | **Yes** | Type of the custom field |
-
-#### `retrieve_work_item_property`
-
-| Parameter | Type | Required |
-| ------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `property_id` | UUID string | **Yes** |
-
-#### `update_work_item_property`
-
-| Parameter | Type | Required |
-| ------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `property_id` | UUID string | **Yes** |
-
-#### `delete_work_item_property`
-
-| Parameter | Type | Required |
-| ------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `property_id` | UUID string | **Yes** |
-
----
-
-### Work Item Types
-
-Custom work item type definitions (e.g., Bug, Feature, Task, Epic).
-
-#### `list_work_item_types`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `create_work_item_type`
-
-| Parameter | Type | Required |
-| ------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `name` | string | **Yes** |
-| `description` | string | No |
-| `is_active` | boolean | No |
-
-#### `retrieve_work_item_type`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `type_id` | UUID string | **Yes** |
-
-#### `update_work_item_type`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `type_id` | UUID string | **Yes** |
-
-#### `delete_work_item_type`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `type_id` | UUID string | **Yes** |
-
----
-
-### Worklogs
-
-Time tracking for work items. All durations are in **minutes**.
-
-#### `list_work_logs`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `create_work_log`
-
-| Parameter | Type | Required | Description |
-| -------------- | ----------- | -------- | -------------------- |
-| `project_id` | UUID string | **Yes** | |
-| `work_item_id` | UUID string | **Yes** | |
-| `duration` | integer | **Yes** | Minutes logged (≥ 0) |
-| `description` | string | No | What was done |
-
-#### `update_work_log`
-
-| Parameter | Type | Required |
-| -------------------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `work_log_id` | UUID string | **Yes** |
-| `duration` / `description` | - | No |
-
-#### `delete_work_log`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-| `work_log_id` | UUID string | **Yes** |
-
----
-
-### States
-
-Workflow states for a project's work items.
-
-#### `list_states` / `create_state` / `retrieve_state` / `update_state` / `delete_state`
-
-All state tools accept `project_id`. Create and update accept:
-
-| Field | Type | Required | Description |
-| ------------- | ------ | ---------------- | --------------------------------------------------------------- |
-| `name` | string | **Yes** (create) | Display name |
-| `color` | string | **Yes** (create) | Hex color code, e.g., `#FF5733` |
-| `group` | string | **Yes** (create) | `backlog` · `unstarted` · `started` · `completed` · `cancelled` |
-| `description` | string | No | |
-
----
-
-### Labels
-
-Tags for work items.
-
-#### `list_labels` / `create_label` / `retrieve_label` / `update_label` / `delete_label`
-
-All label tools accept `project_id`. Create and update accept:
-
-| Field | Type | Required |
-| -------- | ----------- | ---------------- |
-| `name` | string | **Yes** (create) |
-| `color` | string | **Yes** (create) |
-| `parent` | UUID string | No |
-
----
-
-### Cycles
-
-Time-boxed iterations (sprints).
-
-#### `list_cycles`
-
-Returns all cycles in a project including upcoming, active, and completed.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `list_archived_cycles`
-
-Returns archived cycles only.
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `create_cycle`
-
-| Parameter | Type | Required | Description |
-| ------------- | ----------- | -------- | ------------ |
-| `project_id` | UUID string | **Yes** | |
-| `name` | string | **Yes** | Cycle name |
-| `start_date` | string | No | `YYYY-MM-DD` |
-| `end_date` | string | No | `YYYY-MM-DD` |
-| `description` | string | No | |
-
-#### `retrieve_cycle`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `cycle_id` | UUID string | **Yes** |
-
-#### `update_cycle` / `delete_cycle`
-
-Accept `project_id` and `cycle_id`.
-
-#### `add_work_items_to_cycle`
-
-| Parameter | Type | Required |
-| --------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `cycle_id` | UUID string | **Yes** |
-| `work_item_ids` | UUID[] | **Yes** |
-
-#### `remove_work_item_from_cycle`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `cycle_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `list_cycle_work_items`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `cycle_id` | UUID string | **Yes** |
-
-#### `transfer_cycle_work_items`
-
-Moves all incomplete work items from one cycle to another.
-
-| Parameter | Type | Required | Description |
-| -------------- | ----------- | -------- | ------------ |
-| `project_id` | UUID string | **Yes** | |
-| `cycle_id` | UUID string | **Yes** | Source cycle |
-| `new_cycle_id` | UUID string | **Yes** | Target cycle |
-
----
-
-### Modules
-
-Feature groupings within a project.
-
-#### `list_modules` / `list_archived_modules`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `create_module`
-
-| Parameter | Type | Required |
-| ------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `name` | string | **Yes** |
-| `description` | string | No |
-| `start_date` | string | No |
-| `target_date` | string | No |
-| `lead` | UUID string | No |
-| `members` | UUID[] | No |
-
-#### `retrieve_module` / `update_module` / `delete_module` / `archive_module`
-
-Accept `project_id` and `module_id`.
-
-#### `add_work_items_to_module`
-
-| Parameter | Type | Required |
-| --------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `module_id` | UUID string | **Yes** |
-| `work_item_ids` | UUID[] | **Yes** |
-
-#### `remove_work_item_from_module`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `module_id` | UUID string | **Yes** |
-| `work_item_id` | UUID string | **Yes** |
-
-#### `list_module_work_items`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `module_id` | UUID string | **Yes** |
-
----
-
-### Epics
-
-Large work items that group related items. The server resolves the Epic work item type automatically.
-
-#### `list_epics` / `create_epic` / `retrieve_epic` / `update_epic` / `delete_epic`
-
-| Parameter | Type | Required |
-| ----------------------- | ----------- | ------------------- |
-| `project_id` | UUID string | **Yes** |
-| `epic_id` | UUID string | Varies by operation |
-| name, description, etc. | - | Varies |
-
----
-
-### Milestones
-
-Point-in-time goals within a project.
-
-#### `list_milestones` / `create_milestone` / `retrieve_milestone` / `update_milestone` / `delete_milestone`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | ---------------- |
-| `project_id` | UUID string | **Yes** |
-| `milestone_id` | UUID string | Varies |
-| `name` | string | **Yes** (create) |
-
-#### `add_work_items_to_milestone`
-
-| Parameter | Type | Required |
-| --------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `milestone_id` | UUID string | **Yes** |
-| `work_item_ids` | UUID[] | **Yes** |
-
-#### `remove_work_items_from_milestone`
-
-| Parameter | Type | Required |
-| --------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `milestone_id` | UUID string | **Yes** |
-| `work_item_ids` | UUID[] | **Yes** |
-
-#### `list_milestone_work_items`
-
-| Parameter | Type | Required |
-| -------------- | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `milestone_id` | UUID string | **Yes** |
-
----
-
-### Initiatives
-
-Workspace-scoped strategic goals that span multiple projects.
-
-#### `list_initiatives` / `create_initiative` / `retrieve_initiative` / `update_initiative` / `delete_initiative`
-
-Initiatives are workspace-scoped - no `project_id` required. `retrieve_initiative`, `update_initiative`, and `delete_initiative` accept an `initiative_id` UUID.
-
----
-
-### Intake
-
-Triage queue for incoming work items before they enter a project.
-
-#### `list_intake_work_items`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-
-#### `create_intake_work_item`
-
-| Parameter | Type | Required |
-| ------------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `name` | string | **Yes** |
-| `description_html` | string | No |
-
-#### `retrieve_intake_work_item` / `update_intake_work_item` / `delete_intake_work_item`
-
-Accept `project_id` and `work_item_id`.
-
----
-
-### Pages
-
-Wiki-style documents. Pages can be workspace-scoped or project-scoped.
-
-#### `retrieve_workspace_page`
-
-| Parameter | Type | Required |
-| --------- | ----------- | -------- |
-| `page_id` | UUID string | **Yes** |
-
-#### `retrieve_project_page`
-
-| Parameter | Type | Required |
-| ------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `page_id` | UUID string | **Yes** |
-
-#### `create_workspace_page`
-
-| Parameter | Type | Required |
-| ------------------ | ------ | -------- |
-| `name` | string | **Yes** |
-| `description_html` | string | No |
-
-#### `create_project_page`
-
-| Parameter | Type | Required |
-| ------------------ | ----------- | -------- |
-| `project_id` | UUID string | **Yes** |
-| `name` | string | **Yes** |
-| `description_html` | string | No |
+::: tip Running your own MCP server?
+You can skip `mcp.plane.so` entirely and deploy `plane-mcp-server` yourself — Docker Compose, Helm, OAuth app setup: [Self-host MCP Server](/dev-tools/mcp-server-self-host).
+:::
---
@@ -1442,17 +684,19 @@ Model calls `list_modules` to find the UUID, then `add_work_items_to_module` wit
The server propagates errors from the Plane SDK as MCP tool errors.
-| Scenario | HTTP Status | Cause | Resolution |
-| --------------------------------- | ----------- | --------------------------------------- | --------------------------------------------------- |
-| Invalid API key | 401 | `PLANE_API_KEY` is wrong or revoked | Regenerate the token in Plane settings |
-| Invalid OAuth token | 401 | Token expired or revoked | Re-authorise through OAuth flow |
-| Missing `x-workspace-slug` header | - | Header auth missing workspace | Include `x-workspace-slug` header |
-| Wrong workspace slug | 404 | Slug doesn't exist | Check the exact slug in your Plane URL |
-| Insufficient permissions | 403 | User role too low | Check your role in the workspace/project |
-| Resource not found | 404 | UUID or identifier doesn't exist | Verify the ID; check if resource was deleted |
-| Validation error | 400 | Required field missing or invalid value | Check required fields and value constraints |
-| Redis unavailable | - | Token storage down | Set `REDIS_HOST`/`REDIS_PORT` or omit for in-memory |
-| Network error | - | Cannot reach Plane API | Verify `PLANE_BASE_URL` and connectivity |
+| Scenario | HTTP Status | Cause | Resolution |
+| ----------------------------------- | -------------------- | ----------------------------------------------- | --------------------------------------------------- |
+| Invalid API key | 401 | `PLANE_API_KEY` is wrong or revoked | Regenerate the token in Plane settings |
+| Invalid OAuth token | 401 | Token expired or revoked | Re-authorise through OAuth flow |
+| Missing `x-workspace-slug` header | - | Header auth missing workspace | Include `x-workspace-slug` header |
+| Wrong workspace slug | 404 | Slug doesn't exist | Check the exact slug in your Plane URL |
+| Insufficient permissions | 403 | User role too low | Check your role in the workspace/project |
+| Resource not found | 404 | UUID or identifier doesn't exist | Verify the ID; check if resource was deleted |
+| Validation error | 400 | Required field missing or invalid value | Check required fields and value constraints |
+| Redis unavailable | - | Token storage down | Set `REDIS_HOST`/`REDIS_PORT` or omit for in-memory |
+| Network error | - | Cannot reach Plane API | Verify `PLANE_BASE_URL` and connectivity |
+| Server not listed in Claude Desktop | Wrong transport type | Claude Desktop doesn't support `"type": "http"` | Use `npx mcp-remote@latest` or SSE transport |
+| Server config skipped | JSON syntax error | Config file ignored silently | Validate JSON — check for trailing commas |
**Verify connectivity (stdio/PAT):**
@@ -1474,6 +718,25 @@ curl http://localhost:8211/http/mcp
# Should return MCP protocol response or 401
```
+**Claude Code: enable debug logging:**
+
+```bash
+claude --mcp-debug
+```
+
+**Claude Code: re-authenticate OAuth:**
+
+```bash
+rm -rf ~/.mcp-auth
+```
+
+Restart Claude Code and run `/mcp` to authenticate again.
+
+## See also
+
+- [Self-host MCP Server](/dev-tools/mcp-server-self-host)
+- [Tool Reference](/dev-tools/mcp-server-tools)
+
---
_Plane MCP Server is open source and licensed under MIT. Source at [github.com/makeplane/plane-mcp-server](https://github.com/makeplane/plane-mcp-server)._
diff --git a/vercel.json b/vercel.json
index 0a3e7bef..f1bdea82 100644
--- a/vercel.json
+++ b/vercel.json
@@ -115,6 +115,10 @@
{
"source": "/self-hosting/govern/aws-opensearch-embedding",
"destination": "/self-hosting/govern/plane-ai/configure-embedding-model"
+ },
+ {
+ "source": "/dev-tools/mcp-server-claude-code",
+ "destination": "/dev-tools/mcp-server#claude-code-cli"
}
],
"rewrites": [