Content
# SpyFu MCP
A Model Context Protocol server that exposes the [SpyFu](https://www.spyfu.com/api) PPC intelligence API as tools usable from Claude Code, Cursor, and other MCP-aware clients.
Ten tools cover domain stats, ad history, top PPC competitors, paid SERPs, kombat (shared-keyword analysis), related keywords, paid keyword exports, organic keywords, and historic rankings.
## Install
Requires Python 3.11+.
```bash
git clone <this-repo> spyfu-mcp
cd spyfu-mcp
python3 -m venv .venv
./.venv/bin/pip install -e ".[dev]"
```
This creates a console script at `./.venv/bin/spyfu-mcp`.
**macOS / iCloud Drive note:** Python 3.14 skips `.pth` files marked with the macOS `UF_HIDDEN` flag, which iCloud Drive applies to files in `~/Library/Mobile Documents/`. If you cloned this repo inside iCloud Drive and `import spyfu_mcp` fails after install, put the venv outside iCloud:
```bash
python3 -m venv ~/.local/share/spyfu-mcp/venv
~/.local/share/spyfu-mcp/venv/bin/pip install -e ".[dev]"
```
## Configure
Get an API key from the [SpyFu API dashboard](https://www.spyfu.com/api).
Copy `.env.example` if you want to keep your key in a `.env` file for development; in production the key is passed via the MCP server's `env` block (see below).
| Variable | Required | Default | Purpose |
|---|---|---|---|
| `SPYFU_API_KEY` | yes | — | Your SpyFu API key. The server refuses to start without it. |
| `SPYFU_COUNTRY_CODE` | no | `US` | Default country for all calls. Override per-call with the `country_code` tool argument. |
## Wire into Claude Code
Add to your project's `.mcp.json` (or `~/.claude/settings.json` for global):
```json
{
"mcpServers": {
"spyfu": {
"command": "/absolute/path/to/.venv/bin/spyfu-mcp",
"env": {
"SPYFU_API_KEY": "your-key-here",
"SPYFU_COUNTRY_CODE": "US"
}
}
}
}
```
Restart Claude Code. The 10 `spyfu_*` tools become available. Verify with `/mcp`.
## Wire into Cursor
Same config schema. Add to `~/.cursor/mcp.json` (global) or `.cursor/mcp.json` (per-project):
```json
{
"mcpServers": {
"spyfu": {
"command": "/absolute/path/to/.venv/bin/spyfu-mcp",
"env": { "SPYFU_API_KEY": "your-key-here" }
}
}
}
```
## Tools
| Tool | Args | Returns |
|---|---|---|
| `spyfu_domain_stats` | `domain` | All-time monthly stats (budget, clicks, keywords, avg ad rank) |
| `spyfu_domain_stats_for_date` | `domain`, `month`, `year` | Stats for a specific month |
| `spyfu_ad_history` | `domain` | Historical ad creatives (title, body, position, keywords) |
| `spyfu_top_ppc_competitors` | `domain` | Top PPC competitors ranked by keyword overlap |
| `spyfu_paid_serps` | `query` | Every domain bidding on the keyword, with ad copy + position |
| `spyfu_domain_paid_keywords` | `domain` | Full paid-keyword list for a domain |
| `spyfu_kombat` | `domains: list[str]` (2+) | Keywords multiple domains compete on |
| `spyfu_related_keywords` | `query` | Related keywords with volume, CPC, paid competitors |
| `spyfu_most_valuable_keywords` | `domain` | Top organic keywords by estimated traffic value |
| `spyfu_historic_rankings` | `domain` | Historic organic SERP ranking changes |
All tools accept optional `country_code` (overrides the env default for that call) and most accept `starting_row` / `page_size` for pagination.
## Example prompts
See [`examples/usage.md`](examples/usage.md) for natural-language prompts that exercise each tool.
## Development
```bash
./.venv/bin/pytest # offline tests (24 tests, ~7s)
SPYFU_LIVE=1 ./.venv/bin/pytest tests/test_smoke.py # hits real API
```
Offline test suite covers URL/param construction for every endpoint, env handling, structured HTTP errors, the rate-limit floor, and end-to-end MCP tool registration & dispatch via the in-process FastMCP client.
## Rate limits & cost
The client enforces a 0.5-second floor between requests. SpyFu's own API quota is consumed per call — check your plan limits before doing high-volume pulls.
## License
MIT.