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.
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.
{
"mcpServers": {
"ceyo": {
"url": "https://api.ceyo.ai/api/public/v1/projects/123/mcp",
"headers": {
"X-Api-Key": "your_api_key_here"
}
}
}
} Get your project ID — open Ceyo, navigate to your project, and copy the numeric ID from the URL (e.g.
/projects/123).Get your API key — go to Workspace → Settings → API Keys and create or copy an existing key.
Add to your MCP client — paste the config above, replacing the project ID and API key.
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:
| Header | Format | Example |
|---|---|---|
X-Api-Key | Raw key value | X-Api-Key: ceyo_live_abc… |
Authorization | Bearer token | Authorization: Bearer ceyo_live_abc… |
Protocol
The server speaks JSON-RPC 2.0 over HTTP POST. All responses return HTTP 200, even for JSON-RPC-level errors.
Supported methods
| Method | Description |
|---|---|
initialize | Handshake — returns server name, version, and capabilities. |
tools/list | Returns all available tools with their input schemas. |
tools/call | Invokes a tool by name with the given arguments. |
ping | Liveness 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:
| Layer | Shape | When |
|---|---|---|
| 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 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 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 active prompts tracked by this project, with per-prompt visibility score, average AI position, sentiment, and competitor mention counts.
Parameters
| Name | Type | Description |
|---|---|---|
page | integer | Page number (1-based). Defaults to 1. |
per_page | integer | Results per page. Max 50. Defaults to 50. |
start | string | Start date for metrics (ISO 8601, e.g. 2026-04-01). Defaults to 7 days before end. |
end | string | End date for metrics (ISO 8601). Defaults to today. |
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
| Name | Type | Description |
|---|---|---|
prompt_id required | integer | ID of the prompt. |
start | string | Start date (ISO 8601). Defaults to 7 days before end. |
end | string | End date (ISO 8601). Defaults to today. |
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
| Name | Type | Description |
|---|---|---|
prompt_id required | integer | ID of the prompt. |
start | string | Start date (ISO 8601). Defaults to 7 days before end. |
end | string | End date (ISO 8601). Defaults to today. |
page | integer | Page number. Defaults to 1. |
per_page | integer | Results 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 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
| Name | Type | Description |
|---|---|---|
prompt_id required | integer | ID of the prompt. |
start | string | Start date (ISO 8601). Defaults to 7 days before end. |
end | string | End date (ISO 8601). Defaults to today. |
page | integer | Page number. Defaults to 1. |
per_page | integer | Results per page. Max 50. Defaults to 15. |
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
| Name | Type | Description |
|---|---|---|
topic_id required | integer | ID of the topic this prompt belongs to. |
content required | string | The 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.
|
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
| Name | Type | Description |
|---|---|---|
prompt_id required | integer | ID of the prompt to archive. |
Enqueue AI-powered optimization action generation for one or more prompts. Actions are created asynchronously and appear in list_actions once ready.
total_credit_cost — check this value before proceeding. If the workspace has insufficient credits, the call fails before any credits are consumed.
Parameters
| Name | Type | Description |
|---|---|---|
prompt_ids required | integer[] | 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 for the project. Returns each topic's ID and name. Use the returned IDs when calling create_prompt.
Parameters
| Name | Type | Description |
|---|---|---|
page | integer | Page number. Defaults to 1. |
per_page | integer | Results per page. Max 150. Defaults to 50. |
Create a new topic. Topic names must be unique within the project. Returns the new topic ID — use it immediately in create_prompt.
Parameters
| Name | Type | Description |
|---|---|---|
name required | string | Topic 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 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
| Field | Type | Description |
|---|---|---|
id | integer | Action ID — use in update_action_status. |
title | string | Short action title. |
detail | string | Full description of what to do and why. |
priority | string | high, medium, or low. |
effort_level | string | Estimated implementation effort. |
estimated_impact | number | Predicted visibility impact (0–1 scale). |
md_implementation_guide | string | null | Step-by-step guide in Markdown, if available. |
Update the status of an optimization action to track progress as work is completed.
Parameters
| Name | Type | Description |
|---|---|---|
action_id required | integer | ID of the action to update. |
status required | string |
One of: todo, in_progress, completed, dismissed.
|
Competitor tools
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
| Name | Type | Description |
|---|---|---|
start | string | Start of date window (ISO 8601). Defaults to 7 days ago. Maximum window is 1 month. |
end | string | End of date window (ISO 8601). Defaults to today. |
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 a competitor website to track. The competitor is included in future scans. Display name is derived from the domain automatically if not provided.
Parameters
| Name | Type | Description |
|---|---|---|
website required | string | Competitor website URL (e.g. https://competitor.com). |
name | string | Display name. Auto-derived from the domain if omitted. |
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
| Name | Type | Description |
|---|---|---|
competitor_id required | integer | ID of the competitor to remove. |