Developers · MCP

MCP tools

The MazeRank MCP server gives AI agents your visibility data and your ranked fixes, with the evidence and done-for-you solutions. This is the exact catalogue tools/list returns; a key only sees the tools its scopes allow. Setup, auth and limits are in the API reference.

Endpoint
https://mcp.mazerank.com
What agents can change. Fix statuses (in progress, done with the published URL, dismissed, reopened), solutions, swapping a plan task, and business facts (with facts_write). apply_fix only returns a change set (CMS draft, pull request or manual steps) and marks the fix awaiting approval: a person reviews and publishes, then the agent calls mark_fix_done. get_fix_solution never writes one unless called with generate: true; a full solution uses the site's monthly budget (Pro 20, Scale 60), and on Spark the one free solution is spent only with use_free: true. MazeRank never publishes pages, edits sites or sends outreach by itself.

Visibility data

list_sites

scope: sitesreadOnlyHintREST: GET /sites

List the websites this API key can read (id, name, website, city, plan).

inputSchema
{
  "type": "object",
  "properties": {}
}

get_mention_rates

scope: ratesreadOnlyHintREST: GET /sites/{id}/mention-rates

Current AI mention rate (share of AI answers naming the business, latest complete check) and the weekly trend.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "weeks": {
      "type": "number",
      "description": "Weeks of history (default 12, max 52)"
    }
  },
  "required": [
    "site_id"
  ]
}

get_engines

scope: enginesreadOnlyHintREST: GET /sites/{id}/engines

Mention rate per AI engine (ChatGPT, Google AI Overviews, Perplexity, Gemini, Claude, AI Mode), latest complete check.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

get_competitors

scope: competitorsreadOnlyHintREST: GET /sites/{id}/competitors

Businesses AI names most for this site's questions, with mention rates, vs the site itself.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "limit": {
      "type": "number"
    }
  },
  "required": [
    "site_id"
  ]
}

get_answers

scope: answersreadOnlyHintREST: GET /sites/{id}/answers

Recent AI answers: question, engine, whether the business was named, rank, competitors, citations.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "limit": {
      "type": "number",
      "description": "Default 50, max 200"
    },
    "engine": {
      "type": "string"
    }
  },
  "required": [
    "site_id"
  ]
}

get_alerts

scope: alertsreadOnlyHintREST: GET /sites/{id}/alerts

Alerts: big drops, competitors overtaking, wrong facts in AI answers.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

get_reports

scope: reportsreadOnlyHintREST: GET /sites/{id}/reports

Latest monthly PDF report and weekly report links.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

get_plan

scope: planreadOnlyHintREST: GET /sites/{id}/plan

This week's plan: up to 3 tasks (fixes and wrong-answer corrections) with effort, who can do it, estimated gain and status. Work them in order.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

get_wins

scope: planreadOnlyHintREST: GET /sites/{id}/wins

The month's wins: tasks done, proven, extra questions now naming the business (and on which engines), wrong answers corrected, score change, with receipt links.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "month": {
      "type": "string",
      "description": "YYYY-MM (default: this month, UTC)"
    }
  },
  "required": [
    "site_id"
  ]
}

get_accuracy

scope: accuracyreadOnlyHintREST: GET /sites/{id}/accuracy

Accuracy: correct / checkable claims AI makes about the business (wrong, outdated, mixed up, misleading counts), per engine and weekly. Separate from the visibility score.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

list_wrong_answers

scope: accuracyreadOnlyHintREST: GET /sites/{id}/claims

Claims AI made about the business that don't match its confirmed facts: the claim, the quote, engine, verdict, severity and the likely source page. Default verdicts: wrong, outdated, mixed_up, misleading.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "verdict": {
      "type": "string",
      "description": "Comma list: correct, wrong, outdated, mixed_up, misleading, unverifiable"
    },
    "limit": {
      "type": "number",
      "description": "Default 50, max 200"
    }
  },
  "required": [
    "site_id"
  ]
}

get_facts

scope: factsreadOnlyHintREST: GET /sites/{id}/facts

The business facts MazeRank checks AI answers against (name, services, prices, hours, location, phone, policies…), with status (confirmed / to review) and source.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

update_fact

scope: facts_writewrites · not destructive · idempotentREST: PUT /sites/{id}/facts

Set a confirmed business fact (only with the owner's say-so). One-value fields (phone, hours…) replace the current value, which stays in history; services/prices add a row. Triggers a re-grade of AI claims. Not available to admin keys.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "field": {
      "type": "string",
      "enum": [
        "name",
        "domain",
        "what",
        "service",
        "not_offered",
        "price",
        "hours",
        "location",
        "phone",
        "email",
        "founded",
        "policy",
        "claim_ok"
      ]
    },
    "value": {
      "type": "string"
    },
    "key": {
      "type": "string",
      "description": "Optional label, e.g. the service a price is for"
    }
  },
  "required": [
    "site_id",
    "field",
    "value"
  ]
}

Fixes

list_fix_categories

scope: fixesreadOnlyHintREST: GET /sites/{id}/fix-categories

Fix categories with counts per status: content (pages/articles), tool (free tools), technical (llms.txt, schema, robots.txt), listing (directories), reviews_community, outreach. Use a category id to filter list_fixes or get_next_fix.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    }
  },
  "required": [
    "site_id"
  ]
}

list_fixes

scope: fixesreadOnlyHintREST: GET /sites/{id}/fixes

The site's fixes, ranked (rank 1 = do first), compact. Each fix is grounded in the latest check: what AI cited instead of the site, for which questions. Filter by category, status, type and impact; paginate with cursor. Includes the plan's monthly full-solution budget.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "category": {
      "type": "string",
      "description": "Comma list: content, tool, technical, listing, reviews_community, outreach"
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "open",
        "in_progress",
        "awaiting_approval",
        "done",
        "verified",
        "dismissed",
        "all"
      ],
      "description": "Default active (open + in_progress + awaiting_approval)"
    },
    "type": {
      "type": "string",
      "description": "Comma list: article, tool, directory, outreach, community, technical"
    },
    "impact": {
      "type": "string",
      "description": "Comma list: high, medium, low"
    },
    "limit": {
      "type": "number",
      "description": "Default 20, max 50"
    },
    "cursor": {
      "type": "string",
      "description": "next_cursor from the previous page"
    }
  },
  "required": [
    "site_id"
  ]
}

get_fix

scope: fixesreadOnlyHintREST: GET /sites/{id}/fixes/{fix_id}

One fix with its evidence (pages AI cited instead of the site, questions and engines missed, who was named instead), why it matters, the re-check, and an implementation brief: goal, acceptance criteria, ordered steps with action types, files/URLs to create or edit, who can do it, placeholders, dependencies, verification and a ready-to-paste agent_prompt in the site's language. include="solution" adds the written solution and puts its content into agent_prompt.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    },
    "include": {
      "type": "string",
      "enum": [
        "solution"
      ],
      "description": "\"solution\" adds the written solution and a content-complete agent_prompt (larger response). Default: compact."
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

get_next_fix

scope: fixesreadOnlyHintREST: GET /sites/{id}/fixes/next

The fix to work on now: the in-progress one if any, otherwise the top-ranked open fix (optionally within a category). Same shape as get_fix, so an agent can loop: get_next_fix → mark_fix_in_progress → implement → mark_fix_done. Returns data: null when nothing is left.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "category": {
      "type": "string",
      "description": "Optional category id from list_fix_categories"
    },
    "include": {
      "type": "string",
      "enum": [
        "solution"
      ],
      "description": "\"solution\" adds the written solution and a content-complete agent_prompt (larger response). Default: compact."
    }
  },
  "required": [
    "site_id"
  ]
}

get_fix_solution

scope: fixes · generate needs fixes_writewrites · not destructive · idempotentREST: GET|POST /sites/{id}/fixes/{fix_id}/solution

The done-for-you solution for a fix as structured parts (title tag, meta description, slug, article markdown/HTML, JSON-LD, FAQ, internal links, tool build prompt, listing fields, outreach pitch text to copy) plus the blanks to fill. Without generate it only returns an existing solution. generate=true (needs fixes_write) writes one: lite outlines are free; a full solution uses the site's monthly budget (Pro 20, Scale 60). On Spark the single free full solution is spent ONLY when you pass use_free=true for this fix. Returns budget_remaining. Nothing is published or sent.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    },
    "generate": {
      "type": "boolean",
      "description": "Write a solution if none exists (default false)"
    },
    "mode": {
      "type": "string",
      "enum": [
        "full",
        "lite"
      ],
      "description": "Default full"
    },
    "use_free": {
      "type": "boolean",
      "description": "Spark only: spend this month's free full solution on this fix"
    },
    "regenerate": {
      "type": "boolean",
      "description": "Pro/Scale: write a new full solution even if one exists (uses budget)"
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

mark_fix_in_progress

scope: fixes_writewrites · not destructive · idempotentREST: POST /sites/{id}/fixes/{fix_id}/start

Mark an open fix as in progress, so teammates and other agents see it's being worked on (get_next_fix returns it first). Changes only the fix's status.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

mark_fix_done

scope: fixes_writewrites · not destructive · idempotentREST: POST /sites/{id}/fixes/{fix_id}/done

Mark a fix as done in MazeRank. Its questions are re-checked at ~72 hours, day 7 if needed and day 21 (2 of 3 runs), and the fix shows before/after with a proof receipt. Pass published_url (the live page) when there is one: it feeds the proof, the AI-traffic and crawler-visit signals. Changes only the fix's status.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    },
    "published_url": {
      "type": "string",
      "description": "Optional: the live URL of the page/profile this fix created or changed."
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

dismiss_fix

scope: fixes_writewrites · not destructive · idempotentREST: POST /sites/{id}/fixes/{fix_id}/dismiss

Dismiss a fix (hide it from the open list). Reversible with reopen_fix; nothing is deleted. Pass a short reason when you know it.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    },
    "reason": {
      "type": "string",
      "description": "Optional: why it doesn't apply (e.g. already done, not relevant)."
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

reopen_fix

scope: fixes_writewrites · not destructive · idempotentREST: POST /sites/{id}/fixes/{fix_id}/reopen

Move a done, dismissed or awaiting-approval fix back to open.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

apply_fix

scope: fixes_writewrites · not destructive · idempotentREST: POST /sites/{id}/fixes/{fix_id}/apply

Package a fix's written solution as a change set for YOU to apply: a pull request (branch, commit message, PR body, file changes such as the new page, JSON-LD, llms.txt, robots.txt), a CMS draft (WordPress/Webflow: title, slug, HTML, meta, JSON-LD) or manual steps for off-site fixes. MazeRank changes nothing on the site: open the PR / save the draft, get a person to approve and publish it, then call mark_fix_done with published_url. Sets the fix to awaiting_approval. Needs an active plan and a written solution (get_fix_solution generate=true first; budget applies).

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    },
    "format": {
      "type": "string",
      "enum": [
        "pull_request",
        "cms_draft",
        "manual"
      ],
      "description": "Optional hint; the fix type decides the format."
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

get_fix_proof

scope: fixesreadOnlyHintREST: GET /sites/{id}/fixes/{fix_id}/proof

Proof for a done fix: same questions and engines before vs after, re-check passes (~72 h, day 7, day 21), verdict (proven / not_yet / not_proven), per-engine result and the public receipt link (+PDF). A signal, never a promise.

inputSchema
{
  "type": "object",
  "properties": {
    "site_id": {
      "type": "string",
      "description": "Site id from list_sites"
    },
    "fix_id": {
      "type": "string",
      "description": "Fix id from list_fixes (stable across checks)"
    }
  },
  "required": [
    "site_id",
    "fix_id"
  ]
}

Prompts

Returned by prompts/list to keys with the fixes scope. Clients such as Claude and Cursor show them as slash commands. The text below is what prompts/get returns.

work_through_fixes · Work through my fixes

Walk through the site's fixes one by one: pick the next fix, read its evidence and brief, implement it (or guide the owner), verify, mark it done, repeat.

  • site_id (required): Site id from list_sites
  • category: Optional: content, tool, technical, listing, reviews_community or outreach
  • max_fixes: Stop after this many fixes (default 3)
prompts/get → messages[0].content.text
Work through the MazeRank fixes for site SITE_ID, one at a time, at most 3.

For each fix:
1. Call get_next_fix with site_id "SITE_ID". If data is null, stop: nothing left.
2. Read evidence, implementation.goal and implementation.dependencies. If a dependency says the solution isn't written yet, ask the user before calling get_fix_solution with generate=true: it uses the site's monthly budget (on Spark only with use_free=true, and only if the user picks this fix).
3. Call mark_fix_in_progress.
4. Call get_fix with include "solution" and follow implementation.agent_prompt exactly. who_can_do_it tells you whether you can edit the codebase (developer/agent) or must guide the owner (owner_manual: listings, reviews, outreach; never send or post anything yourself).
5. Ask the user to fill every item in implementation.placeholders. Never invent prices, reviews or claims.
6. Check each implementation.verification item you can check (URLs return 200, schema validates).
7. When the user confirms it's live, call mark_fix_done with published_url (MazeRank re-checks the questions at ~72 hours, day 7 and day 21; the status becomes verified). If you can open pull requests or CMS drafts, apply_fix packages the solution for you; a person still approves and publishes.
8. Summarise what changed, then continue with the next fix.

implement_fix · Implement one fix

Implement a single fix in the current codebase using its brief and solution.

  • site_id (required): Site id
  • fix_id (required): Fix id
prompts/get → messages[0].content.text
Implement MazeRank fix FIX_ID for site SITE_ID.
1. Call get_fix with site_id "SITE_ID", fix_id "FIX_ID", include "solution".
2. If there's no solution yet, ask the user before calling get_fix_solution with generate=true (it uses the monthly budget).
3. Call mark_fix_in_progress, then follow implementation.agent_prompt.
4. List implementation.placeholders for the user, run the verification checks, and call mark_fix_done once the user confirms it's live.

Agent loop

What an agent does with work_through_fixes, call by call:

  1. get_next_fix { site_id }: the in-progress fix, or rank 1. data: null means done for now.
  2. mark_fix_in_progress { site_id, fix_id }.
  3. If implementation.dependencies lists a missing solution: ask the user, then get_fix_solution { generate: true } (uses the monthly budget; Spark only with use_free).
  4. get_fix { include: "solution" } and follow implementation.agent_prompt in the codebase, or guide the owner when who_can_do_it is owner_manual.
  5. Ask the user for every item in implementation.placeholders; run implementation.verification.
  6. mark_fix_done once it's live. MazeRank re-checks the questions; the fix becomes verified. Repeat.

The full REST version with example responses is in the agent walkthrough.

Errors

Tool errors come back as a result with isError: true and the same JSON body as REST (for example {"error":"free_pick_required", "budget_remaining":1, …}). Codes are listed in the API reference.