Status Back

MCP Server

Connect AI agents — Claude, Cursor, and any MCP-compatible client — directly to your Ceyo GEO data. The Ceyo MCP server exposes 17 tools covering your full project state: visibility metrics, prompt tracking, LLM response intelligence, competitor rankings, and optimization actions.

ℹ️
Same API key. The MCP server uses the same credentials as the Ceyo REST API. No separate setup needed.

The server implements Model Context Protocol (protocol version 2024-11-05) over a single HTTP endpoint using JSON-RPC 2.0. Each endpoint is scoped to one project — configure the URL once per project in your MCP client.


Quick start

The MCP endpoint for a project is:

POST https://api.ceyo.ai/api/public/v1/projects/{project_id}/mcp

Replace {project_id} with your project's numeric ID, visible in the Ceyo dashboard URL or via the REST API.

Claude Desktop

Add to claude_desktop_config.json under mcpServers.

Cursor

Add to Cursor → Settings → MCP or your project's .cursor/mcp.json.

mcp.json / claude_desktop_config.json
{
  "mcpServers": {
    "ceyo": {
      "url": "https://api.ceyo.ai/api/public/v1/projects/123/mcp",
      "headers": {
        "X-Api-Key": "your_api_key_here"
      }
    }
  }
}
  1. Get your project ID — open Ceyo, navigate to your project, and copy the numeric ID from the URL (e.g. /projects/123).

  2. Get your API key — go to Workspace → Settings → API Keys and create or copy an existing key.

  3. Add to your MCP client — paste the config above, replacing the project ID and API key.

  4. Test the connection — ask your agent: "Call get_project to tell me about this Ceyo project." It should return the project name, website, and description.


Authentication

Every request must include a Ceyo API key. Two header formats are accepted:

HeaderFormatExample
X-Api-Key Raw key value X-Api-Key: ceyo_live_abc…
Authorization Bearer token Authorization: Bearer ceyo_live_abc…
⚠️
Billing gate: if your workspace billing is inactive or your plan does not include public API access, requests fail with HTTP 402 or 403 before the JSON-RPC layer is reached.

Protocol

The server speaks JSON-RPC 2.0 over HTTP POST. All responses return HTTP 200, even for JSON-RPC-level errors.

Supported methods

MethodDescription
initializeHandshake — returns server name, version, and capabilities.
tools/listReturns all available tools with their input schemas.
tools/callInvokes a tool by name with the given arguments.
pingLiveness check — returns an empty result object.
notifications/*Notification messages (no id) are silently acknowledged with HTTP 200 and no body.

Initialize handshake

Request
{
  "jsonrpc": "2.0",
  "id": 1,
  "method": "initialize",
  "params": { "protocolVersion": "2024-11-05" }
}
Response
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "protocolVersion": "2024-11-05",
    "serverInfo": { "name": "ceyo", "version": "1.0.0" },
    "capabilities": { "tools": { "listChanged": false } }
  }
}

Calling a tool

Request
{
  "jsonrpc": "2.0",
  "id": 2,
  "method": "tools/call",
  "params": {
    "name": "get_project",
    "arguments": {}
  }
}
Response
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [
      {
        "type": "text",
        "text": "{\"id\": 123, \"name\": \"Acme Corp\", ...}"
      }
    ]
  }
}

The text field contains a JSON-encoded string with the tool's payload. MCP clients automatically present this to the agent.


Error handling

Three error layers, each with a distinct shape:

LayerShapeWhen
HTTP errors {"error":"…","error_code":"…"} + non-200 status Invalid API key, billing inactive, project not found, malformed body
JSON-RPC errors {"error":{"code":…,"message":"…"}} + HTTP 200 Unknown method, parse error, internal server error
Tool errors {"content":[…],"isError":true} + HTTP 200 Bad arguments, record not found, quota exceeded

Tool errors use isError: true inside the standard MCP content envelope. The text field contains a human-readable message the agent can relay to the user.


Project tools

get_project
read

Get details about the current project: name, website, description, location, language, and focus area. Call this first to understand what brand or entity you are working on.

Parameters

No parameters required.

Example response

{
  "id": 123,
  "name": "Acme Corp",
  "website": "https://acme.com",
  "description": "B2B SaaS platform for...",
  "country": "United States",
  "language": "en",
  "focus": "product"
}
get_project_metrics
read

Get the project's GEO visibility metrics over the last 3 months. Returns a time-series of visibility score (0–100), average AI ranking position, mention count, and coverage percentage, plus a per-brand competitor ranking breakdown for each data point.

Parameters

No parameters required.

Example response

{
  "project_name": "Acme Corp",
  "rows": [
    {
      "date": "2026-04-07",
      "visibility_score": 42.5,
      "avg_position": 2.1,
      "mentions": 38,
      "coverage_pct": 61.3,
      "ranking": [
        { "name": "Acme Corp", "is_main_brand": true, "mentions": 38, "visibility_score": 42.5 },
        { "name": "Competitor X", "is_main_brand": false, "mentions": 55, "visibility_score": 58.2 }
      ]
    }
  ]
}

Prompt tools

list_prompts
read

List active prompts tracked by this project, with per-prompt visibility score, average AI position, sentiment, and competitor mention counts.

Parameters

NameTypeDescription
pageintegerPage number (1-based). Defaults to 1.
per_pageintegerResults per page. Max 50. Defaults to 50.
startstringStart date for metrics (ISO 8601, e.g. 2026-04-01). Defaults to 7 days before end.
endstringEnd date for metrics (ISO 8601). Defaults to today.
get_prompt
read

Get full details and performance metrics for a single prompt by ID. Returns visibility score, average AI position, sentiment, and competitor mention breakdown. Use list_prompts to discover IDs.

Parameters

NameTypeDescription
prompt_id requiredintegerID of the prompt.
startstringStart date (ISO 8601). Defaults to 7 days before end.
endstringEnd date (ISO 8601). Defaults to today.
get_prompt_responses
read

Get the actual text responses from ChatGPT, Gemini, Perplexity, and other AI models for a specific prompt. Each row includes the model key, the full response text, whether the brand was mentioned, the brand's ranking position, and a citations preview. This is the core intelligence tool for understanding how AI models talk about a brand.

Parameters

NameTypeDescription
prompt_id requiredintegerID of the prompt.
startstringStart date (ISO 8601). Defaults to 7 days before end.
endstringEnd date (ISO 8601). Defaults to today.
pageintegerPage number. Defaults to 1.
per_pageintegerResults per page. Max 50. Defaults to 15.

Example response row

{
  "model_key": "chatgpt",
  "position": 2,
  "brand_present": true,
  "response_text": "Acme Corp is a leading provider of...",
  "citations_count": 4,
  "citations": [ { "domain": "acme.com", "url": "https://acme.com/product" } ]
}
get_prompt_citations
read

Get the domains and URLs that AI models cite when responding to a prompt, ranked by frequency. Each row includes the domain, page path, total citation count, and a per-model frequency breakdown. Use this to understand which sources AI models trust — and whether the brand's own site is being cited.

Parameters

NameTypeDescription
prompt_id requiredintegerID of the prompt.
startstringStart date (ISO 8601). Defaults to 7 days before end.
endstringEnd date (ISO 8601). Defaults to today.
pageintegerPage number. Defaults to 1.
per_pageintegerResults per page. Max 50. Defaults to 15.
create_prompt
write

Add a new prompt to be tracked by the project. The prompt is queued for the next scheduled scan across all enabled AI models. Requires a topic_id — use list_topics to find available topics, or create_topic to create a new one.

Parameters

NameTypeDescription
topic_id requiredintegerID of the topic this prompt belongs to.
content requiredstringThe prompt text — the question or query to track.
category required string One of: organic_search, brand_sentiment, competitor_comparison.
organic_search: SEO-style discovery queries.
brand_sentiment: brand reputation questions.
competitor_comparison: questions comparing brands.
archive_prompt
write

Stop tracking a prompt. Archived prompts are excluded from future scans and hidden from the active list. This is a soft-delete — historical data is fully preserved and the prompt can be found in the archived list via the REST API.

Parameters

NameTypeDescription
prompt_id requiredintegerID of the prompt to archive.
generate_actions
writecosts credits

Enqueue AI-powered optimization action generation for one or more prompts. Actions are created asynchronously and appear in list_actions once ready.

⚠️
This tool costs credits. The response includes total_credit_cost — check this value before proceeding. If the workspace has insufficient credits, the call fails before any credits are consumed.

Parameters

NameTypeDescription
prompt_ids requiredinteger[]Array of prompt IDs to generate actions for. Maximum 50 per call.

Example response

{
  "enqueued_prompts_count": 3,
  "credit_cost_per_prompt": 5,
  "total_credit_cost": 15,
  "request_id": "a1b2c3d4-...",
  "message": "Enqueued action generation. Actions will be created asynchronously."
}

Topic tools

Topics are groupings that organise prompts (e.g. "Product Features", "Brand Awareness"). Every prompt belongs to exactly one topic.

list_topics
read

List topics for the project. Returns each topic's ID and name. Use the returned IDs when calling create_prompt.

Parameters

NameTypeDescription
pageintegerPage number. Defaults to 1.
per_pageintegerResults per page. Max 150. Defaults to 50.
create_topic
write

Create a new topic. Topic names must be unique within the project. Returns the new topic ID — use it immediately in create_prompt.

Parameters

NameTypeDescription
name requiredstringTopic name (e.g. AI capabilities, Customer support). Must be unique within the project.

Action tools

Actions are AI-generated optimization recommendations — specific changes to content, positioning, or strategy to improve GEO visibility.

list_actions
read

List active (todo or in_progress) AI-generated optimization actions for the project, sorted high → medium → low priority. Each action includes a title, implementation detail, priority, effort level, estimated impact score, and an optional Markdown implementation guide.

Parameters

No parameters required.

Action fields

FieldTypeDescription
idintegerAction ID — use in update_action_status.
titlestringShort action title.
detailstringFull description of what to do and why.
prioritystringhigh, medium, or low.
effort_levelstringEstimated implementation effort.
estimated_impactnumberPredicted visibility impact (0–1 scale).
md_implementation_guidestring | nullStep-by-step guide in Markdown, if available.
update_action_status
write

Update the status of an optimization action to track progress as work is completed.

Parameters

NameTypeDescription
action_id requiredintegerID of the action to update.
status required string One of: todo, in_progress, completed, dismissed.

Competitor tools

get_competitor_rankings
read

Get the visibility ranking table for all tracked brands and competitors. Returns mention count, average AI position, and visibility score (% of prompts where each brand appears) from the most recent scan data.

Parameters

NameTypeDescription
startstringStart of date window (ISO 8601). Defaults to 7 days ago. Maximum window is 1 month.
endstringEnd of date window (ISO 8601). Defaults to today.
list_direct_competitors
read

List the direct competitors currently configured for this project. Returns each competitor's ID, name, and website. Use the competitor ID when calling remove_direct_competitor.

Parameters

No parameters required.

add_direct_competitor
write

Add a competitor website to track. The competitor is included in future scans. Display name is derived from the domain automatically if not provided.

Parameters

NameTypeDescription
website requiredstringCompetitor website URL (e.g. https://competitor.com).
namestringDisplay name. Auto-derived from the domain if omitted.
remove_direct_competitor
write

Remove a competitor from tracking. Future scans will no longer include this competitor. Historical data is preserved. Use list_direct_competitors to find competitor IDs.

Parameters

NameTypeDescription
competitor_id requiredintegerID of the competitor to remove.