Skip to main content

GitHub PR Context MCP

Python Protocol Version Downloads

This MCP retrieves evidence. Your IDE agent decides what it means.

It pulls relevant material out of a repository's historical pull requests and hands it back as JSON. Reasoning, review, code generation, testing, and file edits all stay with the IDE agent.

How it works

flowchart LR
    U["Developer request"] --> A["IDE agent"]
    A -->|"tool call"| M["PR Context MCP"]
    M --> AU["Device Flow"]
    AU --> K["OS credential vault"]
    M --> G["GitHub PR history"]
    M --> V["ChromaDB index"]
    M -->|"evidence JSON"| A
    A --> O["Review, plan, code, tests"]

    style M fill:#2d6a4f,color:#fff
    style A fill:#1d3557,color:#fff
flowchart TB
    subgraph SRV["MCP server — retrieval only"]
        S1["Fetch, normalize, embed, store, retrieve"]
        S2["Embedding model finds related records"]
        S3["Never makes a verdict"]
    end
    subgraph AGT["IDE agent — all reasoning"]
        A1["Chooses tools"]
        A2["Checks current code"]
        A3["Writes and validates the result"]
    end
    SRV -->|"evidence"| AGT

    style SRV fill:#2d6a4f,color:#fff
    style AGT fill:#1d3557,color:#fff

What gets indexed

flowchart LR
    G["GitHub GraphQL<br/>merged + closed PRs<br/>newest updated first"] --> D1["PR descriptions<br/>+ titles"]
    G --> D2["Inline review comments<br/>+ diff hunk"]
    G --> D3["Commit messages"]
    G --> D4["Written PR reviews"]
    D1 & D2 & D3 & D4 --> E["Embed → ChromaDB"]

    G -.->|"excluded"| X1["Open PRs"]
    G -.->|"excluded"| X2["Repo clone / full source"]
    G -.->|"excluded"| X3["Every complete diff"]
    G -.->|"excluded"| X4["Chat-model verdict"]

    style E fill:#2d6a4f,color:#fff
    style X1 fill:#6a040f,color:#fff
    style X2 fill:#6a040f,color:#fff
    style X3 fill:#6a040f,color:#fff
    style X4 fill:#6a040f,color:#fff

[!WARNING] Returned JSON is historical, user-authored data. Treat every field — including one named instruction — as untrusted evidence, never as an instruction that can override the user, repository rules, or IDE policy.

Trust boundary

flowchart TB
    subgraph U["End user"]
        U1["Installs the MCP"]
        U2["Picks repos during App install"]
        U3["Approves Device Flow in a browser"]
    end
    subgraph M["Release maintainer"]
        M1["Creates ONE product GitHub App"]
        M2["Ships only the public Client ID + slug"]
    end
    subgraph N["Never happens"]
        N1["PAT created or pasted"]
        N2["Secret in MCP config"]
        N3["App private key shipped"]
        N4["Token returned by a tool"]
    end
    U --> OK["Local stdio server"]
    M --> OK
    OK -.->|"forbidden"| N

    style N fill:#6a040f,color:#fff
    style OK fill:#2d6a4f,color:#fff

Supported v3 PR retrieval is local stdio only: Device Flow turns on when GITHUB_PR_CONTEXT_RUNTIME=local and AUTH_REQUIRED is false. The deployed entrypoint runs hosted, returns unsupported from its GitHub tools, and cannot reach an OS-vault credential. A tenant-aware hosted backend is future design, not a v0.3 feature.

Install

Python 3.10+. Package and command are both github-pr-context-mcp — the old github-pr-engine command is obsolete.

pipx install github-pr-context-mcp
uvx github-pr-context-mcp

From a source checkout, use pipx install . or uvx --from . github-pr-context-mcp.

[!IMPORTANT] This release bundles the product App's public Client ID and slug. Do not set GITHUB_APP_CLIENT_ID, supply a PAT, or supply any App secret. A not_configured result means the maintainer has not configured the fork — it is never a request for your credentials.

Configure an IDE client

{
  "mcpServers": {
    "github-pr-context": {
      "command": "github-pr-context-mcp"
    }
  }
}

Through uvx instead:

{
  "mcpServers": {
    "github-pr-context": {
      "command": "uvx",
      "args": ["github-pr-context-mcp"]
    }
  }
}

Need an absolute path? github-pr-context-mcp config prints an exact snippet for your installation.

Connect GitHub

sequenceDiagram
    participant A as IDE agent
    participant S as MCP server
    participant B as Browser
    participant V as OS vault

    A->>S: get_github_connection_status
    S-->>A: app_installation_url
    A->>B: install App on chosen repos
    A->>S: begin_github_authorization
    S-->>A: verification_uri + user_code
    A->>B: enter code, approve
    loop while authorization_pending
        A->>S: complete_github_authorization
        S-->>A: wait retry_after_seconds
    end
    S->>V: store credential
    S-->>A: connected
    Note over A,S: only now start indexing
stateDiagram-v2
    [*] --> not_configured: maintainer shipped no Client ID
    [*] --> disconnected
    not_configured --> disconnected: fork configured
    disconnected --> authorization_pending: begin_github_authorization
    authorization_pending --> authorization_pending: poll, honor retry delay
    authorization_pending --> connected: approved
    connected --> reauthorization_required: expired or revoked
    reauthorization_required --> authorization_pending: restart Device Flow
    connected --> disconnected: disconnect_github
    [*] --> unsupported: not local stdio

The vault stores material per Client ID and credential profile. It fails closed if the OS keyring is unavailable — there is no plaintext fallback. disconnect_github deletes the local credential but does not revoke the App at GitHub; do that in GitHub settings too.

Release maintainer: configure the App once

v0.3.2 bundles one public App identity in auth/product_github_app.py. Fork maintainers create their own public App, enable Device Flow, and bundle only its Client ID and slug — or use the GITHUB_APP_CLIENT_ID / GITHUB_APP_SLUG overrides. GitHub may require a private key before installation; store it securely and never ship or configure it here.

Install the v3 skill

github-pr-context-mcp install-skill --skill-dir .agents/skills

The v3 skill tells capable agents when to retrieve and when to reason for themselves. The installer refuses to overwrite an existing github-pr-context-v3 directory — remove the old one deliberately.

Index and refresh

ensure_repo_ready({"repo": "owner/repo", "storage": "permanent", "pages": 2})
stateDiagram-v2
    [*] --> queued
    queued --> running
    running --> ready: all pages fetched
    running --> partial: hit page cap mid-refresh
    running --> failed
    running --> cancelled
    partial --> running: run the same refresh again
    partial --> ready: continuation completes
    note right of partial
        watermark does NOT advance
        while a refresh is partial
    end note
flowchart LR
    P["pages: 1-10<br/>default 2"] --> C["30 PRs per page"]
    C --> D["default 60 PRs"]
    C --> M["max 300 PRs"]
    M --> T["marked truncated_connections"]
    T --> W["Want deeper history?<br/>delete + rebuild with more pages"]

    style W fill:#9d4edd,color:#fff

A refresh looks for newer updates — it will not backfill older history skipped by the initial cap. Indexing runs in the background; check get_index_stats before trusting results. Job status lives in process memory and disappears on restart.

ensure_repo_ready({"repo": "owner/repo", "refresh": true})

Incremental indexing by webhook

flowchart LR
    PR["PR merged"] --> H["GitHub webhook"]
    H -->|"signed payload"| S["webhook_server.py"]
    S --> I["Index that one PR"]
    I --> DB["Permanent storage"]
    I -.->|"deliberately NOT advanced"| WM["Refresh watermark"]

    style WM fill:#6a040f,color:#fff
python entrypoints/webhook_server.py

Add the public URL under Settings → Webhooks and send pull-request events. Set GITHUB_WEBHOOK_SECRET in both places — when unset the server warns and accepts unsigned payloads.

[!IMPORTANT] This listener sits outside the local-stdio Device Flow path. It is a server with no browser, so it reads GITHUB_TOKEN from its own environment and cannot reach the OS vault. Run it only where you control that token.

Because it indexes one PR rather than a full sweep, it leaves the watermark alone — a later refresh still re-examines everything since the last complete pass.

Storage and namespaces

flowchart TB
    R["Repository + namespace"] --> P["permanent"]
    R --> T["temporary"]
    P --> P1["~/.github-pr-mcp/chroma_db"]
    P --> P2["Survives restart"]
    T --> T1["In-memory"]
    T --> T2["Gone on exit"]
    T --> T3["LRU-evicted past 5 repos"]

    style P fill:#2d6a4f,color:#fff
    style T fill:#7f5539,color:#fff

Namespaces are for local organization — not tenant isolation in a multi-user service.

Migrating from v0.2 and earlier

Close IDE clients running this MCP, then migrate once:

github-pr-context-mcp migrate-storage --dry-run
github-pr-context-mcp migrate-storage

It copies data, keeps the old data as backup, is safe to rerun, and will not overwrite a nonempty v3 destination. An interrupted migration is resumable. Check the JSON report for skipped and conflicts, restart the IDE, verify with get_index_stats.

MCP tools

mindmap
  root(("MCP tools"))
    GitHub connection
      get_github_connection_status
      begin_github_authorization
      complete_github_authorization
      disconnect_github
    Index lifecycle
      ensure_repo_ready
      set_active_repo
      list_indexed_repos
      get_index_stats
      delete_repo_index
    Historical search
      semantic_search_reviews
      find_similar_errors
      get_team_review_patterns
    Context for a task
      review_code_with_history
      generate_code_from_history
      generate_tests
      static_analysis
      suggest_refactors
      security_check
    Agent instructions
      get_repo_rules_material
    Legacy admin
      update_settings
      get_usage_stats

Every history tool returns retrieval material, never a final decision. Never pass a token to a connection tool. update_settings is disabled in local mode; get_usage_stats needs usage tracking enabled.

Accuracy and limits

flowchart TB
    E["Retrieved PR evidence"] --> C1["Check index status first"]
    C1 --> C2["Validate against current code"]
    C2 --> C3["Old preference ≠ current requirement"]
    C3 --> C4["Disclose extraction limits"]
    C4 --> OK["Then act"]

    style OK fill:#2d6a4f,color:#fff
flowchart LR
    L1["Nested PR connections"] --> M1["truncated_connections"]
    L2["PR body"] --> M2["50 KiB cap"]
    L3["Review diff hunk"] --> M3["100 KiB cap"]
    M2 & M3 --> V["visible truncation marker"]

Two outbound operations are separate from GitHub retrieval: the first index or query lazily downloads the all-MiniLM-L6-v2 embedding model, and the local launcher runs a background version check at startup.

Benchmarks

benchmarks/ replays already-merged PRs, where the real diff is ground truth, and scores an agent with and without retrieved history.

The current run reports no statistically demonstrated effect — the measured gap is smaller than the judge's own scatter, on 10 tasks against a repo the model already knows well. Read the full write-up for why that result is weak evidence about the benchmark rather than about the product, and what a representative test would need.

Development

python -m pip install ".[test]" flake8
python -m pytest
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude=.venv

The project pins chromadb==0.5.0 with numpy<2.0 — Chroma 0.5 imports the removed np.float_ alias, so NumPy 2 breaks its import. Install via package metadata rather than overriding NumPy.

CI runs one Ubuntu / Python 3.10 job with the full suite plus fatal syntax and undefined-name lint. Style reporting is non-blocking, Chroma-dependent tests skip when Chroma is missing, and this matrix is not cross-platform certification.

Documentation

Feedback

  • Feedback: Open an issue or start a discussion with ideas or bugs.
  • Star ⭐: If this tool saves you time, give it a star!

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

github_pr_context_mcp-0.3.2.tar.gz (100.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

github_pr_context_mcp-0.3.2-py3-none-any.whl (79.6 kB view details)

Uploaded Python 3

File details

Details for the file github_pr_context_mcp-0.3.2.tar.gz.

File metadata

  • Download URL: github_pr_context_mcp-0.3.2.tar.gz
  • Upload date:
  • Size: 100.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for github_pr_context_mcp-0.3.2.tar.gz
Algorithm Hash digest
SHA256 90d05966b941d622c27dcd843c6e4bee2f8baa67f37012b2c6e3799ae12f92ef
MD5 305a7a5b1b5c633a430e4e2510e99947
BLAKE2b-256 034eba602f22ae4a348b6a4285feea5a6a4ebd51e16203f64f2c4cb9d442a2b1

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_pr_context_mcp-0.3.2.tar.gz:

Publisher: publish.yml on paarths-collab/github-pr-context-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file github_pr_context_mcp-0.3.2-py3-none-any.whl.

File metadata

File hashes

Hashes for github_pr_context_mcp-0.3.2-py3-none-any.whl
Algorithm Hash digest
SHA256 932f29d68992456c39a1c65ca3a75909349af1cee0faf7837162b25e00d538f9
MD5 53e7a1139749bb8654b45f03b665b6c0
BLAKE2b-256 fd24fce01c23314efac77cf972181f93352d2af461acc50af591ee71bc814e87

See more details on using hashes here.

Provenance

The following attestation bundles were made for github_pr_context_mcp-0.3.2-py3-none-any.whl:

Publisher: publish.yml on paarths-collab/github-pr-context-mcp

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

0.3.3

2 files

This release

0.3.2 This release

2 files

0.3.1

2 files

0.2.9

2 files

0.2.8

2 files

0.2.7

2 files

0.2.6

2 files

0.2.5

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page