Reviewing Code with MCP
Once Optibot MCP is installed and configured, you can run code reviews live inside your AI editor and watch them progress in real time. For CI pipelines, use the Optibot CLI instead: the MCP server speaks the Model Context Protocol over stdin and stdout and is built for interactive AI assistants, not for headless runners.
Watch Review Progress in Real Time
When you trigger a review (e.g., “review my local changes” or “review this branch”), Optibot streams the review progress back to your editor. You’ll see the review move through these stages:
| Stage | What’s happening |
|---|---|
started | Review initiated — Optibot has received the code |
analyzing_patch | Optibot is parsing and structuring the diff |
tool_call | Optibot is running analysis tools against the code |
generating_review | Findings are being compiled and written |
completed | Review is finished — results are ready |
Progress updates appear in real time in your editor so you always know where the review stands.
Agent-mode reviews (the review_agent tool) are the exception: they have no progress socket, so the server polls for the result instead of streaming stages. Two timeouts bound any review. The service stops an agent review at its own ten-minute limit, and the MCP server gives up polling after fifteen minutes.
Reviews in CI/CD: use the CLI, not the MCP server
The MCP server is not a command-line tool. It speaks the Model Context Protocol over stdin and stdout, and running optibot-mcp in a CI step starts a server that waits for a client that never connects, until the job times out. Use the Optibot CLI instead. It runs the same reviews against the same service and is built for headless environments.
1. Mint an API key
Run this on a development machine, not inside a runner:
optibot setup ci
It logs you in if needed, confirms the organization, mints a long-lived API key, and prints ready-to-paste snippets for GitHub Actions and GitLab CI. The key is permanently bound to the organization that is active when you create it.
2. Store the key as a CI secret
- GitHub Actions — add it as a repository or organization secret named
OPTIBOT_API_KEY. - GitLab CI — add it under Settings > CI/CD > Variables.
- Other providers — use the equivalent secrets mechanism, exposed as an environment variable.
GitHub Actions
name: Optibot Code Review
on:
pull_request:
jobs:
optibot-review:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run Optibot Review
env:
OPTIBOT_API_KEY: ${{ secrets.OPTIBOT_API_KEY }}
run: npx -y @optimalai/optibot review -b origin/${{ github.base_ref }} --fail-on-issues
Leaving branches: off the trigger runs the review on every pull request, whatever it targets. origin/${{ github.base_ref }} is the branch the pull request targets, so the review compares against the right base even when the PR is not aimed at main. fetch-depth: 0 matters too: without it the runner has a shallow clone and the CLI cannot resolve that branch. --fail-on-issues exits non-zero when the review does not pass, which is what turns the step into a gate.
GitLab CI
code-review:
image: node:20
script:
- git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_NAME
- npx -y @optimalai/optibot review -b origin/$CI_MERGE_REQUEST_TARGET_BRANCH_NAME --fail-on-issues
variables:
OPTIBOT_API_KEY: $OPTIBOT_API_KEY
only:
- merge_requests
The git fetch line is required. GitLab’s default clone does not bring down the target branch, so without it the CLI reports Branch 'origin/...' not found and exits 1.
Machine-readable output
Add --json when a script reads the result. In agent mode (--agent --json) the structured review goes to stdout and progress text is suppressed, so stdout carries only the JSON. See Agent review mode.
Environment variables
| Variable | Required | Description |
|---|---|---|
OPTIBOT_API_KEY | Yes | The API key from optibot setup ci. Takes precedence over any credentials in ~/.optibot/config.json. |
OPTIBOT_API_URL | No | Override the Optibot API endpoint. The default is https://agents.getoptimal.ai. The URL must use https:; an http: endpoint is rejected. |