diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts index 2b58f94..ba753fd 100644 --- a/docs/.vitepress/config.mts +++ b/docs/.vitepress/config.mts @@ -1040,7 +1040,11 @@ 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: "For Claude Code", link: "/dev-tools/mcp-server-claude-code" }, + { 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-self-host.md b/docs/dev-tools/mcp-server-self-host.md new file mode 100644 index 0000000..f2d3053 --- /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 0000000..7ea0207 --- /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 7b18d42..bec98c5 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 --- @@ -104,7 +104,7 @@ the slug is `acme-corp`. ### 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 +128,23 @@ 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. + #### 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 +183,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 +195,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 +265,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 +433,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 +461,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 +473,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 +568,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. @@ -623,759 +602,7 @@ 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 | - ---- +See the [MCP Server Tool Reference](/dev-tools/mcp-server-tools) for a complete list of all 100+ tools — work items, projects, cycles, modules, worklogs, and more. ## Common workflows @@ -1474,6 +701,20 @@ 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. + --- _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)._