{"openapi":"3.1.0","info":{"title":"That SEO Agent — agent surface","version":"1.0.0","summary":"Discovery documents and the MCP endpoint for That SEO Agent.","description":"That SEO Agent is an SEO analysis product an AI agent drives over MCP.\n\n**When to use this API.** Reach for it when a task needs real search data\nfor a specific website — Google Search Console queries and impressions,\nGA4 traffic, PageSpeed/Core Web Vitals, on-page and schema audits, or a\nsite crawl. It answers questions about *one site the user controls and has\nconnected*; it is not a keyword-research database, a rank tracker for\narbitrary domains, or a backlink index.\n\n**How to call it.** 62 tools are exposed over MCP\n(Streamable HTTP) at `POST /mcp`, authenticated with a Bearer API key.\nFetch `/.well-known/mcp/server-card.json` first: it declares the\ntransport, the auth metadata, and the full tool manifest. Then use an MCP\nclient rather than hand-rolling JSON-RPC.\n\nThe `/.well-known` documents below need no credentials.\n\n**Versioning.** This surface is versioned by protocol revision, not by\nURL. `/mcp` is a stable address and will not move: send the\n`MCP-Protocol-Version` header to pin the revision you were written\nagainst, or omit it and the server uses the one negotiated during\n`initialize`. A revision this server does not support is answered with a\n400, never silently downgraded. The discovery documents under\n`/.well-known` carry their own spec version inside the payload —\n`specVersion` for the AI catalog, `$schema` for the skills index and the\nserver card.\n\n**Deprecation.** The full policy is published at\n`/deprecation-policy.md`, and it is the normative statement: what counts\nas breaking, what notice you get, and what we promise not to do. In\nshort — a tool on its way out keeps working and says so in its own\ndescription first, the `Deprecation` and `Sunset` (RFC 8594) headers\nappear on a resource only once it is genuinely deprecated, and nothing is\nremoved in the release that deprecates it. The server card's `tools`\narray is generated from the live registry, so it is the authority on what\nexists today.","contact":{"name":"That SEO Agent support","email":"support@thatseoagent.com","url":"https://thatseoagent.com/contact"},"license":{"name":"Proprietary","url":"https://thatseoagent.com/en/terms"}},"servers":[{"url":"https://thatseoagent.com","description":"Production"}],"externalDocs":{"description":"MCP server documentation","url":"https://thatseoagent.com/mcp-server-for-seo"},"tags":[{"name":"MCP","description":"The Model Context Protocol endpoint — where the tools live."},{"name":"Discovery","description":"Unauthenticated documents describing this service."}],"paths":{"/mcp":{"post":{"operationId":"callMcp","summary":"Call the MCP server (JSON-RPC 2.0 over Streamable HTTP)","description":"Single entry point for all 62 SEO tools. The body is a JSON-RPC 2.0\nrequest — `initialize`, `tools/list`, `tools/call`, `resources/list`,\n`prompts/list`. Send `Accept: application/json, text/event-stream`.\n\nThe transport is stateless, so there is no GET stream to open: a GET\nanswers 405. `/api/mcp` is the same endpoint under its original path.\n\nPrefer an MCP client library. `tools/list` returns the exhaustive input\nschema for every tool, which is what a function-calling loop needs.","tags":["MCP"],"parameters":[{"name":"MCP-Protocol-Version","in":"header","required":false,"description":"The MCP protocol revision this request is written against, as a date string (for example `2025-11-25`). Omit it and the server uses the revision negotiated during `initialize`. Send one the server does not support and it answers 400 rather than guessing. The supported set is the one the server advertises in its `initialize` result — read it there rather than hardcoding it.","schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcRequest"},"examples":{"listTools":{"summary":"List every available tool","value":{"jsonrpc":"2.0","id":1,"method":"tools/list"}},"callTool":{"summary":"Run a Search Console quick-wins analysis","value":{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{"name":"gsc_detect_quick_wins","arguments":{"siteUrl":"https://example.com"}}}}}}}},"responses":{"200":{"description":"A JSON-RPC response, or an SSE stream when the client accepts one.","headers":{"RateLimit":{"description":"Remaining tool calls in the current window and seconds until it resets, as IETF structured fields: `\"mcp\";r=118;t=42`.","schema":{"type":"string"}},"RateLimit-Policy":{"description":"The quota and window this endpoint enforces: `\"mcp\";q=120;w=60`.","schema":{"type":"string"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JsonRpcResponse"}},"text/event-stream":{"schema":{"type":"string"}}}},"400":{"description":"Malformed JSON-RPC, or an `MCP-Protocol-Version` header naming a revision this server does not support.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"401":{"description":"Missing, malformed, revoked, or expired API key.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"405":{"description":"Method not allowed — the transport is stateless, so GET has no stream to give.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}},"429":{"description":"Rate limit exceeded.","content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/Problem"}}}}}}},"/.well-known/mcp/server-card.json":{"get":{"operationId":"getMcpServerCard","summary":"MCP server card (SEP-1649)","description":"Transport, authentication metadata, capabilities, and the full tool manifest. Fetch this before anything else — it is generated from the live tool registry.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpServerCard"}}}}}}},"/.well-known/api-catalog":{"get":{"operationId":"getApiCatalog","summary":"API catalog (RFC 9727)","description":"A linkset pointing at this document, the server card, the OAuth metadata, and llms.txt.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/linkset+json":{"schema":{"$ref":"#/components/schemas/ApiCatalog"}}}}}}},"/.well-known/ai-catalog.json":{"get":{"operationId":"getAiCatalog","summary":"AI catalog (Agentic Resource Discovery v1.0)","description":"The same entry points in the Agentic Resource Discovery shape.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AiCatalog"}}}}}}},"/.well-known/agent-skills/index.json":{"get":{"operationId":"getAgentSkillsIndex","summary":"Agent skills index (v0.2.0)","description":"Installable skills, each with a `sha256` digest. Individual skills are markdown at `/.well-known/agent-skills/{slug}/SKILL.md`.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSkillsIndex"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"operationId":"getOauthProtectedResource","summary":"OAuth 2.0 protected resource metadata (RFC 9728)","description":"Which authorization server guards the MCP endpoint.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthProtectedResourceMetadata"}}}}}}},"/.well-known/oauth-authorization-server":{"get":{"operationId":"getOauthAuthorizationServer","summary":"OAuth 2.0 authorization server metadata (RFC 8414)","description":"Endpoints and supported flows for obtaining a token.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthAuthorizationServerMetadata"}}}}}}},"/llms.txt":{"get":{"operationId":"getLlmsTxt","summary":"Site guide for language models","description":"Every page worth reading, what each MCP tool does, and the machine-readable entry points. Also served from `/`, `/en`, and `/es` under `Accept: text/markdown`.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"text/markdown":{"schema":{"type":"string","contentMediaType":"text/markdown","description":"The site guide, as markdown."}}}}}}},"/deprecation-policy.md":{"get":{"operationId":"getDeprecationPolicy","summary":"Versioning and deprecation policy","description":"What counts as a breaking change, the notice you get before one, and when the `Deprecation`/`Sunset` headers appear. Normative: `info.description` summarises it, this document states it.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"text/markdown":{"schema":{"type":"string","contentMediaType":"text/markdown","description":"The policy, as markdown."}}}}}}},"/pricing.md":{"get":{"operationId":"getPricingMarkdown","summary":"Pricing as markdown","description":"Generated from the live plan catalog, so it cannot drift from the /pricing page.","tags":["Discovery"],"security":[],"responses":{"200":{"description":"The document.","content":{"text/markdown":{"schema":{"type":"string","contentMediaType":"text/markdown","description":"The plan catalog, as markdown."}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"http","scheme":"bearer","description":"An API key issued from the dashboard: `Authorization: Bearer sea_…`. Create one at https://thatseoagent.com/dashboard#api-keys."}},"schemas":{"McpServerCard":{"type":"object","description":"SEP-1649 server card. Identity is served twice: flat at the root for generic readers, and nested under `serverInfo` for MCP clients.","required":["name","description","version","serverUrl","transport","tools"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"version":{"type":"string"},"serverUrl":{"type":"string","format":"uri","description":"The MCP endpoint. Mirrors `transport.endpoint`."},"serverInfo":{"type":"object","additionalProperties":true,"description":"The same identity in its SEP-1649 position."},"transport":{"type":"object","additionalProperties":true},"authentication":{"type":"object","additionalProperties":true},"capabilities":{"type":"object","additionalProperties":true},"toolCount":{"type":"integer"},"toolsByCategory":{"type":"object","additionalProperties":{"type":"integer"}},"tools":{"type":"array","description":"The full manifest. Input schemas are summarised as parameter names; `tools/list` returns the exhaustive JSON Schemas.","items":{"type":"object","required":["name","description"],"properties":{"name":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"category":{"type":"string"},"readOnly":{"type":"boolean"},"destructive":{"type":"boolean"},"parameters":{"type":"array","items":{"type":"string"}}}}},"contact":{"type":"object","additionalProperties":true}},"additionalProperties":true},"ApiCatalog":{"type":"object","description":"RFC 9727 linkset. Each entry anchors on a resource and lists the documents describing it.","required":["linkset"],"properties":{"linkset":{"type":"array","items":{"type":"object","required":["anchor"],"properties":{"anchor":{"type":"string","format":"uri"},"item":{"type":"array","items":{"type":"object","additionalProperties":true}}},"additionalProperties":true}}}},"AiCatalog":{"type":"object","description":"Agentic Resource Discovery v1.0.","required":["specVersion","entries"],"properties":{"specVersion":{"type":"string"},"host":{"type":"object","additionalProperties":true},"entries":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"AgentSkillsIndex":{"type":"object","description":"agentskills.io discovery index v0.2.0.","required":["skills"],"properties":{"$schema":{"type":"string","format":"uri"},"skills":{"type":"array","items":{"type":"object","required":["name","description","type","url"],"properties":{"name":{"type":"string"},"description":{"type":"string"},"type":{"type":"string","enum":["skill-md","archive"]},"url":{"type":"string","format":"uri"},"digest":{"type":"string","pattern":"^sha256:[0-9a-f]{64}$","description":"SHA-256 of the artifact's raw bytes."}}}}}},"OAuthProtectedResourceMetadata":{"type":"object","description":"RFC 9728.","required":["resource","authorization_servers"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"}}}},"OAuthAuthorizationServerMetadata":{"type":"object","description":"RFC 8414.","required":["issuer","authorization_endpoint","token_endpoint"],"properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"registration_endpoint":{"type":"string","format":"uri"},"client_id_metadata_document_supported":{"type":"boolean"},"response_types_supported":{"type":"array","items":{"type":"string"}},"grant_types_supported":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_methods_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}},"JsonRpcRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"description":"Omit for a notification.","oneOf":[{"type":"string"},{"type":"integer"}]},"method":{"type":"string","description":"A JSON-RPC method the MCP server implements.","examples":["initialize","tools/list","tools/call","resources/list","prompts/list"]},"params":{"type":"object","additionalProperties":true}},"additionalProperties":false},"JsonRpcResponse":{"type":"object","required":["jsonrpc"],"properties":{"jsonrpc":{"type":"string","const":"2.0"},"id":{"oneOf":[{"type":"string"},{"type":"integer"},{"type":"null"}]},"result":{"type":"object","additionalProperties":true},"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"integer"},"message":{"type":"string"},"data":{"additionalProperties":true}}}}},"Problem":{"type":"object","required":["type","title","status"],"properties":{"type":{"type":"string","format":"uri","description":"A URI identifying the problem type."},"title":{"type":"string","description":"Short, human-readable summary."},"status":{"type":"integer","description":"The HTTP status code."},"detail":{"type":"string","description":"What went wrong with this specific request."},"instance":{"type":"string","format":"uri"},"code":{"type":"string","description":"Stable machine-readable error code."},"resolution":{"type":"string","description":"What the caller should do next."},"documentation_url":{"type":"string","format":"uri"}}}}},"security":[{"apiKey":[]}]}