Skip to content

Commit c329f90

Browse files
committed
chore: improve token expiration warning message clarity
1 parent ed97fd7 commit c329f90

File tree

1 file changed

+342
-0
lines changed

1 file changed

+342
-0
lines changed
Lines changed: 342 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,342 @@
1+
---
2+
title: Self-host MCP Server
3+
description: Deploy your own Plane MCP Server with Docker Compose or Helm. Create an OAuth app, configure credentials, and connect AI clients to your self-hosted instance.
4+
keywords: plane mcp server, self-hosted mcp, plane mcp deployment, docker compose mcp, helm mcp, plane oauth mcp, plane ai integration, mcp server setup
5+
---
6+
7+
# Self-host MCP Server
8+
9+
Run your own instance of the Plane MCP Server to connect AI clients to a self-hosted Plane installation or to maintain full control over your MCP infrastructure. This guide walks you through creating the required OAuth application in Plane, deploying the server, and connecting your AI tools.
10+
11+
::: info
12+
The Plane MCP Server is currently in **Beta**. Please send any feedback to support@plane.so.
13+
:::
14+
15+
## Prerequisites
16+
17+
Before you begin, make sure you have:
18+
19+
- A running **Plane instance** (self-hosted or cloud) with workspace admin access
20+
- **Docker** and Docker Compose v2+ (for Docker deployment) _or_ **Kubernetes** v1.21+ with Helm v3+ (for Helm deployment)
21+
- A **public URL** where your MCP server will be reachable (e.g., `https://mcp.yourdomain.com`)
22+
23+
## Step 1: Create an OAuth application in Plane
24+
25+
The MCP server authenticates with Plane using OAuth 2.0. You need to register an OAuth application in your Plane workspace to obtain the credentials.
26+
27+
1. Navigate to **Workspace Settings****Integrations**.
28+
29+
```text
30+
https://app.plane.so/<workspace>/settings/integrations/
31+
```
32+
33+
2. Click **Build your own**.
34+
35+
3. Fill in the application details:
36+
37+
| Field | Value |
38+
| ---------------- | ----------------------------------------------------------------- |
39+
| **App Name** | A name for your MCP server (e.g., `Plane MCP Server`) |
40+
| **Setup URL** | Your MCP server's public URL (e.g., `https://mcp.yourdomain.com`) |
41+
| **Redirect URI** | Add all three redirect URIs listed below |
42+
| **Webhook URL** | Leave empty unless you need webhook events |
43+
44+
::: tip Redirect URIs
45+
Add **all three** of the following redirect URIs to your OAuth app to ensure compatibility across all transports and MCP clients:
46+
47+
| Transport | Redirect URI |
48+
| --------------- | ------------------------------------- |
49+
| OAuth Callback | `<MCP_SERVER_URL>/callback` |
50+
| HTTP with OAuth | `<MCP_SERVER_URL>/http/auth/callback` |
51+
| SSE (Legacy) | `<MCP_SERVER_URL>/auth/callback` |
52+
53+
For example, if your MCP server is at `https://mcp.yourdomain.com`, add the following URIs **space-separated** in the Redirect URI field:
54+
55+
```text
56+
https://mcp.yourdomain.com/callback https://mcp.yourdomain.com/http/auth/callback https://mcp.yourdomain.com/auth/callback
57+
```
58+
59+
:::
60+
61+
4. Select the **read** and **write** scopes from the **Scopes & Permissions** section. The MCP server requires both to function correctly.
62+
63+
5. Save and securely store the generated **Client ID** and **Client Secret**.
64+
65+
::: warning
66+
Never expose your Client Secret in client-side code or commit it to version control.
67+
:::
68+
69+
For more details on creating OAuth applications, see [Create an OAuth Application](/dev-tools/build-plane-app/create-oauth-application).
70+
71+
## Step 2: Deploy the MCP server
72+
73+
### Option A: Docker Compose
74+
75+
1. Create a project directory and add the following `docker-compose.yaml`:
76+
77+
```yaml
78+
name: plane-mcp
79+
80+
services:
81+
mcp:
82+
image: makeplane/plane-mcp-server:${APP_RELEASE_VERSION:-latest}
83+
restart: always
84+
ports:
85+
- "8211:8211"
86+
env_file:
87+
- variables.env
88+
environment:
89+
REDIS_HOST: valkey
90+
REDIS_PORT: "6379"
91+
depends_on:
92+
valkey:
93+
condition: service_healthy
94+
95+
valkey:
96+
image: valkey/valkey:8-alpine
97+
restart: always
98+
volumes:
99+
- valkey-data:/data
100+
healthcheck:
101+
test: ["CMD", "valkey-cli", "ping"]
102+
interval: 5s
103+
timeout: 3s
104+
retries: 5
105+
106+
volumes:
107+
valkey-data:
108+
```
109+
110+
2. Create a `variables.env` file with the OAuth credentials from Step 1:
111+
112+
```env
113+
# Image tag (pin to a specific version for production)
114+
APP_RELEASE_VERSION=latest
115+
116+
# Plane API URL (use your self-hosted Plane API URL if applicable)
117+
PLANE_BASE_URL=https://api.plane.so
118+
119+
# Internal URL for server-to-server calls (optional, for same-network setups)
120+
# PLANE_INTERNAL_BASE_URL=
121+
122+
# OAuth credentials from Step 1
123+
PLANE_OAUTH_PROVIDER_CLIENT_ID=your-client-id
124+
PLANE_OAUTH_PROVIDER_CLIENT_SECRET=your-client-secret
125+
126+
# Public URL where MCP clients reach the server
127+
PLANE_OAUTH_PROVIDER_BASE_URL=https://mcp.yourdomain.com
128+
```
129+
130+
3. Start the server:
131+
132+
```bash
133+
docker compose up -d
134+
```
135+
136+
4. Verify the server is running:
137+
138+
```bash
139+
docker compose logs -f mcp
140+
```
141+
142+
#### Configuration reference
143+
144+
| Variable | Required | Description |
145+
| ------------------------------------ | -------- | ----------------------------------------------- |
146+
| `APP_RELEASE_VERSION` | No | Image tag to deploy (default: `latest`) |
147+
| `PLANE_BASE_URL` | No | Plane API URL (default: `https://api.plane.so`) |
148+
| `PLANE_INTERNAL_BASE_URL` | No | Internal API URL for server-to-server calls |
149+
| `PLANE_OAUTH_PROVIDER_CLIENT_ID` | Yes | OAuth Client ID from your Plane app |
150+
| `PLANE_OAUTH_PROVIDER_CLIENT_SECRET` | Yes | OAuth Client Secret from your Plane app |
151+
| `PLANE_OAUTH_PROVIDER_BASE_URL` | Yes | Public URL where MCP clients reach the server |
152+
153+
#### Upgrading
154+
155+
```bash
156+
docker compose pull
157+
docker compose up -d
158+
```
159+
160+
### Option B: Helm chart
161+
162+
1. Add the Plane Helm repository:
163+
164+
```bash
165+
helm repo add plane https://helm.plane.so
166+
helm repo update
167+
```
168+
169+
2. Create a `values.yaml` with your configuration:
170+
171+
```yaml
172+
ingress:
173+
enabled: true
174+
host: mcp.yourdomain.com
175+
ingressClass: nginx
176+
ssl:
177+
enabled: true
178+
issuer: cloudflare # cloudflare | digitalocean | http
179+
email: you@yourdomain.com
180+
181+
services:
182+
api:
183+
plane_base_url: "https://api.plane.so"
184+
plane_oauth:
185+
enabled: true
186+
client_id: "<your-oauth-client-id>"
187+
client_secret: "<your-oauth-client-secret>"
188+
provider_base_url: "https://mcp.yourdomain.com"
189+
```
190+
191+
3. Install the chart:
192+
193+
```bash
194+
helm install plane-mcp plane/plane-mcp-server \
195+
--namespace plane-mcp \
196+
--create-namespace \
197+
-f values.yaml
198+
```
199+
200+
#### Helm values reference
201+
202+
| Value | Default | Description |
203+
| -------------------------------------------- | ----------------- | --------------------------------------------------- |
204+
| `dockerRegistry.default_tag` | `latest` | Image tag to deploy |
205+
| `ingress.enabled` | `true` | Enable ingress |
206+
| `ingress.host` | `mcp.example.com` | Public hostname |
207+
| `ingress.ingressClass` | `nginx` | Ingress class name |
208+
| `ingress.ssl.enabled` | `false` | Enable TLS via cert-manager |
209+
| `ingress.ssl.issuer` | `cloudflare` | ACME issuer (`cloudflare`, `digitalocean`, `http`) |
210+
| `services.api.replicas` | `1` | Number of MCP server replicas |
211+
| `services.api.plane_base_url` | `""` | Plane API URL |
212+
| `services.api.plane_oauth.enabled` | `false` | Enable OAuth endpoints |
213+
| `services.api.plane_oauth.client_id` | `""` | OAuth Client ID |
214+
| `services.api.plane_oauth.client_secret` | `""` | OAuth Client Secret |
215+
| `services.api.plane_oauth.provider_base_url` | `""` | Public URL the server is reachable on |
216+
| `services.redis.local_setup` | `true` | Deploy Valkey in-cluster |
217+
| `services.redis.external_redis_url` | `""` | External Valkey/Redis URL (if not using in-cluster) |
218+
219+
#### Upgrading
220+
221+
```bash
222+
helm upgrade plane-mcp plane/plane-mcp-server \
223+
--namespace plane-mcp \
224+
-f values.yaml
225+
```
226+
227+
#### Uninstalling
228+
229+
```bash
230+
helm uninstall plane-mcp --namespace plane-mcp
231+
```
232+
233+
## Step 3: Connect your AI tools
234+
235+
Once the server is running, configure your AI tools to connect to it. Replace `https://mcp.yourdomain.com` with your actual MCP server URL.
236+
237+
### Available endpoints
238+
239+
| Endpoint | Auth | Description |
240+
| --------------------------------------------- | ---------- | -------------------------------- |
241+
| `https://mcp.yourdomain.com/http/mcp` | OAuth | OAuth-based MCP endpoint |
242+
| `https://mcp.yourdomain.com/http/api-key/mcp` | PAT header | Personal Access Token endpoint |
243+
| `https://mcp.yourdomain.com/sse` | OAuth | Legacy SSE endpoint (deprecated) |
244+
245+
### Claude Desktop / Cursor / Windsurf
246+
247+
Use `mcp-remote` to connect via the HTTP OAuth endpoint:
248+
249+
```json
250+
{
251+
"mcpServers": {
252+
"plane": {
253+
"command": "npx",
254+
"args": ["mcp-remote@latest", "https://mcp.yourdomain.com/http/mcp"]
255+
}
256+
}
257+
}
258+
```
259+
260+
### Claude Code
261+
262+
```bash
263+
claude mcp add --transport http plane https://mcp.yourdomain.com/http/mcp
264+
```
265+
266+
### VSCode
267+
268+
Add to your `.vscode/mcp.json`:
269+
270+
```json
271+
{
272+
"servers": {
273+
"plane": {
274+
"command": "npx",
275+
"args": ["mcp-remote@latest", "https://mcp.yourdomain.com/http/mcp"]
276+
}
277+
}
278+
}
279+
```
280+
281+
### HTTP with PAT token
282+
283+
For automated workflows or CI/CD pipelines, use the PAT endpoint with a [Plane API key](/api-reference/introduction#creating-an-api-key):
284+
285+
```json
286+
{
287+
"mcpServers": {
288+
"plane": {
289+
"command": "npx",
290+
"args": ["mcp-remote@latest", "https://mcp.yourdomain.com/http/api-key/mcp"],
291+
"headers": {
292+
"Authorization": "Bearer <YOUR_API_KEY>",
293+
"X-Workspace-slug": "<YOUR_WORKSPACE_SLUG>"
294+
}
295+
}
296+
}
297+
}
298+
```
299+
300+
## Troubleshooting
301+
302+
**Server not starting?**
303+
304+
Check the MCP server logs for errors:
305+
306+
```bash
307+
docker compose logs mcp
308+
```
309+
310+
**Valkey connection issues?**
311+
312+
Verify Valkey is healthy:
313+
314+
```bash
315+
docker compose exec valkey valkey-cli ping
316+
```
317+
318+
**OAuth authentication errors?**
319+
320+
- Verify all three **Redirect URIs** are added to your Plane OAuth app: `<MCP_SERVER_URL>/callback`, `<MCP_SERVER_URL>/http/auth/callback`, and `<MCP_SERVER_URL>/auth/callback`.
321+
- Confirm `PLANE_OAUTH_PROVIDER_CLIENT_ID` and `PLANE_OAUTH_PROVIDER_CLIENT_SECRET` in your environment match the values from Plane.
322+
- Ensure `PLANE_OAUTH_PROVIDER_BASE_URL` is the publicly accessible URL of your MCP server.
323+
- Clear cached auth tokens on the client side:
324+
325+
```bash
326+
rm -rf ~/.mcp-auth
327+
```
328+
329+
**Reset and start fresh (Docker Compose):**
330+
331+
```bash
332+
docker compose down -v
333+
docker compose up -d
334+
```
335+
336+
**Getting help**
337+
338+
If issues persist:
339+
340+
1. Verify your OAuth credentials and workspace settings
341+
2. Check the [Plane MCP Server repository](https://github.com/makeplane/plane-mcp-server) for known issues
342+
3. Contact support at support@plane.so

0 commit comments

Comments
 (0)