Developers

The Ranking Factory is reached by agents in three ways: a read/write MCP server over one customer account, a free MCP server that needs no sign-in, and the same free site check as a plain REST endpoint with an OpenAPI document. Everything below is what those servers answer today.

The servers

Account server

com.therankingfactory/mcp

https://therankingfactory.com/api/mcp

One customer account: visibility runs, evidence gaps, cited sources, published evidence and the entity. Reads from the moment a credential connects; writes only with the write scope. Sign in with OAuth or send an agent key.

Free check server

com.therankingfactory/site-check

https://therankingfactory.com/api/mcp/check

No account and no sign-in. One tool, check_site, which changes nothing, asks no AI engine and stores nothing.

Free check REST API

OpenAPI 3.1

GET https://therankingfactory.com/api/public/site-check?url=

The same check as check_site for a client that does not speak MCP, with the same answer.

Both MCP servers speak JSON-RPC 2.0 over HTTP POST (streamable HTTP, no server-push stream: a GET answers 405). They speak MCP 2026-07-28 per request, and 2025-11-25 or 2025-06-18 through initialize. A request body over 64 KB is refused with 413.

Connect

Sign in (OAuth)

Add https://therankingfactory.com/api/mcp to a client that supports MCP authorization. An unauthenticated request gets 401 with WWW-Authenticate: Bearer resource_metadata="…" naming the protected-resource metadata; the client follows it to the authorization server. Authorization code with PKCE (S256) and theresource parameter; client identity by a Client ID Metadata Document or registration atPOST /api/oauth/register. Access tokens (rfa_) last one hour; refresh tokens (rfr_) last 30 days and rotate on every use. The customer chooses every project or one.

An agent key

For any MCP client. The customer creates a key under Settings → Agent access, chooses what it may read, and leaves or ticks “Let it make changes” (unticked by default). It is shown once; only its hash is kept. Send it on every request as Authorization: Bearer rft_…. A key sees every project in the account.

Both credentials work on every plan, Starter included, and in the 14-day trial, and only at the MCP endpoint: neither opens anything else on this API. The free check server takes no credential at all.

curl -s https://therankingfactory.com/api/mcp \
  -H "Authorization: Bearer rft_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-11-25","capabilities":{},"clientInfo":{"name":"example","version":"1.0"}}}'

curl -s https://therankingfactory.com/api/mcp \
  -H "Authorization: Bearer rft_..." \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
curl -s https://therankingfactory.com/api/mcp/check \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"check_site","arguments":{"url":"example.com"}}}'

Step-by-step connection guide |What people ask it

Tools

tools/list shows a credential only the tools its scopes unlock, and every tool carries the MCP annotations readOnlyHint, destructiveHint, idempotentHint andopenWorldHint. Every read tool answers across all of the account's projects unlessproject (a domain or a project's name) narrows it, and rates come with their sample sizes.

Account server: 11 read tools

Read tools
ToolScopeWhat it does
get_visibility_summaryvisibility:readRecent AI-visibility runs per engine, model and surface: answers back, and how many named, cited or recommended the business, with their denominators.
get_topic_visibilityvisibility:readPer-topic measurement history: runs that measured each topic, runs that named the business, and runs that named it unprompted.
list_cited_sourcesvisibility:readThe sites AI answers actually cited, grouped by site and kind, with declared versus extracted citations and naming rates.
get_gapsgaps:readThe evidence-gap list: counts by status, the open items with ids, and citations since each gap's evidence was published.
get_published_evidenceevidence:readThe published-evidence ledger, newest first: what was published where and when, and which engine first cited it.
get_topic_evidence_poolevidence:readThe outside sources a writer may cite for one subject, each fetched and checked, with the refused ones listed as such.
get_answerabilityevidence:readWhether pages published to the customer's own site answer the questions they are shown for.
get_entityentity:readWho the business is, as asserted: name, type, what it does, where, its main topic and its sameAs links.
get_claimsentity:readThe facts asserted about the business and its stated relationships, with their confidence.
get_sourcesentity:readThe sources behind the claims, each classed Owned, Controlled, Independent or Unattributable.
list_waitingevidence:readWhat is written and waiting for the owner's approval, with whether approve_publish can send each item.

Account server: 6 write tools (need write as well)

Write tools
ToolScopeWhat it does
update_entityentity:readCorrects one project's entity: description, main topic, location, tags and sameAs links. Only the fields passed change.
confirm_productentity:readSays what one of the business's own named products is, from the owner's words or a page on its own site.
close_gapgaps:readAsks the Evidence Engine to work one open gap now, with the same refusals as "Close it now" in the app.
approve_publishevidence:readApproves one item from list_waiting, by id and version, on the owner's instruction. Publishes; cannot be undone from here.
schedule_held_releaseevidence:readPlans spreading held Google files over N days; starts the schedule only with start: true, on the owner's word.
run_visibility_nowvisibility:readStarts a visibility run for one project from its saved watchlist, on the account's own AI keys.

Each write calls the same code as the app's own button, with the same refusals, names one project by its exact domain, and is recorded for the account owner under Settings → Agent access.

Free check server: 1 tool

Free check server tool
ToolScopeWhat it does
check_sitenoneChecks one public website's readiness for AI search, free and without an account: finding titles and tiers, every check made, and a link to the full report.

Scopes

  • visibility:readAI-visibility measurements: runs, per-engine rates, per-topic history.
  • gaps:readThe evidence-gap list: open, in flight, closed, abandoned, and waiting on a person.
  • evidence:readThe published-evidence ledger: what was published where, when, and what AI answers cited.
  • entity:readThe business itself: its identity, the facts asserted about it, and the sources behind them.
  • recommendations:readThe project reviewer's recommendations, where the reviewer is switched on for the account. Reading only.
  • writeMake changes through the six write tools. Never granted by default: a box that starts unticked on every connection and key.

A write tool called without write answers 403 withWWW-Authenticate: Bearer error="insufficient_scope" and a scope naming the scopes the credential holds plus the ones the tool needs.

Limits

  • Writes: 30 write attempts an hour per credential - done, refused or failed alike, in a sliding hour. Reads are not limited.
  • Free check: 60 checks an hour in all, shared by check_site and the REST endpoint, and 20 checks of one site a day.

Every call to a write tool carries the IETF rate-limit headers (draft-ietf-httpapi-ratelimit-headers):RateLimit-Policy with the quota and the window in seconds, and RateLimit with what is left and the seconds until the oldest counted attempt leaves the hour. A call the ceiling refused also carriesRetry-After. The refusal itself is a tool error inside a 200, as every write refusal is.

RateLimit-Policy: "writes";q=30;w=3600
RateLimit: "writes";r=0;t=1260
Retry-After: 1260

Errors

Every error body is JSON.

No credential, or one that is unknown, expired or revoked (account server)

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer resource_metadata="https://therankingfactory.com/.well-known/oauth-protected-resource/api/mcp", scope="…"

{"error":"This endpoint needs a credential: sign in from your AI client (OAuth), or send an agent key as \"Authorization: Bearer rft_…\". How to get either is described at https://therankingfactory.com/.well-known/auth.md"}

A write tool without the write scope

HTTP/1.1 403 Forbidden
WWW-Authenticate: Bearer error="insufficient_scope", resource_metadata="…", scope="…", error_description="…"

{"jsonrpc":"2.0","id":7,"error":{"code":-32001,"message":"close_gap changes the account, and this credential does not hold \"write\". …"}}

A refused or failed tool call

{"jsonrpc":"2.0","id":8,"result":{"content":[{"type":"text","text":"Refused: … Nothing was changed."}],"isError":true}}

Protocol errors are JSON-RPC errors: -32700 the body is not JSON, -32600 not a single request object (batches are not supported), -32601 unknown method, -32602 unknown tool. A 2026-07-28 request that is malformed, mismatched or names an unsupported version is answered 400, and an unknown method 404, each with a JSON-RPC error body.

The REST check

HTTP/1.1 429 Too Many Requests
Retry-After: 2400

{"code":"site_limit","message":"That site has been checked many times today. …"}

Codes: url_required and invalid_url and address_refused (400),busy and site_limit (429, with Retry-After), check_failed (502). The app's own API, behind its login, answers a missing or expired session with 401{"error":"unauthorized","message":"…"} and a refused one with 403{"error":"forbidden","message":"…"}; it is not a public API.

REST and OpenAPI

GET https://therankingfactory.com/api/public/site-check?url=example.com runs the free check and answers with the site checked, when, three scores (SEO, GEO and agent readiness, each 0-100 or null), each finding's tier and title (Blocker first), every check made with its result, and fullReport: where the person can have the full report emailed. No key, open to any origin. It is described by an OpenAPI 3.1 document, the only REST API we publish; the rest of our API serves our own app and is not documented for outside use.

curl -s "https://therankingfactory.com/api/public/site-check?url=example.com"

https://therankingfactory.com/openapi/site-check.json

Machine-readable files

Every response also carries an RFC 8288 Link header naming llms.txt, the sitemap and the API catalog. Questions, or an interface you need that is not here: [email protected].