Skip to main content
Glama
README.md
# plane-local-mcp

MCP (Model Context Protocol) local para [Plane Community Edition](https://plane.so/) self-hosted.

Usa a API pública `/api/v1/.../issues/` (compatível com Plane CE). Útil para listar projetos, issues, estados, labels, cycles e buscar itens pelo identificador humano (`PROJECT-N`, ex.: `CKTPC-838`).

## Pré-requisitos

- Python `>= 3.10`
- [uv](https://docs.astral.sh/uv/) instalado e no `PATH`
- Instância Plane CE acessível + API key

## Instalação

```bash
git clone https://github.com/JonatanCosta/plane-local-mcp.git
cd plane-local-mcp
uv sync
```

Anote o caminho absoluto do clone (ex.: `/Users/voce/plane-local-mcp`). Ele será usado nas configs abaixo.

## Variáveis de ambiente

| Variável | Obrigatória | Descrição |
| --- | --- | --- |
| `PLANE_API_KEY` | sim | API key do Plane |
| `PLANE_WORKSPACE_SLUG` | sim | Slug do workspace |
| `PLANE_BASE_URL` | sim | URL base da instância (sem `/api`) |

Exemplo:

```bash
export PLANE_API_KEY="plane_api_..."
export PLANE_WORKSPACE_SLUG="meu-workspace"
export PLANE_BASE_URL="https://plane.exemplo.com"
```

## Cursor

Edite `~/.cursor/mcp.json` (ou Settings → MCP → Add server) e adicione:

```json
{
  "mcpServers": {
    "plane": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/ABS/PATH/plane-local-mcp",
        "plane-local-mcp"
      ],
      "env": {
        "PLANE_API_KEY": "plane_api_...",
        "PLANE_WORKSPACE_SLUG": "meu-workspace",
        "PLANE_BASE_URL": "https://plane.exemplo.com"
      }
    }
  }
}
```

Substitua `/ABS/PATH/plane-local-mcp` pelo caminho absoluto do repositório. Reinicie o Cursor (ou recarregue os MCPs) e confira se o servidor `plane` aparece com as tools.

## Claude Desktop

1. Abra **Settings → Developer → Edit Config** (cria o arquivo se ainda não existir).
2. Edite `claude_desktop_config.json`:

   - macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
   - Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```json
{
  "mcpServers": {
    "plane": {
      "command": "uv",
      "args": [
        "run",
        "--directory",
        "/ABS/PATH/plane-local-mcp",
        "plane-local-mcp"
      ],
      "env": {
        "PLANE_API_KEY": "plane_api_...",
        "PLANE_WORKSPACE_SLUG": "meu-workspace",
        "PLANE_BASE_URL": "https://plane.exemplo.com"
      }
    }
  }
}
```

3. Feche completamente o Claude Desktop e abra de novo.
4. No chat, o ícone de ferramentas (martelo) deve listar as tools do Plane.

> Dica: se `uv` não for encontrado, use o caminho absoluto do binário (ex.: `/Users/voce/.local/bin/uv`).

## Claude Code (CLI)

```bash
claude mcp add plane --env PLANE_API_KEY=plane_api_... \
  --env PLANE_WORKSPACE_SLUG=meu-workspace \
  --env PLANE_BASE_URL=https://plane.exemplo.com \
  -- uv run --directory /ABS/PATH/plane-local-mcp plane-local-mcp
```

Ou edite `~/.claude/settings.json` / `.claude/settings.json` com o mesmo bloco `mcpServers` do Cursor.

## Codex (CLI / IDE)

Edite `~/.codex/config.toml` (ou `.codex/config.toml` no projeto, se ele estiver trusted):

```toml
[mcp_servers.plane]
command = "uv"
args = [
  "run",
  "--directory",
  "/ABS/PATH/plane-local-mcp",
  "plane-local-mcp",
]

[mcp_servers.plane.env]
PLANE_API_KEY = "plane_api_..."
PLANE_WORKSPACE_SLUG = "meu-workspace"
PLANE_BASE_URL = "https://plane.exemplo.com"
```

Alternativa via CLI:

```bash
codex mcp add plane --env PLANE_API_KEY=plane_api_... \
  --env PLANE_WORKSPACE_SLUG=meu-workspace \
  --env PLANE_BASE_URL=https://plane.exemplo.com \
  -- uv run --directory /ABS/PATH/plane-local-mcp plane-local-mcp
```

Em uma sessão Codex, use `/mcp` para validar que o servidor conectou.

## Tools disponíveis

| Tool | Descrição |
| --- | --- |
| `get_instance_info` | Base URL, workspace e estilo de API |
| `list_projects` | Lista projetos do workspace |
| `retrieve_project` | Projeto por UUID |
| `list_states` | Estados (colunas) do projeto |
| `list_labels` | Labels do projeto |
| `list_modules` | Modules do projeto |
| `list_cycles` | Cycles do projeto |
| `list_issues` | Issues do projeto (`/issues/`) |
| `retrieve_issue` | Issue por UUID |
| `get_issue_by_identifier` | Issue por `PROJECT-N` (ex.: `CKTPC-838`) |
| `list_issue_children` | Filhos de um épico/issue |
| `update_issue` | Edita título, descrição, prioridade e/ou status |
| `add_issue_to_cycle` | Adiciona issue a um cycle |
| `remove_issue_from_cycle` | Remove issue de um cycle |

### Exemplos de edição

```text
update_issue(identifier="CKTPC-844", name="Novo título")
update_issue(identifier="CKTPC-844", description="Texto simples da descrição")
update_issue(identifier="CKTPC-844", state_name="Em Execução")
add_issue_to_cycle(identifier="CKTPC-844", cycle_name="Payment Sprint - 23")
```

Notas:
- Descrição no Plane usa HTML (`description_html`). Se passar `description` em texto puro, o MCP converte para HTML mínimo.
- Status e cycle aceitam UUID (`state_id` / `cycle_id`) ou nome (`state_name` / `cycle_name`).
- Cycle não entra no PATCH da issue: a API exige `POST .../cycles/{id}/cycle-issues/`.

## Desenvolvimento

```bash
uv sync
uv run plane-local-mcp
```

O servidor fala MCP via **stdio**.

## Licença

MIT

TDQS

B3.3/5.0

Scored across 14 tools

Disambiguation4/5

Each tool targets a distinct resource or action, but the pair retrieve_issue and get_issue_by_identifier both retrieve a single issue, differing only by lookup key. This minor overlap is clarified by descriptions, so most tools are unambiguous.

Naming Consistency4/5

Names follow a verb_noun pattern with snake_case throughout, but verbs are inconsistent (list, get, retrieve, update, add, remove). This is readable but not as uniform as using the same verb for the same operation.

Tool Count5/5

With 14 tools, the server covers issues, cycles, states, labels, modules, and projects without feeling bloated. This is well-scoped for a project management integration.

Completeness3/5

The surface has strong read and update coverage for issues and cycles, but notably lacks a create_issue tool or any deletion capability. Agents cannot create new issues, so the lifecycle is incomplete.

Maintenance

ActivitySlowing
ResponsivenessNo issues