Skip to content

MCP server (bubo-mcp)

Bubo ships its own Model Context Protocol server so chat clients (Codex, Claude Desktop, …) can inspect review state and trigger reviews on demand. Launch it with the bubo-mcp console script (or bin/bubo mcp). Two interfaces, three deployment patterns.

Two interfaces

Metrics — read-only, against SQLite:

Tool Returns
health {status, last_status, last_updated_at, age_seconds} — same semantics as bubo-poller --health.
list_recent_reviews Recent reviewed_mrs rows newest-first, with optional status / project / limit filters.
get_review One review row by (project, iid[, sha]); resolves to the latest SHA when unspecified.
get_findings Per-finding rows (file, line, severity, category, confidence, posted body, discussion id).
get_finding_outcomes Resolution state populated by --sync-outcomes (resolved / disputed / merged_unresolved / …).
get_metrics Aggregated counts + token / cost sums for a since_hours window, optionally filtered by project.

Review — trigger a one-shot review:

Tool Args Returns
review_change url=… or provider={gitlab,github,auto} + project=… + number=…; optional timeout_seconds. {provider, project, number, exit_code, duration_seconds, findings, raw_output}.

provider="auto" (the default) infers the provider from the URL when one is given, otherwise falls back to [scm].provider in config/env.toml. review_change blocks until the underlying reviewer_command subprocess completes — set the client-side tool_timeout_sec accordingly. MCP-triggered reviews return findings inline; they do not write to reviewed_mrs, so they won't show up in the metrics tools. Use the poller for state-tracked reviews.

Three deployment patterns

The server supports two transports — stdio (default) and HTTP+SSE with bearer-token auth — selected via [mcp_server].transport in config/env.toml. Pick the pattern that matches where Codex and the reviewer live.

Pattern 1 — same host (laptop runs Codex and the reviewer):

# ~/.codex/config.toml
[mcp_servers.bubo]
command = "/absolute/path/to/bubo/bin/bubo"
args    = ["mcp"]
startup_timeout_sec = 20
tool_timeout_sec    = 1800   # ≥ [review].timeout_seconds for review_change

No reviewer-side config change needed — [mcp_server].transport defaults to "stdio". ~/ expansion works, so a ~/bubo/... path holds across machines that install to the same per-user location.

Pattern 2 — remote via SSH (laptop runs Codex; server runs the reviewer + holds the SQLite):

# ~/.codex/config.toml
[mcp_servers.bubo]
command = "ssh"
args = [
    "-T",                                      # no pty; keeps stdout clean for MCP framing
    "-o", "ServerAliveInterval=30",            # keeps long review_change calls alive across NAT
    "bubo.example.com",                # ssh_config Host alias, or user@host
    "/opt/bubo/bin/bubo mcp",  # absolute path on the server
]
startup_timeout_sec = 30
tool_timeout_sec    = 1800

Operator prerequisites: key-based SSH (an interactive password breaks the stdio loop), the install root readable by the SSH user, and no MOTD/banner noise on stdout (set PrintMotd no server-side or LogLevel QUIET client-side). No new code — SSH multiplexes the MCP stdio over the wire.

Pattern 3 — remote over HTTP+bearer (multi-tenant or org-wide):

On the reviewer host, set config/env.toml:

[mcp_server]
transport    = "http"
host         = "0.0.0.0"                     # or a specific interface
port         = 8765
bearer_token = "${BUBO_MCP_TOKEN}"   # generate: openssl rand -hex 32

Then run bin/bubo mcp (e.g. under a systemd unit). On the client:

# ~/.codex/config.toml — exact key for HTTP MCP servers varies across
# Codex versions; check `codex --help` if these names look wrong.
[mcp_servers.bubo]
url           = "https://reviewer.example.com/mcp"
bearer_token  = "..."                        # matches BUBO_MCP_TOKEN
startup_timeout_sec = 30
tool_timeout_sec    = 1800

The server enforces Authorization: Bearer <token> on every request and returns 401 otherwise. The server does not terminate TLS — bind to 127.0.0.1 and front it with nginx/caddy, expose it only over a VPN, or accept that the token crosses the network in clear text.

Upstream wrappers

The dispatcher also fronts the upstream MCP servers — bin/bubo mcp-upstream gitlab and bin/bubo mcp-upstream github — which locate the third-party GitLab / GitHub MCP server on PATH and exec it with config/env.toml tokens injected. The poster path uses these to create inline review threads. Point Codex at them directly for a chat-driven session with the same MCP surface the reviewer uses.