# Mcp Geo

> AI visibility tracker MCP server. Track brand citations across ChatGPT, Claude, Perplexity, Gemini & Google AI Overviews. Self-host on Cloudflare Workers. GEO/AEO.

- **Type:** MCP server
- **Install:** `agentstack add mcp-akzar1el-mcp-geo`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [AKzar1el](https://agentstack.voostack.com/s/akzar1el)
- **Installs:** 0
- **Category:** [Cloud & Infrastructure](https://agentstack.voostack.com/c/cloud-infrastructure)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [AKzar1el](https://github.com/AKzar1el)
- **Source:** https://github.com/AKzar1el/mcp-geo
- **Website:** https://digestseo.com

## Install

```sh
agentstack add mcp-akzar1el-mcp-geo
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# DigestSEO — AI Visibility MCP for SEO & GEO

[](https://github.com/AKzar1el/mcp-geo/actions/workflows/ci.yml)
[](https://www.npmjs.com/package/digestseo-mcp)
[](https://registry.modelcontextprotocol.io/v0/servers?search=io.github.AKzar1el/digestseo-mcp)
[](./LICENSE)
[](https://www.typescriptlang.org/)
[](https://workers.cloudflare.com/)
[](https://modelcontextprotocol.io/)
[](https://github.com/AKzar1el/mcp-geo/stargazers)

## Quick Install

Runs locally over stdio with your own API keys — all data stays on your machine (see [Privacy Policy](#privacy-policy)). Set at least one engine key (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GEMINI_API_KEY`, `PERPLEXITY_API_KEY`, `SERPAPI_API_KEY`); engines without a key skip gracefully.

**Claude Desktop / any MCP client (npx):**

```json
{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "digestseo-mcp"],
      "env": {
        "OPENAI_API_KEY": "sk-...",
        "GEMINI_API_KEY": "your_key_here"
      }
    }
  }
}
```

**Claude Code:**

```bash
claude mcp add --transport stdio digestseo -s user --env GEMINI_API_KEY=your_key_here -- npx -y digestseo-mcp
```

**Cursor:**

[](https://cursor.com/en/install-mcp?name=digestseo&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsImRpZ2VzdHNlby1tY3AiXSwiZW52Ijp7Ik9QRU5BSV9BUElfS0VZIjoiIiwiQU5USFJPUElDX0FQSV9LRVkiOiIiLCJHRU1JTklfQVBJX0tFWSI6IiIsIlBFUlBMRVhJVFlfQVBJX0tFWSI6IiIsIlNFUlBBUElfQVBJX0tFWSI6IiJ9fQ%3D%3D)

**Claude Desktop extension (one-click):** download the `.mcpb` bundle from the [latest release](https://github.com/AKzar1el/mcp-geo/releases/latest) and double-click it — Claude Desktop prompts for the API keys.

**First run:** ask your client to *"track acme.com as brand `acme`, then refresh it"* — `track_brand` creates the brand with generated prompts, `refresh_brand` runs the first scan, `check_visibility` shows the scores.

AI agents installing this server: follow [llms-install.md](./llms-install.md). Prefer a remote server with cron auto-refresh? Self-host on Cloudflare Workers below.

---

**mcp-geo** is an open-source **AI visibility tracker** that measures how often your brand is cited by ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews. It's the **GEO** (Generative Engine Optimization) and **AEO** (Answer Engine Optimization) equivalent of Google Search Console — built as an MCP server so you can query your AI visibility data directly inside Claude.ai, Claude Desktop, Claude Code, Cursor, Codex CLI, or any MCP-compatible client.

> **Prefer zero setup?** Try the hosted version at [digestseo.com](https://digestseo.com) — managed Cloudflare infra, no API keys to manage, multi-brand, scheduled refresh, web UI. Waitlist now open. [Join waitlist →](https://digestseo.com/#waitlist)

---

## What it produces

Connect via MCP, ask Claude *"Run an AI visibility analysis on [my brand]"*, and within 90 seconds you get a strategist-quality memo grounded in real per-engine data:

[](docs/demo-report-full.png)

*[View the full report including content gaps, engine recommendations, and synthesis →](docs/demo-report-full.png)*

The report above was generated by Claude through the digestseo-mcp MCP server. The conversation chained five tools — `check_visibility`, `compare_competitors`, `get_citations` (Perplexity + Claude), and `get_content_gaps` — to produce a 4-engine analysis with citation excerpts and a 3-recommendation strategy memo.

---

## What's New

### [0.3.0] — July 2026

- **Local stdio CLI on npm** (`npx -y digestseo-mcp`): the same MCP tools backed by a local SQLite database (`~/.digestseo/digestseo.sqlite`) — no Cloudflare account needed. Engines run inline with your own API keys.
- **Local brand-management tools** (CLI only): `track_brand`, `list_brands`, `generate_prompts`. Workers deployments keep these behind the `X-Seed-Secret`-gated `/admin/*` routes.
- **Runtime-agnostic core** (`src/core/`) shared by the Worker and the CLI, with a `Db` contract implemented by D1 and better-sqlite3 adapters. All 0.2.1 accuracy and security fixes carry over to both runtimes.
- **Distribution metadata**: official MCP Registry `server.json`, MCPB desktop extension (`.mcpb` bundle), Dockerfile, `llms-install.md` for AI agents, release-publish workflow.

### [0.2.1] — June 2026

- **Optional `CONNECT_SECRET` gate on the OAuth flow.** By default the OSS build auto-completes `/authorize` for any MCP client that knows your worker URL — anyone who finds the URL can connect and call `refresh_brand`, spending your engine API credits. Set `CONNECT_SECRET` and the browser step of the connect flow now asks for it before issuing a token. See [SECURITY.md](./SECURITY.md).
- **Accurate citation matching.** Brand/competitor mentions now require word boundaries (`acme` no longer matches "acmeshop"), and linked-citation checks require the exact domain or a subdomain (`notacme.com` no longer counts as a link to `acme.com`).
- **Per-brand `aliases` and `exclude_terms`.** Aliases always count as a mention; exclude terms suppress the bare-word match on the brand name and domain root — so "Monday" the brand stops matching "monday" the weekday, while `monday.com` still counts. Apply `migrations/0005_brand_alias_exclude.sql`; existing brands behave exactly as before.
- **`get_visibility_history` consistency.** Partially-finished runs now count toward history (matching `check_visibility`'s 0.2.0 behavior), and fully-failed runs no longer show up as fake zero scores.
- **CI + unit tests.** GitHub Actions runs `tsc --noEmit` plus a pure-function unit suite (`npm run test:unit`) covering mention matching, citation extraction, and score aggregation on every push.
- **Docs now recommend OpenAI + Anthropic as the starting engine pair** — the Gemini free tier rate-limits brands with more than ~5 prompts and produced misleading first-run data as the documented cheapest path.
- Constant-time comparison for `SEED_SECRET` / `CONNECT_SECRET`.

### [0.2.0] — May 2026

- **Per-engine HTTP fan-out.** `/admin/run-live` now creates one runs row per engine and self-fetches `/admin/run-engine` once per engine. Each engine runs in its own worker invocation with its own free-plan 50-subrequest budget — a single-invocation fan-out used to burst past the cap mid-run and lose half the rows.
- **Service binding (`env.SELF`)** dispatches the per-engine fan-out through Cloudflare's internal fabric instead of a public-URL fetch, dodging the "Worker called itself" guard (error 1042) that silently blocks the latter.
- **Status column** on `prompt_responses` (`ok` / `failed` / `skipped`) plus `error_message`. Failed engine calls used to write `raw_response='ERROR: ...'` rows that downstream scoring treated as real zero-mention hits; now they're explicitly excluded.
- **FK-resistant inserts.** `/admin/run-engine` `INSERT OR IGNORE`s its runs row before persisting — D1 is eventually consistent across edge regions, and the upstream `INSERT INTO runs` from `/admin/run-live` doesn't always replicate before the downstream engine call lands. The IGNORE makes the FK happy either way.
- **Bulk D1 batch.** Each engine collects its 20 prompt results in memory then flushes inserts + cache writes + the final `UPDATE runs SET status='completed'` in a single `D1.batch()` call. Drops the per-invocation subrequest count from ~89 to ~26.
- **Relaxed visibility queries.** `getLatestCompletedRun` anchors on `EXISTS(ok rows)` instead of `status='completed'`, so partially-finished runs still surface their data in MCP tool output instead of silently disappearing.
- **New admin route `POST /admin/cleanup-failed-runs`** for one-shot deletion of legacy polluted rows after migrating to 0004.

### [0.1.1] — May 2026

- Manual install is now the canonical path. The unreliable bash setup script was removed; SETUP.md is self-contained and copy-pasteable, with every interactive wrangler prompt documented inline.

### [0.1.0] — May 2026

- Initial public release.
- 5-engine support: ChatGPT (`gpt-4o-mini`), Claude (`claude-haiku-4-5`), Perplexity (`sonar`), Gemini (`gemini-2.5-flash-lite`), and Google AI Overviews (via SerpAPI).
- 6 MCP tools: `check_visibility`, `get_visibility_history`, `compare_competitors`, `get_citations`, `get_content_gaps`, `refresh_brand`.
- Engines are opt-in based on which API keys you provide — set only the credentials you have, the rest skip gracefully.
- Cloudflare Cron Trigger that auto-refreshes tracked brands every 6h, respecting per-brand `refresh_frequency` (daily/weekly).
- D1-backed storage for brands, prompts, runs, citations, and a shared prompt cache.

---

## What Can This Do?

- **See which AI tools cite your brand and which don't** — get a per-engine breakdown of who's citing you for buyer-intent queries.
- **Track AI visibility weekly, automatically** — the built-in Cron Trigger re-runs scans on the cadence you configure per brand.
- **Compare your AI visibility to competitors** — share-of-voice percentages, prompts you win, prompts they win.
- **Find content gaps** — Claude-Haiku-synthesized recommendations grounded in your actual losing prompts.
- **Use it inside Claude.ai conversations** — add the deployed Worker URL as a custom MCP connector and ask in natural language.
- **Self-hosted on your own Cloudflare account** — your API keys, your data, your cost ceiling. The free Workers + D1 tiers cover a single brand with daily refreshes.

*See [the example report above](#what-it-produces) for what this looks like in practice.*

---

## Available Tools

| Tool | What it does | What you provide |
|---|---|---|
| `check_visibility` | Latest AI visibility snapshot across all configured engines for a tracked brand, with per-engine scores, winning prompts, and losing prompts. | `brand_id`, optional `engines[]` filter |
| `get_visibility_history` | Time-series history of overall and per-engine visibility, bucketed daily or weekly. | `brand_id`, optional `days` (default 30), optional `granularity` (`daily`/`weekly`) |
| `compare_competitors` | Share-of-voice comparison against competitor domains, with prompts you win and prompts they win. | `brand_id`, optional `competitor_domains[]`, optional `days` |
| `get_citations` | The actual citation events — prompt, engine, response excerpt, citation type, brand URL when present. | `brand_id`, optional `days`, optional `engine` filter |
| `get_content_gaps` | Prioritized Claude-Haiku-generated content recommendations targeting your losing prompts. | `brand_id`, optional `max_recommendations` (1-10) |
| `refresh_brand` | Manually trigger a fresh scan across every engine whose API key is set. | `brand_id`, optional `engines[]` filter |

The local stdio CLI (npx, desktop extension, Docker) additionally provides brand management — on a Workers deployment the same operations live behind the `X-Seed-Secret`-gated `/admin/*` routes instead:

| Tool (local CLI only) | What it does | What you provide |
|---|---|---|
| `track_brand` | Start tracking a brand: creates it locally and generates its buyer-intent prompt set (Claude Haiku when `ANTHROPIC_API_KEY` is set, three starter prompts otherwise). | `brand_id`, `name`, `domain`, optional `category`, `competitors[]`, `aliases[]`, `exclude_terms[]`, `prompt_count` |
| `list_brands` | List tracked brands with domains, competitors, and active prompt counts. | — |
| `generate_prompts` | Regenerate a brand's prompt set via Claude Haiku (replaces active prompts, keeps history). | `brand_id`, optional `count` (default 20) |

---

## Getting Started

### Step 1 — Get API keys

Engines are opt-in. Pick the ones you want; the rest skip silently.

- **OpenAI** — ChatGPT engine. ~€0.0004 per prompt with `gpt-4o-mini`. Batch path roughly halves that. [platform.openai.com](https://platform.openai.com/api-keys)
- **Anthropic** — Claude engine, plus prompt generation and content-gap analysis (both call Claude Haiku). ~€0.0002 per prompt. Free trial credits are usually enough to evaluate. [console.anthropic.com](https://console.anthropic.com/)
- **Google AI Studio (Gemini)** — Gemini engine. ~€0.0001 per prompt. The free tier has a low per-minute cap, so brands with more than ~5 prompts hit HTTP 429 and drop out of scoring (see [Troubleshooting](#troubleshooting)) — treat it as an opt-in add-on, not a starting engine. [aistudio.google.com](https://aistudio.google.com/app/apikey)
- **Perplexity** — Perplexity Sonar engine. ~€0.005-0.008 per prompt. Paid only. [perplexity.ai/settings/api](https://www.perplexity.ai/settings/api)
- **SerpAPI** — Google AI Overviews engine. ~€0.005 (free tier) / ~€0.0015 (volume) per prompt. Free tier covers ~100 calls/month — enough for development. [serpapi.com/dashboard](https://serpapi.com/dashboard)

**Recommended starting pair: OpenAI + Anthropic (Claude).** Both bill per token with no rate-limit surprises, so your first scan returns clean, scorable data across the ChatGPT and Claude engines — and the Anthropic key also powers prompt generation and content-gap analysis. Solo evaluation runs comfortably under €1/month on the two together. Add Gemini, Perplexity, or SerpAPI deliberately once you want more coverage; Gemini's free tier rate-limits and Google AI Overviews often returns no result (scored as a zero), so leading with the cheapest path can skew your first run.

### Step 2 — Deploy to your Cloudflare account

The deploy is 6 commands and takes about 5 minutes. See [SETUP.md](./SETUP.md) for the full walkthrough with explanations and troubleshooting, or follow the quick version below.

```bash
# 1. Install deps
npm install

# 2. Log in to Cloudflare
npx wrangler login

# 3. Copy the config template
cp wrangler.example.jsonc wrangler.jsonc

# 4. Create KV namespace + D1 database, paste each printed id into wrangler.jsonc
npx wrangler kv namespace create OAUTH_KV
npx wrangler d1 create digestseo-db

# 5. Set the required secret + at least one engine API key
#    Recommended starting pair — both bill per token, clean first-run data:
npx wrangler secret put SEED_SECRET
npx wrangler secret put CONNECT_SECRET      # recommended — gates who can connect (see SECURITY.md)
npx wrangler secret put OPENAI_API_KEY      # ChatGPT engine
npx wrangler secret put ANTHROPIC_API_KEY   # Claude engine + prompt generation

# 6. Apply migrations and deploy
npx wrangler d1 migrations apply digestseo-db --remote
npx wrangler deploy
```

After deploy, wrangler prints your Worker URL. Save it.

### Step 3 — Connect to your MCP client

After `wrangler deploy` finishes, you get a URL like
`https://digestseo-mcp.YOUR-SUBDOMAIN.workers.dev`.

#### Claude.ai (web)

Settings → Connectors → Add custom connector. Paste:

```
https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/mcp
```

Complete the OAuth handshake. The connector turns green when ready.

#### Claude Code

```bash
claude mcp add --transport http digestseo https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/mcp
```

Then run `/mcp` inside Claude Code to complete the OAuth handshake in your browser.

#### Claude Desktop

Edit your Claude Desktop config:

- macOS: `~/Library/Application Support/Claude/claude_desktop_config.json`
- Windows: `%APPDATA%\Claude\claude_desktop_config.json`

```jsonc
{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/mcp"
      ]
    }
  }
}
```

Restart Claude Desktop after editing.

#### Cursor

Edit `~/.cursor/mcp.json`:

```jsonc
{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": [
        "-y",
        "mcp-remote",
        "https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/mcp"
      ]
    }
  }
}
```

Restart Cursor.

#### Codex CLI

Add to `~/.codex/config.toml`:

```toml
[mcp_servers.digestseo]
command = "npx"
args = [
  "-y",
  "mcp-remote",
  "https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/mcp",
]
```

---

## Environment Variables Reference

| Variable | Required | Default | Description |

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [AKzar1el](https://github.com/AKzar1el)
- **Source:** [AKzar1el/mcp-geo](https://github.com/AKzar1el/mcp-geo)
- **License:** MIT
- **Homepage:** https://digestseo.com

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** yes
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-akzar1el-mcp-geo
- Seller: https://agentstack.voostack.com/s/akzar1el
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
