Multi-Server FastMCP PR Reviewer
README.md
# Multi-Server FastMCP PR Reviewer
Zero-cost, multi-server Model Context Protocol (MCP) suite with a unified
gateway and a LangGraph automated PR-review agent. Every tool/API used is
free-tier eligible (GitHub PAT, Groq LLM).
## Architecture
```
Claude Desktop / Agent
|
v
FastMCP Gateway (namespaces: code., gh., doc. — dot-separated per MCP tool-naming spec)
/ | \
v v v
Code GitHub Documentation
Intel Server Server (Groq)
(AST+Radon)(PyGithub)
\ | /
Shared Security & Audit Layer
(API key auth, SQLite WAL, rate limiting)
```
## Project layout
```
mcp-pr-reviewer/
├── core/
│ └── security.py # auth + rate limit + SQLite audit decorator
├── servers/
│ ├── code_server.py # AST/radon static analysis (no external API)
│ ├── github_server.py # PyGithub-backed PR/issue/commit tools
│ └── doc_server.py # Groq-backed docstring/README/API doc generation
├── gateway/
│ └── gateway.py # unifies all three servers under code:/gh:/doc: namespaces
├── agent/
│ └── workflow.py # LangGraph PR-review pipeline (fetch → analyze → doc → publish)
├── data/ # SQLite audit_log.db lives here (gitignored)
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
├── .env.example
└── claude_desktop_config.example.json
```
## Setup
```bash
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
cp .env.example .env
# edit .env with your real MCP_API_KEY, GITHUB_TOKEN, GROQ_API_KEY
```
Load the env vars before running anything locally, e.g.:
```bash
export $(grep -v '^#' .env | xargs) # macOS/Linux
```
## Running
### Individual servers (stdio, for local testing)
```bash
python servers/code_server.py
python servers/github_server.py
python servers/doc_server.py
```
### Gateway
```bash
fastmcp run gateway/gateway.py:gateway
```
### Docker
```bash
docker compose up --build
```
## Claude Desktop integration
Copy `claude_desktop_config.example.json` into your Claude Desktop config
(`claude_desktop_config.json`), fix the absolute path to `gateway/gateway.py`,
and fill in real credentials. Restart Claude Desktop to pick it up.
## Testing checklist
### 1. Schema verification
```bash
fastmcp inspect servers/code_server.py
fastmcp inspect servers/github_server.py
fastmcp inspect servers/doc_server.py
```
### 2. Security / audit verification
```bash
# Should raise 401 Unauthorized
CLIENT_API_KEY=wrong_key python -c "from servers.code_server import analyse_code; analyse_code('x = 1')"
# Inspect the WAL SQLite audit log
sqlite3 data/audit_log.db "SELECT * FROM access_log ORDER BY id DESC LIMIT 5;"
```
### 3. End-to-end PR review
```bash
python -c "
import asyncio
from agent.workflow import app
async def run():
result = await app.ainvoke({
'repo': 'your-username/your-repo',
'pr_number': 1
})
print('Review published:', result['issue_url'])
asyncio.run(run())
"
```
## Notes / things to double-check before you rely on this in production
- `core/security.py`'s `bucket` is a single process-wide `TokenBucket` — every
tool across a server shares the same 60/min budget. Split into per-tool or
per-client buckets if you need finer-grained limits.
- `secure_tool` raises FastAPI's `HTTPException`, which only maps cleanly to
HTTP status codes if the FastMCP transport you're running actually sits
behind FastAPI/ASGI. If you run a server over plain stdio, catch this at the
MCP layer or replace it with a transport-appropriate exception.
- Rotate `MCP_API_KEY`, `GITHUB_TOKEN`, and `GROQ_API_KEY` out of `.env` and
into a real secrets manager before any non-local deployment — `.env` is
fine for dev only.
- GitHub's code search API is capped much lower than the core API (30 req/min
vs 5,000 req/hr) — `search_repo_code` will hit that ceiling first under load.
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues