diff --git a/README.md b/README.md
index 3cdaf62..2b6bb6a 100644
--- a/README.md
+++ b/README.md
@@ -9,12 +9,26 @@
[](https://mountainowl.github.io/bubo/)
[](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.
-
+## 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:
-
-
-
-
-
-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.
-
+
-[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