@planoda/mcp-server
by Planoda
README.md
# @planoda/mcp-server
Connect Claude, Cursor, or any [Model Context Protocol](https://modelcontextprotocol.io)
client to a [Planoda](https://planoda.com) workspace.
**What this is:** a small, dependency-free stdio bridge. It forwards JSON-RPC
between your MCP client and Planoda's hosted MCP endpoint. It does not
implement tools itself — the tool list, the schemas, and every permission
check live on the Planoda server.
**What Planoda is:** an AI-native work platform (issues, projects, cycles,
docs, agents). It's a hosted product at [planoda.com](https://planoda.com) and
is pre-launch. This bridge is MIT-licensed and open source; the platform
itself is not.
---
## Requirements
- Node.js **20 or newer** (uses the built-in `fetch`), or Docker
- A Planoda API key — **Settings → API keys** in your workspace
## Install
You don't need to install anything globally. Every snippet below runs the
package on demand via `npx`.
```bash
# Verify it works before wiring it into a client:
PLANODA_API_KEY=ttm_... npx -y @planoda/mcp-server --version
```
---
## Client setup
### Claude Code
```bash
claude mcp add planoda \
--env PLANODA_API_KEY=ttm_your_key_here \
-- npx -y @planoda/mcp-server
```
Planoda also serves MCP over HTTP directly, so you can skip this package
entirely if you prefer:
```bash
claude mcp add --transport http planoda \
https://planoda.com/api/mcp/streamable-http \
--header "Authorization: Bearer ttm_your_key_here"
```
Use this package when your client only speaks stdio, or when you want the
flag ergonomics (`--profile`, `--workspace`) without hand-editing a URL.
### Claude Desktop
Edit `claude_desktop_config.json`:
- macOS — `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows — `%APPDATA%\Claude\claude_desktop_config.json`
```json
{
"mcpServers": {
"planoda": {
"command": "npx",
"args": ["-y", "@planoda/mcp-server"],
"env": {
"PLANODA_API_KEY": "ttm_your_key_here"
}
}
}
}
```
Restart Claude Desktop. Planoda appears in the tools menu.
### Cursor
Edit `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per project):
```json
{
"mcpServers": {
"planoda": {
"command": "npx",
"args": ["-y", "@planoda/mcp-server"],
"env": {
"PLANODA_API_KEY": "ttm_your_key_here"
}
}
}
}
```
### Docker
```bash
docker build -t planoda/mcp-server .
```
```json
{
"mcpServers": {
"planoda": {
"command": "docker",
"args": [
"run", "-i", "--rm",
"-e", "PLANODA_API_KEY",
"planoda/mcp-server"
],
"env": {
"PLANODA_API_KEY": "ttm_your_key_here"
}
}
}
}
```
`-i` is required — MCP stdio needs stdin held open. Do not pass `-t`.
---
## Configuration
Every option has a CLI flag and an environment variable. Flags win.
| Flag | Env var | Default | Purpose |
| --- | --- | --- | --- |
| `--api-key` | `PLANODA_API_KEY` | — | **Required.** Prefer the env var. |
| `--url` | `PLANODA_URL` | `https://planoda.com` | Origin or full endpoint URL. |
| `--profile` | `PLANODA_PROFILE` | — | Narrow the tool surface (see below). |
| `--ns` | `PLANODA_NAMESPACES` | — | Narrow by namespace; wins over `--profile`. |
| `--workspace` | `PLANODA_WORKSPACE` | — | Target a workspace by slug. |
| `--timeout` | — | `120000` | Per-request timeout in ms. |
| `--no-stream` | `PLANODA_STREAM=0` | stream on | Disable the server→client SSE stream. |
| `--verbose` | `PLANODA_VERBOSE=1` | off | Mirror JSON-RPC traffic to stderr. |
### Tool profiles
Planoda exposes a large tool surface. Some clients have a tight budget for
tool schemas, and a smaller surface also makes the model choose better. Pass
`--profile` to scope it:
| Profile | Covers |
| --- | --- |
| `core` | Issues, comments, search, notifications |
| `issues` | Issues, comments, labels, links, checklists |
| `planning` | Projects, cycles, initiatives, milestones, releases |
| `support` | Customer requests, customers, comments, issues |
| `insights` | Insights, dashboards, search (read-only) |
| `deep-research` | Just `search` + `fetch`, for ChatGPT-style connectors |
```json
"args": ["-y", "@planoda/mcp-server", "--profile", "core"]
```
Profiles only filter what's *listed*. They are a token-budget tool, not a
security boundary — the actual boundary is your API key's scopes.
---
## Security model
Read this before you decide how much to trust an agent with your workspace.
**The bridge holds no authority.** It has no tool definitions, no schemas, and
no permission logic. It serializes JSON-RPC frames onto an HTTPS request and
writes the response back to stdout. Forking or patching this package grants
no additional access — everything is decided server-side from your API key.
**Destructive tools require approval.** Planoda's tool registry marks
destructive operations (`delete`, `bulkUpdate`, `bulkArchive`, …) with a
`destructive` flag. Every `tools/call` is evaluated against that flag before
anything executes:
- **Non-destructive tools** run normally.
- **Destructive tools** run only if the session holds the destructive
capability — which requires an appropriate workspace role *and* the acting
user having opted in under **Settings → Agents**. Guest-role sessions never
qualify.
- **Otherwise** the call is refused and you get a structured
*"approval required"* result instead. The tool does not run. Re-issue it
from an interactive Planoda agent session where a human can approve it.
Auto-approved destructive calls are recorded in the workspace audit log under
the same `agent.proposal.*` trail as human-approved ones, so an MCP-driven
change and an in-app one reconcile in one place.
The bridge passes an "approval required" result through untouched, exactly
like any other tool result. **This behavior cannot be disabled from the
client side**, and there is no flag in this package that bypasses it — by
design.
**Tenancy.** An API key is bound to one workspace. Every read and write
executes inside a row-level-security scope for that workspace and the acting
user, so a session cannot observe or modify another workspace's data.
**Handling your key.** Prefer `PLANODA_API_KEY` over `--api-key` so the key
stays out of shell history and process listings. The bridge sends it only to
the configured Planoda origin, and never logs it — `--verbose` prints methods
and ids, not headers. Revoke a key under **Settings → API keys**.
---
## Troubleshooting
**`No API key`** — set `PLANODA_API_KEY`. In Claude Desktop and Cursor, it goes
in the `env` block of the server entry, not your shell profile; those clients
don't inherit your login shell.
**`Planoda rejected the credential (HTTP 401)`** — the key is wrong, revoked,
or from a different workspace. Mint a fresh one under **Settings → API keys**.
**Tools don't appear** — restart the client fully after editing its config.
Then run with `--verbose` and check stderr for the `initialize` exchange.
**A tool returns "approval required"** — working as intended; see the security
model above. That is the guardrail, not an error.
**`npx` is slow to start** — pin the version (`@planoda/mcp-server@0.1.0`) or
`npm i -g @planoda/mcp-server` and use `planoda-mcp` as the command directly.
---
## Development
```bash
npm install
npm run build # tsc → dist/
npm run typecheck
```
The bridge has zero runtime dependencies. TypeScript and `@types/node` are the
only devDependencies.
Layout:
- `src/index.ts` — CLI entry, flag parsing, signal handling
- `src/config.ts` — config precedence and endpoint resolution
- `src/bridge.ts` — the stdio ⇄ Streamable HTTP proxy
- `src/jsonrpc.ts` — JSON-RPC framing and SSE parsing
## License
MIT — see [LICENSE](./LICENSE).
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues