web-search-mcp
by bartdorlandt
README.md
# web-search-mcp
An MCP server that exposes a real, cited `web_search` tool by shelling out to the [Claude Code CLI](https://github.com/anthropics/claude-code) running inside an isolated Docker container, logged into a personal claude.ai **Pro** subscription.
## Why this exists
Some environments proxy Claude Code through a gateway (e.g. an internal LiteLLM-style proxy) that doesn't support Anthropic's built-in `web_search` server tool for the model it routes to. This project sidesteps that entirely: it's a separate, single-purpose MCP tool backed by its own Claude Code CLI session, running in a container so its login never touches the host's own Claude Code config.
See [`docs/superpowers/specs/2026-07-28-web-search-mcp-design.md`](docs/superpowers/specs/2026-07-28-web-search-mcp-design.md) for the full design rationale, including why a raw Anthropic API key doesn't work for this and why Docker isolation is necessary.
## How it works
```
MCP client ──tool call──▶ server.py (FastMCP, stdio) ──subprocess──▶ docker run --rm -v claude-pro-home:/root web-search-claude:latest
│
▼
Claude Code CLI, logged into a Pro account
(real web_search tool, real Anthropic models)
```
`server.py` runs `docker run` per query, parses the CLI's JSON output, and returns the answer text (which includes a `Sources:` section whenever the CLI actually searched).
## Setup
Requires Docker and [`uv`](https://docs.astral.sh/uv/).
```bash
git clone https://github.com/bartdorlandt/web-search-mcp.git
cd web-search-mcp
uv sync
# Build the image (bundles the Claude Code CLI)
docker build -t web-search-claude:latest .
# Create a volume to hold the Pro-account login, then log in (interactive, opens a browser)
docker volume create claude-pro-home
docker run --rm -it -v claude-pro-home:/root web-search-claude:latest /login
```
The login only needs to happen once — the OAuth session persists in the `claude-pro-home` volume across container runs.
## Manual test
```bash
uv run python -c "from server import _web_search_impl; print(_web_search_impl('What are today\'s top technology news headlines?'))"
```
## Using it standalone
```bash
uv run python server.py
```
This starts the MCP server over stdio — point any MCP client at that command directly.
## Adding it to gridctl
If you're using [gridctl](https://github.com/gridctl/gridctl) as an MCP gateway, add it as a local-process server in your `stack.yaml`:
```yaml
mcp-servers:
- name: web-search
command: [uv, run, --directory, /path/to/web-search-mcp, python, server.py]
transport: stdio
```
Clone this repo to `/path/to/web-search-mcp` (or wherever you like) and update the path above, then `gridctl reload`. No `env:` block is needed — the only credential this tool uses lives in the `claude-pro-home` Docker volume, not in gridctl's variable store.
Repo: https://github.com/bartdorlandt/web-search-mcp
## Notes
- No automated test suite — the wrapper's logic is thin enough that its correctness is verified functionally (see the design doc's Testing section).
- Calls are assumed serial, not concurrent — see "Operational assumptions" in the design doc.
- Every query bills against the logged-in account's subscription usage.
TDQS
A3.6/5.0
Scored across 1 tool
Disambiguation5/5
Only one tool exists, so there is no possibility of confusion or overlap.
Naming Consistency5/5
With a single tool named 'web_search', naming is trivially consistent.
Tool Count4/5
One tool is slightly minimal but acceptable for a focused web search server; the scope is clear and the tool appears self-contained.
Completeness4/5
The tool provides search with synthesized cited answers, covering the core need. Minor gaps like different search modes or filters exist but are not critical.
Maintenance
ActivitySlowing
ResponsivenessNo issues