Content
# chromium-codesearch-mcp
**A token-preserving MCP server for searching Chromium source code.**
It gives your AI coding agent cheap, deterministic access to the entire
[Chromium](https://source.chromium.org) codebase — code search, symbol/file
lookup, ranged file reads, directory listings, git history, Gerrit code reviews,
commit search, and OWNERS — **without a local checkout or any indexing**. Every
tool returns compact results (paths, symbols, short snippets, URLs) so the agent
spends tokens on reasoning, not on dumping whole files.
It connects to any MCP-enabled client (Claude Code, Claude Desktop, Cursor, …)
via the [Model Context Protocol](https://modelcontextprotocol.io).
---
## Why
Chromium work usually starts with *locator* questions — "Where is this
implemented?", "Who calls this?", "Where is this flag used?", "What does this CL
change?". The token-cheap answer is **top-N matches → path · symbol · a few lines
· URL**, not twenty files dumped into the context window. This server is built
around that idea:
- **Always fresh, no checkout.** Queries the live index behind
`source.chromium.org`, so you search current `chromium/src@main` even if you
have nothing cloned locally.
- **Deterministic, not semantic.** Exact Code Search syntax (`class:`,
`function:`, `usage:`, `file:`, regex) — no embeddings, no guessing.
- **Token-preserving by design.** Hard result caps, snippet-first output, and a
guardrail that refuses to dump large files without a line range.
It pairs naturally with symbol-level tools like
[Serena](https://github.com/oraios/serena) (local navigation/refactoring on a
checkout) and your agent's own file tools — this server is the **broad, remote
discovery layer**.
---
## Tools
13 tools across three areas. All return plain, compact text.
### Code search & navigation
| Tool | What it does |
|------|--------------|
| `search_chromium_code(query, path?, language?, case_sensitive?, exclude_generated?, limit?, context_lines?)` | Full-text code search over `chromium/src@main`. `query` supports Code Search syntax (`class:`, `function:`, `usage:`, `file:`, `-exclude`, `"phrase"`, regex). `path` scopes to a directory prefix; `language` adds a `lang:` filter. Returns path + line + snippet + URL. |
| `find_chromium_symbol(symbol, kind?, language?, path?, limit?)` | Find a symbol's definition/usages. `kind` = auto \| symbol \| class \| function \| usage. `language` (e.g. `c++`) disambiguates common names that also exist in vendored Python/JS. |
| `find_chromium_file(name, path_prefix?, limit?)` | Fuzzy lookup of files by (partial) name. |
| `get_chromium_file(path, start_line?, end_line?, ref?)` | Read a file — ideally a line range. Refuses to dump large files without a range. `ref` may be a branch or tag (e.g. `refs/tags/144.0.7559.98`). |
| `list_chromium_directory(path, ref?)` | List a directory's immediate contents (files, subdirs, submodules) at any branch/tag. |
| `get_chromium_file_history(path, ref?, max_entries?)` | Recent commits (SHA, date, author, subject) for a file or directory. |
### Gerrit (code review)
| Tool | What it does |
|------|--------------|
| `get_gerrit_cl_status(cl)` | CL subject, state, owner, label votes, and submit requirements, plus a link. `cl` is the change number. |
| `get_gerrit_cl_comments(cl, unresolved_only?)` | Review comments (file, line, author, message). `unresolved_only` shows only open threads. |
| `get_gerrit_cl_diff(cl, file?)` | Changed-files summary (path, +/- lines), or one file's diff when `file` is given. |
| `list_gerrit_cls(query, limit?)` | Search Gerrit changes with raw Gerrit query syntax (e.g. `status:open owner:me`, `project:chromium/src is:wip`). |
### Commits, ownership & issues
| Tool | What it does |
|------|--------------|
| `search_chromium_commits(query?, author?, since?, limit?)` | Search landed commits (merged CLs). `query` matches the commit message, `author` is an owner email/name, `since` is a `YYYY-MM-DD` date. |
| `find_chromium_owners(path, ref?)` | OWNERS for a file/dir, walking up the tree (and stopping at `set noparent`). |
| `get_chromium_issue(issue_id)` | Best-effort issue title/reporter + canonical URL. The Chromium issue tracker has no clean public API, so detail is limited — open the URL for the full issue. |
> **Branch coverage:** code/file/symbol *search* covers `chromium/src@main` only.
> File reads, directory listings, and history accept an explicit `ref` (any
> branch or tag) via the File Service.
---
## Quick Start
### 1. Prerequisites
The only requirement is [**uv**](https://docs.astral.sh/uv/) — it manages the
Python interpreter and dependencies for you (no manual virtualenv needed).
- **macOS / Linux:** `curl -LsSf https://astral.sh/uv/install.sh | sh`
- **Windows (PowerShell):** `irm https://astral.sh/uv/install.ps1 | iex`
The server's dependencies (`mcp`, plus `pywin32` on Windows) are installed
automatically by `uv`/`uvx` the first time the server starts.
### 2. The launch command
**No clone needed** — clients launch the server straight from GitHub with `uvx`
(uv downloads, builds, and runs it, then caches it):
```
uvx --from git+https://github.com/daniel-koc/chromium-codesearch-mcp chromium-codesearch-mcp
```
That's the command to use in the client configs below. To pin a version, append a
tag, e.g. `…/chromium-codesearch-mcp@v0.1.0`.
Sanity-check it from a terminal (hits the live API and prints sample output):
```bash
uvx --from git+https://github.com/daniel-koc/chromium-codesearch-mcp chromium-codesearch-mcp --selftest
```
> **If your client can't find `uvx`:** some clients don't inherit your shell
> `PATH`. Use the absolute path to the executable (`which uvx` on macOS/Linux,
> `where.exe uvx` on Windows — typically `~/.local/bin/uvx` or
> `C:\Users\<you>\.local\bin\uvx.exe`).
### 3. Configure your client
<details open>
<summary><b>Claude Code (CLI)</b></summary>
Add the server with the `claude mcp add` command. Use the user scope to make it
available in every project:
```bash
claude mcp add --scope user chromium-search -- \
uvx --from git+https://github.com/daniel-koc/chromium-codesearch-mcp chromium-codesearch-mcp
```
Or, for the current project only, omit `--scope user`. You can also create a
`.mcp.json` in a project directory:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** run `/mcp` inside Claude Code — `chromium-search` should be listed
(reconnect if needed).
</details>
<details>
<summary><b>Claude Desktop</b></summary>
Open **Settings → Developer → Edit Config** (this opens
`claude_desktop_config.json`) and add:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** fully quit Claude Desktop (**File → Exit**, not just close) and
reopen it. The tools appear under the hammer/tools icon.
</details>
<details>
<summary><b>Cursor (IDE)</b></summary>
Open **Cursor Settings → MCP & Integrations → New MCP Server**, or edit the
config file directly:
- Global (all projects): `~/.cursor/mcp.json`
- Project-only: `.cursor/mcp.json` in the project root
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** the server and its tools show up (and can be toggled) in
**Settings → MCP & Integrations**.
</details>
<details>
<summary><b>Cursor CLI (<code>cursor-agent</code>)</b></summary>
The Cursor CLI reads the **same** MCP configuration as the IDE — global
`~/.cursor/mcp.json` and project `.cursor/mcp.json`. So the JSON shown for the
Cursor IDE above applies here too:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** run `/mcp` inside `cursor-agent` to confirm `chromium-search` is
connected.
</details>
<details>
<summary><b>VS Code (GitHub Copilot)</b></summary>
Run **MCP: Add Server** from the Command Palette and pick **Command (stdio)**, or
create `.vscode/mcp.json` in your workspace. Note VS Code uses the `servers` key
and a `type`:
```json
{
"servers": {
"chromium-search": {
"type": "stdio",
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** open Chat in **Agent** mode and check the tools button.
</details>
<details>
<summary><b>Codex (CLI and app)</b></summary>
Add to `~/.codex/config.toml` (create it if it doesn't exist):
```toml
[mcp_servers.chromium-search]
command = "uvx"
args = ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
```
**Verify:** run `/mcp` in Codex.
</details>
<details>
<summary><b>Gemini CLI</b></summary>
Add to `~/.gemini/settings.json`:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** run `/mcp` in Gemini CLI.
</details>
<details>
<summary><b>Windsurf</b></summary>
Open **Settings → Cascade → MCP Servers** (use *View raw config*), or edit
`~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** the server appears in the Cascade MCP panel.
</details>
<details>
<summary><b>Cline / Roo Code (VS Code extensions)</b></summary>
Open the extension's **MCP Servers → Configure** view (it opens a
`*_mcp_settings.json`) and add:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
**Verify:** the server shows as connected in the extension's MCP panel.
</details>
<details>
<summary><b>JetBrains (Junie / AI Assistant)</b></summary>
- **Junie:** edit `~/.junie/mcp/mcp.json` (global) or `<project>/.junie/mcp/mcp.json`.
- **AI Assistant:** **Settings → Tools → AI Assistant → Model Context Protocol (MCP)**.
Both use the same entry:
```json
{
"mcpServers": {
"chromium-search": {
"command": "uvx",
"args": ["--from", "git+https://github.com/daniel-koc/chromium-codesearch-mcp", "chromium-codesearch-mcp"]
}
}
}
```
</details>
<details>
<summary><b>Any other MCP client</b></summary>
Most MCP clients accept a stdio launch command. Add a new server with:
- **command:** `uvx`
- **args:** `--from git+https://github.com/daniel-koc/chromium-codesearch-mcp chromium-codesearch-mcp`
If the client uses a config file it is almost always the `mcpServers` JSON shown
above (Codex uses TOML; VS Code uses `servers` with `"type": "stdio"`). See your
client's MCP documentation for the exact file location, and remember the
`uvx`-not-on-PATH note above if the server fails to start.
</details>
---
## Example prompts
Once connected, ask your agent things like — each line exercises a tool:
**Code search & navigation**
- *"Find where `WebContents` is created — usages only."* → `search_chromium_code`
- *"Search C++ files under `content/browser/` for `RenderFrameHostImpl`, with 3 lines of context."* → `search_chromium_code` (path + language + context)
- *"Find the definition of the `Browser::Create` function in C++."* → `find_chromium_symbol`
- *"Locate the file `web_contents_impl.h`."* → `find_chromium_file`
- *"Show `content/public/browser/web_contents.h` lines 90–140."* → `get_chromium_file`
- *"Read `base/check.h` at tag `refs/tags/144.0.7559.98`."* → `get_chromium_file` (pinned ref)
- *"List what's in `content/public/browser/`."* → `list_chromium_directory`
- *"Show the last 5 commits that touched `base/check.h`."* → `get_chromium_file_history`
**Gerrit code review**
- *"What's the status of Gerrit CL 6624568?"* → `get_gerrit_cl_status`
- *"Show the unresolved review comments on CL 6624568."* → `get_gerrit_cl_comments`
- *"What files did CL 6624568 change? Then show the diff for `serialized_script_value.cc`."* → `get_gerrit_cl_diff`
- *"Find open Gerrit CLs touching the password manager."* → `list_gerrit_cls`
**Commits, ownership & issues**
- *"Search landed commits mentioning the password manager since 2025-06-01."* → `search_chromium_commits`
- *"Who owns `chrome/browser/ui/browser.cc`?"* → `find_chromium_owners`
- *"Get the title of issue 422768753."* → `get_chromium_issue`
A good workflow is **discover broadly, then read narrowly**: search to locate the
right paths/lines, then read only the specific ranges you need. Pair it with
[Serena](https://github.com/oraios/serena) for local symbol navigation and edits.
---
## Configuration
Environment variables (all optional):
| Var | Purpose | Default |
|-----|---------|---------|
| `CR_SEARCH_API_KEY` | Override the public Code Search API key | built-in |
| `CR_HTTP_TIMEOUT` | Per-request timeout, in seconds | 15 |
Set them in your shell, or add an `"env": { ... }` block to the MCP server entry
in your client config.
By default, `search_chromium_code` and `find_chromium_symbol` exclude generated
build output (`out/`); `third_party/` (including blink, the renderer) is **kept**.
Pass `exclude_generated=false` to include `out/` as well.
---
## How it works
The server talks to two public, no-auth backends:
- **Chromium Code Search (Grimoire) API** behind `source.chromium.org` — for code
search, file-name suggest, file/directory contents, and git history.
- **Gerrit REST API** at `chromium-review.googlesource.com` — for CL status,
comments, diffs, change search, and (via merged changes) commit search.
It is a thin, deterministic bridge with no local state, no indexing, and no
write operations (search/read only). Results are formatted compactly to keep the
agent's context small.
---
## Development
From a local clone:
```bash
git clone https://github.com/daniel-koc/chromium-codesearch-mcp
cd chromium-codesearch-mcp
uv run pytest # unit tests (offline)
uv run chromium-codesearch-mcp --selftest # exercise every tool against the live API
uv run tests/mcp_smoke.py # drive the server over real MCP stdio
uvx ruff check chromium_codesearch_mcp tests # lint
```
The package (`chromium_codesearch_mcp/`) is a small set of mostly stdlib-only
modules — `remote.py` for the Code Search API, `gerrit.py` for Gerrit, plus
`owners.py`, `issues.py`, `formatting.py`, `model.py`, `config.py`; `main.py`
wraps them as MCP tools with [FastMCP](https://github.com/modelcontextprotocol/python-sdk).
---
## Limitations
- **Code search is `main`-only.** The index covers `chromium/src@main`; if your
local checkout is pinned to a release tag, search results may differ. File
reads and history can target a specific `ref`, and your agent's own local tools
cover the working tree.
- **Issue support is best-effort.** The Chromium issue tracker exposes no clean
public API, so `get_chromium_issue` returns a title/reporter and the canonical
URL; issue *search* and CI/try-bot error extraction are not included.
- It is a **discovery/read** layer — for local symbol navigation and edits, pair
it with Serena and your editor's own tools.
---
## Acknowledgements
Built on the public **Chromium Code Search** and **Gerrit** APIs that power
[source.chromium.org](https://source.chromium.org) and
[chromium-review.googlesource.com](https://chromium-review.googlesource.com).
Chromium is a project of The Chromium Authors.
---
## License
[MIT](./LICENSE) © 2026 Daniel Kocielinski
MCP Config
Below is the configuration for this MCP Server. You can copy it directly to Cursor or other MCP clients.
mcp.json
Connection Info
You Might Also Like
No recommendations available