Operate
Wrenda MCP
An MCP server for Wrenda itself. Point Claude, Cursor or a custom agent at api.wrenda.ai/mcp with an API key and it can read everything the dashboard shows — and, with a write key, add optimizations for the URLs you name.
What it is (and what it isn't)
Wrenda has two things called MCP. They point in opposite directions:
| Wrenda MCP (this page) | Site MCP Tools | |
|---|---|---|
| Who connects | Your agent — Claude Desktop, Claude Code, Cursor, ChatGPT, a script | Third-party agents visiting your site |
| Endpoint | https://api.wrenda.ai/mcp | /.well-known/mcp.json on your domain |
| What it exposes | Your Wrenda account: domains, analytics, health, optimizations, citations, usage | Tools you define about your site (search, cart, contact…) |
| Credential | A tenant API key (aics_…) | Per-domain auth tokens |
| Where to manage it | Settings → API & MCP | MCP Tools in the sidebar |
Use Wrenda MCP when you want to ask questions like “which pages did GPTBot hit this week?” from the tool you already work in, or hand an agent a task like “analyze the pricing page and enable the FAQ suggestion” without opening the dashboard.
1. Create an API key
Open Settings → API & MCP
You need the admin role. The page lists every key with its preview, scopes, last use and expiry.
Create key
Name it after what will hold it (“Claude Code — laptop”). Choose a scope: Read for reporting and questions, Read + Write if the agent should be able to change optimizations or purge cache. Pick an expiry — 90 days is a sensible default for a laptop.
Copy it — once
The full key (
aics_…) is shown exactly once, with the four configs below already filled in. Wrenda stores only a hash. If you lose it, revoke it and create another.
2. Connect a client
Replace <key> with your key. The endpoint is the same for every client: https://api.wrenda.ai/mcp.
Claude Code
Run once in any project (or add --scope user to make it available everywhere).
claude mcp add --transport http wrenda https://api.wrenda.ai/mcp --header "Authorization: Bearer <key>"Claude Desktop
Settings → Developer → Edit Config. Claude Desktop reaches remote servers through mcp-remote (needs Node 18+). Restart the app afterwards.
{
"mcpServers": {
"wrenda": {
"command": "npx",
"args": [
"-y",
"mcp-remote",
"https://api.wrenda.ai/mcp",
"--header",
"Authorization: Bearer <key>"
]
}
}
}Cursor
Project-level (.cursor/mcp.json) or global (~/.cursor/mcp.json). Cursor picks it up without a restart.
{
"mcpServers": {
"wrenda": {
"url": "https://api.wrenda.ai/mcp",
"headers": {
"Authorization": "Bearer <key>"
}
}
}
}Raw HTTP
Stateless Streamable HTTP: one JSON-RPC 2.0 request per POST, JSON back. No sessions, no SSE.
# 1. Handshake
curl -s -X POST https://api.wrenda.ai/mcp \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"curl","version":"1.0"}}}'
# 2. List the tools
curl -s -X POST https://api.wrenda.ai/mcp \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
# 3. Call one
curl -s -X POST https://api.wrenda.ai/mcp \
-H "Authorization: Bearer <key>" \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"list_domains","arguments":{}}}'initialize answers with serverInfo.name: "Wrenda" and a short instructions string; tools/list returns the 20 tools below. In Claude Code, /mcp shows wrenda as connected; ask “list my Wrenda domains” to confirm.
- Transport
- MCP Streamable HTTP, stateless — one JSON-RPC 2.0 request (or batch) per POST, JSON response. No sessions, no server-initiated streams.
- Protocol version
2025-03-26- Auth header
Authorization: Bearer aics_…- Domain arguments
- Accept the hostname (
shop.acme.com) or the domain id. Unknown → a readable error telling the agent to calllist_domains. - Discovery
GET https://api.wrenda.ai/mcpreturns{ name, version, transport, docs }without auth.
3. Tools
Every result is JSON in content[0].text and again as structuredContent; errors are plain sentences an agent can act on. The example prompts are what you would type into the client.
Read — any key
| Tool | Arguments | Returns | Try |
|---|---|---|---|
list_domains | — | Your domains with mode, DNS verification, health, platform and integration mode. | “Which of my domains are still in shadow mode?” |
get_domain_health | {domain} | The stored Integration Health report plus setup completeness and the next step. | “Is shop.acme.com healthy? What should I fix first?” |
get_analytics_overview | {domain, hours?} | Requests, AI requests, cache hit rate, latency, top crawlers and top pages for a window. | “Summarise the last 24 hours of crawler traffic on acme.com.” |
get_crawler_activity | {domain, limit?, bot?} | Recent request-log rows — timestamp, user agent, path, action, cached, status, latency. | “Show me the last 20 GPTBot requests on acme.com.” |
get_ai_insights | {domain, days?} | AI crawler insights: platform breakdown, top pages and daily trends. | “Which AI platforms crawled acme.com most this week?” |
list_page_optimizations | {domain, url?, status?, render_target?, limit?} | Page Optimization suggestions and enabled changes, filterable by URL, status and target. | “List the suggested optimizations for /pricing.” |
get_page_optimization | {id} | One Page Optimization in full — rationale, evidence and verification result. | “Why was optimization 42 suggested, and did it work?” |
list_template_optimizations | {domain} | Template Optimizations (content rules): path pattern, prompt additions, settings, TTL, priority. | “What template optimizations apply to /products/*?” |
get_citations_overview | {domain?} | AI Citations per brand: visibility score, mention rate, share of voice, by platform, last run. | “How is our brand visibility trending across AI platforms?” |
list_citation_opportunities | {domain?, limit?} | Open citation opportunities with platform, query, recommendation and status. | “What are the top 5 citation opportunities right now?” |
get_usage | — | Plan, uncached requests used vs. limit, billing period and any over-limit state. | “How much of this month’s allowance have we used?” |
Write — Read + Write keys only
| Tool | Arguments | Does | Try |
|---|---|---|---|
analyze_page | {domain, url} | Run the AI page analyzer on a URL; new suggestions are created as "suggested" and returned. | “Analyze https://acme.com/pricing and enable the FAQ suggestion.” |
create_page_optimization | {domain, url, render_target, type, title, payload, rationale?, enable?} | Add a Page Optimization for a URL — a prerender modification (title, meta, H1, schema) or a transformation instruction. | “Set the meta description of /pricing to "…" and enable it.” |
enable_page_optimization | {id} | Enable a suggested or disabled Page Optimization (bumps the cache version). | “Enable optimization 42.” |
disable_page_optimization | {id} | Disable an enabled Page Optimization without deleting it. | “Turn off the H1 change on /pricing.” |
dismiss_page_optimization | {id} | Dismiss a suggestion so it stops being proposed. | “Dismiss the schema suggestion for /blog/hello.” |
create_template_optimization | {domain, name, path_pattern, prompt_additions?, template?, cache_ttl?, …} | Create a Template Optimization for a path pattern, optionally from one of the nine archetype templates. | “Add a template optimization for /products/* using the product template.” |
update_template_optimization | {id, …fields} | Partially update a Template Optimization (pattern, prompt, TTL, priority, active). | “Raise the cache TTL on the products template to 24 hours.” |
delete_template_optimization | {id} | Delete a Template Optimization. | “Remove the old /legacy/* template.” |
purge_cache | {domain, urls?} | Purge cached optimized / pre-rendered copies — given URLs only, or the whole domain (re-optimizing counts against your allowance). | “Purge the cache for /pricing and /about on acme.com.” |
Page Optimization payloads
create_page_optimization takes a render_target that decides the payload shape. Both are validated; the URL must be on the named domain and is canonicalised to origin + path.
| render_target | type | payload |
|---|---|---|
prerender | title · meta_description · h1 · schema_markup | { "modification": { "type": <same as type>, "action": "set" | "append", "value": "…" } } |
transformation | faq · entity · comparison · custom | { "instruction": "…" } |
Pass enable: true to switch it on immediately (the cached copy is versioned so crawlers see it on the next request); otherwise it lands as suggested for review in the dashboard.
4. Safety
- Write scope
- Read-only keys get a clear "This key is read-only" tool error on write tools — nothing changes. Give agents write keys only for the session that needs them.
- Audit log
- Every write-tool call is recorded in the audit log as
mcp_<tool>with the key that made it. Read calls are not logged. - Rate limit
- 120 calls per minute per key. Over that the endpoint answers HTTP 429; well-behaved clients back off automatically.
- Allowance
- Optimizations created over MCP are the same as ones from the dashboard: they count against nothing extra, but
purge_cacheon a whole domain means every page is re-optimized on its next crawl, which does spend uncached requests. See Cache & purge. - Revoke
- Revoking a key ends every client using it at once. Keys with an expiry stop working at the timestamp shown in the table.
Troubleshooting
| Symptom | Cause | Fix |
|---|---|---|
401 / JSON-RPC error -32001 Unauthorized | Missing, mistyped, revoked or expired key — or a JWT from the dashboard instead of an aics_ key. | Check the header reads Authorization: Bearer aics_… and the key shows as active under Settings → API & MCP. Create a new one if in doubt. |
Tool result isError: “This key is read-only” | A read-scope key called a write tool. | Create a Read + Write key for that client, or keep the agent to read tools. |
| 429 | More than 120 calls in a minute from one key. | Wait a minute. Agents that loop over every page should ask for limits (list_page_optimizations limit) rather than per-URL calls. |
| “Domain 'x' not found — call list_domains” | The agent guessed a hostname or used a domain that belongs to another workspace. | Ask it to call list_domains first; hostnames and ids both work. |
| Claude Desktop shows the server but no tools | mcp-remote could not start (Node missing) or the header was quoted wrongly in JSON. | Run npx -y mcp-remote https://api.wrenda.ai/mcp --header "Authorization: Bearer aics_…" in a terminal to see the error; restart the app after editing the config. |
| Cursor: "no tools" / red dot | Old Cursor versions only support stdio servers. | Update Cursor, or use the Claude Desktop config (mcp-remote) as a stdio bridge. |