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 Wellknown reliability 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, XAI_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"
      }
    }
  }
}

ChatGPT (remote MCP): ChatGPT does not connect directly to local STDIO MCP servers. For ChatGPT, use the self-hosted remote MCP setup below, or the OpenAI Secure MCP Tunnel setup for a server running on a local/private machine. The public geo-mcp.digestseo.com/mcp endpoint is not a turnkey no-key fresh-scan service.

Perplexity Computer (remote MCP): Perplexity Computer supports custom remote MCP connectors on eligible plans. After self-hosting mcp-geo, open Account settings > Connectors > + Custom connector, choose Remote, name it digestseo, and enter your own deployment's https://<worker-host>/mcp URL. Use the connector's OAuth option for the Worker flow; if you configured CONNECT_SECRET, complete that browser gate during connection. Do not use the public geo-mcp.digestseo.com/mcp endpoint as a turnkey no-key scan service. See Perplexity's current Computer connector guidance.

Replit Agent (remote MCP): after self-hosting mcp-geo, open Integrations -> MCP Servers for Replit Agent -> Add MCP server, name it digestseo, and enter your own deployment's https://<worker-host>/mcp URL. Choose the OAuth flow when prompted: Replit supports OAuth dynamic client registration (DCR), which the self-hosted Worker exposes through its standard discovery and registration endpoints. Select Test & Save, then complete the browser authorization step; if you configured CONNECT_SECRET, enter it in that gate. Replit supports remote HTTPS MCP servers rather than this package's local stdio process, so use your configured Worker URL and do not treat the public geo-mcp.digestseo.com/mcp endpoint as a turnkey provider-key service. See Replit's current MCP guide.

Claude Code:

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

Or install the same local MCP integration through this repository's owner-controlled Claude Code marketplace:

/plugin marketplace add AKzar1el/mcp-geo
/plugin install digestseo-geo@digestseo-mcp

The marketplace plugin uses the repository's .mcp.json to launch npx -y @digestseo/mcp-geo. Zero provider keys are enough for tool discovery; for engine-backed scans, make only the provider keys you want available to the Claude Code process. The direct claude mcp add command above remains the simplest option when you want to attach provider keys explicitly to the server configuration.

Codex CLI:

codex mcp add digestseo -- npx -y @digestseo/mcp-geo

The zero-key command is enough for tool discovery. Add only the provider keys you want with repeated --env NAME=VALUE options before the -- when engine-backed scans are needed.

Amp CLI:

amp mcp add digestseo -- npx -y @digestseo/mcp-geo

Amp runs this as a local STDIO MCP server. The zero-key command is enough for tool discovery; before engine-backed scans, make only the provider keys you want available to the Amp process or configure them in Amp's local MCP env settings instead of committing secrets. See Amp's current MCP guide.

OpenCode v2:

opencode mcp add digestseo --global -- npx -y @digestseo/mcp-geo

OpenCode v2 runs this as a local STDIO server. Omit --global for project-only configuration. Zero keys are enough for MCP tool discovery. For engine-backed scans, edit the generated OpenCode v2 config and add only the provider variables you want under mcp.servers.digestseo.environment, mapping each to an environment reference such as "OPENAI_API_KEY": "{env:OPENAI_API_KEY}"; keep the actual secret value in the process environment rather than in the config file. Verify the connection with opencode mcp list. See the current OpenCode v2 MCP guide.

Mistral Vibe Code: add mcp-geo to the user-level ~/.vibe/config.toml or project-level ./.vibe/config.toml:

[[mcp_servers]]
name = "digestseo"
transport = "stdio"
command = "npx"
args = ["-y", "@digestseo/mcp-geo"]

The zero-key entry is enough for tool discovery. For engine-backed scans, pass only the provider keys you want through Vibe's STDIO environment configuration or the environment inherited by Vibe instead of committing secrets. Use /mcp digestseo (or /mcp) in Vibe to verify the server and tools. See Mistral's current MCP server guide and Vibe configuration reference.

LibreChat: add mcp-geo to librechat.yaml as a local STDIO server:

mcpServers:
  digestseo:
    type: stdio
    command: npx
    args:
      - -y
      - '@digestseo/mcp-geo'

Restart LibreChat after changing librechat.yaml. The zero-key entry is enough for MCP tool discovery. Before engine-backed scans, expose only the provider API keys you intend to use to the LibreChat process rather than committing secret values into the YAML file. See LibreChat's current MCP configuration guide and MCP feature guide.

AnythingLLM: add mcp-geo from Settings -> Agent Configuration -> MCP, or merge this entry into anythingllm_mcp_servers.json in AnythingLLM's storage plugins directory:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

AnythingLLM treats command-backed servers as local STDIO MCP servers and can start them when an agent needs their tools. The zero-key entry is enough for MCP discovery; before engine-backed scans, add only the provider environment variables you intend to use through AnythingLLM's MCP configuration or the process environment instead of committing raw secrets. See AnythingLLM's current MCP compatibility guide.

Langflow: open Settings -> MCP Servers (or the MCP sidebar -> Add MCP Server), choose STDIO, name the server digestseo, set Command to npx, and add Arguments -y and @digestseo/mcp-geo. The zero-key server is enough for MCP tool discovery; before engine-backed scans, add only the provider keys you intend to use in Langflow's MCP Environment Variables fields rather than storing raw secrets in a flow. Then select the saved server from an MCP Tools component and connect its tools to a Langflow Agent. If Langflow itself runs in Docker, its image must include Node.js before it can launch an npx server. See Langflow's current MCP client guide.

Flowise: for a local/self-hosted Flowise instance, add a Custom MCP tool to an Agent and use STDIO with {"command":"npx","args":["-y","@digestseo/mcp-geo"]}. Refresh Available Actions to load the twelve mcp-geo tools. Zero provider keys are enough for discovery; before engine-backed scans, make only the provider keys you intend to use available to the Flowise process/service environment. Flowise explicitly recommends STDIO only when it is running locally rather than in a cloud service because the npx package is launched on the Flowise host. See Flowise's current Tools & MCP guide.

Kilo Code: open Settings -> Agent Behaviour -> MCP Servers, add a Local (stdio) server named digestseo, and launch npx with arguments -y and @digestseo/mcp-geo. The equivalent macOS/Linux kilo.jsonc entry is:

{
  "mcp": {
    "digestseo": {
      "type": "local",
      "command": ["npx", "-y", "@digestseo/mcp-geo"],
      "enabled": true
    }
  }
}

On Windows, Kilo's current guidance uses "command": ["cmd", "/c", "npx", "-y", "@digestseo/mcp-geo"]. Zero provider keys are enough for discovery. Before engine-backed scans, add only the provider keys you intend to use through Kilo's MCP environment settings or the local process environment, and keep raw secrets out of project-level kilo.jsonc. See Kilo Code's current MCP configuration guide and CLI MCP guide.

Google Antigravity: Antigravity 2.0, Antigravity CLI, and Antigravity IDE can launch custom local STDIO MCP servers. In the IDE, open the agent panel -> MCP Servers -> Manage MCP Servers -> View raw config; from the CLI, /mcp opens the interactive MCP manager. Add digestseo to the global ~/.gemini/config/mcp_config.json or a workspace .agents/mcp_config.json:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

The zero-key configuration is enough for MCP tool discovery. Before engine-backed scans, expose only the provider keys you intend to use through the local server environment; if you use workspace .agents/mcp_config.json, keep raw secrets out of any shared or committed copy. See Google's current Antigravity MCP guide.

Cherry Studio: open Settings -> MCP -> MCP Servers -> Add, choose STDIO, name the server digestseo, set Command to npx, and add Arguments -y and @digestseo/mcp-geo. The zero-key server is enough for MCP tool discovery. Before engine-backed scans, add only the provider keys you intend to use in Cherry Studio's MCP environment-variable fields rather than putting secrets in prompts or screenshots. Enable the server, inspect its Tools, then bind it to the intended Agent under Work -> Agent -> Edit -> MCP. See Cherry Studio's current official MCP configuration guide and MCP workflow guide.

Raycast AI: open Install MCP Server (or Manage MCP Servers -> Install New Server), choose Standard Input/Output, set Command to npx, and set Arguments to -y and @digestseo/mcp-geo. The zero-key install is enough for tool discovery. Before engine-backed scans, add only the provider keys you want in Raycast's MCP Environment fields rather than hard-coding them into shared project files. Restart Raycast if npx was added to PATH after Raycast started. See Raycast's current MCP manual.

Msty Studio: open Toolbox -> Add New Tool, choose STDIO / JSON, and use:

{
  "command": "npx",
  "args": ["-y", "@digestseo/mcp-geo"]
}

The zero-key tool is enough for MCP discovery. For engine-backed scans, define only the provider keys you want in Msty Studio Environments and attach them to the tool rather than storing raw secrets in shared files. Msty Studio Desktop can run the tool locally; Studio Web needs its documented Desktop/Sidecar connection for local MCP tools. See Msty Studio's current Toolbox MCP guide and environment guide.

Jan Desktop / Jan Agent: in Jan Desktop open Settings -> MCP Servers -> + Add MCP Server, choose STDIO, set Command to npx, and add Args -y and @digestseo/mcp-geo. The zero-key server is enough for tool discovery; add only the provider keys you intend to use through Jan's MCP Env fields. Jan Agent reads the same MCP configuration, or you can add it from the terminal with jan cli mcp add digestseo --command npx --arg -y --arg @digestseo/mcp-geo and then enable it. If you run Path B on your own Worker, Jan also supports HTTP MCP servers at https://<worker-host>/mcp and handles advertised OAuth with metadata discovery, dynamic client registration, and authorization-code + PKCE. Do not present the public DigestSEO endpoint as a turnkey provider-key service. See Jan's current MCP server guide and Agent MCP guide.

Zed: open Settings -> AI -> MCP Servers, choose Add Server -> Add Local Server, and configure digestseo with command npx and arguments -y, @digestseo/mcp-geo. The zero-key local server is enough for tool discovery; for engine-backed scans, add only the provider keys you intend to use in Zed's local MCP env map rather than committing secrets into shared project settings. If you run Path B on your own Worker instead, choose Add Remote Server and use https://<worker-host>/mcp; when no Authorization header is configured, Zed uses the standard MCP OAuth flow. Do not treat the public DigestSEO endpoint as a turnkey provider-key service. See Zed's current MCP guide.

TraeCode: open Settings -> MCP -> Add -> Manually add and paste this local STDIO configuration, or save the same mcpServers object as .trae/mcp.json in a trusted project:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

TraeCode recommends NPX/UVX for local MCP servers and supports env values when engine-backed scans need provider keys. The zero-key form is enough for discovery; keep raw provider secrets out of project-level .trae/mcp.json. TraeCode CLI can also load that project-level MCP file, or you can add an equivalent stdio entry through traecli config edit and inspect it with /mcp. See TraeCode's current IDE MCP setup and CLI MCP guide.

Qwen Code: this repository already ships the portable Agent Plugins v1 metadata that Qwen Code can load directly from GitHub:

qwen extensions install AKzar1el/mcp-geo

Or add only the local MCP server as a user-scoped STDIO entry:

qwen mcp add --scope user digestseo npx -y @digestseo/mcp-geo
qwen mcp list

Qwen Code natively supports Agent Plugins v1, including the repository's root plugin.json + mcp.json, so the extension path reuses the same npx -y @digestseo/mcp-geo server without another wrapper. Direct MCP configuration is stored in ~/.qwen/settings.json; project-scoped servers can instead live in .qwen/settings.json under mcpServers. The zero-key setup is enough for tool discovery. Before engine-backed scans, expose only the provider variables you intend to use to the Qwen process, or reference existing environment variables from the MCP env map instead of committing raw keys to project settings. Start Qwen Code and run /mcp to verify the server and tools. See Qwen Code's current extension guide and MCP server guide.

Augment Code / Auggie: in the Augment extension for VS Code or JetBrains, open Settings -> MCP servers and use Import from JSON with:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

For Auggie CLI, the equivalent user-level install is:

auggie mcp add digestseo -- npx -y @digestseo/mcp-geo
auggie mcp list

Auggie persists MCP servers in ~/.augment/settings.json; run /mcp in an Auggie session to inspect them. The zero-key setup is enough for tool discovery. Before engine-backed scans, add only the provider keys you intend to use through Augment's MCP environment fields or Auggie's --env NAME=VALUE option rather than committing raw secrets. If the twelve local tools consume too much agent context, Augment's optional MCP Tool Search can load tool schemas on demand. See Augment's current MCP setup guide and Auggie integrations/MCP guide.

GitHub Copilot CLI:

copilot mcp add digestseo -- npx -y @digestseo/mcp-geo

The base install starts with zero provider keys so tool discovery works. Add only the engine keys you want with Copilot CLI's --env NAME=VALUE option before running scans.

GitHub Copilot cloud agent / code review: repository administrators can also add mcp-geo under Settings -> Copilot -> MCP servers. Use the local npm package rather than the hosted OAuth endpoint, because Copilot cloud agent and code review do not currently support remote MCP servers that rely on OAuth.

Start with a conservative read-only profile because repository MCP tools can run autonomously:

{
  "mcpServers": {
    "digestseo": {
      "type": "local",
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"],
      "tools": [
        "check_visibility",
        "get_visibility_history",
        "compare_competitors",
        "get_citations",
        "list_brands",
        "list_prompts"
      ]
    }
  }
}

Copilot code review only accepts tools whose MCP metadata marks them read-only; the tools above already publish readOnlyHint: true. This profile is useful when the task has access to an mcp-geo local database created during that run. For a task that should create/refresh visibility data, explicitly add only the mutating tools you intend to permit (for example track_brand and refresh_brand) and remember that refresh_brand can make billable provider calls.

Provider credentials belong in Copilot Agents secrets/variables, not in repository JSON. GitHub only exposes names prefixed COPILOT_MCP_; map a selected secret into mcp-geo with env, for example "OPENAI_API_KEY": "$COPILOT_MCP_OPENAI_API_KEY". See GitHub's current repository MCP configuration guide.

Portable Agent Plugin (GitHub Copilot / VS Code / Kiro and other Agent Plugins 1.0 clients): this repository now ships the standard root plugin.json + mcp.json pair. GitHub Copilot CLI can install it directly from GitHub:

copilot plugin install AKzar1el/mcp-geo

In VS Code, run Chat: Install Plugin from Source and enter https://github.com/AKzar1el/mcp-geo. In Kiro, use Powers -> Add Custom Power -> Import power from GitHub with the same repository URL. The portable plugin launches npx -y @digestseo/mcp-geo; zero provider keys are enough for discovery, while engine-backed scans inherit only the provider keys you intentionally make available to the host client. Existing native install paths above remain valid.

Qoder CLI:

qoder mcp add digestseo -- npx -y @digestseo/mcp-geo
qoder mcp list

Qoder launches this as a local STDIO MCP server. The zero-key command is enough for tool discovery; make only the provider keys you want available to the Qoder process before engine-backed scans. If Qoder is already running, use /mcp reload to rediscover the server and tools. See Qoder's current MCP server guide and MCP reference.

Docker Agent: Docker Agent can launch local STDIO MCP servers directly from agent YAML. Add this toolset to the agent that should use mcp-geo:

toolsets:
  - type: mcp
    command: npx
    args: ["-y", "@digestseo/mcp-geo"]

The zero-key form is enough for tool discovery. For engine-backed scans, add only the provider keys you need under the toolset's env: map (Docker Agent supports ${env.NAME} expansion) instead of committing secret values. See Docker's current local MCP tool documentation.

goose: add mcp-geo as a local STDIO extension in ~/.config/goose/config.yaml (macOS/Linux) or %APPDATA%\Block\goose\config\config.yaml (Windows):

extensions:
  digestseo-geo:
    type: stdio
    name: digestseo-geo
    enabled: true
    cmd: npx
    args: ["-y", "@digestseo/mcp-geo"]
    timeout: 300

The zero-key extension is enough for tool discovery. Before engine-backed scans, configure only the provider environment variables you want for this extension through goose's extension settings / secret storage instead of putting raw API keys in the YAML file. The same server can also be added interactively with goose configure -> Add Extension -> Command-Line Extension. See goose's current extension setup and configuration reference.

GitLab Duo CLI: current GitLab Duo CLI releases can consume Claude-compatible plugin marketplaces directly. Register this repository and install the existing digestseo-geo plugin:

glab duo plugin marketplace add https://github.com/AKzar1el/mcp-geo.git
glab duo plugin install digestseo-geo@digestseo-mcp

The installed plugin loads the same local npx -y @digestseo/mcp-geo MCP server from .mcp.json. Zero provider keys allow discovery; make only the provider keys you want available to the GitLab Duo CLI process before engine-backed scans.

Factory Droid:

droid mcp add digestseo "npx -y @digestseo/mcp-geo"
droid mcp list

Droid runs this as a local STDIO MCP server. The zero-key install is enough for tool discovery; add only the provider keys you choose in Droid's user-level MCP configuration before engine-backed scans. Keep provider secrets out of project-level .factory/mcp.json files.

Amazon Q Developer (IDE): open the Q Developer chat panel ? Tools ? +, choose STDIO, name the server digestseo, set Command to npx, and add Arguments -y and @digestseo/mcp-geo. Add only the provider environment variables you want before running scans; zero keys still allow MCP tool discovery.

Amazon Q Developer CLI: add the same local STDIO server through Q's native MCP manager:

q mcp add --name digestseo --command npx --args '["-y", "@digestseo/mcp-geo"]'
q mcp list

The zero-key server is enough for MCP tool discovery. Before engine-backed scans, add only the provider variables you intend to use to the Q CLI MCP configuration instead of committing secrets to the repository. Amazon Q Developer CLI supports local process-backed MCP servers and manages them through q mcp; use /tools inside a Q session to inspect the tools that loaded. See AWS's current Amazon Q Developer MCP guide and CLI MCP configuration reference.

JetBrains AI Assistant (IDE): open Settings > Tools > AI Assistant > Model Context Protocol (MCP) > Add, choose STDIO, and use:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

JetBrains AI Assistant supports local STDIO and NPX MCP servers. The zero-key form is enough for tool discovery; before engine-backed scans, make only the provider keys you want available to the IDE process, or import an already-configured Claude MCP server.

JetBrains Junie (CLI / IDE): run /mcp in Junie CLI to open the MCP Installation Assistant. You can search the Official MCP Registry for mcp-geo, or add the local server manually in .junie/mcp/mcp.json for one project or ~/.junie/mcp/mcp.json for your user:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

Junie CLI and the Junie IDE plugin use the same MCP configuration. The zero-key server is enough for tool discovery; before engine-backed scans, make only the provider keys you intend to use available to the Junie process and keep raw secrets out of a shared or committed project .junie/mcp/mcp.json. Use /mcp to verify the active server and tools. See JetBrains' current Junie CLI MCP guide and Junie IDE MCP settings.

JetBrains Air: this repository already ships the standard root .mcp.json that launches npx -y @digestseo/mcp-geo. In Air, open Settings > AI > MCP Servers, enable MCP support and Launch workspace MCP servers, then use the Workspace scope so Air reuses that checked-in file. The repository config contains no provider secrets and is sufficient for zero-key tool discovery. Engine-backed scans still require the selected provider keys in the local server process environment; keep them out of committed .mcp.json. See the JetBrains Air MCP server guide.

Visual Studio 2022 17.14+ / Visual Studio 2026: Visual Studio uses its own servers-shaped MCP configuration. Create %USERPROFILE%\.mcp.json for a user-wide install or <SOLUTIONDIR>\.mcp.json for one solution:

{
  "servers": {
    "digestseo": {
      "type": "stdio",
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

Open GitHub Copilot Chat in Agent mode and use the Tools menu to verify digestseo is available. Zero provider keys are enough for tool discovery; before engine-backed scans, make only the provider keys you want available to the Visual Studio process rather than committing secrets into the solution file. See Microsoft's current Visual Studio MCP setup.

Cursor:

Add to Cursor

Windsurf: open Manage MCPs → View raw config and add the local stdio package:

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

Use only the provider keys you want; zero keys still allow MCP tool discovery.

Roo Code: open MCP Servers > Edit Global MCP, or create .roo/mcp.json for a project-scoped install, and add:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

Roo Code supports local STDIO MCP servers. The zero-key form is enough for tool discovery; add only the provider keys you want before scans. On Windows, if Roo cannot launch npx directly, use "command": "cmd" with "args": ["/c", "npx", "-y", "@digestseo/mcp-geo"], matching Roo's documented Windows fallback.

VS Code: Install the local stdio server in VS Code. The base install starts with no provider keys so tool discovery works; add only the API keys you want in your VS Code MCP user configuration before running scans.

LM Studio: Add the local stdio server to LM Studio. The base install starts with no provider keys so tool discovery works; add only the API keys you want in LM Studio's mcp.json before running scans.

Kiro: Add to Kiro for a one-click local install, or open the user MCP config (~/.kiro/settings/mcp.json) / workspace config (.kiro/settings/mcp.json) and add the local stdio package manually:

{
  "mcpServers": {
    "digestseo": {
      "command": "npx",
      "args": ["-y", "@digestseo/mcp-geo"]
    }
  }
}

Kiro supports local STDIO MCP servers across its current surfaces. The zero-key form is enough for discovery; add only the provider environment variables you want before engine-backed scans. For remote use, self-host the Worker below and configure your own deployed /mcp URL instead. The public geo-mcp.digestseo.com/mcp endpoint is not a turnkey no-key fresh-scan service.

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, Grok, Google AI Overviews, and Google AI Mode. 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 ChatGPT through a configured remote MCP app, Claude.ai, Claude Desktop, Claude Code, GitHub Copilot CLI, 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 →

Want to reproduce the same evidence-first structure with your own data? Use the reusable AI Visibility Audit report prompt.

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.26] - September 24, 2026

  • OAuth 1.0 resource correctness: self-hosted Workers now bind OAuth grants and tokens to the canonical ${SELF_URL}/mcp resource required by @cloudflare/workers-oauth-provider 1.0.0, with deployment guidance that prevents resource-host mismatches.

  • Broader coding-agent onboarding: Google Antigravity, JetBrains Junie, GitHub Copilot cloud agent/code review, Qwen Code, and Augment Code / Auggie now have first-party-aligned local MCP setup paths using the published npx -y @digestseo/mcp-geo package.

[0.3.25] - September 24, 2026

  • Complete hosted safety metadata: all six hosted visibility tools now explicitly declare read-only, destructive, and open-world behavior for stricter MCP clients and plugin validators.

  • Broader native onboarding: Langflow, Cherry Studio, Flowise, and Kilo Code setup now reuse the published local/self-hosted mcp-geo paths with zero-key discovery and secret-safe provider configuration.

  • Stronger audit fulfillment: the reusable report prompt now turns the existing top_sources citation summary into recurring-source evidence before individual citation examples, without manufacturing derived metrics.

[0.3.24] - September 23, 2026

  • Source-domain intelligence: get_citations / visibility.citations now summarizes the most frequently cited engine-native source domains across the requested window, with prompt counts, contributing engines, representative URLs, and tracked-brand-domain flags.

  • Clear hosted MCP identity: modern SDK-v2 discovery now exposes the human-readable GEO Tracker title, concise description, and canonical product URL without changing the stateless transport contract.

  • More native client onboarding: Replit Agent remote-MCP and Jan Desktop / Jan Agent setup now reuse the existing local or self-hosted mcp-geo paths without introducing another package or hosted turnkey-provider claim.

[0.3.23] - September 23, 2026

  • Current Grok model: grounded Grok visibility scans now use xAI's current grok-4.7 model while preserving the existing Responses API, required Web Search grounding, and BYOK flow.

  • AnythingLLM onboarding: MCP Management / anythingllm_mcp_servers.json setup now covers the published local stdio package with zero-key discovery and secret-safe optional provider configuration.

  • Accurate Perplexity guidance: setup text now matches the already-shipped Agent API fast preset and points to live pricing instead of stale Sonar/fixed per-prompt wording.

[0.3.22] - September 23, 2026

  • Perplexity retirement-safe: Perplexity scans now use the Agent API fast preset instead of the retiring fixed Sonar model selector, preserving grounded web-search visibility after the September 27 Sonar retirement.

  • Current plugin discovery truth: portable Agent Plugin and Claude marketplace metadata now include Google AI Mode alongside the other supported AI-search surfaces.

  • Amazon Q Developer CLI: native q mcp onboarding now covers the existing local stdio package with zero-key discovery and secret-safe provider configuration.

  • Accurate self-hosting guidance: setup documentation now reflects the stateless SDK-v2 hosted MCP path and current manual-refresh scheduling behavior.

[0.3.21] - September 22, 2026

  • Stateless hosted MCP: OAuth-protected /mcp traffic now uses Cloudflare's SDK-v2 createMcpHandler path with legacy stateless compatibility and explicit Host/Origin validation, while the old Durable Object binding remains only as a conservative migration hold.

  • Leaner tool context: all twelve MCP tools now expose concise example-led descriptions and complete input-parameter guidance, reducing client context overhead and making tool selection clearer.

[0.3.20] - September 22, 2026

  • Bounded provider requests: external AI-provider and SerpAPI calls now time out after 90 seconds instead of allowing a stalled upstream API to hang a scan indefinitely.

  • Durable manual Worker scans: authenticated /admin/run-live requests can set wait_for_completion: true so manual/operator refreshes remain attached until service-binding engine work finishes.

[0.3.19] - September 22, 2026

  • Google AI Mode: opt in with SERPAPI_AI_MODE_ENABLED=true to measure Google AI Mode separately through SerpAPI, including citation/source evidence when returned.

  • Safe tracked-brand corrections: local MCP users can call update_brand to change identity, competitors, aliases, exclusions, or refresh cadence without replacing prompts or historical runs.

  • Manual scheduling: set refresh_frequency to manual to pause self-hosted scheduled scans while keeping explicit refresh_brand available.

[0.3.18] - September 21, 2026

  • Grok visibility coverage: opt in with XAI_API_KEY to measure grounded Grok answers via xAI Web Search alongside ChatGPT, Claude, Perplexity, Gemini, and Google AI Overviews.

[0.3.17] - September 21, 2026

  • Exact user-defined measurement sets: local MCP users can now call set_prompts to replace a brand's active prompts with 1-50 agreed buyer questions while preserving historical runs; repeated identical sets are a no-op.

[0.3.16] - September 21, 2026

  • New-project Gemini compatibility: Gemini scans now default to gemini-3.1-flash-lite, avoiding the Gemini 2.5 access restriction Google applies to some new projects while preserving the same GenerateContent integration.

[0.3.15] - September 20, 2026

  • Clearer provider setup failures: an explicit refresh request for an unconfigured engine now names the unavailable engine and explains how to recover instead of reporting that no engines at all are available.

  • Broader local-client onboarding: copy-paste setup now covers Roo Code, Codex CLI, and OpenCode v2 in addition to the existing MCP clients.

  • Reliable installed README links: npm-package readers are routed to durable GitHub URLs for documentation and report assets that are intentionally excluded from the tarball.

[0.3.14] - September 20, 2026

  • Inspectable measurement inputs: local MCP users can now call list_prompts to review the exact active buyer-intent prompt set for a tracked brand without regenerating or changing it.

  • Correct ChatGPT onboarding: ChatGPT guidance now uses a configured remote MCP server or OpenAI Secure MCP Tunnel for local/private servers instead of advertising unsupported direct local STDIO registration.

[0.3.13] - September 20, 2026

  • More faithful citation evidence: get_citations now preserves the exact engine-native cited page URL, including path and query, when the provider returns one.

  • Current Gemini CLI gallery metadata: the extension manifest now stays version-synchronized with the package, preventing stale gallery version labels after release.

[0.3.12] - September 20, 2026

  • Better agent workflow guidance: local and hosted MCP initialize responses now include concise server-level instructions for the correct brand → refresh → visibility flow, asynchronous hosted refresh behavior, and unavailable-engine semantics.

[0.3.11] - September 19, 2026

  • More reliable scheduled tracking: per-engine freshness and due-engine fan-out keep stale providers updating without needlessly rescanning fresh ones, while brands can choose daily or weekly cadence.

  • Safer request handling: duplicate engine selections are deduplicated in hosted refresh and visibility reads, and hosted brand seeding rejects invalid refresh cadence values before persistence.

  • Complete Claude Desktop metadata: the MCPB manifest now declares all nine fixed local tools, including track_brand, list_brands, and generate_prompts, matching the actual stdio server exposed after install.

[0.3.10] - September 19, 2026

  • Safer BYOK refreshes: duplicate engine names are deduplicated before provider dispatch so one request cannot accidentally trigger duplicate scans or provider charges.

  • Stronger MCP contracts: winning/losing prompt and content-gap structured outputs now publish concrete schemas instead of opaque records, improving client-side validation and agent interoperability.

  • Better Registry installs: Official MCP Registry metadata now advertises all five supported provider API keys as optional secret configuration for the npm stdio package.

[0.3.9] - September 19, 2026

  • Transparent snapshot freshness: visibility snapshots now expose each engine's own observation timestamp so older engine data cannot be mistaken for uniformly fresh results.

  • Auditable history trends: visibility history now includes the usable-prompt denominator, brand-mention count, and observation time behind every per-engine score.

[0.3.8] - September 19, 2026

  • More reliable audit evidence: competitor comparisons now honor their requested multi-day window across all usable runs and return exact mention counts; citation excerpts and provider-free content-gap fallbacks are grounded in the same underlying evidence.

  • Broader local install reach: added Amazon Q Developer IDE setup for the existing local stdio package.

[0.3.7] - September 19, 2026

  • Exact audit prompt count: prompt generation now persists exactly the requested number of unique prompts or leaves the existing prompt set untouched, protecting the paid audit's fixed 20-prompt scope.

[0.3.6] - September 18, 2026

  • Grounded ChatGPT scans: live ChatGPT visibility uses web search, and domain-lookalike mention scoring was tightened.

  • Broader local install reach: added Gemini CLI metadata plus one-click VS Code and LM Studio install paths.

[0.3.5] - September 17, 2026

  • Provider/runtime correctness: migrated Perplexity to the Agent API and kept plugin installs on the local stdio package rather than the unconfigured public Worker.

  • Trust/readiness: added owned privacy disclosure, production-only MCPB packaging, and transparent audit score formulas.

[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 — Gemini capacity varies by model, project, and usage tier, so provider-specific quota variability could produce 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, refresh_frequency (daily/weekly/manual, default weekly)

update_brand

Correct an existing brand's domain, name, category, competitors, aliases, exclusions, or refresh cadence without replacing active prompts or historical runs. Set cadence to manual to pause scheduled Worker scans while keeping manual refresh available.

brand_id plus any fields to change

list_brands

List tracked brands with domains, competitors, aliases, exclusions, and active prompt counts.

—

list_prompts

Inspect the exact active buyer-intent prompts for a tracked brand without changing them.

brand_id

set_prompts

Replace the active prompt set with exact user-supplied buyer questions while preserving historical runs.

brand_id, prompts[] (1-50 unique questions)

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 (gpt-5-search-api) with web search. OpenAI currently bills web search at $10 per 1,000 calls plus model token charges; see API pricing and 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

  • Google AI Studio (Gemini) — Gemini engine (gemini-3.1-flash-lite). Google currently offers free-tier token usage for this model, while paid usage is token-priced. Rate limits vary by model, project, and usage tier, and Google says actual capacity can vary; check your project's active limits in AI Studio rather than relying on a fixed RPM/RPD assumption. See Gemini pricing and rate limits.

  • Perplexity — Agent API fast preset for grounded web-search visibility. Paid API usage; pricing depends on the preset workload, so check current Agent API pricing before estimating scan cost. Perplexity Agent API · pricing

  • xAI — Grok engine (grok-4.7) with required Web Search grounding. xAI currently prices Web Search at $5 per 1,000 calls plus model tokens. console.x.ai · pricing

  • SerpAPI — Google AI Overviews plus optional Google AI Mode. One SerpAPI key powers both, but AI Mode is deliberately off by default because it adds a separate paid search per prompt; set SERPAPI_AI_MODE_ENABLED=true when you want that seventh surface. Google AI Mode API · serpapi.com/dashboard

Recommended starting pair: OpenAI + Anthropic (Claude). OpenAI provides grounded ChatGPT visibility through web search and bills search calls plus model tokens; Anthropic also powers prompt generation and content-gap analysis. Review current provider pricing before estimating recurring scan cost. Add Gemini, Perplexity, Grok, or SerpAPI deliberately once you want more coverage; Gemini capacity varies by model, project, and usage tier, and Google AI Overviews often returns no result (scored as a zero). Google AI Mode is a separate SerpAPI call and stays disabled until SERPAPI_AI_MODE_ENABLED=true, preventing an existing SerpAPI setup from silently doubling Google search calls.

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 — OpenAI uses web search plus model tokens; check current pricing:
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

ChatGPT (local/private via OpenAI Secure MCP Tunnel)

OpenAI Secure MCP Tunnel is the supported bridge when you want ChatGPT to use the local stdio package without exposing it as a public HTTPS server. Create a tunnel in OpenAI Platform first, then keep tunnel-client running on the same machine that launches mcp-geo. You need a tunnel ID, a tunnel runtime API key, and ChatGPT developer-mode/tunnel permissions for the target workspace.

Make whichever provider keys you want to use available to the mcp-geo process, then initialize a tunnel profile with the local package command:

tunnel-client init --sample sample_mcp_stdio_local --profile digestseo --tunnel-id tunnel_0123456789abcdef0123456789abcdef --mcp-command "npx -y @digestseo/mcp-geo"
tunnel-client doctor --profile digestseo --explain
tunnel-client run --profile digestseo

While tunnel-client run is healthy, create a developer-mode app in ChatGPT, choose Tunnel as the connection type, and select that tunnel. This path is for private/local use; it does not publish mcp-geo as a public ChatGPT app. Follow OpenAI's current Secure MCP Tunnel guide for tunnel creation, permissions, downloads, and troubleshooting.

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. Rate limits vary by model, project, and usage tier; check the project's active limits in Google AI Studio (see Troubleshooting).

PERPLEXITY_API_KEY

opt-in

unset

Enables the Perplexity Agent API fast preset. Paid API usage; check current Agent API pricing.

XAI_API_KEY

opt-in

unset

Enables the Grok engine (grok-4.7) with required Web Search grounding.

SERPAPI_API_KEY

opt-in

unset

Enables Google AI Overviews via SerpAPI. Also provides the credential for Google AI Mode when the explicit flag below is enabled.

SERPAPI_AI_MODE_ENABLED

no

false

Set to true to add Google AI Mode as a separate visibility engine. It stays off by default to avoid unexpected extra SerpAPI calls/cost.

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.

Provider credentials are set via wrangler secret put VAR in production or .dev.vars locally. SERPAPI_AI_MODE_ENABLED is a non-secret runtime flag and may be stored under Wrangler vars or set in the local process environment.


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 --> MCP["Stateless MCP handler<br/>(SDK v2, 6 hosted 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["xAI<br/>(Grok)"]
    RE --> E6["SerpAPI<br/>(AI Overviews / AI Mode)"]
    RE --> DB[("D1<br/>brands / prompts / runs /<br/>responses / cache")]
    MCP --> DB

The legacy GeoMcpAgent / MCP_OBJECT Durable Object binding is retained temporarily for migration compatibility, but current /mcp traffic is served by the stateless SDK v2 handler shown above.

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, XAI_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 prompts — Gemini API limits vary by model, project, and usage tier, and Google notes that actual capacity can vary. Check the project's current limits in Google AI Studio and Google's rate-limit documentation. When a request is rate-limited, mcp-geo records that engine row as failed and excludes it from successful scoring. Google recommends waiting and retrying after a short period or reducing request rate; if the limit is consistently too low for your scan cadence, consider an appropriate paid tier rather than assuming a universal free-tier RPM/RPD quota.

  • 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 only to the AI providers whose API keys you configure (OpenAI, Anthropic, Google, Perplexity, xAI, and/or SerpAPI); 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

12 tools
check_visibilityCheck AI visibilityA
Read-only

Read the latest stored visibility snapshot, including scores and winning/losing prompts; call refresh_brand first for fresh data. Example: brand_id='acme', engines=['chatgpt','perplexity'].

ParametersJSON Schema
NameRequiredDescriptionDefault
enginesNoEngines to include; omit or pass [] for all stored engines.
brand_idYesTracked brand ID to inspect.

Output Schema

ParametersJSON Schema
NameRequiredDescription
brandYes
per_engineYes
refreshed_atYes
overall_scoreYes
top_losing_promptsYes
top_winning_promptsYes

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 and destructiveHint=false, and the description adds non-obvious behavioral context: the data is a stored snapshot, not live, and may be stale unless refresh_brand is called first. This is meaningful beyond the annotations, though it does not cover error cases or rate limits.

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 plus a concrete example, with the core action and scoping front-loaded. No filler is present and every sentence contributes.

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 tool is simple (2 params, 1 required), has an output schema, and has annotations covering safety. The description adds the key prerequisite workflow (refresh_brand first) and enough context for correct invocation; nothing essential is 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 description coverage is 100%, so the schema already fully documents brand_id and engines. The inline example reinforces the parameter shape and valid engine values, but it adds little 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 uses a specific verb ('Read') and resource ('latest stored visibility snapshot') and adds what is included (scores, winning/losing prompts). It also differentiates itself from refresh_brand by explicitly noting this reads stored data rather than producing fresh 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?

The description explicitly routes the agent to refresh_brand when fresh data is needed, giving a clear when-to-use condition. It does not explicitly contrast with get_visibility_history or state when not to use this tool, so it stops short of full alternative guidance.

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 stored brand and competitor mentions, share of voice, and prompt wins over a time window. Example: brand_id='acme', competitor_domains=['rival.com'], days=7.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoPrevious days to compare.
brand_idYesTracked brand ID to compare.
competitor_domainsNoCompetitor domains; omit to use the brand's configured list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
brand_idYes
competitorsYes
your_mentionsYes
prompts_you_winYes
your_share_of_voice_pctYes
requested_competitor_domainsYes

TDQS

A3.6/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, and the description adds that this operates on stored mentions over a time window, reinforcing the read-only comparison nature. It does not describe return formatting or behavior beyond that, but the output schema exists and no contradiction is present.

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?

One focused sentence plus a minimal working example; no filler or redundancy. The core comparison scope is front-loaded and every part 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?

For a read-only comparison tool with fully documented parameters and an existing output schema, the description covers what is needed to make a correct call. Explicitly naming sibling tools or selection conditions would improve it, but nothing essential is 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 description coverage is 100%, so the schema already explains all three parameters. The description's example adds useful concrete values, but it does not need to compensate for missing schema detail.

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 uses a specific verb ('Compare') and a clear resource: stored brand and competitor mentions, share of voice, and prompt wins over a time window. It does not explicitly distinguish itself from sibling tools like check_visibility or get_visibility_history, so it falls just short of a 5.

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

Usage Guidelines3/5

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

The time-window wording and example imply a comparison use case, but the description gives no explicit when-to-use or when-not-to-use guidance and names no alternatives. With many sibling tools present, the agent must infer the boundary from context rather than being told.

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

Replace active prompts with Claude-Haiku-generated buyer-intent prompts; requires ANTHROPIC_API_KEY and preserves history. Example: brand_id='acme', count=20.

ParametersJSON Schema
NameRequiredDescriptionDefault
countNoBuyer-intent prompts to generate.
brand_idYesTracked brand ID to update.

Output Schema

ParametersJSON Schema
NameRequiredDescription
promptsYes
brand_idYes
next_stepsYes
prompt_sourceYes
prompts_insertedYes

TDQS

A4.3/5.0
Behavior5/5

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

Despite annotations already carrying destructiveHint=true, the description adds real value: it specifies exactly what gets destroyed ('active prompts'), what is preserved ('history'), and the auth requirement (ANTHROPIC_API_KEY). These details materially shape how an agent should treat the call, going well beyond the structured fields.

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 core action is front-loaded in the first clause, and the second half packs the two highest-value caveats (API key requirement, history preservation) plus a one-line example. No filler — every clause earns its place for an agent deciding whether to invoke safely.

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 2-parameter tool with a fully covered schema, an output schema, and annotations carrying the safety profile, the description ties everything together: what happens, what is needed, and what survives the call. No critical operational fact an agent needs to invoke it correctly appears to be 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 both brand_id and count are already described in the input schema; the baseline is therefore 3. The description adds only a compact usage example ('brand_id='acme', count=20') and frames parameters as producing buyer-intent prompts — mild added value, but no semantic depth the schema lacks.

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 action ('Replace active prompts') with a distinctive mechanism ('Claude-Haiku-generated buyer-intent prompts') and scoping detail ('preserves history'). The generation mechanism clearly differentiates it from near-sibling set_prompts and read-only siblings like list_prompts, even without naming them.

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

Usage Guidelines3/5

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

The description states a prerequisite ('requires ANTHROPIC_API_KEY') and gives an invocation example, which implies when the tool is usable. However, it never explicitly names alternatives or when-not-to-use conditions — e.g., when the agent should prefer set_prompts or a non-destructive path. Guidance is mostly implicit.

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 evidenceB
Read-only

Return stored brand citation evidence plus the top engine-native source domains across the same tracked-prompt window. Example: brand_id='acme', days=14, engine='perplexity'.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoPrevious days to search.
engineNoEngine to filter by; omit for all engines.
brand_idYesTracked brand ID to inspect.

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
engineYes
brand_idYes
citationsYes
top_sourcesYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so safety is covered. The description adds useful behavioral context about returning stored evidence and scoping to the same tracked-prompt window, which goes slightly beyond annotations. It does not, however, explain result ordering, limits, or empty-result behavior.

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 zero filler, and the example is an efficient way to convey parameter combination. Every sentence 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?

For a read-only tool with full schema coverage and an output schema, the description is largely complete: it states the returned data, the scoping concept, and gives a call example. Minor ambiguity remains around what 'same tracked-prompt window' means and what happens when no citations exist, but these are not blocking.

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 schema already documents all three parameters. The description's example reinforces valid values like brand_id='acme', days=14, and engine='perplexity', but it does not add meaning beyond the schema.

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 clearly states a specific verb and resource: it returns stored brand citation evidence plus top engine-native source domains. It also scopes the query to a tracked-prompt window and provides a concrete example. However, it does not explicitly contrast with sibling tools like get_visibility_history or check_visibility.

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

Usage Guidelines2/5

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

No guidance is given on when to use this tool versus alternatives such as get_visibility_history or check_visibility. The description explains what the tool returns but does not mention when it is preferred or what conditions make another tool more appropriate.

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

Prioritize content topics and formats from prompts where competitors beat the brand; falls back deterministically if AI analysis is unavailable. Example: brand_id='acme', max_recommendations=5.

ParametersJSON Schema
NameRequiredDescriptionDefault
brand_idYesTracked brand ID to analyze.
max_recommendationsNoMaximum recommendations to return.

Output Schema

ParametersJSON Schema
NameRequiredDescription
reasonNo
brand_idYes
prompt_sourceYes
recommendationsYes

TDQS

A4.3/5.0
Behavior4/5

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

Beyond the readOnly/openWorld annotations, the description discloses a meaningful behavioral trait: a deterministic fallback when AI analysis is unavailable. It also indicates the output is ordered/prioritized, which affects how an agent interprets results. No contradiction with 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 a single focused sentence followed by a concrete example; no filler or repetition. It front-loads the primary action and includes the fallback behavior economically.

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 output schema, complete parameter documentation, and annotations, the description supplies everything needed to decide and invoke the tool correctly. The example and fallback note cover the main contextual ambiguities.

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 both parameters are already documented. The description's example (brand_id='acme', max_recommendations=5) reinforces usage but adds little semantic meaning beyond the schema's own descriptions.

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?

Description uses a specific verb ('Prioritize') and identifies the exact resource ('content topics and formats from prompts where competitors beat the brand'). It clearly distinguishes itself from general visibility tools by describing gap-based recommendation output, and the example reinforces scope.

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 phrase 'where competitors beat the brand' and the title 'Find AI visibility content gaps' signal when the tool is relevant: competitive gap analysis. However, it does not explicitly name alternatives or state when not to use it, though sibling names like compare_competitors imply related but distinct tools.

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 historyB
Read-only

Return daily or weekly visibility history with per-engine evidence. Example: brand_id='acme', days=30, granularity='weekly'.

ParametersJSON Schema
NameRequiredDescriptionDefault
daysNoPrevious calendar days to include.
brand_idYesTracked brand ID to inspect.
granularityNoTime bucket for the series.weekly

Output Schema

ParametersJSON Schema
NameRequiredDescription
daysYes
seriesYes
brand_idYes
granularityYes

TDQS

B3.4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true and destructiveHint=false, so the safety profile is covered. The description adds useful context about per-engine evidence and granularity but does not disclose behaviors like pagination, date handling, or potential lack of data coverage.

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 terse sentences with no filler. The functional statement and example are both valuable, and the example is compact enough to aid understanding without bloating the description.

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 a simple read-only query with full schema documentation, an output schema, and safety annotations, the description is nearly sufficient. The main missing element is explicit sibling differentiation for when to call this instead of check_visibility, but the example and function statement cover 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 the input schema already documents all three parameters. The example maps brand_id, days, and granularity to concrete values, which is helpful illustration, but it does not add meaning beyond what the schema and enum definitions provide.

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 clearly states a specific verb ('Return') and resource ('daily or weekly visibility history with per-engine evidence'), making the basic action unambiguous. It does not explicitly distinguish itself from the sibling check_visibility, but the 'history' framing and granularity options provide enough differentiation.

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

Usage Guidelines2/5

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

There is no guidance on when to use this tool versus alternatives like check_visibility or compare_competitors. The example shows how to invoke it but gives no exclusions, prerequisites, or context for choosing this tool over related siblings.

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 tracked brands with metadata and active-prompt counts. Example: call before other tools when you need a brand_id.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
hintNo
brandsYes

TDQS

A4/5.0
Behavior3/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is fully covered. The description adds context about the return content (metadata, active-prompt counts) but does not disclose additional behavioral traits beyond what annotations provide. This meets the baseline for annotation-covered tools but does not go beyond 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?

Two sentences with zero waste. The primary action and return content are front-loaded, followed by a practical usage example. Every word earns its place, making it an exemplary concise definition.

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 simplicity (no parameters), the presence of an output schema, and annotations covering safety, the description is complete. It tells the agent what the tool returns, when to use it, and why it matters (getting a brand_id). Nothing essential is missing for an agent to invoke it correctly.

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?

The tool has zero parameters, so the schema trivially covers everything. Per the rubric, 0 params earns a baseline of 4. The description does not need to explain parameter semantics because none exist, and it appropriately focuses on output and usage instead.

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 clearly states the verb ('List') and resource ('tracked brands'), and adds specificity with 'metadata and active-prompt counts'. It gives an example usage, which implies differentiation from sibling tools that operate on a single brand, though it does not explicitly name a sibling. This is clear but stops short of the explicit contrast seen in top-tier definitions.

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 includes a direct usage instruction: 'call before other tools when you need a brand_id.' This tells the agent when to use it, but it does not mention alternative tools or when not to use it. The guidance is helpful and context-rich, but lacks explicit exclusions or named alternatives.

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

list_promptsList active promptsA
Read-onlyIdempotent

List a brand's active buyer-intent prompts without changing them. Example: brand_id='acme' before an audit or refresh.

ParametersJSON Schema
NameRequiredDescriptionDefault
brand_idYesBrand ID whose active prompts to list.

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
promptsYes
brand_idYes

TDQS

A4.3/5.0
Behavior4/5

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

Annotations already provide readOnlyHint, idempotentHint, and destructiveHint=false. The description adds the behavioral constraint that only active prompts are listed, which is useful beyond the schema. It does not discuss pagination or auth, but the output schema and annotations cover the main safety/behavioral expectations.

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 with no filler: the first states the verb, resource, and non-mutation guarantee; the second provides a concrete example. The most decision-relevant 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?

With one required parameter fully described in the schema, an output schema present, and annotations covering the read-only/idempotent nature, the description adds the remaining context needed (active-only scope and an example use case). Nothing critical is missing 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 coverage is 100% and brand_id is already described as 'Brand ID whose active prompts to list.' The description adds an example value ('acme') but no additional semantic detail beyond what the schema provides, so the baseline of 3 is appropriate.

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 operation ('List') and resource ('a brand's active buyer-intent prompts'), and explicitly adds 'without changing them', which distinguishes it from mutation siblings like set_prompts and generate_prompts. The example reinforces the intended scope.

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 phrase 'before an audit or refresh' gives a clear practical context for when to call this tool. It does not explicitly name alternatives or state when not to use it, but the non-mutation framing and sibling list make the intended usage fairly obvious.

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

Run a fresh scan on selected configured engines using the brand's active prompts and return after completion. Example: brand_id='acme', engines=['chatgpt','gemini'].

ParametersJSON Schema
NameRequiredDescriptionDefault
enginesNoEngines to run; omit for every configured engine.
brand_idYesTracked brand ID to refresh.

Output Schema

ParametersJSON Schema
NameRequiredDescription
messageYes
run_idsYes
brand_idYes
estimated_completion_secondsYes

TDQS

A3.8/5.0
Behavior4/5

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

Annotations already establish readOnly=false and destructive=false. The description adds that the scan uses the brand's active prompts, runs only on selected configured engines, and returns only after completion – a useful synchronous behavior note. It stops short of explaining side effects or whether previous results are replaced.

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 tight sentences plus an example; the main verb and object are 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.

Completeness4/5

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

Given the small parameter surface, full schema descriptions, and presence of an output schema, the description covers the core behavior, input example, and completion semantics. It leaves minor gaps like runtime expectations and relationship to visibility-check siblings, but nothing essential is 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?

The schema already documents both parameters at 100% coverage. The description adds a concrete example mapping brand_id and engines to values, but does not need to re-explain semantics; the schema's 'omit for every configured engine' note is the key guidance.

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 clearly identifies the action ('run a fresh scan'), the resource (brand visibility on configured engines), and the input context (active prompts). It distinguishes the tool from history/listing siblings by emphasizing 'fresh scan,' though it does not explicitly name or contrast siblings.

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

Usage Guidelines3/5

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

The 'fresh scan' phrasing implies the tool is for regenerating current visibility data, and the example shows a concrete invocation. However, it never states when to prefer this over check_visibility or get_visibility_history, and gives no exclusion criteria.

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

set_promptsSet active promptsA
DestructiveIdempotent

Replace a brand's active prompts with an exact supplied set; history is preserved. Example: brand_id='acme', prompts=['What is the best X for Y?'].

ParametersJSON Schema
NameRequiredDescriptionDefault
promptsYesExact 1-50 prompt set for future scans.
brand_idYesTracked brand ID to update.

Output Schema

ParametersJSON Schema
NameRequiredDescription
changedYes
promptsYes
brand_idYes
next_stepsYes
prompts_insertedYes

TDQS

A4.2/5.0
Behavior4/5

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

Annotations indicate destructiveHint=true and idempotentHint=true. The description adds that history is preserved, which is important context not captured in annotations: although destructive, it doesn't destroy the history. This enriches the behavioral understanding.

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: the first is the core function, the second provides a concrete example. It is front-loaded and has no filler. Every word contributes to clarity.

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 simple two-parameter tool with full schema coverage and an output schema, the description is sufficient. It covers the replacement behavior, preservation of history, and an example. The only minor gap is not specifying the return value, but the output schema likely provides that.

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 both parameters are well-documented in the schema. The description adds the example, which clarifies the exact format expected, and clarifies that 'prompts' is the exact set to be set. It does not add new meaning beyond the schema but reinforces the purpose.

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 it replaces a brand's active prompts with an exact supplied set, distinguishing it from sibling list_prompts and generate_prompts. It uses a specific verb 'Replace' and indicates the resource (brand's active prompts) and the nature of the operation (overwrite with exact set).

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 a concrete example showing the expected parameters (brand_id and prompts) and implies the tool is for setting prompts, contrasting with siblings like generate_prompts. It does not explicitly state when not to use it, but the example and wording provide clear usage context.

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

Create a local tracked brand and starter buyer-intent prompts; uses Claude Haiku when configured, otherwise three generic prompts. Example: brand_id='acme', name='Acme', domain='acme.com'. Call refresh_brand next.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYesBrand display name.
domainYesPrimary domain, e.g. 'acme.com'.
aliasesNoAdditional names that count as brand mentions.
brand_idYesNew stable brand ID, e.g. 'acme'.
categoryNoMarket/category for prompt generation.
competitorsNoCompetitor domains to compare.
prompt_countNoBuyer-intent prompts to create.
exclude_termsNoBare terms to ignore in mention matching; the full domain still matches.
refresh_frequencyNoWorker cron cadence; 'manual' disables cron scans. Local stdio stores this setting only.weekly

Output Schema

ParametersJSON Schema
NameRequiredDescription
domainNo
reasonNo
seededYes
brand_idYes
next_stepsYes
competitorsNo
prompt_sourceNo
prompts_insertedNo
refresh_frequencyNo

TDQS

A4.2/5.0
Behavior4/5

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

Annotations already declare readOnlyHint=false, idempotentHint=true, and destructiveHint=false. The description adds meaningful behavioral context beyond those: it mentions the model selection behavior ('uses Claude Haiku when configured, otherwise three generic prompts'), the local scope ('local tracked brand'), and the follow-up action. No contradictions 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?

The description is two sentences plus a short example: purpose, model behavior, example values, and next-step instruction. Every segment carries weight, no filler, and the core action is front-loaded.

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 a tool with 9 parameters, annotations, and an output schema, the description covers purpose, a usage example, model configuration, and the next step. It does not explicitly clarify when to use alternatives such as update_brand or generate_prompts, nor explain 'starter' prompt semantics, but the high schema coverage and output schema carry much of the load.

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 baseline is 3 even without parameter info in the description. The description provides a compact example mapping brand_id, name, and domain, but adds little beyond what the schema already documents; it does not explain parameter interactions like prompt_count or exclude_terms.

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 action ('Create a local tracked brand') and a concrete additional output ('starter buyer-intent prompts'), which distinguishes it from siblings like refresh_brand, update_brand, and generate_prompts. The example clarifies the exact resource being created.

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?

Clear workflow context is provided: it creates a brand plus prompts, and then explicitly instructs 'Call refresh_brand next.' There is no explicit 'use this instead of X' guidance or exclusions, but the purpose is unambiguous enough for an agent to know when to select it.

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

update_brandUpdate tracked brandA
Idempotent

Change tracked-brand metadata without replacing prompts or history. Example: brand_id='acme', competitors=['rival.com'], refresh_frequency='manual' pauses cron scans but keeps manual refresh.

ParametersJSON Schema
NameRequiredDescriptionDefault
nameNoNew display name.
domainNoNew primary domain.
aliasesNoReplacement mention aliases.
brand_idYesTracked brand ID to update.
categoryNoNew category, or null to clear it.
competitorsNoReplacement competitor domains.
exclude_termsNoReplacement bare terms to ignore in mention matching.
refresh_frequencyNoNew cadence; 'manual' pauses cron scans.

Output Schema

ParametersJSON Schema
NameRequiredDescription
brandYes
updatedYes
brand_idYes
next_stepsYes
changed_fieldsYes

TDQS

A4/5.0
Behavior4/5

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

Annotations already carry the idempotent and non-destructive profile. The description adds genuine value by disclosing what it does NOT destroy ('without replacing prompts or history') and by revealing the cron behavior ('refresh_frequency='manual' pauses cron scans but keeps manual refresh'), which is behavioral nuance not present in the annotations or schema. No contradiction with 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?

Two sentences with zero filler: the purpose and scope are front-loaded first, followed by a single illustrative example that demonstrates the non-obvious cron-pause behavior. Every sentence earns its place and nothing extraneous is present.

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 a mutation tool this is well covered: the output schema exists so return values need not be described, annotations carry the idempotent/destructive profile, and the openWorldHint/readOnlyHint are set. The description adds the key behavioral caveats (no prompt/history loss, cron pause). Minor gaps remain—there is no explicit note about partial-update semantics (whether omitted fields are preserved) and no error-case guidance—but these are modest against the rich schema.

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 every one of the 8 parameters is individually documented and the baseline is 3. The example (brand_id='acme', competitors=['rival.com'], refresh_frequency='manual') adds a small amount of combinational usage context tying parameters to behavior, but does not add per-parameter meaning beyond the schema. The description itself contains no parameter syntax details.

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-plus-resource ('Change tracked-brand metadata') and clarifies scope by explicitly excluding what it does not touch ('without replacing prompts or history'). This differentiates it from sibling tools like set_prompts (prompts) and refresh_brand (data refresh), and from track_brand (creation), which share the brand domain.

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

Usage Guidelines3/5

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

The description implies the tool is for metadata updates by contrasting with prompt/history replacement, but it never explicitly names siblings or states when-not-to-use it (e.g., 'to fetch fresh data use refresh_brand'). The example hints at the refresh-frequency behavior but leaves the selection logic to the agent's inference rather than stating it.

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. 1 tool updatev0.3.24
    • Changedget_citations2 fields changed
      • addedOutput schema / properties / top_sources
        Added value: +{
        +  "items": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "citation_count": {
        +        "type": "number"
        +      },
        +      "domain": {
        +        "type": "string"
        +      },
        +      "engines": {
        +        "items": {
        +          "type": "string"
        +        },
        +        "type": "array"
        +      },
        +      "is_brand_domain": {
        +        "type": "boolean"
        +      },
        +      "prompt_count": {
        +        "type": "number"
        +      },
        +      "sample_url": {
        +        "type": "string"
        +      }
        +    },
        +    "required": [
        +      "domain",
        +      "citation_count",
        +      "prompt_count",
        +      "engines",
        +      "sample_url",
        +      "is_brand_domain"
        +    ],
        +    "type": "object"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "brand_id",
        -  "days",
        -  "engine",
        -  "citations"
        -]New value: +[
        +  "brand_id",
        +  "days",
        +  "engine",
        +  "top_sources",
        +  "citations"
        +]
  2. 11 tool updatesv0.3.23
    • Changedcheck_visibility2 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to inspect."New value: +"Tracked brand ID to inspect."
      • changedInput schema / properties / engines / description
        Previous value: -"Optional engine filter. If omitted or empty, return results for every engine with stored data."New value: +"Engines to include; omit or pass [] for all stored engines."
    • Changedcompare_competitors3 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to compare."New value: +"Tracked brand ID to compare."
      • changedInput schema / properties / competitor_domains / description
        Previous value: -"Optional competitor domains to compare; otherwise use the brand's configured competitors."New value: +"Competitor domains; omit to use the brand's configured list."
      • changedInput schema / properties / days / description
        Previous value: -"Number of previous days to include in the comparison."New value: +"Previous days to compare."
    • Changedgenerate_prompts2 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to update."New value: +"Tracked brand ID to update."
      • changedInput schema / properties / count / description
        Previous value: -"Number of buyer-intent prompts to generate."New value: +"Buyer-intent prompts to generate."
    • Changedget_citations3 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to inspect."New value: +"Tracked brand ID to inspect."
      • changedInput schema / properties / days / description
        Previous value: -"Number of previous days from which to return citations."New value: +"Previous days to search."
      • changedInput schema / properties / engine / description
        Previous value: -"Optional engine filter for the citation events."New value: +"Engine to filter by; omit for all engines."
    • Changedget_content_gaps2 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to analyze."New value: +"Tracked brand ID to analyze."
      • changedInput schema / properties / max_recommendations / description
        Previous value: -"Maximum number of content recommendations to return."New value: +"Maximum recommendations to return."
    • Changedget_visibility_history3 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to inspect."New value: +"Tracked brand ID to inspect."
      • changedInput schema / properties / days / description
        Previous value: -"Number of previous calendar days to include."New value: +"Previous calendar days to include."
      • changedInput schema / properties / granularity / description
        Previous value: -"Time bucket for the returned visibility series."New value: +"Time bucket for the series."
    • Changedlist_prompts1 field changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand whose active prompts to inspect."New value: +"Brand ID whose active prompts to list."
    • Changedrefresh_brand2 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to refresh."New value: +"Tracked brand ID to refresh."
      • changedInput schema / properties / engines / description
        Previous value: -"Optional engine filter. If omitted, refresh every configured engine."New value: +"Engines to run; omit for every configured engine."
    • Changedset_prompts2 fields changed
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to update."New value: +"Tracked brand ID to update."
      • changedInput schema / properties / prompts / description
        Previous value: -"Exact active prompt set to use for future scans (1-50 questions)."New value: +"Exact 1-50 prompt set for future scans."
    • Changedtrack_brand9 fields changed
      • changedInput schema / properties / aliases / description
        Previous value: -"Extra terms that always count as a brand mention (product names, abbreviations)."New value: +"Additional names that count as brand mentions."
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier to assign to the new tracked brand."New value: +"New stable brand ID, e.g. 'acme'."
      • changedInput schema / properties / category / description
        Previous value: -"Optional product or market category for prompt generation."New value: +"Market/category for prompt generation."
      • changedInput schema / properties / competitors / description
        Previous value: -"Optional competitor domains to include in visibility analysis."New value: +"Competitor domains to compare."
      • changedInput schema / properties / domain / description
        Previous value: -"Primary domain of the brand, such as acme.com."New value: +"Primary domain, e.g. 'acme.com'."
      • changedInput schema / properties / exclude_terms / description
        Previous value: -"Terms suppressed from bare-word matching — for brand names that are everyday words (\"Monday\", \"Notion\"). The full domain still matches."New value: +"Bare terms to ignore in mention matching; the full domain still matches."
      • changedInput schema / properties / name / description
        Previous value: -"Display name of the brand to track."New value: +"Brand display name."
      • changedInput schema / properties / prompt_count / description
        Previous value: -"Number of buyer-intent prompts to generate for the brand."New value: +"Buyer-intent prompts to create."
      • changedInput schema / properties / refresh_frequency / description
        Previous value: -"Refresh cadence used by self-hosted Worker cron scheduling. Choose 'manual' to disable cron scans while keeping the brand, prompts, and history. Local stdio stores this setting but does not run a background scheduler."New value: +"Worker cron cadence; 'manual' disables cron scans. Local stdio stores this setting only."
    • Changedupdate_brand8 fields changed
      • addedInput schema / properties / aliases / description
        Added value: +"Replacement mention aliases."
      • changedInput schema / properties / brand_id / description
        Previous value: -"Stable identifier of the tracked brand to update."New value: +"Tracked brand ID to update."
      • addedInput schema / properties / category / description
        Added value: +"New category, or null to clear it."
      • addedInput schema / properties / competitors / description
        Added value: +"Replacement competitor domains."
      • addedInput schema / properties / domain / description
        Added value: +"New primary domain."
      • addedInput schema / properties / exclude_terms / description
        Added value: +"Replacement bare terms to ignore in mention matching."
      • addedInput schema / properties / name / description
        Added value: +"New display name."
      • addedInput schema / properties / refresh_frequency / description
        Added value: +"New cadence; 'manual' pauses cron scans."
  3. 6 tool updatesv0.3.19
    • Changedcheck_visibility1 field changed
      • changedInput schema / properties / engines / items / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "grok",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews",
        +  "ai_mode"
        +]
    • Changedget_citations1 field changed
      • changedInput schema / properties / engine / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "grok",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews",
        +  "ai_mode"
        +]
    • Changedlist_brands3 fields changed
      • addedOutput schema / properties / brands / items / properties / aliases
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • addedOutput schema / properties / brands / items / properties / exclude_terms
        Added value: +{
        +  "items": {
        +    "type": "string"
        +  },
        +  "type": "array"
        +}
      • changedOutput schema / properties / brands / items / required
        Previous value: -[
        -  "brand_id",
        -  "name",
        -  "domain",
        -  "category",
        -  "competitors",
        -  "refresh_frequency",
        -  "active_prompts",
        -  "created_at"
        -]New value: +[
        +  "brand_id",
        +  "name",
        +  "domain",
        +  "category",
        +  "competitors",
        +  "aliases",
        +  "exclude_terms",
        +  "refresh_frequency",
        +  "active_prompts",
        +  "created_at"
        +]
    • Changedrefresh_brand1 field changed
      • changedInput schema / properties / engines / items / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "grok",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews",
        +  "ai_mode"
        +]
    • Changedtrack_brand3 fields changed
      • changedInput schema / properties / refresh_frequency / description
        Previous value: -"Refresh cadence used by self-hosted Worker cron scheduling. Local stdio stores this setting but does not run a background scheduler."New value: +"Refresh cadence used by self-hosted Worker cron scheduling. Choose 'manual' to disable cron scans while keeping the brand, prompts, and history. Local stdio stores this setting but does not run a background scheduler."
      • changedInput schema / properties / refresh_frequency / enum
        Previous value: -[
        -  "daily",
        -  "weekly"
        -]New value: +[
        +  "daily",
        +  "weekly",
        +  "manual"
        +]
      • changedOutput schema / properties / refresh_frequency / enum
        Previous value: -[
        -  "daily",
        -  "weekly"
        -]New value: +[
        +  "daily",
        +  "weekly",
        +  "manual"
        +]
    • Addedupdate_brand
  4. 3 tool updatesv0.3.18
    • Changedcheck_visibility1 field changed
      • changedInput schema / properties / engines / items / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews"
        +]
    • Changedget_citations1 field changed
      • changedInput schema / properties / engine / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews"
        +]
    • Changedrefresh_brand1 field changed
      • changedInput schema / properties / engines / items / enum
        Previous value: -[
        -  "chatgpt",
        -  "claude",
        -  "perplexity",
        -  "gemini",
        -  "ai_overviews"
        -]New value: +[
        +  "chatgpt",
        +  "claude",
        +  "perplexity",
        +  "gemini",
        +  "grok",
        +  "ai_overviews"
        +]
  5. 1 tool updatev0.3.17
    • Addedset_prompts
  6. 5 tool updatesv0.3.15
    • Changedcheck_visibility12 fields changed
      • addedOutput schema / properties / per_engine / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / per_engine / items / properties
        Added value: +{
        +  "engine": {
        +    "type": "string"
        +  },
        +  "prompts_appeared_in": {
        +    "type": "number"
        +  },
        +  "refreshed_at": {
        +    "type": "string"
        +  },
        +  "score": {
        +    "type": "number"
        +  },
        +  "total_prompts": {
        +    "type": "number"
        +  }
        +}
      • addedOutput schema / properties / per_engine / items / required
        Added value: +[
        +  "engine",
        +  "score",
        +  "prompts_appeared_in",
        +  "total_prompts",
        +  "refreshed_at"
        +]
      • addedOutput schema / properties / per_engine / items / type
        Added value: +"object"
      • addedOutput schema / properties / top_losing_prompts / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / top_losing_prompts / items / properties
        Added value: +{
        +  "competitors_cited": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "prompt": {
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / properties / top_losing_prompts / items / required
        Added value: +[
        +  "prompt",
        +  "competitors_cited"
        +]
      • addedOutput schema / properties / top_losing_prompts / items / type
        Added value: +"object"
      • addedOutput schema / properties / top_winning_prompts / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / top_winning_prompts / items / properties
        Added value: +{
        +  "engines_cited_in": {
        +    "items": {
        +      "type": "string"
        +    },
        +    "type": "array"
        +  },
        +  "prompt": {
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / properties / top_winning_prompts / items / required
        Added value: +[
        +  "prompt",
        +  "engines_cited_in"
        +]
      • addedOutput schema / properties / top_winning_prompts / items / type
        Added value: +"object"
    • Changedget_content_gaps4 fields changed
      • addedOutput schema / properties / recommendations / items / additionalProperties
        Added value: +false
      • addedOutput schema / properties / recommendations / items / properties
        Added value: +{
        +  "priority": {
        +    "maximum": 5,
        +    "minimum": 1,
        +    "type": "integer"
        +  },
        +  "rationale": {
        +    "type": "string"
        +  },
        +  "suggested_format": {
        +    "enum": [
        +      "comparison_page",
        +      "listicle",
        +      "how_to_guide",
        +      "faq_page",
        +      "case_study",
        +      "pricing_page",
        +      "integration_landing_page"
        +    ],
        +    "type": "string"
        +  },
        +  "topic": {
        +    "type": "string"
        +  }
        +}
      • addedOutput schema / properties / recommendations / items / required
        Added value: +[
        +  "priority",
        +  "topic",
        +  "rationale",
        +  "suggested_format"
        +]
      • addedOutput schema / properties / recommendations / items / type
        Added value: +"object"
    • Changedget_visibility_history2 fields changed
      • addedOutput schema / properties / series / items / properties / per_engine_evidence
        Added value: +{
        +  "additionalProperties": {
        +    "additionalProperties": false,
        +    "properties": {
        +      "brand_mentions": {
        +        "type": "number"
        +      },
        +      "observed_at": {
        +        "type": "string"
        +      },
        +      "usable_prompts": {
        +        "type": "number"
        +      }
        +    },
        +    "required": [
        +      "brand_mentions",
        +      "usable_prompts",
        +      "observed_at"
        +    ],
        +    "type": "object"
        +  },
        +  "propertyNames": {
        +    "type": "string"
        +  },
        +  "type": "object"
        +}
      • changedOutput schema / properties / series / items / required
        Previous value: -[
        -  "date",
        -  "overall_score",
        -  "per_engine"
        -]New value: +[
        +  "date",
        +  "overall_score",
        +  "per_engine",
        +  "per_engine_evidence"
        +]
    • Addedlist_prompts
    • Changedtrack_brand2 fields changed
      • addedInput schema / properties / refresh_frequency
        Added value: +{
        +  "default": "weekly",
        +  "description": "Refresh cadence used by self-hosted Worker cron scheduling. Local stdio stores this setting but does not run a background scheduler.",
        +  "enum": [
        +    "daily",
        +    "weekly"
        +  ],
        +  "type": "string"
        +}
      • addedOutput schema / properties / refresh_frequency
        Added value: +{
        +  "enum": [
        +    "daily",
        +    "weekly"
        +  ],
        +  "type": "string"
        +}
  7. 1 tool updatev0.3.8
    • Changedcompare_competitors4 fields changed
      • addedOutput schema / properties / competitors / items / properties / mentions
        Added value: +{
        +  "type": "number"
        +}
      • changedOutput schema / properties / competitors / items / required
        Previous value: -[
        -  "domain",
        -  "share_of_voice_pct",
        -  "prompts_won_against_you"
        -]New value: +[
        +  "domain",
        +  "share_of_voice_pct",
        +  "mentions",
        +  "prompts_won_against_you"
        +]
      • addedOutput schema / properties / your_mentions
        Added value: +{
        +  "type": "number"
        +}
      • changedOutput schema / required
        Previous value: -[
        -  "brand_id",
        -  "days",
        -  "your_share_of_voice_pct",
        -  "competitors",
        -  "prompts_you_win",
        -  "requested_competitor_domains"
        -]New value: +[
        +  "brand_id",
        +  "days",
        +  "your_share_of_voice_pct",
        +  "your_mentions",
        +  "competitors",
        +  "prompts_you_win",
        +  "requested_competitor_domains"
        +]
  8. 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"
        +]
  9. 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/5.0

Scored across 12 tools

Disambiguation4/5

Most tools are clearly separated by resource and action, and descriptions clarify temporal or comparison scope. The main ambiguity is between generate_prompts and set_prompts, which both replace active prompts and preserve history, and check_visibility versus get_visibility_history could cause a minor misselection for current data.

Naming Consistency5/5

All tools use a consistent snake_case verb_noun pattern such as get_, list_, set_, refresh_, track_, update_, compare_, and check_. There are no mixed naming conventions or vague verbs.

Tool Count5/5

Twelve tools is within the ideal 3-15 range and matches the server's scope: brand management, prompt management, visibility retrieval, and competitor analysis. Each tool has a distinct role without feeling padded or redundant.

Completeness4/5

The server covers brand creation/update/listing, prompt listing/setting/generation, and comprehensive visibility, citation, and competitor reads. The main gap is lifecycle deletion: there is no delete_brand or remove_prompt, though set_prompts can replace prompt sets as a partial workaround.

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
    97 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