Skip to main content
Glama
geek-o-geek

mcp-diff-system

by geek-o-geek
README.md
# mcp-diff-system

An MCP server that fetches, summarizes and reviews GitHub code diffs — built
with **FastMCP** and deployed on **AWS Fargate**, with an SQS worker plane so
that LLM calls never block the request/response cycle.

Built in phases. Each phase is tagged, runs on its own, and ends with something
demonstrable. See [ROADMAP.md](ROADMAP.md) for the full plan and
[docs/diagrams](docs/diagrams) for the target architecture.

> **Current phase: 1 — walking skeleton.**
> One tool, `get_diff`, hitting the real GitHub API. No auth, no AWS, no LLM.

---

## The core design decision

A large diff takes 30–90 seconds to summarize. ALB idle timeouts — and MCP
client patience — are both shorter than that.

So the summarize/review tools (Phase 3) don't call the LLM inline. They persist
the diff, enqueue a job, and return a `job_id` in ~50ms. A separate worker tier,
autoscaled on queue depth, does the slow work. One large diff can then never
hold a connection open or starve capacity for anyone else.

`get_diff` stays synchronous, because a GitHub API call is a fast network round
trip and the async job machinery would be overhead for no benefit.

---

## Phase 1: running it

Requires Python 3.11+.

```bash
pip install -e ".[dev]"
cp .env.example .env        # optionally add a GitHub token
```

A token is optional for public repos, but without one GitHub allows only 60
requests/hour instead of 5000. You will hit that.

Start the server:

```bash
python -m src.api.server        # HTTP transport on :8000
```

Or poke at the tools interactively:

```bash
fastmcp dev src/api/server.py   # opens MCP Inspector
```

Then call `get_diff` with, say, `repo=psf/requests`, `base=v2.31.0`,
`head=v2.32.0`.

### Connecting Claude Desktop

```json
{
  "mcpServers": {
    "diff": {
      "command": "python",
      "args": ["-m", "src.api.server"],
      "cwd": "/absolute/path/to/mcp-diff-system"
    }
  }
}
```

### Tests

```bash
pytest
ruff check src tests
```

---

## Two things about GitHub's diff API

Both are easy to get wrong, and both are pinned by tests in
`tests/test_github_client.py`:

1. **The diff media type goes in the `Accept` header, not a query parameter.**
   Send `Accept: application/vnd.github.diff`. Get this wrong and GitHub
   quietly returns JSON instead of a diff — no error, just garbage flowing
   downstream.

2. **Rate limiting is a 403, not a 429.** The signal is
   `x-ratelimit-remaining: 0`. Keying off that header beats string-matching the
   response body.

---

## Roadmap

| Phase | Adds | Status |
|-------|------|--------|
| 0 | Repo skeleton, CI, lint, tests | Done |
| 1 | FastMCP server, `get_diff` | Done |
| 2 | S3 + DynamoDB + SQS job plane (stub worker, no LLM) | Next |
| 3 | Diff chunker + Anthropic client — real summaries | |
| 4 | Circuit breakers, retries, DLQ, idempotent claim | |
| 5 | JWT auth, atomic Redis rate limiting, payload guard | |
| 6 | Correlation IDs, CloudWatch metrics, X-Ray | |
| 7 | Terraform, dual ECS services, autoscaling, OIDC CI/CD | |

## License

MIT