MCP & API
Point an assistant at your visibility data. Reads are generous; drafts are reversible; nothing gated ever fires without you.
The three bands
Every tool and every route declares exactly one. The UI shows it everywhere, including here.
Executes now · no side effects
No side effects. An agent can call these freely, in a loop, without asking first. Reads are metered generously on purpose — an agent reads 50× more than a person.
Executes now · produces a reviewable artefact
Changes what is tracked, or produces a draft artefact. Reversible from the dashboard, and every call is written to the activity log. Metered only on the expensive primitive.
Never executes on call · returns pending_approval
Calling a gated tool does not run it. Middleware — not the handler — creates a task in pending_approval, writes the activity log row, and returns an approval URL. A human approves in the dashboard before anything leaves the sandbox. Credits are debited on approval, never on request.
Gated. Calling this never executes it. The middleware creates a task in pending_approval, writes the activity-log row, and returns an approval URL. A human approves here before anything leaves the sandbox — and credits are debited on approval, never on request.
Connect an assistant
Same endpoint, same key, three ways in.
Add this to your Claude Desktop config, replace the key, restart. The tool list appears with the band stated in the first line of every description.
{
"mcpServers": {
"fenn": {
"url": "https://api.fenn.sh/api/aeo-engine/mcp",
"headers": {
"x-api-key": "aeo_live_xxxxxxxxxxxx"
}
}
}
}Create a key
Scopes are bands. There is no gated scope — that is not an omission.
Scopes
API keys (3 active)
Revoking is immediate and does not need a deploy. Last-used is what tells you whether a key is still wired to anything.
| Label | Key | Scopes | Client | Created | Last used | Actions |
|---|---|---|---|---|---|---|
| Claude Desktop (MCP) | aeo_live_7f2b… | readdraft | claude-desktop/2.4 | 5 Jul | 3h ago | |
| CI — nightly | aeo_live_9a41… | readdraft | acme-ci/1.0 | 12 Jun | 2h ago | |
| Read-only — analyst notebook | aeo_live_3c88… | read | — | 31 Jul | 4d ago | |
| Old laptop (revoked)revoked | aeo_live_1d05… | readdraft | — | 14 Apr | 1mo ago | — |
Tool registry (15)
What an assistant sees when it connects. Each tool's description states its band in the first line; read tools carry readOnlyHint.
| Tool | Band | What it does | Arguments | Returns | Metered |
|---|---|---|---|---|---|
| visibility_report | read | Visibility Score, Share of Voice, Average Position and Sentiment for a domain, per engine, over a range. | domain, range?, engines? | Scores per engine + trend series | free |
| prompt_detail | read | Everything about one tracked prompt: the raw answer each engine gave, who was cited, where you appeared, how it moved. | prompt_id, engines?, range? | Per-engine answers, citations, position, sentiment | free |
| list_prompts | read | Every prompt tracked for a domain, with its latest result. | domain, status? | Prompt list with last-run summary | free |
| rank_check | read | Classic rank for a keyword alongside answer-engine presence, so you can see where the two disagree. | domain, keyword, locale? | Rank, AI Overview presence, citing engines | paid SERP call |
| keyword_gaps | read | Prompts and keywords where competitors are cited and you are not, ranked by ask volume. | domain, competitors?, limit? | Gap list with competitor citations | free |
| audit_issues | read | Technical and content issues that suppress citation: thin answers, missing schema, buried definitions, orphaned pages. | domain, severity?, category? | Issue list with severity, URL, evidence | free |
| backlinks | read | Referring domains, and the pages engines actually quote when answering about you. | domain, limit? | Referring domains + cited-source overlap | free |
| suggest_fixes | read | For an issue or gap, the concrete changes most likely to earn the citation. Proposes; does not write. | issue_id | gap_id, max_suggestions? | Ranked suggestions with rationale | free |
| get_fix_prompt | read | The exact prompt to hand your own coding agent, if you would rather implement the fix yourself. | fix_id | Ready-to-paste prompt + file targets | free |
| list_fix_tasks | read | State of every fix: drafted, pending approval, PR open, merged, verified. | domain, status? | Fix task list with PR links | free |
| track_prompt | draft | Start tracking a new prompt. Counts against the prompt allowance on your plan. | domain, prompt, engines? | prompt_id + first scheduled run | on first run |
| track_keyword | draft | Add a keyword to rank tracking. | domain, keyword, locale? | keyword_id + first scheduled check | on first check |
| draft_fix | draft | Turn a suggestion into a real diff against your connected repo. Produces a branch and a patch — it does not push, open, or merge anything. | fix_id | issue_id, repo, base_branch? | fix_task_id + unified diff preview | free (the audit was metered) |
| execute_fix | gated | Open the pull request for a drafted fix. Returns pending_approval and stops; a human approves in the dashboard, and only then is the PR opened. | fix_task_id | status: "pending_approval" + approval_url | on approval |
| request_publish | gated | Publish a report or content change to a connected CMS. Same rule: returns pending_approval and waits for a human. | target, payload_ref | status: "pending_approval" + approval_url | on approval |
These names are a contract. They mirror what the MCP server registers — see the call log for what has actually been invoked against this workspace.