Cituna MCP server

v1.0.0 — first public release. Twelve read tools plus four write tools, five
built-in analysis workflows, and a server that tells your client how to open a
session and which workflow answers which question. The server reports honestly
by design: the citation matrix distinguishes cited / not_cited / not_run
(an engine that sat a query out is not a miss), list_audits exposes
scoring_epoch so you never compare re-based scores, and whoami returns your
real usage meters rather than claiming a Search Console state it cannot see
(that is gsc_status's job).
The AI visibility tool you use from inside the AI. Every other tool in this
category hands you a dashboard and leaves the thinking to you. Cituna puts the
measurements where you already do the reasoning: ask Claude why ChatGPT never
mentions you, and it can pull the answer receipts, cross-check them against what
Google already sends you, and queue the page that fixes it, without you opening
a tab.
Bring Cituna into Claude (Desktop, Code, or any MCP client). This server
is a thin bridge over the Cituna backend: it authenticates as you and calls
the same endpoints the app uses, so Google's OAuth refresh token and your database
stay server-side and nothing sensitive lives in the MCP.
It exposes three things Claude can work with directly:
- Daily visibility tracking — the core deliverable. Your tracked prompts are
re-asked every day across all six engines (ChatGPT, Perplexity, Gemini, Claude,
Grok, Google AI Overviews);
get_visibility returns the latest prompt×engine
grid (cited? which position? which mode?) plus your current score, and
get_engine_answers returns the receipts — what each engine actually said, the
brands it cited, and the source URLs.
- AI-visibility audits — per-engine citation scores across all six engines, the
query×engine citation matrix, competitors cited, and a prioritised gap/action
queue you can update from the chat.
- Live Google Search Console — clicks / impressions / CTR / position, top
queries and pages, and arbitrary Search Analytics queries.
Claude ⇄ (stdio, MCP) ⇄ this server ⇄ (HTTPS + your key) ⇄ Cituna backend ⇄ AI engines + Google Search Console
Tools
Twelve read tools work from Starter; the four write tools — tagged
✍︎ Pro — require Pro or higher (see Plans). The 3-day free
trial is app-only and has no MCP access.
whoami | Starter+ | The authenticated account (email, workspace, role), backend URL, plan (Starter/Pro/Max), and the full usage meters (per-tool used/limit, brand + prompt-pool counts). Call first to confirm the connection. Search Console state is gsc_status's job, not this tool's. |
list_audits | Starter+ | Recent AI-visibility audits, newest first: scanId, domain, date, AI-citation score, SEO/GEO/authority scores, open-gap count, and each audit's scoring_epoch (score-formula version — only compare scores within the same epoch). Optional domain filter. |
get_audit | Starter+ | One audit in detail by scanId: overall + per-engine scores, the query×engine citation matrix (each cell explicitly cited / not_cited / not_run), competitors cited, top gaps, and pass/warn/fail check counts. |
get_visibility | Starter+ | Daily tracking. The latest prompt×engine grid for a brand (id or domain): per tracked prompt and engine — cited?, position, mode (live/value/lite/off), status — plus the current visibility score and the day it was measured. |
get_engine_answers | Starter+ | The receipts. For a brand + prompt (optional engine): the actual stored answer text each engine gave on the most recent day, the brands it cited, the source URLs, and your cited position. Answer text capped ~4k chars with a truncated flag. |
list_gaps | Starter+ | The fix queue for a domain (or scanId): each gap with its gapKey, status (todo/doing/done), title, category, impact, effort, and the concrete fix. |
set_gap_status | ✍︎ Pro | Update one gap's status (todo / doing / done) using the gapKey + domain from list_gaps. |
list_keywords | Starter+ | Keywords with real search demand, each with the stage of the page behind it. Filter stage: "none" for demand you have written nothing for yet — the shortlist worth acting on. |
list_content_queue | Starter+ | What AutoSEO already has in flight, so you never queue a topic that is drafted or live. |
queue_article | ✍︎ Pro | Queue a keyword so AutoSEO drafts it on the next run. Re-queueing a keyword that already has a topic returns a duplicate notice, not a second copy. |
mark_article_published | ✍︎ Pro | Tell Cituna a page for a keyword is live — one you wrote yourself or published from your own CMS. Without it Cituna keeps the keyword as unwritten and offers to write a competing page. |
run_scan | ✍︎ Pro | Run a new audit for a URL and return the completed result. Takes ~1 min and consumes one scan from your monthly quota. |
gsc_status | Starter+ | Whether GSC is connected for your workspace, the connected Google email, and your verified GSC properties. |
list_brands | Starter+ | Domains tracked in your workspace — handy inputs for the audit and gsc_* tools. |
gsc_overview | Starter+ | GSC summary for a domain over the last N days: totals (clicks/impressions/CTR/position), top queries & pages, country/device splits, and a daily series. |
gsc_query | Starter+ | The flexible one. Arbitrary Search Analytics query: any dimensions, explicit date range or trailing window, row limit, and filters. |
Plans
The MCP server is included from the Starter plan ($39/mo) and up
(Starter / Pro / Max, which map to internal solo / agency / scale). There is
no free MCP — the 3-day trial is app-only, and an ended trial with no plan
can't call it.
Read / write split. On Starter the MCP is read-only: read your
audits, gaps, brands, and Search Console data all you like. The write tools — run_scan (spends a scan) and set_gap_status
(mutates your action queue) — require Pro or higher; on Starter you still run
scans and work the queue in the app, just not from Claude. Every MCP call also
counts against your plan's monthly MCP-call allowance (Starter 5k / Pro 10k / Max
30k). If a write tool returns "…is a write action — it needs the Pro/Max plan",
upgrade at https://cituna.com/pricing.
Install
No clone, no build — npx fetches it:
npx -y cituna-mcp
From source (for development):
git clone https://github.com/cituna/cituna-mcp && cd cituna-mcp
npm install && npm run build
Configure
Set CITUNA_API_URL (backend base URL, default https://cituna.com) plus
one auth option, checked in this priority order:
- Personal API key — recommended. In the app: Integrations → "Claude / MCP
access" → Generate token, copy the
cituna_sk_… value. Long-lived, revocable in
the app, and not your password. → CITUNA_API_KEY
- A session JWT. Log into the app, DevTools → Application → Cookies, copy
cituna_token. Works but expires ~30 days. → CITUNA_TOKEN
- Email + password. The server logs in and auto-refreshes on expiry.
→
CITUNA_EMAIL + CITUNA_PASSWORD
Claude Code
claude mcp add cituna --scope user \
--env CITUNA_API_KEY=cituna_sk_your_generated_key \
-- npx -y cituna-mcp
(The backend URL defaults to https://cituna.com; add --env CITUNA_API_URL=…
only to point at a different backend.)
Then in a Claude Code session: /mcp to confirm it's connected, and ask
"what changed in my AI visibility this week?"
Claude Desktop
Edit claude_desktop_config.json (Settings → Developer → Edit Config):
{
"mcpServers": {
"cituna": {
"command": "npx",
"args": ["-y", "cituna-mcp"],
"env": {
"CITUNA_API_KEY": "cituna_sk_your_generated_key"
}
}
}
}
Restart Claude Desktop. The tools appear under the 🔌 menu.
Running from source instead of npm? Use "command": "node",
"args": ["/absolute/path/to/mcp/dist/index.js"].
Built-in prompts
The server ships five reusable analysis workflows via the MCP prompts API. In
Claude they show up in the prompt/command picker; each one runs a worked recipe
over the tools, including the joins between Search Console and the engine
answers that a generic SEO tool cannot make.
why-am-i-not-cited | brand, prompt? | Classifies every uncited prompt into invisible-everywhere vs Google-visible-but-AI-invisible vs partially-cited, with evidence from the actual engine answers and GSC |
gsc-to-ai-gap | domain, days? | Queries with real Google impressions where AI never cites you: the ranked AEO target list |
competitor-teardown | brand, competitor? | Tallies who the engines actually cite from the answer text, and diffs it against your configured competitor list |
weekly-review | brand | Wins, regressions and this week's 3 actions from audits + GSC + the gap queue. Reads only |
prioritize-fixes | domain | Re-ranks the fix queue by the GSC impressions and uncited prompts each gap touches |
All five are read-only by default; none of them triggers a paid scan on its own.
You do not have to pick one from the picker: the server tells Claude which
workflow matches which kind of question, so plain English routes itself.
What it looks like
A real first conversation, once the key is set:
You: We sell scheduling software. Why does ChatGPT never mention us?
Claude: (whoami → Pro, 4 of 25 scans used · list_brands → acme.com ·
gsc_status → connected) Running the not-cited diagnosis on acme.com.
(get_visibility) You are cited in 3 of 18 prompt×engine cells. ChatGPT
answers all six of your category prompts and cites you in none of them.
(get_engine_answers on the 3 biggest) For "best scheduling software for
clinics" ChatGPT cites Calendly, Acuity and a Capterra roundup. Every citation
is a third-party list. Not one is a vendor's own site, including your rivals'.
(gsc_query) Google already sends you 1,240 impressions for that intent at
average position 8.4. So this is not an indexation problem.
The finding: you are Google-visible and AI-invisible. ChatGPT builds that
answer out of roundups you are absent from, so no amount of on-site work moves
it. The lever is getting into those lists.
(list_keywords stage:"none") "scheduling software for clinics" has demand and
no page behind it. Want me to queue it? (queue_article)
Nothing above spends a scan: it is all reads over data Cituna already collected.
Example prompts
- "How is acme.com doing in AI search today — which prompts and engines cite us?" (
get_visibility)
- "For acme.com, on the prompt best CRM for dentists, what did each engine actually say and who did they cite?" (
get_engine_answers)
- "What changed in my AI visibility this week?" (uses
list_audits → get_audit)
- "Which gaps are open for acme.com? Mark the schema one done." (
list_gaps → set_gap_status)
- "Run a fresh visibility scan for acme.com and summarise the top 3 gaps." (
run_scan)
- "Which AI engines cite us, and for which questions?" (the citation matrix from
get_audit)
- "How did example.com do in Search over the last 28 days?" (
gsc_overview)
- "Break down example.com traffic by
country, then by device." (gsc_query)
- "Show queries containing 'pricing' for example.com — filter
query contains pricing." (gsc_query)
Connecting Google Search Console
The gsc_* tools need a one-time connect in the Cituna app, not here. There
is no Google OAuth in this server, by design: the browser consent flow happens in
the app, and the resulting refresh token is stored server-side only.
- In the app, open Integrations and click Connect Google Search Console
(paid plans; the trial does not include GSC).
- Google will ask to grant Cituna read-only Search Console access
(
webmasters.readonly). Cituna never gets write access to anything Google.
- Pick the Google account where your domain is a verified Search Console
property. This is the step people miss: if the account you choose has never
verified the domain, everything connects fine and every query still comes back
empty, because Google has nothing to show that account.
- Back here, run
gsc_status. It lists the connected account and every property
it can query. If your domain is not in that list, fix it in Search Console
(verify the property), not in Cituna.
Disconnecting in the app (Integrations, Disconnect) revokes access for this
server instantly as well.
How auth reaches Google
This server never holds Google credentials. It sends your Cituna key/JWT as a
Bearer token to the backend; the backend looks up your workspace's stored GSC
refresh token, mints a short-lived Google access token, and queries the Search
Console API. Disconnecting GSC in the app instantly cuts off this server too.
Troubleshooting
No API key configured | No credential set. Generate a token (Integrations → Claude / MCP access) and set CITUNA_API_KEY. |
API key invalid, revoked, or the account no longer has access | API keys never expire — the key was revoked or mistyped, a session JWT (CITUNA_TOKEN) expired, or the account/workspace was suspended or removed. Mint a new key in the app; email/password auto-refreshes. |
…needs a Pro plan / write action | You called a write tool (run_scan / set_gap_status) on Starter or the trial, where the MCP is read-only. Run it in the app, or upgrade to Pro at https://cituna.com/pricing. |
requires a paid plan (Starter/Pro/Max) | The tool is premium-gated and your plan isn't eligible. Upgrade at https://cituna.com/pricing. |
{ "configured": false, ... } | GSC OAuth env isn't set on the backend, or you haven't connected GSC, or no property matches the domain. Follow the message. |
Rate limited (HTTP 429) | The burst/abuse ceiling — too many requests at once, or a daily hard cap. Wait the indicated seconds and retry. This is not your monthly plan quota: a used-up monthly quota comes back as a plan-limit message (HTTP 402) — upgrade or wait for the period reset. |
| Tools don't appear | Run npm run build; confirm the absolute path to dist/index.js; check the client's MCP logs. |
ECONNREFUSED | Backend isn't running / wrong CITUNA_API_URL. |
Requires Node 18.17+.
About this repository
The public cituna/cituna-mcp repo is a
published mirror, not the working tree: the server is developed in Cituna's
private monorepo and released on tag, so the tool surface and engine list stay
pinned to what the API actually serves. Pull requests against the mirror can't
be merged directly, but issues are read and acted on, so please do open them.
Looking for BI dashboards instead of a chat client? Cituna also ships a Looker
Studio connector. See cituna.com/integrations.
MIT licensed. Bugs and requests: https://github.com/cituna/cituna-mcp/issues