Skip to main content
The Model Context Protocol (MCP) lets AI assistants like Claude Code, Claude Desktop, Cursor, and other compatible clients call external tools in a structured way. The OtterlyAI MCP server exposes your brand reports, prompts, citations, recommendations, and audit checks as MCP tools so your assistant can answer questions about your AI search visibility directly.

Endpoint

The server speaks the MCP streamable HTTP transport. Authentication is handled entirely through OAuth 2.0 — see below.

Authentication

The OtterlyAI MCP server authenticates with OAuth 2.0. You do not pass an API key. When you add the server to a compatible client, the client walks you through a standard browser sign-in to OtterlyAI and obtains an access token on your behalf. Permissions and workspace scoping match your OtterlyAI account.
The oai_live_ API keys documented under Authentication are for the REST Public API only. The MCP server does not accept them — it is OAuth-only.
The flow is fully automatic for MCP clients: there is nothing to configure by hand. Under the hood the server implements OAuth 2.0 with dynamic client registration and PKCE, and advertises discovery metadata at:
When a request arrives without a valid token, the server responds 401 with a WWW-Authenticate header pointing at the protected-resource metadata, which is the client’s cue to start the OAuth flow.

Quick sanity check

You don’t need a token to confirm the server is up and correctly OAuth-gated. An unauthenticated request returns 401 with a WWW-Authenticate header:
You should see HTTP/1.1 401 and a header of the form WWW-Authenticate: Bearer error="invalid_token", resource_metadata="https://data.otterly.ai/.well-known/oauth-protected-resource/mcp". Fetching that metadata document returns the resource and its authorization server:

Claude.ai

In Customize → Connectors, choose Add connector / ”+” sign, search for OtterlyAI, and click Connect:
A browser window opens to sign in to OtterlyAI and authorize access. Once approved, the OtterlyAI tools are available in your chats. Claude.ai holds the resulting token itself, so it never shares credentials with another client on your machine.

Claude Code

The first time a tool is used, Claude Code opens a browser to complete the OAuth sign-in. Verify with claude mcp list — you should see otterly: ... - ✓ Connected. Tools are then available as mcp__otterly__<tool_name>. Claude Code holds the resulting token itself, so it never shares credentials with another client on your machine.

Claude Desktop

Add a remote connector pointing at the endpoint; Claude Desktop runs the OAuth flow in your browser on first connect. If your version launches stdio servers only, use the mcp-remote bridge — it performs the OAuth handshake for you, so no static Authorization header is needed. Add the following to ~/Library/Application Support/Claude/claude_desktop_config.json (macOS):
Restart Claude Desktop; a browser opens to authorize, and the OtterlyAI tools appear in the tool picker.
If you also run Cursor, a second Claude Desktop profile, or any other mcp-remote client on this machine, the snippet above is not enough — see Running more than one client.

Cursor

In Cursor → Settings → MCP, add a new server using the same mcp-remote bridge (the OAuth flow opens in your browser on first use):
If you also run Claude Desktop or any other mcp-remote client on this machine, the snippet above is not enough — see Running more than one client.

Running more than one client on one machine

The mcp-remote bridge stores every credential in ~/.mcp-auth, keyed by server URL, regardless of which client started it. Two clients pointed at the same URL therefore share a single login: whichever one authorizes last evicts the other, which then opens its own browser tab to authorize and evicts the first. The symptom is an authorization tab that keeps reappearing and a client that reports no connection to OtterlyAI. Separate application folders do not separate these credentials — two Claude Desktop profiles hit this too. Give each client its own store and its own callback port. Claude Desktop:
Cursor:
Use an absolute path for MCP_REMOTE_CONFIG_DIR; ~ is not expanded. Then quit every client, delete the shared ~/.mcp-auth, and authorize one client at a time. This is also how you connect two different OtterlyAI accounts on one machine — with one shared store both clients end up on whichever account authorized last.

Available tools

Every tool has a counterpart in the Public API and returns the same data shapes. Each tool also advertises an outputSchema (JSON Schema) in tools/list and returns its result as structuredContent conforming to that schema, with the same JSON mirrored in the text block — so clients can type and validate responses at the protocol level. Required arguments are listed per tool; optional arguments below the tables.

Account

Workspaces & engines

Brand reports

Agent analytics

AI crawler and agent traffic hitting the brand report’s own domains — the inverse of citations, which are what the engines said about your brand. Same data as the Agent Analytics tab in the app. Unlike the other brand-report tools, startDate and endDate are optional here and default to the last 14 days (UTC) — the window the app shows by default. There is no country argument: crawler traffic is attributed to a URL and a user-agent, and neither carries a country. get_brand_report_agent_stats speaks one engine vocabulary throughout — chatgpt, claude, copilot, perplexity, google (Gemini included), other. That holds for both the summary (topEngine, per-engine totals) and the trend series, whose rows are { dayId, engine, bot, visitCount }. bot is the raw crawler name (GPTBot, Google-Extended), so one engine can appear across several bots on a day — e.g. google for both GoogleOther and Google-Extended. Every response carries an availability field. Check it before reading the numbers: Treating not_connected as zero is the mistake worth avoiding: it reads as “no AI crawler visited this site” when the truth is that nobody is measuring.

GEO audits

Query fan-outs

Write tools (write permission only)

These tools are only registered when your account has write permission; with read-only access they are not advertised by the server.

Common arguments

  • Dates: startDate and endDate are inclusive. Accept YYYY-MM-DD or a full ISO timestamp; only the date portion is used.
  • Country: country is a lowercase ISO 3166-1 alpha-2 code (e.g. us, de). Use uk for the United Kingdom.
  • Engines: engines (multi-value) and engine (single-value) accept chatgpt, claude, google, perplexity, copilot, google_ai_mode, gemini. Call list_engines to see which engines are available in which countries.
  • Engines on the agent-analytics tools: single-value — chatgpt, claude, copilot, perplexity, google, other. google covers the whole Google family (Gemini included), unlike the app which lists Gemini separately. Pass engine=other to match every AI crawler outside the named engines (Amazon, Meta, xAI, ByteDance, Common Crawl, and so on). other also appears in the response breakdown, so it means the same thing in and out. The agent name in list_brand_report_agents is always exact, so other never hides which crawler it was.
  • Pagination: every list tool pages, with limit defaulting to 25 (max 100). The paging object has the same shape as the Public API endpoint behind the tool, but only the shape: several Public API endpoints return the whole list in one response where MCP pages it. Cursor lists (list_workspaces, list_workspace_tags, list_workspace_prompts, list_brand_reports, list_brand_report_recommendations, list_brand_report_annotations, list_crawlability_checks, list_content_checks, list_query_fan_outs) accept cursor and limit and return paging: { nextCursor, hasMore }; pass nextCursor back as cursor for the next page. list_brand_report_prompt_ai_responses is cursor-paged too, with cursor only. Offset lists (list_brand_report_citations, list_brand_report_prompts, list_brand_report_citation_prompts, list_brand_report_agent_pages, list_brand_report_agents) accept limit and offset (a multiple of limit) and return paging: { limit, offset, hasMore }, the agent-analytics lists adding totalCount; add limit to offset for the next page. Either way, stop when hasMore is false. The former page and pageSize arguments are no longer accepted: a list tool rejects them, like any unknown argument, with a validation error rather than ignoring them.
  • Extra filters on list_brand_report_prompts and list_brand_report_citations: engines, tagId, search, sortBy, sortOrder.
  • search on the agent-analytics list tools is a case-insensitive substring match, applied server-side across the whole result set. It is matched literally — % and _ are not wildcards.

Typical conversation flow

  1. get_account_info → your plan and how many MCP tool calls remain this period. Free, so it is safe to call first.
  2. list_workspaces → pick a workspaceId (optional).
  3. list_brand_reports → pick a reportId.
  4. list_brand_report_prompts or list_brand_report_citations with reportId, a date range, and a country code (e.g. us, uk, de).
  5. Drill into get_brand_report_stats, get_brand_report_citation_stats, list_brand_report_recommendations, or the GEO audit tools as needed.
  6. To ask about AI crawlers on your own site rather than what the engines said, start at get_brand_report_agent_stats with just the reportId, then drill into list_brand_report_agent_pages or list_brand_report_agents.

Troubleshooting

The authorization tab keeps reopening, or the client reports no connection to OtterlyAI. Two clients are sharing one mcp-remote credential store — see Running more than one client. Reconnecting repairs one client and breaks the other, so the loop survives any number of reconnects. “state already in use”. A connection link is single-use and retrying the same one lands here. Wait about ten minutes, then start the connection again from the client rather than reloading the page. The wrong OtterlyAI account got connected. Approval is granted by whichever account the browser is already signed into; the client has no say in it. To connect a specific account, sign that account in first — a separate browser profile per account is the reliable way — and then authorize. 401 from a tool call. The OAuth token is missing or expired; reconnect to refresh it. If reconnecting works and then fails again within a day, it is the shared-credential case above rather than an expiry. 403 from a tool call. Your account lacks permission for the requested workspace.

Things to know

  • Most tools are read-only. The tools in the Write tools section above are only available to accounts with the write permission.
  • Workspace scoping matches your OtterlyAI account. See Troubleshooting for 401 and 403 responses.
  • Every tool call except get_account_info counts against your plan’s MCP tool-call limit. Once it is exhausted, calls fail with Request limit exceeded for this billing period until the next period.
  • Each tool’s outputSchema is the contract for its result. The shapes are the Public API response shapes, paging included, so the OpenAPI spec doubles as a field reference.
Hitting a bug or missing a tool you’d like to see? Email support@otterly.ai.