
kunwarvivek/mcp-github-project-manager
Developer toolsAn MCP server that turns GitHub Projects v2 into an agentic project-management layer: agents register, self-assign work, heartbeat, submit work products for review, and spend against token budgets —...
Overview
An MCP server that turns GitHub Projects v2 into an agentic project-management layer: agents register, self-assign work, heartbeat, submit work products for review, and spend against token budgets —...
README
MCP GitHub Project Manager
The task substrate for AI coding agents. An MCP server that turns GitHub Projects v2 into an agentic project-management layer: agents register, self-assign work, heartbeat, submit work products for review, and spend against token budgets — through 21 compound tools exposing 175 actions, backed entirely by GitHub-native storage. No database, no Redis, no external infra.
You bring the agents (Claude Code, Codex, Cursor, Windsurf, Roo, OpenCode, any MCP client). This is the backbone that tells them what to work on and keeps them from colliding.
| Surface | Detail |
|---|---|
| Tools | 21 compound tools, 175 actions, action-routed |
| Resources | 6 read-only GitHub-backed views |
| Prompts | 6 reusable AI templates |
| Transport | MCP v2 over stdio (webhook/SSE optional) |
| Storage | GitHub issues, project fields, comments — no external infra |
| Runtime | Node >= 22.12.0 · MIT license |
Why this exists
- Agents need a work queue, not a chat window.
agent_work/agent_managegive agents atomic task checkout, heartbeats, and a review loop instead of “go figure it out.” - Budgets must be enforced somewhere the agent cannot skip. Each agent has a token budget with warning thresholds and a hard stop; the server debits itself, and
record_usagecovers the agent’s own runtime spend. - AI plans are worthless if they never become issues.
ai_generateruns idea → PRD → tasks → materialized GitHub issues, grouped into milestones and sprints. - Tool lists are a context tax. 21 tools instead of 175 keeps the schema small;
discover_toolsexpands any domain or action on demand. - State should live where the work already is. The agent registry is a file on a dedicated branch (compare-and-swap writes), task claims are project fields, work products are issue comments — no new infrastructure to operate.
Quick start
Requires Node.js >= 22.12.0 (Node 24 recommended).
# 1. Install (global, or use npx / pnpm dlx / docker compose — see below)
npm install -g mcp-github-project-manager
# 2. Configure (a working `gh auth login` means you can skip GITHUB_TOKEN)
export GITHUB_TOKEN="ghp_..."
export GITHUB_OWNER="your-org-or-user"
export GITHUB_REPO="your-repo"
# 3. Run the MCP stdio server
mcp-github-project-manager
Register it with an MCP client:
{
"mcpServers": {
"github-project-manager": {
"command": "npx",
"args": ["-y", "mcp-github-project-manager"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"GITHUB_OWNER": "your-org-or-user",
"GITHUB_REPO": "your-repo"
}
}
}
}
# Claude Code CLI
claude mcp add github-project-manager -- npx -y mcp-github-project-manager
# Docker
docker compose up --build
Install paths: npm install -g mcp-github-project-manager, npx -y mcp-github-project-manager, pnpm dlx mcp-github-project-manager, or docker compose up --build.
A GitHub token needs repo, project, and write:org scopes. Full setup options live in the Deployment Guide and the Getting Started tutorial.
Works with any stdio MCP client — Claude Desktop, Claude Code, Codex, Cursor, Windsurf, Roo Code, VS Code + Copilot, OpenCode, and custom harnesses.
The tool surface
Every tool takes an action string that routes to the underlying operation, so clients see 21 schemas instead of 175.
| Tool | Group | Actions | Covers |
|---|---|---|---|
manage_project |
core | 38 | Projects v2: CRUD, close/reopen, fields, views, items, templates, repo/team linking, collaborators |
manage_issues |
core | 22 | Issue CRUD, comments, drafts, advanced search, sub-issues, native blockers, issue types |
manage_prs |
core | 7 | Create, list, update, merge, reviews |
manage_milestones |
core | 7 | CRUD, metrics, overdue and upcoming |
manage_sprints |
core | 9 | Create, update, delete (needs confirm: true), plan, add/remove issues, metrics |
manage_labels |
core | 2 | Create and list repository labels |
manage_automation |
core | 3 | Project workflows: list, get, delete |
manage_iterations |
core | 5 | Iteration config, current iteration, items, by-date, assign |
manage_status_updates |
core | 3 | Project status updates: create, list, get |
manage_branches |
core | 4 | Branch protection rules and branch listing |
manage_releases |
core | 6 | Releases: create, list, get, update, delete, latest |
manage_workflows |
core | 6 | GitHub Actions: list, dispatch, run status/logs, cancel |
manage_events |
events | 3 | Subscribe, recent events, replay |
ai_generate |
ai | 9 | PRD generate/enhance/parse, features, next task, complexity, expand, traceability, materialize |
ai_analyze |
ai | 8 | Issue enrichment, triage, label suggestion, duplicate and related detection |
ai_plan |
ai | 6 | Capacity, backlog priority, risk, sprint composition, roadmap, visualization |
agent_work |
agents | 12 | Register, checkout, release, complete, heartbeat, review, task context |
agent_manage |
agents | 18 | Registry, activity, work products, budgets, usage, PM coordination, convergence |
system |
system | 2 | Health check (live GitHub rate-limit probe), project field setup |
analytics |
core | 5 | Read-only sprint velocity and burndown, cycle time, throughput, project summary |
discover_tools |
system | meta | Runtime discovery of tools, actions, and parameters |
Call shape — one discriminator, action-specific parameters:
{ "tool": "manage_project", "arguments": { "action": "create", "title": "Q3 Roadmap", "owner": "myorg" } }
{ "tool": "manage_issues", "arguments": { "action": "create", "title": "Add login form", "body": "..." } }
{ "tool": "agent_work", "arguments": { "action": "checkout_task", "agentId": "agent-abc123", "strategy": "highest_priority" } }
{ "tool": "discover_tools", "arguments": { "domain": "sprints" } }
discover_tools takes an optional domain (projects, issues, pull_requests, milestones, sprints, labels, automation, iterations, events, status_updates, analytics, ai_generation, ai_analysis, ai_planning, agents, system) or a free-text query. It stays exposed even when tool groups are filtered.
Cross-cutting contract: create actions accept an optional idempotencyKey (a retry within 24 h replays the first result instead of duplicating it); list actions that page return an additive nextCursor to pass back as cursor; every tool advertises _meta.schemaVersion. See docs/TOOLS.md.
Alongside the tools the server exposes 6 read-only resources (github://config, github://projects, github://sprints/current, github://milestones, github://agents, github://tools) and 6 prompts (review-prd, explain-task-complexity, suggest-issue-labels, analyze-sprint-risk, generate-release-notes, triage-issue).
Full parameter reference: docs/TOOLS.md.
What it can do
AI generation (ai_generate) — generate a PRD from an idea, enhance an existing one, parse a PRD into tasks, add a feature with impact analysis, recommend the next task, analyze complexity and risk, expand a task into subtasks, build a traceability matrix, and materialize tasks into real GitHub issues.
AI analysis (ai_analyze) — enrich one or many issues, triage (single or bulk), suggest labels, detect duplicates, find related issues.
AI planning (ai_plan) — calculate sprint capacity, prioritize a backlog, assess risk, suggest sprint composition, generate a roadmap or visualization. Given a projectId the roadmap is planned from that project’s own issues; with autoCreate the milestones are created and assigned to them.
Agent swarm (agent_work / agent_manage) — agents register with role, runtime, and capabilities; claim tasks by priority, age, skills, or deadline; heartbeat with progress and blockers; submit work products (branch, PR, files, test results) for review; approve, reject, or decompose. PM-side actions add budgets, usage accounting, stale-agent reclaim, workload rebalancing, smart assignment, and one-call project convergence.
Deterministic GitHub surface — projects, issues, pull requests, milestones, sprints, labels, branches, releases, workflows, project automations, events, status updates, and analytics, all with plain action routing and no model in the loop.
The AI tools are optional. Without a provider key, everything else works unchanged.
The agent loop, end to end
{ "tool": "agent_work", "arguments": { "action": "register", "name": "claude-eng-1", "role": "engineer", "runtime": "claude-code", "capabilities": ["typescript", "testing"] } }
{ "tool": "agent_work", "arguments": { "action": "checkout_task", "agentId": "agent-abc123", "strategy": "highest_priority" } }
{ "tool": "agent_work", "arguments": { "action": "get_task_context", "issueNumber": 42 } }
{ "tool": "agent_work", "arguments": { "action": "heartbeat", "agentId": "agent-abc123", "status": "working", "taskId": "issue-42", "progress": 60, "currentBranch": "feat/42-add-login-form" } }
{ "tool": "agent_manage", "arguments": { "action": "submit_work_product", "agentId": "agent-abc123", "taskId": "issue-42", "issueNumber": 42, "branch": "feat/42-add-login-form", "prNumber": 99, "summary": "Added login form with validation" } }
{ "tool": "agent_work", "arguments": { "action": "complete_task", "agentId": "agent-abc123", "taskId": "issue-42", "summary": "Implemented and tested" } }
A runnable version of this loop (worker + reviewer, every id threaded from the previous response, non-zero exit on any failure) lives in examples/basic/agent-loop.ts; --plan prints the call sequence with symbolic references.
Checkout strategies: highest_priority, oldest_first, skills_match, milestone_deadline, ai. Budgets are set with agent_manage and action: "set_budget"; reset periods are daily, weekly, monthly, or never.
Where the state lives — no external database:
| Data | GitHub-native storage |
|---|---|
| Agent registry | registry.json on the agent-registry branch (Contents API, sha compare-and-swap) |
| Task claims | Project custom fields (agent_claimed_by, agent_status, agent_pr_number, …) |
| Work products | Structured issue comments |
| Budgets and heartbeats | Agent records in the registry |
Configuration
| Variable | Required | Purpose |
|---|---|---|
GITHUB_TOKEN |
yes* | GitHub PAT with repo, project, write:org |
GITHUB_OWNER |
yes | Owner (user or org) of the target repository |
GITHUB_REPO |
yes | Target repository name |
GITHUB_APP_ID, GITHUB_APP_PRIVATE_KEY, GITHUB_APP_INSTALLATION_ID |
no | GitHub App installation auth; outranks the PAT when all three are set (a partial set falls back to the PAT) |
ANTHROPIC_API_KEY, OPENAI_API_KEY, GOOGLE_API_KEY, PERPLEXITY_API_KEY |
no | Unlocks the ai_* tools |
AI_{MAIN,PRD,RESEARCH,FALLBACK}_{PROVIDER,MODEL,API_KEY,BASE_URL} |
no | Per-role provider, model, key, endpoint |
MCP_TOOL_GROUPS |
no | Expose only some groups: core, ai, agents, events, system (default all) |
SECRETS_DIR |
no | Read secrets from files named after the variable (Docker/k8s convention) |
WEBHOOK_SECRET, WEBHOOK_PORT, SSE_ENABLED |
no | Webhook/SSE transport; signature validation fails closed |
WEBHOOK_HOST, EVENTS_AUTH_TOKEN, WEBHOOK_TRUSTED_PROXIES |
no | HTTP hardening: binds 127.0.0.1 by default; /events/* needs the bearer token; X-Forwarded-For trusted only from listed proxies |
SYNC_ENABLED, CACHE_DIRECTORY, MAX_CACHE_ENTRIES |
no | Bidirectional sync and cache tuning |
RATE_LIMIT_FLOOR |
no | Remaining GraphQL points below which requests back off proactively (default 100) |
AUDIT_LOG_ENABLED, AUDIT_LOG_PATH |
no | Append-only, redacted JSONL record of every state-changing tool call (.mcp-audit/mutations.jsonl) |
OTEL_EXPORTER_OTLP_ENDPOINT, OTEL_SERVICE_NAME |
no | Opt-in OpenTelemetry tracing (tool. spans) |
AI_SESSION_TOKEN_LIMIT |
no | Per-operation token budget for AI task generation (distinct from per-agent budgets) |
LOG_LEVEL, LOG_FORMAT |
no | debug|info|warn|error, text or json |
* Credential chain (first hit wins): --token CLI flag → $SECRETS_DIR/GITHUB_TOKEN file → GITHUB_TOKEN env var → gh auth token. If you are already logged in with gh, you need no token configuration at all. Disable the fallback with GH_CLI_TOKEN_FALLBACK=false. CLI flags override env vars everywhere.
Narrow the exposed surface with group filters (group names, not tool names):
MCP_TOOL_GROUPS=core # project management only
MCP_TOOL_GROUPS=core,ai # add the AI tools
MCP_TOOL_GROUPS=all # default — everything
AI providers: anthropic, openai, google, perplexity, and openai-compatible (OpenRouter, Together, Groq, Ollama, LM Studio, Azure OpenAI, …). There are no default models — you configure the models you use, per role, so you can run OpenRouter for cheap daily work and a frontier model for PRD generation. A partially configured GitHub App falls back to the PAT rather than locking you out.
Full list: docs/CONFIGURATION.md.
Running it
Every script is package-manager agnostic — npm run X and pnpm run X are identical, and both lockfiles are committed.
| Task | Command |
|---|---|
Build (tsc → fix-imports.js → chmod) |
npm run build |
| Typecheck (src + examples, src + tests) | npm run typecheck |
| Lint | npm run lint |
| Format | npm run format |
| Unit tests | npm test |
| Dev (watch) | npm run dev |
| Coverage | npm run test:coverage |
| E2E, mocked GitHub/AI | npm run test:e2e:tools |
| E2E, live API (uses rate limit) | E2E_REAL_API=true npm run test:e2e:tools:real |
| AI suites | npm run test:ai |
| Inspect the server | npm run inspect |
Point an MCP client at a local build with {"command": "node", "args": ["build/index.js"]}.
Deployment and MCP-client setup: docs/deployment.md. When something misbehaves: docs/TROUBLESHOOTING.md.
Architecture at a glance
Four layers, dependencies pointing inward:
- Domain (
src/domain/) — types, Zod schemas, errors, and rich entities (entities/) that carry their own invariants and state-transition logic. Orchestration and I/O live in services. - Services (
src/services/) — business logic;ProjectManagementServiceorchestrates per-feature services,src/services/ai/holds the AI SDK providers. - Infrastructure (
src/infrastructure/) —github/(Octokit GraphQL/REST),tools/(tool definitions, registry, validators,compound/), plus cache, persistence, resilience, events, secrets, logger, MCP resources and prompts. - MCP (
src/index.ts) — bootsMcpServer(MCP v2) over stdio; every tool is registered withregisterTooland shares onedispatchToolcarrying the shutdown gate, in-flight tracking, and result formatting.
src/container.ts wires the components index.ts owns with tsyringe DI; src/env.ts and src/cli.ts resolve configuration (CLI flags beat env vars). Tool executors self-construct through one shared factory (createGitHubFactory()), a documented exception to container resolution. Authentication is resolved once by resolveGitHubAuth() (GitHub App outranks the PAT) and all GitHub traffic goes through one GitHubRequestExecutor with retry and proactive rate-limit budgeting. AI providers plug in behind AIServiceFactory: it returns a model per role, wraps it in usage-reporting middleware, and the shared dispatcher debits the calling agent’s budget once per tool call (a hard-stop budget gates AI tools with BudgetExhausted).
A tool that runs and fails returns { content, isError: true } with a stable code in _meta.error so the model can recover; a JSON-RPC error is reserved for an unknown tool or protocol faults.
Design details: docs/architecture.md.
Contributing
Task tracking uses bd (beads) — bd ready, bd show , bd update --claim, bd close . Code traversal and audits use GitNexus: run impact analysis before editing a symbol and change analysis before committing. Refresh the index with node .gitnexus/run.cjs analyze --index-only when that runner exists in your checkout; otherwise bootstrap the CLI with npx/bunx/pnpm dlx gitnexus@latest analyze. Per-task recipes live in .agents/skills/gitnexus-*/SKILL.md.
The quality gate, in order: npm run build → npm run typecheck → npm run lint → npm test.
Traps that bite contributors:
- Source imports omit
.js. Thepostbuildstep adds the extension. Never ship rawtscoutput — always run the full build. isolatedModulesis on. A type re-exported as a value is a compile error; useexport type/import type, including for decorated constructor parameters.- Vitest rejects foreign test-runner CLI flags.
--testPathPatternfails withCACError: Unknown option; filter with a positional pattern and exclude with--exclude='**/e2e/**'. - Mocks must use
function, not an arrow, wherever the code under test callsnew. AbeforeEachwith an implicit return is treated as a teardown callback — use a block body.
Start with CONTRIBUTING.md and docs/contributing/index.md.
License
MIT — see CHANGELOG.md for the release history.
Documentation
| Guide | What it covers |
|---|---|
| Tool Reference | 21 compound tools, 175 actions, per-action parameters |
| Configuration | Every environment variable and per-role AI setup |
| Deployment | Install paths, Docker, MCP client configuration |
| Architecture | Layers, patterns, data flow, agent orchestration |
| User Guide | Day-to-day usage |
| Tutorials | Step-by-step walkthroughs |
| Troubleshooting | Common failures and fixes |
| Contributing | Development workflow and standards |
Install
npx -y mcp-github-project-managerConfiguration
{
"mcpServers": {
"github-project-manager": {
"command": "npx",
"args": ["-y", "mcp-github-project-manager"],
"env": {
"GITHUB_TOKEN": "ghp_...",
"GITHUB_OWNER": "your-org-or-user",
"GITHUB_REPO": "your-repo"
}
}
}
}