gh-board-mcp
# gh-board-mcp
MCP server for managing **GitHub Projects v2** as a personal kanban board. Create activities (draft items), move them between columns, track priority — without linking to real issues.
## Requirements
- Node.js >= 18
- A [GitHub Personal Access Token](https://github.com/settings/tokens) with the **project** scope (fine-grained: Projects read/write)
## Usage
The package is published on npm — any MCP client can launch it with `npx gh-board-mcp`:
```bash
GITHUB_TOKEN=ghp_xxx npx -y gh-board-mcp
```
### Claude Code
Register it globally (available in all projects):
```bash
claude mcp add gh-board-mcp -s user -e GITHUB_TOKEN=ghp_xxx -- npx -y gh-board-mcp
```
- `-s user` → global config (all projects); use `-s project` to scope it to a single repo.
- `-e GITHUB_TOKEN=...` sets the token env var; the `--` separates the server command.
- Verify with `claude mcp list` → `gh-board-mcp` should show `Connected`.
### OpenCode
Add it to the global config at `~/.config/opencode/opencode.json` (or `.jsonc`):
```jsonc
{
"mcp": {
"gh-board-mcp": {
"type": "local",
"command": ["npx", "-y", "gh-board-mcp"],
"enabled": true,
"environment": {
"GITHUB_TOKEN": "ghp_xxx"
}
}
}
}
```
Verify with `opencode mcp list` → `gh-board-mcp` should show `connected`.
## Tools
| Tool | Description |
|------|-------------|
| `list_projects` | List your GitHub Projects v2 boards |
| `create_project` | Create a new board (default Status + Priority fields, opens with a board view) |
| `list_activities` | List activities (draft items), filter by status/priority |
| `create_activity` | Create an activity with optional status/priority |
| `move_activity` | Move an activity to another status (and set priority) |
| `update_activity` | Edit an activity's title/description |
| `delete_activity` | Delete an activity (permanent) |
| `archive_activity` | Archive an activity (hidden from lists, reversible) |
| `unarchive_activity` | Restore an archived activity |
## Status & Priority
- `create_project` creates a new board with Status = **Todo / In Progress / Done**, Priority = **Urgent / High / Medium / Low**, and a board (kanban) view as its default view.
- Boards created from a GitHub template keep their own Status/Priority options — pass values that exist on the board. `create_activity`, `move_activity`, and `list_activities` report the valid options when given an unknown value.
- Custom columns are not supported via the API (configure them in the GitHub UI).
## Notes
- **Read cap:** `list_activities` and `list_projects` read up to 100 items / projects in one call; larger boards are truncated.
- **Archive ≠ delete:** `archive_activity` hides an item from `list_activities` but keeps it (restorable via `unarchive_activity`); `delete_activity` removes it permanently.
- **Eventual consistency:** GitHub Projects v2 writes can take a moment to appear in reads — a `list_activities` immediately after `create_activity` may briefly miss the new item.
- **Create is not atomic:** `create_activity` validates the status/priority options before creating, so a bad option leaves nothing behind; a transient network error mid-create can still leave a draft without its field values.
## Development
```bash
npm install
npm test
npm run build
npm run dev
```
## License
MIT
TDQS
Scored across 7 tools
Each tool targets a distinct resource or action: projects (list/create) vs activities (create/list/move/update/delete). No two tools have overlapping purposes, and descriptions clearly differentiate them.
All tools follow a consistent verb_noun pattern where listing uses plural nouns (list_projects, list_activities) and other actions use singular nouns (create_project, create_activity, move_activity, update_activity, delete_activity).
With 7 tools, the server covers the essential operations for GitHub Projects v2 board management without being bloated or minimal. Each tool serves a clear and necessary purpose.
Core CRUD on activities is mostly covered, but missing operations like updating or deleting a project are notable omissions. There is no tool to retrieve a single activity by ID, though list_activities with filters partially compensates.