An MCP server that exposes the self-hosted codeJung code-review service as tools any MCP client can call — Claude Code, Claude Desktop, Cursor, Codex CLI, Windsurf, and others.
It is a thin client: it depends only on codeJung's stable /v1 HTTP API, not on
any codeJung internals. The service binds to loopback on its host, so every call
is executed on that host over SSH — the service token is read there and never
leaves the machine.
Speaks codeJung's /v1 job API (POST /v1/jobs, GET /v1/jobs/{id},
GET /v1/jobs/{id}/result). If codeJung ever breaks /v1, bump this client to
match. The quickest health check is the smoke test in Verifying.
| Tool | Purpose |
|---|---|
review_pr(pr_url, wait_secs=300) |
Submit a GitHub PR, wait up to wait_secs, return review markdown + findings. |
submit_review(pr_url) |
Submit a PR and return jobId immediately (for long reviews). |
get_review(job_id) |
Status, plus result once the job has succeeded. |
review_dir(path, wait_secs=300) |
Review a local directory (full-file scan, no PR needed) — stages it to the host and reviews every source file. |
review_pr / review_dir wait at most wait_secs for the review, emitting
progress to stderr, then return {"status":"running","jobId":...} if it hasn't
finished — they never block indefinitely. Fetch a still-running result later with
get_review(job_id). Set wait_secs=0 to return as soon as the job is
submitted. For clients with short tool-call timeouts, prefer the non-blocking
pattern: submit_review → get_review.
- python3 ≥ 3.10,
pip install -r requirements.txt(installsmcp) - openssh client + passwordless SSH to the codeJung host
rsyncon both machines (only needed forreview_dir)- codeJung service running on the host (
~/codeJung/deploy, api + worker)
| Var | Default | Meaning |
|---|---|---|
CODEJUNG_SSH_HOST |
codejung |
SSH host running the service |
CODEJUNG_ENV_PATH |
~/codeJung/deploy/codejung.env |
path to codejung.env on the host (holds the service token) |
CODEJUNG_REVIEW_STAGING |
~/cj-review-staging |
host dir bind-mounted into the worker at /review-staging (used by review_dir) |
review_dirrequires the worker container to bind-mount the staging dir. Indeploy/docker-compose.ymlthe worker must have:- ${CODEJUNG_REVIEW_STAGING:-/home/you/cj-review-staging}:/review-staging:ro
The same stdio server works with any local MCP client. Ready-made config
snippets are in client-configs/.
claude mcp add codejung -s user -- python3 /path/to/codeJung-mcp/codejung_mcp.pyMerge the codejung entry from client-configs/mcp.json into the client's MCP
config (paths listed in client-configs/README.md). Edit the absolute path to
match where you cloned this repo. MCP tools run in Agent mode, and the
selected model is irrelevant — the client (not the model) drives the server, so
it works with any tool-calling model (GPT, Claude, Gemini, Grok, …).
Merge client-configs/codex-config.toml into ~/.codex/config.toml.
pip install -r requirements.txt
# smoke test — should print the tool names:
python3 -c "import asyncio, codejung_mcp as m; \
print([t.name for t in asyncio.run(m.mcp.list_tools())])"
# end-to-end — the host's models must be reachable:
python3 -c "import codejung_mcp as m; print(m.review_pr('https://github.com/OWNER/REPO/pull/N')['status'])""review https://github.com/owner/repo/pull/123 with codejung" "use codejung to review the directory ./my-service"
- The service token is read on the host and never transits to the client.
- PR URLs and job IDs are strictly validated before being interpolated into the remote command, to prevent shell injection.
review_dircopies the target directory to the host (excluding.git,node_modules, virtualenvs, build output) and removes the staged copy when the review finishes.
For MCP clients that connect to a URL instead of spawning a local process
(Cursor remote servers, ChatGPT/Grok connectors, etc.), codeJung also runs a
streamable-HTTP MCP server on the host — codejung_mcp_http.py. Unlike the
stdio server, it runs on the codeJung host and talks to the API directly
over localhost (no SSH). It exposes the PR tools only (review_pr,
submit_review, get_review) — remote clients have no local dir to review.
Public endpoint: https://codejung.wint3rmute.com/mcp
Auth: Authorization: Bearer <CODEJUNG_SERVICE_API_TOKEN> (enforced at the
Caddy edge; the request never reaches the MCP server without it).
Exposure is off by default — open it for a demo with
agentic_scripts/codejung-expose/codejung-expose.sh enable (and disable after).
"codejung-remote": {
"url": "https://codejung.wint3rmute.com/mcp",
"headers": { "Authorization": "Bearer <TOKEN>" }
}ChatGPT (custom connectors) and Grok can point at the same URL, but their MCP client/auth support varies by product and plan (some expect OAuth rather than a static bearer header). The endpoint itself is a standards-compliant streamable-HTTP MCP server with a bearer gate; whether a given product accepts it depends on that product.
- venv:
~/.codejung-mcp-venv(pip install mcp) - service:
codejung-mcp-http.service(systemd), binds127.0.0.1:8765 - Caddy:
/mcproute, bearer-gated viaCJ_MCP_TOKEN, rewrites upstream Host to127.0.0.1:8765(the MCP SDK's DNS-rebinding guard only trusts localhost)
Redeploy after editing this file: copy it to the host and
sudo systemctl restart codejung-mcp-http.