Skip to main content

MCP server adding an independent second LLM perspective (Judge B) with full project graph context

Project description

Contrarian

MCP server that adds a second LLM perspective (Judge B) directly inside Claude Code.

Claude Code is Judge A — it already has full project context. Contrarian adds Judge B, an independent model from a different lab, via a single tool call. Same rubric, different priors, no context switch.


How it works

  1. Claude Code invokes contrarian_review() — no args for auto-detect, or pass specific files.
  2. Contrarian resolves the input: git diff, last commit, or full audit (in that order).
  3. Judge B (external model) reviews against JUDGE.md in the project root.
  4. Findings are returned inline and appended to REPORT.md for the dialogue log.

Auto-detect order:

  • diff — any staged/unstaged changes or untracked files
  • last-commit — clean tree → reviews the last commit
  • audit — forced with audit=true, or nothing else found

Installation

Requires Python 3.10+ and git (auto-detect mode uses git diff/git log; without a git repo, Contrarian falls back to a full audit). You'll need a free API key from Google AI Studio (no credit card required).

pip install contrarian
contrarian setup

contrarian setup prompts for your API key, then writes the MCP server config to ~/.claude/.claude.json automatically. Restart Claude Code after running it.

That's it.


Manual config (alternative)

If you prefer to configure manually, add to ~/.claude/.claude.json:

{
  "mcpServers": {
    "contrarian": {
      "type": "stdio",
      "command": "contrarian",
      "args": [],
      "env": {
        "JUDGE_B_API_KEY": "AI...",
        "JUDGE_B_BASE_URL": "https://generativelanguage.googleapis.com/v1beta/openai/"
      }
    }
  }
}

Default provider is Gemini (generativelanguage.googleapis.com, model gemini-2.5-pro). Change JUDGE_B_BASE_URL and JUDGE_B_MODEL to use any OpenAI-compatible provider (DeepSeek, Groq, Ollama, OpenRouter, etc.).

Anthropic models are blocked at runtime — Judge B must come from a different lab than Judge A.

Provider switching

Judge B has two kinds of provider:

API providers (per-token billing) — any OpenAI-compatible endpoint, selected by JUDGE_B_BASE_URL + JUDGE_B_MODEL (or contrarian use <preset>). JUDGE_B_API_KEY required.

CLI-agent providers (flat subscription cost) — drive a local agent CLI instead of an API. No API key, no per-token cost. Two providers:

  • cli:codex — runs Judge B on your Codex subscription via codex exec, agentic: read-only inside the project, so it reads files beyond the diff and catches cross-file ripple effects the diff-only API path misses. Optional model pin: cli:codex:<model> (e.g. cli:codex:gpt-5.2).
  • cli:agy — runs Judge B on Antigravity (agy), a different lab (Gemini). Isolated (not agentic): runs sandboxed from a throwaway workspace and sees only the inline diff. Optional model pin: cli:agy:<model> (e.g. cli:agy:gemini-3.1-pro-high).
JUDGE_B_MODEL=cli:codex                       # persistent: all reviews via Codex subscription
contrarian_review({ model: "cli:agy" })       # per-call override

Fan out to several models at once — one review, N independent opinions, never merged:

JUDGE_B_MODEL="cli:codex+cli:agy"                          # persistent multi-model
contrarian_review({ models: ["cli:codex", "cli:agy"] })    # per-call

Each model's review is returned as a separate labelled block; you remain the supreme judge (no reconciliation, no auto-merge). One provider failing (timeout, outage, auth error — any reason) shows as a FAILED block and doesn't sink the others; if OpenAI is down, a cli:codex+cli:agy fan-out still returns agy's review. JUDGE_B_CLI_TIMEOUT (default 300s) bounds each CLI call.

Security invariant: a Judge never mutates the code it judges. codex is forced --sandbox read-only (non-configurable, runtime-guarded); agy runs sandboxed from a throwaway cwd where headless mode auto-denies all file tools. Independence is preserved — Judge B is always a different lab than Judge A (Claude), and an explicit adversarial preamble overrides the agent CLI's own collaboration framing (verified by a differential: same diff, project vs neutral cwd, no softening of verdict or core findings).


Usage

Inside any Claude Code session, the tool is available as contrarian_review.

contrarian_review()                                    # auto-detect mode
contrarian_review({ path: "src/auth.py" })             # single file, diff
contrarian_review({ path: "src/auth.py", full: true }) # full file
contrarian_review({ paths: ["src/a.py", "src/b.py"] }) # multi-file, reviewed as a unit
contrarian_review({ audit: true })                     # force full repo walk
contrarian_review({ model: "google/gemini-3.1-pro-preview" }) # one-off model override

Rubric

Place a JUDGE.md at the project root to customize what Judge B looks for. Without it, a built-in fallback rubric applies.

The built-in rubric covers four dimensions:

Dimension What to find
Exactitude Logic errors, wrong assumptions, incorrect implementation
Missing Unhandled cases, absent validation, unconsidered implications
Premises Assumptions that could be wrong
Alternatives Fundamentally different approaches

Output is always JSON:

{
  "exactitude": { "verdict": "ok|warn|fail", "findings": [] },
  "missing": [],
  "premises": [],
  "alternatives": []
}

Report log

Findings are appended to REPORT.md at the project root under [Judge B] blocks. Claude Code annotates findings under [Judge A] blocks. Judge B reads previous exchanges before each review — closed findings (addressed, won't fix, disagree) are not re-raised.

Run contrarian stats from the project root for a summary: review count, model breakdown, exactitude verdicts, and finding totals parsed from REPORT.md.


Phase roadmap

  • Phase 2: MCP server + project graph context. Auto-detect mode. Python rewrite.
  • Phase 3: Operational hardening — token budget guard, graph latency, detached HEAD handling.
  • Phase 4 (current): PyPI distribution, CLI provider switching (setup/model/use), usage stats (contrarian stats). Next: agent watchdog — autonomous background review on commit.

License

Dual-licensed: AGPL-3.0-or-later, with a commercial license available — see LICENSING.md. Versions ≤ 0.2.4 remain MIT.

Project details


Download files

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

Source Distribution

contrarian-0.3.0.tar.gz (46.4 kB view details)

Uploaded Source

Built Distribution

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

contrarian-0.3.0-py3-none-any.whl (48.7 kB view details)

Uploaded Python 3

File details

Details for the file contrarian-0.3.0.tar.gz.

File metadata

  • Download URL: contrarian-0.3.0.tar.gz
  • Upload date:
  • Size: 46.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for contrarian-0.3.0.tar.gz
Algorithm Hash digest
SHA256 a556b71e0f54278aa67162ad11aef71bc4ead66642303bf6dafcfe1e8c79393c
MD5 4f3ea5efd3cee9e418ac4df054a70747
BLAKE2b-256 c7d4af488ace550193eb0917de65c9f92c2c3ef2bdcd0b03144a11c1ff04db3a

See more details on using hashes here.

File details

Details for the file contrarian-0.3.0-py3-none-any.whl.

File metadata

  • Download URL: contrarian-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 48.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.14.6

File hashes

Hashes for contrarian-0.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2ccee130bbcbae507634f134fdccea7cb1786d39dabb1535462a933328693c75
MD5 6e7d58b72526491ba0b2aadc3ecbaeb9
BLAKE2b-256 4f9eb654d77a5b32cc5551f8f7db42ecb7680964456fb41814348e4fe315dc15

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page