Productboard MCP — Curve & Flex
README.md
# Productboard MCP — Curve & Flex
Custom MCP server exposing read/write tools over the Productboard v2 API, with
Google-OAuth 2.1 login, a per-email allowlist, and per-user workspace binding
(Curve + Flex served from one Cloud Run service).
**This is the canonical source.** Baseline captured from the source of the
May 26 2026 production deploy and committed as v1 (July 2026). Earlier local
prototypes live in `../_Archive/` — do not edit those; they are pre-OAuth and
out of date.
## Layout
- `src/server.py` — the MCP tools (the tool surface Claude sees)
- `src/productboard.py` — Productboard v2 API client (auth, retries, pagination, notes)
- `src/auth.py` — the MCP's own OAuth 2.1 (Google IDP + JWT). NOT Productboard auth.
- `src/allowlist.py` — who may use the MCP + their workspace binding
- `Dockerfile`, `requirements.txt`, `deploy.sh` — build & deploy
- `ROADMAP.md` — forward plan
## Deploy
```
./deploy.sh # READ_ONLY=true (write tools disabled) — default
READ_ONLY=false ./deploy.sh # enable write tools
```
Target: project `productboard-mcp`, region `us-central1`, service
`productboard-mcp` (`gcloud run deploy --source=.`). Secrets — the per-workspace
Productboard API tokens, the OAuth client secret, and the JWT signing key — are
mounted from Secret Manager. Never store them here.
## Rules
- No secrets in the repo. Tokens live in Secret Manager; `src/allowlist.py` is the
only access config in-tree, and git history is its audit trail.
- Safe surface by design: no create-feature tool, no permanent delete (soft-delete
via `archived`). Keep it that way.
- Write access is per-user: only allowlist entries with `writer: True` can call
the write tools, even when the service runs `READ_ONLY=false` (the env var
stays as the global kill switch). Currently: Luke only.
## Revocation
- **One user, immediately:** set `tokens_valid_after` on their allowlist entry
(or remove the entry), commit, redeploy. Takes effect on their next request —
permissions are re-derived from the allowlist on every call, not frozen into
tokens.
- **Everyone at once (break-glass):** bump the `TOKEN_VERSION` env var
(`gcloud run services update productboard-mcp --region=us-central1
--update-env-vars=TOKEN_VERSION=<n+1>`). All outstanding tokens die instantly;
users re-auth via Google. No code change, no key rotation.
- Refresh tokens live 7 days; offboarding must still remove the allowlist entry
(leaver-checklist item — disabling the Google account alone does NOT cut
existing sessions).
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing