From 35252cd986dcf02944f1e3804b01a92b4ac1f429 Mon Sep 17 00:00:00 2001 From: mountainowl Date: Tue, 16 Jun 2026 13:23:58 -0700 Subject: [PATCH] fix(docs): owl intro, feature tables, MCP page; drop stale-branded images Lead the README + docs overview with a short owl intro (Bubo = the eagle-owl genus, Wikipedia-linked) drawing the owl <-> code-review parallel. Replace the dense feature bullet list with a scannable at-a-glance table, and restyle the overview's hero links as Material grid cards. Add a dedicated docs/mcp.md (moved out of run.md, which now points to it) and surface metrics by renaming the nav entry to "Metrics & telemetry". Drop the stale-branded images that can't be pixel-edited: the hero banner had the old github.com/mountainowl/ai-code-review URL baked in, and the two GitLab MR screenshots show the old "LLM Reviewer" bot. Removing them from the README also clears the wrong-URL hero from the PyPI project page (this fix: cuts a release that republishes the cleaned README). Fresh Bubo-branded visuals can follow. mkdocs --strict clean. --- README.md | 34 +++++++++------ docs/index.md | 72 ++++++++++++++++++++------------ docs/mcp.md | 111 +++++++++++++++++++++++++++++++++++++++++++++++++ docs/run.md | 113 ++------------------------------------------------ mkdocs.yml | 3 +- 5 files changed, 184 insertions(+), 149 deletions(-) create mode 100644 docs/mcp.md diff --git a/README.md b/README.md index 3cdaf62..2b6bb6a 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,26 @@ [![Docs](https://img.shields.io/badge/docs-mountainowl.github.io%2Fbubo-4f62ad)](https://mountainowl.github.io/bubo/) [![License: MIT](https://img.shields.io/badge/license-MIT-111827)](https://github.com/mountainowl/bubo/blob/main/LICENSE) -Bubo reviews your GitLab MRs and GitHub PRs with **the LLM you choose** (Codex, -Claude, or any model your CLI drives) and posts only the findings worth acting on -as inline threads — no chatbot noise, no praise, no summaries. Like the owl it's -named for, it stays silent until it has something worth saying. +[Bubo](https://en.wikipedia.org/wiki/Bubo_(genus)) is the genus of the great +horned and eagle owls — patient night hunters that sit silent, see in the dark, +and strike only when sure. Code review, same idea: Bubo reviews your GitLab MRs +and GitHub PRs with **the LLM you choose** (Codex, Claude, or any model your CLI +drives) and posts only the findings worth acting on as inline threads — no +chatbot noise, no praise, no summaries. -![Bubo hero](https://raw.githubusercontent.com/mountainowl/bubo/main/docs/images/bubo-hero.png) +## Features at a glance + +| | | +|---|---| +| 🧠 **Bring your own LLM** | Codex, Claude, or any model your CLI drives — no vendor lock-in. | +| 🔒 **Self-hosted** | Code, diffs, and review data stay on your infrastructure. | +| 🔀 **GitLab + GitHub** | MRs and PRs, one config, identical behavior on both. | +| 🎯 **Signal over noise** | Only actionable inline findings; one "all good" ack on a clean change. | +| 🎭 **Moods** | Pick the review voice — terse / collaborative / socratic / formal / casual. | +| 📉 **Learns your taste** | Suppresses finding-classes your team repeatedly disputes. | +| ✅ **Verify before posting** | Optional "is this real?" passes drop findings that don't hold up. | +| 🛡️ **Governance-ready** | AI-code provenance, rigor modulation, auditable on-prem report. | +| 🔌 **MCP + CI** | Built-in `bubo-mcp` server + a GitHub Action to review PRs in CI. | ## 📖 Documentation @@ -90,14 +104,8 @@ your humans without touching the data your compliance reports run on. Ships as `terse`; opt in when you're ready, set it once, leave it to the operator. → [tone reference](https://github.com/mountainowl/bubo/blob/main/docs/configuration.md#review-comment-tone-moods) -Real (sanitized) inline findings on GitLab MRs: - -![Sanitized inline finding — data primer](https://raw.githubusercontent.com/mountainowl/bubo/main/docs/images/gitlab-mr-review-data-primer.png) - -![Sanitized inline finding — exception handler](https://raw.githubusercontent.com/mountainowl/bubo/main/docs/images/gitlab-mr-review-exception-handler.png) - -More sanitized examples are in [docs/examples/README.md](https://github.com/mountainowl/bubo/blob/main/docs/examples/README.md). -Demo GIF: [docs/media/bubo-demo.gif](https://github.com/mountainowl/bubo/blob/main/docs/media/bubo-demo.gif). +More sanitized review examples are in +[docs/examples/README.md](https://github.com/mountainowl/bubo/blob/main/docs/examples/README.md). ## 60-second quickstart diff --git a/docs/index.md b/docs/index.md index 7577cda..9c00c1d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -2,37 +2,57 @@ **Agentic AI code review — with the LLM of your choice.** -Bubo reviews your GitLab MRs and GitHub PRs, posts only the findings worth -acting on, and runs on the LLM *you* pick — self-hosted, so nothing leaves your -infrastructure. Like the owl it's named for, it stays quiet until it has -something worth saying: no chatbot chatter, no praise, no summaries. +[Bubo](https://en.wikipedia.org/wiki/Bubo_(genus)) is the genus of the great +horned and eagle owls — patient night hunters that sit silent, see in the dark, +and strike only when they're sure. Code review, same idea: Bubo watches your +diffs, stays quiet through the noise, and speaks only when it finds something +worth the author's time. It runs on the LLM *you* pick, self-hosted, so nothing +leaves your infrastructure — no chatbot chatter, no praise, no summaries. -![Bubo hero](images/bubo-hero.png) +
-[Copy-paste recipes :material-silverware-fork-knife:](recipes.md){ .md-button .md-button--primary } -[60-second quickstart :material-rocket-launch:](install-and-configure.md){ .md-button } -[Source on GitHub :material-github:](https://github.com/mountainowl/bubo){ .md-button } +- :material-silverware-fork-knife:{ .lg .middle } **Copy-paste recipes** + + --- + + GitLab & GitHub setups you can paste and run. + + [:octicons-arrow-right-24: Recipes](recipes.md) + +- :material-rocket-launch:{ .lg .middle } **60-second quickstart** + + --- + + Install, configure, first review — fast. + + [:octicons-arrow-right-24: Get started](install-and-configure.md) + +- :material-github:{ .lg .middle } **Source on GitHub** + + --- + + MIT-licensed, self-hostable, BYO-LLM. + + [:octicons-arrow-right-24: View the repo](https://github.com/mountainowl/bubo) + +
--- -## Features - -- **Bring your own LLM.** Codex, Claude, or any model your CLI can drive. No - vendor lock-in. -- **Self-hosted.** Code, diffs, and review data stay on your infrastructure. -- **GitLab MRs and GitHub PRs**, one config, same behavior on both. -- **Signal over noise.** Only actionable inline findings — Issue / Impact / - Evidence / Fix / Confidence. A clean change gets one "all good" acknowledgement. -- **Give it a mood.** Pick the review voice — `terse`, `collaborative`, - `socratic`, `formal`, or `casual` — without touching the underlying data. -- **Learns your team's taste.** Tracks which findings get accepted vs. disputed - and can suppress the finding-classes you keep rejecting. -- **Verify before posting.** Optional independent "is this real?" passes drop - findings that don't hold up — point them at a second model for real diversity. -- **Built for governance.** Opt-in AI-code provenance, review-rigor modulation, - and an auditable on-prem report (accept rate, ROI, noise trend, latency, - policy decisions) via CLI and MCP. -- **Observability in.** OpenTelemetry metrics; cosign-signed releases with SBOMs. +## Features at a glance + +| | | +|---|---| +| 🧠 **Bring your own LLM** | Codex, Claude, or any model your CLI drives — no vendor lock-in. | +| 🔒 **Self-hosted** | Code, diffs, and review data stay on your infrastructure. | +| 🔀 **GitLab + GitHub** | MRs and PRs, one config, identical behavior on both. | +| 🎯 **Signal over noise** | Only actionable inline findings (Issue / Impact / Evidence / Fix / Confidence); one "all good" ack on a clean change. | +| 🎭 **Moods** | Pick the review voice — `terse` / `collaborative` / `socratic` / `formal` / `casual` — without touching the data. | +| 📉 **Learns your taste** | Suppresses finding-classes your team repeatedly disputes. | +| ✅ **Verify before posting** | Optional "is this real?" passes drop findings that don't hold up — point them at a second model for real diversity. | +| 🛡️ **Governance-ready** | AI-code provenance, review-rigor modulation, and an auditable on-prem report (accept rate, ROI, noise trend, latency, policy decisions). | +| 📊 **Observability** | OpenTelemetry metrics; cosign-signed releases with SBOMs. | +| 🔌 **MCP + CI** | Built-in `bubo-mcp` server, and a GitHub Action to review PRs in CI. | ## What it does diff --git a/docs/mcp.md b/docs/mcp.md new file mode 100644 index 0000000..6332f86 --- /dev/null +++ b/docs/mcp.md @@ -0,0 +1,111 @@ +# 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):** + +```toml +# ~/.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):** + +```toml +# ~/.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`: + +```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: + +```toml +# ~/.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 ` 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. diff --git a/docs/run.md b/docs/run.md index a974eb9..039b4fe 100644 --- a/docs/run.md +++ b/docs/run.md @@ -20,116 +20,11 @@ deliberately no daemon mode. Each invocation processes up to `max_merge_requests_per_poll` MRs and exits. See [operate.md](operate.md) for ready-to-copy cron/systemd templates. -## MCP interface (`bubo-mcp`) +## MCP server (`bubo-mcp`) -Bubo ships its own MCP server with **two interfaces**: a metrics side for -inspecting review state, and a review side for triggering a fresh review by -URL or `(provider, project, number)`. - -**Metrics interface — 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 interface — 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):** - -```toml -# ~/.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):** - -```toml -# ~/.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`: - -```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: - -```toml -# ~/.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 ` 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. +Bubo ships an MCP server with read-only metrics tools and a one-shot +`review_change` trigger, over stdio or HTTP. Full setup and the three deployment +patterns are on the **[MCP server](mcp.md)** page. ## How the GitHub provider talks to GitHub diff --git a/mkdocs.yml b/mkdocs.yml index 4859927..55e2f5a 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -65,10 +65,11 @@ nav: - Prerequisites: prerequisites.md - Install and configure: install-and-configure.md - Run: run.md + - MCP server: mcp.md - GitHub Action (CI review): github-action.md - Configuration reference: configuration.md - Operate: operate.md - - Telemetry: telemetry.md + - Metrics & telemetry: telemetry.md - Examples: examples/README.md - References: references.md