# MCP server

SuperDuperSEO is a remote MCP server (Streamable HTTP): **`https://app.superduperseo.com/mcp`**. An agent with it can connect a site, write and publish pages, and see how the site does in search.

## Connect

- **Claude Code:** `claude mcp add --transport http --scope user superduperseo https://app.superduperseo.com/mcp`, then `/mcp`, choose superduperseo, Authenticate.
- **Claude, ChatGPT, Cursor and other clients:** add a custom connector or MCP server with the URL `https://app.superduperseo.com/mcp` and sign in when asked.
- **Agents that run on their own:** send an account API key (https://app.superduperseo.com/settings/api) as `Authorization: Bearer sf_...`.

Sign-in is OAuth 2.1, and your client handles it. A call without credentials answers 401 with `WWW-Authenticate: Bearer resource_metadata="https://app.superduperseo.com/.well-known/oauth-protected-resource/mcp"`. Clients register themselves (RFC 7591), use PKCE (S256), and the user approves once on a consent screen. Connected apps can be removed in Settings, API.

## How to use it

- If the user skipped setup in the app, `get_setup` says what's missing (pages a day, author, topics, connection, balance) and which tool fills it. Until it's done, every answer ends with the same note.
- Start with `get_site_setup` for a site. Run `check_site` after every deploy and fix what it lists.
- Errors say what to do next (`Next: ...`).
- Tools that cost money, or change or remove something, show a preview first and act on `confirm: true`. Show the user the preview.
- Pages with search traffic cannot be removed (unpublish_post refuses them).
- At most 120 calls a minute per account.

Resources: `sds://docs/setup` (the setup guide) and `sds://{site}/posts/{slug}` (each published post as markdown). Prompt: `set_up_blog` (site, framework).

## Tools

## Set up a site

### `list_sites`: List sites

The sites in this SuperDuperSEO account: how each is served, whether it shows its pages yet (connection: waiting = the site has not read from us, reading = it has but no page is live, live, verified), its SEO check, page counts and any setup still missing (get_setup).

Read only.

No parameters.

### `create_site`: Add a site

Add a website to the account. SuperDuperSEO researches it in the background (topics, keywords, strategy). It gets 3 pages a day unless pages_per_day says otherwise; daily writing (and spend) starts once the site shows its first page and the account has balance. set_pace changes it later.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `hostname` | string | yes | The site, e.g. example.com |
| `language` | string |  | Content language, default en |
| `country` | string |  | Target country, default US |
| `pages_per_day` | integer |  | Pages a day, default 3; 0 for none |

### `get_site_setup`: How to connect a site

Everything needed to make a site read its pages, SEO tags and sitemap from SuperDuperSEO: the content API, the key variable, the starter for the framework, the route map, webhook and the current state. Start here.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `framework` | "nextjs" \\| "cloudflare" \\| "other" |  | nextjs (App Router), cloudflare (Worker or Pages, plain HTML/Vite sites), other. Default: from what the site is built with, when we detected it |

### `create_site_key`: Create a site key

A secret key the site's server code uses to read its content (shown once; store it as SUPERDUPERSEO_CONTENT_KEY in the server environment, never in code). With rotate, the old key keeps working 7 days.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `rotate` | boolean |  | Replace the current key (it keeps working 7 days) |
| `confirm` | boolean |  | Required with rotate |

### `revoke_site_key`: Revoke a site key

Stop a site key at once (the site stops getting content with it). Needs confirm:true.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `key_prefix` | string | yes | The key prefix, e.g. sds_live_ab12 |
| `confirm` | boolean |  |  |

### `add_webhook`: Add a webhook

We POST to this URL (signed) when a page is published, updated or removed, so the site can refresh it. Returns the signing secret once: store it as SUPERDUPERSEO_WEBHOOK_SECRET.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `url` | string | yes | https URL on the site, e.g. https://example.com/api/revalidate |

### `test_webhook`: Test a webhook

Send a signed test call to a webhook and report whether the site answered 2xx.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `webhook_id` | string | yes |  |

### `check_site`: Check the live site

Fetch the live site like a search engine (no JavaScript) and compare it with what SuperDuperSEO published: canonical, title, description, structured data, one h1, server rendering, robots.txt, sitemap, 404s, Search Console. Returns verified or each issue with its fix. Run after every deploy.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `get_site_status`: Site status

Whether a site shows its pages yet (connection), the last SEO check result, Search Console state and CMS, without running a new check.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `update_site`: Change site settings

The site's organisation details for search engines: its name (WebSite and Organization name, og:site_name, the feed and llms.txt), a short description, its logo, and its profiles elsewhere (X, LinkedIn, Facebook; used as sameAs). Use the name the site calls itself on its homepage. "" clears a field. Pages served by SuperDuperSEO are rebuilt at once; pages on another CMS pick it up on their next update. undo_activity puts the old details back.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `name` | string |  | The brand name, e.g. Kickmyass (not a page title) |
| `description` | string |  | One or two sentences about the site |
| `logo_url` | string |  | https:// address of a square logo, at least 512px |
| `twitter_url` | string |  |  |
| `linkedin_url` | string |  |  |
| `facebook_url` | string |  |  |

### `set_routes`: Change where pages live

Change the paths a site serves its posts, author pages and topic pages at (e.g. /blog/{slug} to /articles/{slug}). Every page that moves keeps a 301 from its old URL. Only for sites served by SuperDuperSEO. The first call shows what moves and the search traffic at stake; confirm:true applies it. Deploy the frontend for the new paths first: the SDK follows site.routes, hand-written routes need a change.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `post_path` | string |  | e.g. /blog/{slug}, /articles/{slug}, /{slug} |
| `author_path` | string |  | e.g. /blog/author/{slug} |
| `topic_path` | string |  | e.g. /blog/topic/{slug} |
| `confirm` | boolean |  |  |

### `connect_search_console`: Connect Search Console

Start Search Console verification for a site: returns the DNS TXT record to add at the domain's DNS provider. Then check_search_console.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `reissue` | boolean |  | Ask Google for a new token |

### `check_search_console`: Check Search Console verification

Ask Google whether the DNS TXT record is in place; on success the site is added to Search Console and its sitemap submitted.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `switch_site_to_cms`: Serve the site from SuperDuperSEO

Move a site onto SuperDuperSEO as its CMS (its old CMS is kept, switched off, for rollback). Dry run first by default; the real switch needs confirm:true and a verified check_site.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `dry_run` | boolean |  |  |
| `confirm` | boolean |  |  |

### `delete_site`: Delete a site

Delete a site and everything it owns: its pages stop being served at once, and its plan, voice, rules, keys, redirects and history are deleted. The balance stays. Cannot be undone. Without confirm it shows what goes; the user must say to delete it, then call with confirm:true and hostname set to the site's address exactly.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `confirm` | boolean |  |  |
| `hostname` | string |  | The site's address, typed as confirmation |

## Finish setup

### `get_setup`: What setup is missing

For each site (or one): whether its setup is done, and for anything missing (pages a day, author, topics, connection, balance) the tool that fills it. SuperDuperSEO writes nothing for a site until all five are done. Start here when the user skipped setup in the app.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string |  | The site: its hostname (example.com) or id |

### `set_author`: Set who signs the pages

Make a person the main author of a site: their name signs new pages (byline and Person structured data). Creates the author, or links one the account already has (author_id). Ask the user who it should be; usually them.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `name` | string |  | Full name, e.g. Simon Sovič. Not needed with author_id |
| `bio` | string |  | One or two sentences: who they are and why they know the topic |
| `job_title` | string |  |  |
| `url` | string |  | Their personal site or profile |
| `linkedin_url` | string |  |  |
| `twitter_url` | string |  |  |
| `image_url` | string |  |  |
| `author_id` | string |  | An author the account already has (from another site) |

### `set_voice`: Set how the site sounds

How a site's pages sound, used from the next page written: tone (plain, friendly, expert), depth (short, standard, in depth), who reads it, and the owner's own words about the voice (up to 500 characters, e.g. "Write like a practice manager who has tried every tool. Short sentences, real prices, no hype."). Send only what changes; ask the user first.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `tone` | "plain" \\| "friendly" \\| "expert" |  |  |
| `depth` | "short" \\| "standard" \\| "in depth" |  |  |
| `audience` | string |  | Who reads it, e.g. "owners and office managers of small dental clinics" |
| `words` | string |  | How it should sound, in the owner's words |

### `add_topics`: Add topics to write about

Add topics (search keywords, e.g. "how to price a saas product") to a site's queue; daily writing picks from it, best first. Topics already queued or written are skipped. suggest_topics gives ideas; agree on them with the user first. Free.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `topics` | string[] | yes |  |
| `first` | boolean |  | Write these before the rest of the queue |

### `remove_topic`: Remove a queued topic

Take a topic out of a site's queue so it is never written. Pages already written stay (unpublish_post removes those).

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `topic` | string | yes |  |

### `pin_topic`: Write a topic next

Move a queued topic to the front of a site's queue so daily writing takes it next (pinned:false puts it back in its place). add_topics with first:true adds new topics at the front.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `topic` | string | yes |  |
| `pinned` | boolean |  | Default true |

## How pages are written

### `get_plan`: How a site's pages are written

A site's voice (tone, depth, who reads it, the owner's words), its rules (always / never, with ids for update_rule), the owner's notes the writer works into pages (with ids for update_note), and its competitors. suggest_topics shows the topics queued.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `add_rule`: Add a writing rule

Something the writer must always or never do on a site, used for every page written and every refresh: either a rule in plain words (rule: "Never name a competitor in a page title") or a word swap (say: "clinic", instead_of: "practice"). fix_existing_pages:true also changes the swap on the site's pages that already exist, live ones included (undo_activity puts them back). Ask the user first.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `rule` | string |  |  |
| `say` | string |  | The words to use |
| `instead_of` | string |  | The words to replace |
| `fix_existing_pages` | boolean |  |  |

### `update_rule`: Turn a rule on, off, or remove it

on:false stops the writer following a rule from the next page (on:true brings it back); remove:true deletes it. Pages already written keep their words. Rule ids are in get_plan.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `rule_id` | string | yes |  |
| `on` | boolean |  |  |
| `remove` | boolean |  |  |

### `add_note`: Add the owner's experience

A story, number or opinion from the owner, in their words (up to 2000 characters, e.g. "Most no-shows were people who booked more than three weeks out."). The writer works it into the site's pages where the topic fits, and never invents details beyond it. draft (default true) also writes a draft page from it, which waits in the site's pages and costs nothing unless published. Only add what the user tells you.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `text` | string | yes |  |
| `draft` | boolean |  |  |

### `update_note`: Change or remove a note

Change a note's words (text), give a note without a site to this one (assign:true), or stop using it (remove:true; pages that use it keep their words). Note ids are in get_plan.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `note_id` | string | yes |  |
| `text` | string |  |  |
| `assign` | boolean |  |  |
| `remove` | boolean |  |  |

### `set_competitors`: Set who a site competes with

The sites a site competes with (up to 3 addresses, e.g. ["weave.com"]); replaces the list, [] clears it. We read their sitemap and homepage for what they write about. comparison_topics:true also queues comparison topics against each ("acme vs weave", "acme vs weave pricing"); free until a page goes live. Ask the user first.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `competitors` | string[] | yes |  |
| `comparison_topics` | boolean |  |  |

## Write and publish

### `list_posts`: List posts

A site's pages: published, drafts (with any scheduled time), failed, or all; newest first.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `status` | "published" \\| "draft" \\| "failed" \\| "all" |  |  |
| `limit` | integer |  |  |
| `offset` | integer |  |  |

### `get_post`: Get a post

One page of a site by slug. With version, an earlier version (see get_post_history). By default the body as stored, ready to edit with update_post (the byline, CTAs and footer are added when it is published); as_published:true returns the page exactly as served, with its SEO fields.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |
| `format` | "markdown" \\| "html" |  | Format of content (default markdown) |
| `as_published` | boolean |  |  |
| `version` | integer |  | Read an earlier version (get_post_history lists them) |

### `create_draft`: Create a draft

Add a draft page to a site. Either give the page yourself (title + content, markdown by default; free), or give only a keyword and SuperDuperSEO writes it with its own research, the site's voice and internal links (costs the site's page price from the balance; the first call shows the price, confirm:true writes it). Drafts are never published by this tool.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `title` | string |  | Title (H1 and SEO title) of a page you wrote |
| `content` | string |  | The body of a page you wrote (no title heading needed) |
| `format` | "markdown" \\| "html" |  | Format of content (default markdown) |
| `keyword` | string |  | The search query the page targets. Alone: we write the page |
| `slug` | string |  | URL slug (derived from the title when left out) |
| `description` | string |  | Meta description (derived from the body when left out) |
| `template` | "ARTICLE" \\| "LISTICLE" \\| "HOWTO" \\| "COMPARISON" \\| "FAQ" \\| "CASE_STUDY" \\| "COST" \\| "CHECKLIST" \\| "ROUNDUP" \\| "REVIEW" \\| "ALTERNATIVE" \\| "STATISTICS" \\| "GLOSSARY" \\| "LOCATION" \\| "SERVICE_PAGE" \\| "SAAS_PAGE" \\| "PRODUCT_PAGE" |  |  |
| `confirm` | boolean |  | Confirms the page price when we write the page |

### `update_post`: Edit a post

Change a page's title, meta description, body, slug, author or CTAs. A published page is updated on the live site at once. Changing the URL of a published page needs confirm:true (on SuperDuperSEO the old URL redirects; on another CMS it stops working, so pages with search traffic keep their URL).

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |
| `title` | string |  |  |
| `description` | string |  |  |
| `content` | string |  | The full new body (get_post returns the current one) |
| `format` | "markdown" \\| "html" |  | Format of content (default markdown) |
| `new_slug` | string |  |  |
| `author` | string |  | Author id or name, one of the site's authors |
| `suppress_ctas` | boolean |  | true: no calls to action on this page |
| `confirm` | boolean |  |  |

### `publish_post`: Publish a post

Publish a draft on its site now (a page that was live before returns to its old URL). Only hard problems block it (thin content, invalid structured data); the quality score comes back as advice.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |

### `get_post_history`: Post history

The versions of a page served by SuperDuperSEO (the last 20): when, by whom (editor, an agent, automation...) and what changed. Read one with get_post {version}; restore one with rollback_post.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |

### `rollback_post`: Restore an earlier version

Make an earlier version of a page current again (its text, title, description, feature image and author). It is published as a new version, the URL never changes, and calls to action follow the current rotation. The first call shows what changes; confirm:true restores.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |
| `version` | integer | yes |  |
| `confirm` | boolean |  |  |

### `schedule_post`: Schedule a post

Publish a draft later: at a given time (15 minutes to 30 days ahead), or without a time in the site's publishing queue, which spaces pages out.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |
| `at` | string |  | ISO 8601 time; leave out for the queue |

### `unpublish_post`: Unpublish a post

Take a page off its site (it becomes a draft). Its URL then answers 410, or 301 to redirect_to (merging it into another page). Pages with search traffic stay live. The first call shows what happens; confirm:true does it.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `slug` | string | yes | The post's slug (or its URL) |
| `redirect_to` | string |  | Path on the site or https URL the old URL should redirect to |
| `confirm` | boolean |  |  |
| `confirm_unmeasured` | boolean |  | The user accepts removing it although its search traffic cannot be measured |

### `add_redirect`: Add a redirect

On a site served by SuperDuperSEO: make a path redirect (301) to another path or https URL, or answer 410 (gone:true). Chains are collapsed. Not over a live post (use unpublish_post with redirect_to).

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `from` | string | yes | Path on the site, e.g. /old-page |
| `to` | string |  | Path on the site or https URL |
| `gone` | boolean |  | Answer 410 instead of redirecting |

### `remove_redirect`: Remove a redirect

Remove a redirect added with add_redirect. Redirects made automatically (slug changes, unpublished pages) protect old links and stay.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `from` | string | yes |  |

## Pace, publishing and balance

### `set_pace`: Set pages a day

How many pages a day SuperDuperSEO writes and publishes for a site (0 for none), paid from the prepaid balance at the site's page price. A site writes once it shows its first page and the account has balance. Raising the daily spend shows the new cost first; confirm:true applies it.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `pages_per_day` | integer | yes |  |
| `confirm` | boolean |  |  |

### `pause_site`: Pause a site

Stop daily writing for one site. Its published pages stay live; nothing is charged while paused. resume_site starts it again.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `resume_site`: Resume a site

Start daily writing again for a site paused with pause_site (or in the app). Says whether it writes today and, if not, what it waits for.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `set_publishing`: How a site publishes

How a site's pages go live: review_before_publishing (every page waits for the user), quality_floor (40-90; pages scoring under it are held, default 65), publishing hours (hours_from / hours_to, 0-23 in the account's time zone), gifs (a fitting GIF in pages), auto_refill_topics (add researched topics when the queue runs low). Send only what changes; with none it shows the current settings. Ask the user first. undo_activity reverses a change.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `review_before_publishing` | boolean |  |  |
| `quality_floor` | integer |  |  |
| `hours_from` | integer |  |  |
| `hours_to` | integer |  |  |
| `gifs` | boolean |  |  |
| `auto_refill_topics` | boolean |  |  |

### `set_adult_mode`: Adult content mode

For sites about adult products: pages go through a separate writer and checks at a different price per page, from the next page. Pages a day stay the same. Without confirm it shows both prices; tell the user, then confirm:true switches it. undo_activity switches it back.

Changes something.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `on` | boolean | yes |  |
| `confirm` | boolean |  |  |

### `get_balance`: Balance and prices

The account balance, what a page costs on each site, each site's pages a day and spend, whether it writes today (and if not, why), and how long the balance lasts. Prepaid only: every page SuperDuperSEO writes is paid from the balance, charged when it goes live (pages waiting to go live are reserved). Read only: balance is added by the user in the app; set_pace changes a site's pace.

Read only.

No parameters.

## Inbox and activity

### `get_inbox`: What needs the user

The user's inbox, the same list as the app's Home: pages waiting for approval, failed publishes, a site not connected, site check issues, missing setup, low balance, few topics left, pages held for quality, and a weekly suggestion. Each item says the tool that fixes it, or that only the user can.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string |  | The site: its hostname (example.com) or id |

### `get_activity`: What happened

What happened on the user's sites, newest first: pages published, held, refreshed, edited, linked, redirects and settings changed, with who did it (SuperDuperSEO, the user, or an agent), why, and what it cost. Events marked undoable can be reversed with undo_activity.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string |  | The site: its hostname (example.com) or id |
| `who` | "everyone" \\| "you" \\| "agent" \\| "system" |  | "you" is the user; "system" is SuperDuperSEO |
| `kind` | "published" \\| "held" \\| "refreshed" \\| "linked" \\| "redirected" \\| "settings" |  |  |
| `before` | string |  | An event id from a previous answer: events older than it |
| `limit` | integer |  |  |

### `undo_activity`: Undo something

Reverse an event from get_activity that is marked undoable: take a published page down, put it back, restore the version before an edit or refresh, set a pace back, pause or resume, move page addresses back, remove a redirect. The first call says what it will do; confirm:true does it. Pages with search traffic stay live.

Changes or removes something: shows a preview first, `confirm: true` does it.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `event_id` | string | yes |  |
| `confirm` | boolean |  |  |
| `remove_unmeasured` | boolean |  | Take a page down even though its search traffic can't be measured (Search Console not connected) |

## Insight

### `get_seo_report`: SEO report

How a site does in search: clicks, impressions, position and top pages from Search Console (last 30 days), pages nearly on page one, pages losing clicks, indexing, content health and the last live-site check.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |

### `suggest_topics`: Suggest topics

What to write next for a site: the topics already queued, the topics our research found for it (not queued yet), and with fresh:true new AI suggestions that fill gaps (each flagged when it would compete with an existing page). add_topics queues the ones the user wants. Free.

Read only.

| Parameter | Type | Required | Meaning |
|---|---|---|---|
| `site` | string | yes | The site: its hostname (example.com) or id |
| `fresh` | boolean |  | Also ask for new suggestions (up to 10 times an hour) |
| `count` | integer |  |  |
