plane-selfhost-mcp
Enables interaction with self-hosted Plane project management instances using X-API-Key authentication, offering tools for project discovery, issue management, and workflow state operations.
README
plane-selfhost-mcp
Custom MCP server for self-hosted Plane instances that require X-API-Key authentication instead of Authorization: Bearer.
This project exists because the official Plane MCP flow did not work reliably against this self-hosted environment. This server talks directly to the Plane REST API, exposes a small focused MCP toolset, and is designed to be consumed from OpenCode.
What this project does
- Connects to a self-hosted Plane workspace with
X-API-Key - Exposes Plane operations as MCP tools over stdio
- Supports project discovery, issue listing, issue creation, issue updates, comments, and workflow state lookup
- Works with OpenCode through a local MCP server entry such as
plane-selfhost
Why it was created
The official Plane MCP server uses Authorization: Bearer <token>. In this self-hosted setup that produced auth failures, while direct API calls with X-API-Key worked correctly.
So the right move was NOT to keep fighting the wrong auth model. The right move was to build a thin MCP wrapper around the API behavior that the real instance actually accepts.
Quick start
Requirements
- Python 3.10+
- A reachable self-hosted Plane instance
- A Plane API key with workspace access
- The Plane workspace slug
Install
cd plane-selfhost-mcp
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
Configure environment
Preferred path: copy .env.example to a project-root .env file so OpenCode and local commands can share one source of truth.
cp .env.example .env
Then edit .env with your real values.
At startup the MCP loads .env automatically, then reads the real process environment on top of it. That means explicit environment variables still win when you need a one-off override.
If you prefer, you can still export the variables directly instead of using .env.
The server fails fast with a clear error if any required variable is missing from both sources.
Run locally
stdio mode
source .venv/bin/activate
python -m plane_selfhost_mcp
Installed script
source .venv/bin/activate
plane-selfhost-mcp
Makefile shortcuts
After installing the package, you can use the local Makefile instead of manually activating the virtual environment:
make help # list available targets
make install # install the package and dev dependencies in .venv
make run # run the MCP server (sources .env automatically if present)
make smoke-test # verify config loads (sources .env automatically if present)
make whoami # print the authenticated Plane user (sources .env automatically if present)
make list-projects # list workspace projects (sources .env automatically if present)
make list-states # list workflow states for a project (requires PROJECT_ID=...)
make create-test-issue # create a test issue in a project (requires PROJECT_ID=... TITLE=...)
make move-issue # move an issue to a target state (requires PROJECT_ID=... ISSUE_ID=... STATE_ID=...)
make comment # add an HTML/plain comment to an issue (requires PROJECT_ID=... ISSUE_ID=... COMMENT="...")
make test # run pytest
Free-form values such as TITLE and COMMENT are passed to the inline Python scripts through environment variables, so quotes and special characters do not break the command.
make run, make smoke-test, make whoami, make list-projects, make list-states, make create-test-issue, make move-issue, and make comment will source a .env file in the project root if one exists, so you do not need to export variables manually every time.
OpenCode integration
Add this MCP server to your OpenCode config:
{
"mcp": {
"plane-selfhost": {
"type": "local",
"enabled": true,
"command": [
"/absolute/path/to/plane-selfhost-mcp/.venv/bin/python",
"-m",
"plane_selfhost_mcp"
]
}
}
}
Recommended setup for OpenCode: keep Plane credentials in the repo's .env file and let the MCP load them automatically at startup.
Use the MCP env block only when you intentionally want OpenCode to override the .env values for that process.
Replace /absolute/path/to/plane-selfhost-mcp/.venv/bin/python with the Python executable from your own local virtual environment.
After updating OpenCode config, restart OpenCode. MCP config is not hot-reloaded.
Available tools
| Tool | What it does | Typical use |
|---|---|---|
get_user_me |
Returns the authenticated Plane user | Verify auth/config works |
list_projects |
Lists projects in the configured workspace | Resolve a target project before issue work |
list_project_issues |
Lists issues for a project | Find an issue before updating it |
create_issue |
Creates a new issue | Add a task/bug/story in Plane |
update_issue |
Updates issue fields | Move states, rename, reprioritize, assign |
add_issue_comment |
Adds an HTML comment to an issue | Leave progress notes or audit comments |
list_states |
Lists workflow states for a project | Resolve initial/done state IDs before transitions |
How the MCP should be used
This MCP is intentionally simple. The safest usage flow is:
- Call
get_user_meto prove the connection. - Call
list_projectsto resolve the targetproject_id. - If the action depends on workflow placement, call
list_states. - Create or update issues only after resolving IDs from live responses.
- Treat responses as successful only when the MCP payload returns
ok: true.
Important operational rules
- Do not invent
project_id,issue_id, orstatevalues. - Use
description_htmlandcomment_htmlfor rich text fields. - Self-hosted Plane in this setup expects
X-API-Key, not bearer auth. - If auth fails, debug credentials first; do not assume the API path is wrong.
Shared OpenCode skill
This repository includes a shared plane-mcp skill artifact that another user can copy into their own OpenCode skills setup.
- Skill location in this repository:
skills/plane-mcp/SKILL.md
The repository does not auto-register that skill for anyone. OpenCode will only use it after each user copies or registers it in their own local OpenCode configuration.
Skill purpose
The plane-mcp skill exists so agents follow the correct operational contract every time instead of improvising.
It teaches the agent to:
- target the custom
plane-selfhost-mcp - verify config and auth first
- resolve IDs from live Plane responses
- use
list_statesbefore state transitions - stop and surface errors when the MCP payload returns
ok: false
How another user can use it
- Clone this repository and install the MCP package.
- Configure the repository root
.envfile with real Plane credentials. - Add the MCP server entry shown in
OpenCode integrationto your own OpenCode config. - Copy
skills/plane-mcp/SKILL.mdinto your own OpenCode skills directory, or register it from your own OpenCode setup. - Restart OpenCode after registering the skill.
The .env-first recommendation stays the same: keep credentials in the repository root .env file by default, and use the MCP env block only for intentional per-process overrides.
Verification and smoke tests
Config loader only
source .venv/bin/activate
python -c "from plane_selfhost_mcp.config import load_config; print(load_config())"
Real API check
source .venv/bin/activate
python -c "
import asyncio
from plane_selfhost_mcp.config import load_config
from plane_selfhost_mcp.client import PlaneClient
async def main():
cfg = load_config()
client = PlaneClient(cfg)
try:
print('ME:', await client.get_user_me())
print('PROJECTS:', await client.list_projects())
finally:
await client.close()
asyncio.run(main())
"
Expected result:
get_user_mereturns the authenticated userlist_projectsreturns workspace projects
Development
Run tests
make test
Or, with the virtual environment activated:
pytest
Package facts
| Topic | Value |
|---|---|
| Python | >=3.10 |
| Entry point | plane-selfhost-mcp = plane_selfhost_mcp.server:main |
| Runtime deps | httpx, mcp, pydantic |
| Test deps | pytest, pytest-asyncio, respx |
Project structure
src/plane_selfhost_mcp/
├── client.py # Plane REST client
├── config.py # env loading and validation
├── server.py # MCP tool registration and stdio server
└── __main__.py # python -m entrypoint
tests/
└── test_client.py # HTTP client tests
Troubleshooting
Missing environment variables
If you see a runtime error about missing PLANE_BASE_URL, PLANE_API_KEY, or PLANE_WORKSPACE_SLUG, check the project-root .env file first, then check whether the MCP process is receiving any explicit env overrides.
401 Unauthorized
Plane received no credentials. Check whether .env exists in the project root, then check whether the MCP env block is actually being passed.
403 Forbidden
The credential reached Plane but the API key is invalid or lacks access.
Project not found
Verify the workspace slug and call list_projects before attempting issue operations.
License
MIT
推荐服务器
Baidu Map
百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。
Playwright MCP Server
一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。
Magic Component Platform (MCP)
一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。
Audiense Insights MCP Server
通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。
VeyraX
一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。
graphlit-mcp-server
模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。
Kagi MCP Server
一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。
e2b-mcp-server
使用 MCP 通过 e2b 运行代码。
Neon MCP Server
用于与 Neon 管理 API 和数据库交互的 MCP 服务器
Exa MCP Server
模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。