Skip to main content
Glama
AKzar1el

GEO MCP by DigestSEO

DigestSEO — AI Visibility MCP for SEO & GEO

CI npm version MCP Registry License: MIT TypeScript Cloudflare Workers MCP mcp-geo MCP server GitHub stars EUR 99 AI Visibility Audit

Quick Install

Runs locally over stdio with your own API keys — all data stays on your machine (see 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.

Runtime: Node.js 22.13+ (CI exercises Node 22 and 24).

Claude Desktop / any MCP client (npx):

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

Claude Code:

claude mcp add --transport stdio digestseo -s user --env GEMINI_API_KEY=your_key_here -- npx -y @digestseo/mcp-geo

Cursor:

Add to Cursor

Kiro (remote MCP): self-host the Worker below with the engine API keys you want to use, then add your own deployed /mcp URL to Kiro. The public geo-mcp.digestseo.com/mcp endpoint is not a turnkey fresh-scan service and should not be used as a no-key substitute for a configured Worker.

Claude Desktop extension (one-click): download the .mcpb bundle from the latest release 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. 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.

Canonical product page: DigestSEO mcp-geo — AI Visibility MCP Server

Engineering case study: DigestSEO MCP Suite — AI visibility, Search Console, web validation, and trend intelligence

Need a client-ready baseline without running the stack yourself? The mcp-geo AI Visibility Audit is EUR 99 one time: one brand, up to three competitors, 20 buyer-intent prompts, checks across up to five supported AI surfaces where configured providers return usable results, citation evidence, and a prioritized action memo. The open-source package remains free.

See proof first: Open the sample report generated through mcp-geo to see the output style and evidence depth before requesting the audit.

Ready to request it? Open a prefilled email with your brand/domain and up to three competitors. No subscription or sales call is required.

Payment handoff: After fit and scope are confirmed, I reply with the normal invoice/payment instructions.

Methodology: The same 20 buyer-intent prompts are run as a point-in-time diagnostic and reported per engine, with citation/source evidence where available. The audit is an observed snapshot, not a proprietary ranking promise or guaranteed forecast.

Want the protocol before buying? Read the AI Visibility Audit methodology, including scope, engine coverage, interpretation limits, and what the audit does not claim.

Prefer zero setup? Try the hosted version at digestseo.com — managed Cloudflare infra, no API keys to manage, multi-brand, scheduled refresh, web UI. Waitlist now open. Join waitlist →


Related MCP server: websearch-mcp

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:

Example AI visibility report

View the full report including content gaps, engine recommendations, and synthesis →

The report above was generated by Claude through the digestseo-mcp MCP server. The conversation chained five hosted tools — visibility.check, visibility.compare, visibility.citations (Perplexity + Claude), and visibility.content_gaps — to produce a 4-engine analysis with citation excerpts and a 3-recommendation strategy memo.


What's New

[0.3.4] - September 15, 2026

  • Claude Desktop MCPB portability: the bundle no longer ships better-sqlite3 native binaries; local storage uses built-in node:sqlite on Node.js 22.13+.

  • Registry accuracy: official metadata now advertises the npm stdio package only while the public hosted endpoint is not a turnkey configured fresh-scan service.

[0.3.3] - September 10, 2026

  • Optional one-time audit: the open-source package stays free; teams that want a client-ready baseline can request the EUR 99 mcp-geo AI Visibility Audit from the CTA above.

  • Lower-friction request path: the README now opens a prefilled, source-marked email, while the audit details remain available at https://geo-mcp.digestseo.com/audit.

[0.3.2] — July 27, 2026

  • Published scoped package: @digestseo/mcp-geo with synchronized Worker, MCP Registry, and MCPB metadata.

  • Hosted tool metadata: visibility.* namespaces with typed input/output schemas; local stdio tool names remain flat.

  • Distribution and deployment: dedicated mcp-geo-db D1 configuration, Cursor and Claude Code plugin metadata, and patched production dependency pins.

[0.3.0] — July 2026

  • Local stdio CLI on npm (npx -y @digestseo/mcp-geo): 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 visibility.refresh, 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.

  • 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.

  • visibility.history consistency. Partially-finished runs now count toward history (matching visibility.check'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 IGNOREs 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 hosted MCP tools: visibility.check, visibility.history, visibility.compare, visibility.citations, visibility.content_gaps, visibility.refresh.

  • 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 for what this looks like in practice.


Available Tools

The six analysis capabilities are shared across both transports, but the exposed MCP names are intentionally transport-specific: hosted/Worker connections use the visibility.* namespace, while the local stdio package uses flat names.

Hosted / Worker

Local stdio

What it does

What you provide

visibility.check

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

visibility.history

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)

visibility.compare

compare_competitors

Share-of-voice comparison against competitor domains, with prompts you win and prompts they win.

brand_id, optional competitor_domains[], optional days

visibility.citations

get_citations

The actual citation events — prompt, engine, response excerpt, citation type, brand URL when present.

brand_id, optional days, optional engine filter

visibility.content_gaps

get_content_gaps

Prioritized Claude-Haiku-generated content recommendations targeting your losing prompts.

brand_id, optional max_recommendations (1-10)

visibility.refresh

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

  • 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

  • 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) — treat it as an opt-in add-on, not a starting engine. aistudio.google.com

  • Perplexity — Perplexity Sonar engine. ~€0.005-0.008 per prompt. Paid only. perplexity.ai/settings/api

  • SerpAPI — Google AI Overviews engine. ~€0.005 (free tier) / ~€0.0015 (volume) per prompt. Free tier covers 250 searches/month — enough for development. 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 for the full walkthrough with explanations and troubleshooting, or follow the quick version below.

# 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 mcp-geo-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 mcp-geo-db --remote
npx wrangler deploy

After deploying your own Worker, use that deployment's /mcp URL as the remote endpoint, for example:

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

Use your configured Worker URL for directory or client integrations. The public geo-mcp.digestseo.com/mcp endpoint is not a no-key hosted substitute for a deployment with engine provider credentials.

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.

ChatGPT (remote MCP)

ChatGPT custom MCP apps connect to remote MCP servers, so use the /mcp URL from your configured Worker deployment above. In ChatGPT, enable Developer Mode/custom apps for your workspace and add that remote MCP URL. Availability depends on your ChatGPT plan and workspace admin policy; OpenAI's current MCP support does not require special search or fetch tool names.

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

Claude Code

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

{
  "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:

{
  "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:

[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

OPENAI_API_KEY

opt-in

unset

Enables the ChatGPT engine. Without it, ChatGPT is skipped.

ANTHROPIC_API_KEY

opt-in

unset

Enables the Claude engine and the Claude-Haiku-powered prompt generator + content-gap analyzer.

GEMINI_API_KEY

opt-in

unset

Enables the Gemini engine. Free tier is rate-limited for brands with more than ~5 prompts (see Troubleshooting); opt-in add-on.

PERPLEXITY_API_KEY

opt-in

unset

Enables the Perplexity Sonar engine. Paid only.

SERPAPI_API_KEY

opt-in

unset

Enables the Google AI Overviews engine (via SerpAPI).

SEED_SECRET

yes

unset

Shared secret that gates every /admin/* route. Pick a high-entropy string.

CONNECT_SECRET

recommended

unset

When set, the OAuth connect flow asks for this secret in the browser before issuing a token. Without it, anyone who knows your worker URL can connect an MCP client. See SECURITY.md.

TURNSTILE_SITE_KEY

no

unset

Reserved for forks that add a public /check form. Unused by the OSS build.

TURNSTILE_SECRET_KEY

no

unset

Same — reserved for forks.

All values are set via wrangler secret put VAR in production or .dev.vars locally. None are stored in wrangler.jsonc.


Architecture

flowchart LR
    C["MCP client<br/>(Claude.ai / Claude Code / Cursor / ...)"] -- "MCP over HTTP + OAuth" --> W["Cloudflare Worker<br/>digestseo-mcp"]
    CRON["Cron Trigger<br/>every 6h"] --> W
    W --> DO["GeoMcpAgent<br/>(Durable Object, 6 MCP tools)"]
    W -- "one self-fetch per engine<br/>via SELF service binding" --> RE["/admin/run-engine<br/>(own invocation per engine)"]
    RE --> E1["OpenAI"]
    RE --> E2["Anthropic"]
    RE --> E3["Gemini"]
    RE --> E4["Perplexity"]
    RE --> E5["SerpAPI<br/>(AI Overviews)"]
    RE --> DB[("D1<br/>brands / prompts / runs /<br/>responses / cache")]
    DO --> DB

Each engine runs in its own Worker invocation with its own free-plan 50-subrequest budget; results are flushed in a single D1.batch() per engine. The whole system fits the Cloudflare free tier for a single brand on a daily cadence.


Security

  • /admin/* is gated by SEED_SECRET (constant-time compared).

  • /mcp requires OAuth; set CONNECT_SECRET so only people with the secret can complete the connect flow — strongly recommended whenever your worker URL is shared anywhere, since connected clients can call visibility.refresh and spend your engine API credits.

  • All engine keys live in Cloudflare's encrypted secret store; all data stays in your own D1 database.

Full details and vulnerability reporting: SECURITY.md.


Sample Prompts

The example report above was generated by the first prompt below.

Once the connector is live in Claude.ai (or any MCP client), try:

Tool

Example prompt

visibility.check

"How visible is brand_id acme on AI right now?"

visibility.history

"Show me the visibility trend for acme over the last 60 days, daily."

visibility.compare

"Compare acme against asana.com and monday.com over the last 14 days."

visibility.citations

"Show me real Perplexity citations for acme from the last week."

visibility.content_gaps

"What content should acme publish to close its visibility gap? Give me the top 5."

visibility.refresh

"Refresh acme across every available engine right now."

visibility.refresh

"Refresh acme but only for Gemini and Claude."


Hosted Version

If you'd rather not run your own Cloudflare account, manage API keys, or pay individual engine bills, the hosted version of DigestSEO runs the same MCP server on managed infrastructure with multi-brand support, scheduled refresh, a web UI, and consolidated billing. Waitlist now open — join at digestseo.com.


Troubleshooting

  • Worker deploys but tools return empty data — at least one engine API key is missing. Check wrangler secret list and add the keys you intend to use. Engines without keys are silently skipped, which can leave visibility.check with no data.

  • no engines available error in logs — no engine API keys are set at all. Set at least one of OPENAI_API_KEY, ANTHROPIC_API_KEY, GEMINI_API_KEY, PERPLEXITY_API_KEY, SERPAPI_API_KEY.

  • D1 migration fails — make sure you've run npx wrangler d1 migrations apply mcp-geo-db --remote (and also --local for wrangler dev). For ad-hoc fixes, npx wrangler d1 execute mcp-geo-db --remote --file=migrations/0001_initial.sql.

  • Custom MCP connector in Claude.ai not connecting — the URL must end in /mcp. The OAuth handshake auto-completes in the OSS build (single dev user); if you set CONNECT_SECRET, the browser step shows a one-field form — enter the secret you set during deploy. If it loops, clear the connector and re-add it. Double-check the Worker is publicly reachable (curl https://YOUR-WORKER-NAME.YOUR-SUBDOMAIN.workers.dev/healthz should return ok).

  • Cron not firing — check the Cloudflare dashboard at Workers & Pages → digestseo-mcp → Settings → Triggers. The "Cron Triggers" section should list 0 */6 * * *. If it's missing, run npx wrangler deploy again — the trigger is registered on deploy. The handler also only dispatches engines for brands whose refresh_frequency cadence has elapsed, so a freshly-seeded brand might not fire on the next 6h boundary.

  • 401 unauthorized from /admin/*X-Seed-Secret header is missing or doesn't match the deployed SEED_SECRET. Re-run npx wrangler secret put SEED_SECRET and update your .env.test.

  • Worker returns 404 on self-fetch / error code 1042 — the services binding in wrangler.jsonc is missing or the service name doesn't match the worker's name field. /admin/run-live self-fetches /admin/run-engine via env.SELF (a Cloudflare service binding) precisely because a public-URL fetch back to your own workers.dev hostname is blocked by Cloudflare's "Worker called itself" guard. Confirm the wrangler.jsonc you deployed contains "services": [{ "binding": "SELF", "service": "<your-worker-name>" }] with the same name you set in the top-level "name" field. After fixing, npx wrangler deploy and re-run.

  • Gemini rate limit (HTTP 429) on every prompt — the Gemini free tier caps gemini-2.5-flash-lite at single-digit requests per minute and a low daily total. For brands with more than ~5 prompts you'll see status='failed' rows with 429 error messages, which excludes Gemini from scoring. Workarounds: upgrade to paid Gemini, switch the MODEL constant in src/core/gemini.ts to a different model with a higher quota, or invoke /admin/run-engine for one engine at a time so the per-minute window has time to refill between batches.

  • FOREIGN KEY constraint failed in wrangler tail during /admin/run-engine — the handler defensively INSERT OR IGNOREs the runs row before persisting prompt responses. This is an idempotency/FK guard for independently dispatched engine work, so you should not see this on the 0.2.0+ build; if you do, confirm you've deployed the latest src/index.ts (grep -n "INSERT OR IGNORE INTO runs" src/index.ts should match).


Contributing

Issues and PRs welcome. See CONTRIBUTING.md for the short version.


Privacy Policy

Full policy for the local package and Claude Desktop extension: https://geo-mcp.digestseo.com/privacy

When you run digestseo-mcp locally (npx, the desktop extension, or Docker), all of your data — brands, prompts, runs, responses, and the response cache — stays on your machine in a local SQLite database at ~/.digestseo/digestseo.sqlite (override with DIGESTSEO_DB_PATH). The scan prompts are sent to whichever AI providers you configured with your own API keys (OpenAI, Anthropic, Google, Perplexity, and/or SerpAPI), and only to those; their handling of that traffic is governed by their respective privacy policies. Nothing is ever sent to the author of this project: no telemetry, no analytics, no account.

Data use and storage: Local brand configuration, prompts, scan runs, responses, and cached responses are used only to provide the MCP server features you invoke. They remain in the local SQLite database described above; this project does not operate an account service or collect telemetry.

Third-party processing: Prompt and scan traffic is sent only to the AI providers you explicitly configure. Those providers process and retain that traffic under their own privacy policies; the project author does not receive copies of it.

Retention and deletion: Local data remains on your machine until you delete the SQLite database (or the custom DIGESTSEO_DB_PATH you configured). Removing that local database removes mcp-geo's stored local history and cache. Provider-side retention is controlled by each configured provider.

Contact: Privacy questions about mcp-geo can be sent to info@tomiseregi.si.


License

MIT.

Built and maintained by Tomi Šeregi.


Changelog

See CHANGELOG.md for the full version history.

[0.3.2] — July 27, 2026

  • Published @digestseo/mcp-geo with synchronized Worker, MCP Registry, and MCPB metadata.

  • Hosted visibility.* tool namespaces with typed input/output schemas; local stdio names remain flat.

  • Dedicated mcp-geo-db D1 configuration and Cursor/Claude Code plugin metadata.

  • Patched production dependency pins.

[0.3.0] — July 2026

  • Local stdio CLI on npm (npx -y @digestseo/mcp-geo) with SQLite storage and inline engine runs.

  • Local brand-management tools: track_brand, list_brands, generate_prompts.

  • Runtime-agnostic core shared by Worker and CLI; D1 + better-sqlite3 Db adapters.

  • MCP Registry server.json, MCPB desktop extension, Dockerfile, llms-install.md.

[0.2.1] — June 2026

  • Optional CONNECT_SECRET gate on the OAuth connect flow.

  • Word-boundary brand/competitor matching; exact-domain-or-subdomain linked-citation checks.

  • Per-brand aliases and exclude_terms (migration 0005) for homograph brands like Monday/Notion.

  • visibility.history includes partial runs and drops fully-failed runs.

  • CI workflow (typecheck + unit tests) and a pure-function unit test suite.

  • Docs recommend OpenAI + Anthropic as the starting engine pair.

  • Constant-time secret comparison.

[0.2.0] — May 2026

  • Per-engine HTTP fan-out via env.SELF service binding (one worker invocation per engine, dodges Cloudflare's 1042 self-call guard).

  • status + error_message columns on prompt_responses — failed engine calls are now explicit rows, no more ERROR: strings in raw_response.

  • INSERT OR IGNORE on the runs row inside /admin/run-engine (handles D1 cross-region replication lag without dropping prompt_responses to FK violations).

  • Bulk D1 batch in each engine's runLive (~26 subrequests/invocation instead of ~89; full 20-prompt runs now fit under the free-plan cap).

  • getLatestCompletedRun anchored on EXISTS(ok rows); partially-finished runs still show their data.

  • New POST /admin/cleanup-failed-runs admin route.

[0.1.1] — May 2026

  • Removed the unreliable bash setup script. Manual install via SETUP.md is now the canonical path.

[0.1.0] — May 2026

  • Initial public release.

  • 5-engine support: ChatGPT, Claude, Perplexity, Gemini, Google AI Overviews.

  • 6 MCP tools.

  • Engines opt-in based on which API keys you provide.

  • Cloudflare Cron Trigger for auto-refresh.

Available Tools

9 tools
check_visibilityCheck AI visibilityA
Read-only

Get the latest AI visibility data for a tracked brand: which AI assistants (ChatGPT, Claude, Perplexity, Gemini, Google AI Overviews) cite this brand, for which prompts, and how it compares to competitors. Use when the user asks 'how visible am I on AI?', 'who's citing my brand?', or 'show me my AI visibility score'. Returns stored data — for fresh data, call refresh_brand.

ParametersJSON Schema
NameRequiredDescriptionDefault
enginesNoOptional engine filter. If omitted or empty, return results for every engine with stored data.
brand_idYesStable identifier of the tracked brand to inspect.

Output Schema

ParametersJSON Schema
NameRequiredDescription
brandYes
per_engineYes
refreshed_atYes
overall_scoreYes
top_losing_promptsYes
top_winning_promptsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only; the description adds that it 'returns stored data' rather than performing a live fetch, which is behaviorally important. It also discloses what data is included (assistants, prompts, competitor comparison) without contradicting the readOnlyHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with no filler: lead with the data returned, give concrete user-phrase triggers, then state the freshness caveat and refresh alternative. Every sentence adds decision-relevant value.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given an output schema and safe read-only annotations, the description is largely sufficient; the stored-data caveat and refresh routing are important. It could be more explicit about when to prefer get_visibility_history or compare_competitors, but the trigger phrases compensate.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the description does not need to explain the parameters. It reinforces the meaning of the engine filter by naming the supported assistants, but adds no new mechanics beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource ('Get the latest AI visibility data for a tracked brand'), enumerates the assistants, prompts, and competitor comparison it covers, and distinguishes itself from refresh_brand. It does not explicitly delineate overlap with siblings like get_citations or compare_competitors, but the core purpose is unmistakable.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit trigger queries ('how visible am I on AI?', 'who's citing my brand?', 'show me my AI visibility score') and an explicit alternative when data must be fresh ('call refresh_brand'). This gives an agent a clear basis for selecting this tool and routing to another when needed.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

compare_competitorsCompare competitor AI visibilityA
Read-only

Compare a brand's AI visibility against competitors for the same category. Returns share-of-voice percentages, prompts the user wins, and prompts where competitors win. Use when the user asks 'who beats me in AI search?', 'compare me to my competitors', or 'why does [competitor] get cited more?'.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of previous days to include in the comparison.
brand_idYesStable identifier of the tracked brand to compare.
competitor_domainsNoOptional competitor domains to compare; otherwise use the brand's configured competitors.

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
brand_idYes
competitorsYes
prompts_you_winYes
your_share_of_voice_pctYes
requested_competitor_domainsYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true)Skip and openWorldHint=false. The description adds useful behavioral context beyond that: it returns share-of-voice percentages and prompt-level wins/losses, and mentions brand-configured competitors. No mutation or side effects are implied, consistent with the annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences with zero filler: the first states the action and scope, the second lists return values, and the third gives direct invocation triggers. The most actionable information is front-loaded, and every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given a 3-parameter schema with 100% coverage, a full output schema, and read-only annotations, the description supplies everything an agent needs to decide when to invoke the tool and what to expect back. No critical behavioral or usage details are missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so parameters are already documented. The description adds minimal semantic value beyond the schema, mostly reinforcing that the comparison is category-scoped and competitors may be the brand's configured set. This meets the baseline but does not elevate it.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Compare'), a precise resource ('a brand's AI visibility against competitors'), and the category scope ('same category'). It also names concrete outputs (share-of-voice percentages, winning prompts), which clearly differentiates it from siblings like check_visibility or get_citations.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The 'Use when' clause lists three concrete user intents ('who beats me in AI search?', 'compare me to my competitors', 'why does [competitor] get cited more?'). This gives clear context for invocation, though it does not explicitly name alternative tools or when-not-to-use conditions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

generate_promptsGenerate brand promptsA
Destructive

Regenerate the buyer-intent prompt set for a tracked brand using Claude Haiku (requires ANTHROPIC_API_KEY). Replaces the brand's active prompts; historical run data is preserved. Use when the user wants better or more prompts, or to upgrade from the generic starter prompts after adding an Anthropic key.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoNumber of buyer-intent prompts to generate.
brand_idYesStable identifier of the tracked brand to update.

Output Schema

ParametersJSON Schema
NameRequiredDescription
promptsYes
brand_idYes
next_stepsYes
prompt_sourceYes
prompts_insertedYes

TDQS

A4.5/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, the description adds valuable behavioral context: it explicitly says the tool 'Replaces the brand's active prompts' while 'historical run data is preserved,' and it calls out the ANTHROPIC_API_KEY requirement and the use of Claude Haiku. This gives an agent a clear picture of side effects and prerequisites beyond the destructiveHint and openWorldHint annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is three sentences with no filler: the first states the core operation and prerequisite, the second discloses the side effect, and the third gives clear usage guidance. Every sentence earns its place and the most important information is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with only two parameters, one required, and an output schema present, the description is complete. It covers what the tool does, when to use it, the key prerequisite, and the destructive side effect. Nothing essential is missing for an agent to select and invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema already documents both parameters fully (100% coverage), including defaults and constraints for count and the meaning of brand_id. The description does not add parameter-specific details beyond the schema, so the baseline of 3 applies. It does provide general context about what the prompts are for, but not enough to raise the score.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('Regenerate') and resource ('buyer-intent prompt set for a tracked brand'), making the tool's purpose immediately clear. It goes beyond the title by specifying the model (Claude Haiku) and the fact that it replaces active prompts, which also helps differentiate it from sibling tools like list_brands or refresh_brand.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit when-to-use guidance: 'Use when the user wants better or more prompts, or to upgrade from the generic starter prompts after adding an Anthropic key.' It also states the key prerequisite. However, it does not mention when not to use it or name direct alternative tools, so it falls slightly short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_citationsGet AI citation evidenceA
Read-only

Get citation events where AI assistants mention the brand. Each event includes the prompt that triggered it, the LLM's response excerpt, whether the brand was mentioned with or without a link, and the matched brand URL from engine-native citation data when available. Use when the user asks 'show me where I'm cited', 'what are ChatGPT/Claude/Perplexity actually saying about my brand?', or 'give me proof of AI citations'.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of previous days from which to return citations.
engineNoOptional engine filter for the citation events.
brand_idYesStable identifier of the tracked brand to inspect.

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
engineYes
brand_idYes
citationsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark this as read-only and closed-world focused. The description adds behavioral context by detailing exactly what each citation event includes and notes the 'matched brand URL from engine-native citation data when available,' which sets expectations about conditional data. No destructive or surprising behavior is hidden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is concise and well-structured: the first sentence defines the tool's core purpose, the second sentence itemizes the return data, and the final sentence gives user-facing triggers. Every sentence earns its place, with no redundancy or filler.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool is read-only, has an output schema, and fully documented parameters, the description covers what the tool does, what it returns, and when to use it. Minor omissions like pagination or rate limits are not critical here, but an explicit 'when not to use' might slightly strengthen completeness.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, with each parameter (days, engine, brand_id) already documented with defaults, ranges, and enums. The description adds no parameter-specific semantics beyond what the schema provides, so the baseline score of 3 applies.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the specific action: 'Get citation events where AI assistants mention the brand.' It also enumerates the event contents (prompt, response excerpt, link presence, matched brand URL), which makes the resource unambiguous. The name and content are distinct from sibling tools like check_visibility or get_visibility_history.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly says 'Use when the user asks...' and provides three concrete example phrasings. It does not list when not to use it or direct to an alternative, but the context is clear enough and the sibling set makes the selection decision straightforward.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_content_gapsFind AI visibility content gapsA
Read-only

Get actionable content recommendations based on AI visibility gaps. Returns prioritized topics and content formats that would close the gap between this brand and competitors winning the same prompts. Use when the user asks 'what should I write to improve AI visibility?', 'what content gaps do I have?', or 'how do I get cited more by AI?'.

ParametersJSON Schema
NameRequiredDescriptionDefault
brand_idYesStable identifier of the tracked brand to analyze.
max_recommendationsNoMaximum number of content recommendations to return.

Output Schema

ParametersJSON Schema
NameRequiredDescription
reasonNo
brand_idYes
prompt_sourceYes
recommendationsYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool read-only and open-world, and the description adds meaningful context beyond them: it returns prioritized topics/formats and performs a gap analysis against competitors winning the same prompts. No destructive or unexpected behavior is hidden.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two tight sentences: the first states purpose and output, the second gives direct invocation examples. Every sentence earns its place with no filler or redundancy.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With a rich input schema, an output schema, and read-only annotations, the description is nearly complete for a straightforward recommendation tool. It could mention that the brand must already be tracked, but that is implied by the schema's 'tracked brand' wording.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema covers both parameters with 100% description coverage, and the tool description does not add extra parameter-level detail. A baseline of 3 is appropriate since the schema carries the semantic weight.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description names a specific verb and resource: 'Get actionable content recommendations based on AI visibility gaps.' It also states the concrete output, prioritized topics and content formats, which clearly distinguishes it from siblings like check_visibility or compare_competitors.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly provides three user-query triggers for when to use the tool, making the use case clear. It does not state when not to use it or name alternatives, so it stops short of a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_visibility_historyGet AI visibility historyA
Read-only

Get the time-series history of a brand's AI visibility score, broken down per engine. Use when the user asks 'how has my AI visibility changed over time?', 'is my visibility growing or shrinking?', or 'show me the trend for the last month'.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoNumber of previous calendar days to include.
brand_idYesStable identifier of the tracked brand to inspect.
granularityNoTime bucket for the returned visibility series.weekly

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
seriesYes
brand_idYes
granularityYes

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description is consistent with the readOnlyHint annotation (a read operation) but adds little beyond that. It mentions the breakdown per engine, which is a useful behavioral trait, but does not disclose other traits like rate limits, authentication, or data freshness. With the readOnly annotation lowering the bar, the description provides marginal added transparency, hence a 3.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is two sentences with no fluff; the core purpose is front-loaded and the example queries provide immediate usage context. Every word earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has an output schema and readOnly annotation, so the description does not need to explain return values or safety. The examples cover the main use cases. A minor gap is that it does not mention whether a brand must be tracked before history is available (suggested by track_brand sibling), but this is not critical for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so all parameters (brand_id, days, granularity) are already documented. The description adds no parameter-specific meaning beyond the usage example ('last month' implying days=30), which is not substantial. Baseline 3 applies because the schema does the heavy lifting.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool gets a time-series history of AI visibility score, broken down per engine, which is a specific verb+resource. This distinguishes it from siblings like check_visibility (which likely returns current values) and compare_competitors (which compares across brands).

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides explicit user query examples ('how has my AI visibility changed over time?', 'is my visibility growing or shrinking?', 'show me the trend for the last month') that signal when to use the tool. However, it does not explicitly mention when not to use it or name alternative tools, so it lacks the when-not/alternatives element for a 5.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

list_brandsList tracked brandsA
Read-onlyIdempotent

List every brand tracked in the local database, with domain, category, competitors, refresh frequency, and how many prompts are active. Use when the user asks 'which brands am I tracking?' or to look up the brand_id the other tools need.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
hintNo
brandsYes

TDQS

A4.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already indicate readOnlyHint, idempotentHint, and nondestructive behavior document the safe profile. The description adds useful context about the local database scope, return content, and the brand_id lookup purpose, going beyond the annotations without contradicting them.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences, no filler, with core action and returned fields front-loaded. The usage trigger appears immediately after, making the definition efficient and scannable.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The output schema covers return values, annotations cover safety, and the description covers scope, contents, and usage context. An agent has everything needed to select and invoke this tool correctly without missing details.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With zero parameters stub parameters in the schema at 100% coverage, the baseline is 4. The description adds no parameter-specific semantics because none exist, and none are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description uses a specific verb ('List') with a clear resource ('every brand tracked in the local database') and enumerates the returned fields. It clearly distinguishes itself from siblings like track_brand and refresh_brand by focusing on read-only listing.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description gives explicit triggers: when the user asks 'which brands am I tracking?' and when looking up brand_id for other tools. It lacks explicit when-not-to-use guidance, but the invocation context is clear and sufficient for a zero-parameter read tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

refresh_brandRefresh AI visibility scanA
Destructive

Manually trigger a fresh AI visibility scan for a tracked brand. Runs every selected configured engine (ChatGPT, Claude, Perplexity, Gemini, Google AI Overviews) against the brand's current prompt set sequentially. Use when the user asks 'refresh my data', 'rerun the scan', or 'I want fresh data right now'. Returns only after all selected engine scans finish.

ParametersJSON Schema
NameRequiredDescriptionDefault
enginesNoOptional engine filter. If omitted, refresh every configured engine.
brand_idYesStable identifier of the tracked brand to refresh.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
run_idsYes
brand_idYes
estimated_completion_secondsYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare destructiveHint=true and readOnlyHint=false. The description adds valuable behavioral context beyond that: engines run sequentially and the tool returns only after all scans finish (blocking behavior). This extra detail is useful for an agent deciding whether to call it.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

All four sentences earn their place: purpose, behavior, usage triggers, and completion semantics. It is front-loaded with the core action and has no filler, making it easy to parse quickly.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's low complexity (2 parameters, one required), the presence of an output schema, and annotations covering safety profile, the description provides everything an agent needs to decide when and how to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the input schema fully documents both brand_id and engines, including the enum values and the default behavior when engines is omitted. The description adds no significant parameter-level meaning beyond what the schema already provides.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states a specific verb ('trigger'), a specific resource ('fresh AI visibility scan for a tracked brand'), and enumerates the engines involved. It clearly distinguishes itself from siblings like check_visibility or get_visibility_history by emphasizing 'fresh' scan triggering rather than reading existing data.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It provides explicit trigger phrases ('refresh my data', 'rerun the scan', 'I want fresh data right now') that map to user intents. However, it does not explicitly name alternatives or exclusion criteria, so it stops short of the highest bar.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

track_brandTrack a brandA
Idempotent

Start tracking a brand's AI visibility. Creates the brand in the local database and generates buyer-intent prompts for it — via Claude Haiku when ANTHROPIC_API_KEY is configured, otherwise three generic starter prompts (upgrade later with generate_prompts). Use when the user says 'track my brand', 'add my site', 'start monitoring acme.com', or when another tool reported the brand doesn't exist. After tracking, call refresh_brand to run the first scan.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesDisplay name of the brand to track.
domainYesPrimary domain of the brand, such as acme.com.
aliasesNoExtra terms that always count as a brand mention (product names, abbreviations).
brand_idYesStable identifier to assign to the new tracked brand.
categoryNoOptional product or market category for prompt generation.
competitorsNoOptional competitor domains to include in visibility analysis.
prompt_countNoNumber of buyer-intent prompts to generate for the brand.
exclude_termsNoTerms suppressed from bare-word matching — for brand names that are everyday words ("Monday", "Notion"). The full domain still matches.

Output Schema

ParametersJSON Schema
NameRequiredDescription
domainNo
reasonNo
seededYes
brand_idYes
next_stepsYes
competitorsNo
prompt_sourceNo
prompts_insertedNo

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, openWorldHint=true, idempotentHint=true, destructiveHint=false. The description adds genuinely useful behavioral context: the conditional Claude-Haiku-vs-generic-prompts behavior depending on ANTHROPIC_API_KEY, and the DB-creation side effect. No contradiction with annotations; the only gap is it doesn't spell out idempotent re-tracking behavior, which the annotation partially covers.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Three sentences, front-loaded with the core purpose, and every sentence earns its place: purpose, conditional behavior, then usage triggers. Slightly long due to the enumerated trigger phrases, but they add routing value rather than bloat.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an 8-parameter mutation tool with an output schema, the description covers purpose, side effects, conditional behavior, and follow-up actions. Could note what happens if the brand already exists (idempotency semantics), but idempotentHint=true and the output schema reduce the burden.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100% with well-written parameter descriptions (aliases, exclude_terms, prompt_count all documented). The description adds minimal param-level detail beyond the schema, which is acceptable at the baseline-3 level; it doesn't need to compensate for coverage gaps.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb+resource ('Start tracking a brand's AI visibility') and names its concrete effects: creates the brand in the local database and generates buyer-intent prompts. It also routes to siblings (refresh_brand for first scan, generate_prompts for upgrade), clearly distinguishing it from the list/visibility/compare tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicitly lists trigger conditions ('use when the user says track my brand, add my site, start monitoring acme.com, or when another tool reported the brand doesn't exist') and gives a follow-up action ('After tracking, call refresh_brand to run the first scan'). Names generate_prompts as the alternative for upgrading prompts. Little is left to inference.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 3 tool updatesv0.3.4
    • Changedcheck_visibility3 fields changed
      • changedInput schema / properties / engines / description
        Previous value: -"Optional engine filter. If omitted, return results for every engine with stored data."New value: +"Optional engine filter. If omitted or empty, return results for every engine with stored data."
      • removedOutput schema / properties / brand / properties / category / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / brand / properties / category / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedget_citations4 fields changed
      • removedOutput schema / properties / citations / items / properties / cited_url / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / citations / items / properties / cited_url / type
        Added value: +[
        +  "string",
        +  "null"
        +]
      • removedOutput schema / properties / engine / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / engine / type
        Added value: +[
        +  "string",
        +  "null"
        +]
    • Changedlist_brands2 fields changed
      • removedOutput schema / properties / brands / items / properties / category / anyOf
        Removed value: -[
        -  {
        -    "type": "string"
        -  },
        -  {
        -    "type": "null"
        -  }
        -]
      • addedOutput schema / properties / brands / items / properties / category / type
        Added value: +[
        +  "string",
        +  "null"
        +]
  2. 9 tool updatesv0.3.2
    • First observedcheck_visibility
    • First observedcompare_competitors
    • First observedgenerate_prompts
    • First observedget_citations
    • First observedget_content_gaps
    • First observedget_visibility_history
    • First observedlist_brands
    • First observedrefresh_brand
    • First observedtrack_brand

TDQS

A4.4/5.0

Scored across 9 tools

Disambiguation5/5

Each tool targets a distinct aspect of brand visibility monitoring: current state, history, competition, raw citations, recommendations, refresh action, onboarding, listing, and prompt management. No two tools have overlapping purposes; an agent can clearly distinguish them based on descriptions.

Naming Consistency5/5

All tools follow the verb_noun pattern with snake_case (e.g., check_visibility, get_visibility_history, refresh_brand). Verbs are action-oriented and consistent, making the tool set predictable.

Tool Count5/5

With 9 tools, the server is well-scoped for its purpose of tracking and analyzing AI brand visibility. Each tool covers a necessary function without redundancy, fitting the ideal range.

Completeness4/5

The tool surface covers the full workflow from onboarding (track_brand) to ongoing monitoring (refresh_brand, check_visibility), analysis (history, competitors, citations, gaps), and list management. Missing delete/update brand operations are minor gaps, but agents can work around them.

Maintenance

ActivityActive
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    Not graded
    maintenance
    A production-ready MCP server for AI agents, providing deep web research and RAG capabilities via Cloudflare Workers.
    -
  • A
    license
    A
    quality
    D
    maintenance
    A self-hosted MCP server that gives AI agents deep internet research capabilities — no API keys required, powered by SearxNG, Playwright, and Docker.
    4
    53 npm
    ISC
  • A
    license
    B
    quality
    D
    maintenance
    SEO + GEO MCP server: live Google Search Console & GA4 data, keyword and page analysis, AI-visibility tracking across ChatGPT, Claude, Gemini & Perplexity, site audit and SEO task management — all from chat.
    38
    2
    MIT