
Each local area page used to take us half a day to create and optimize.
With SEOmatic, we can create hundreds of pages in the same time, which helps our clients make the best use of their budget.
It's transformed how we deliver scalable SEO solutions.
Will Hawkins
Marketing Director, Digi-Business UK
Agents read your Search Console data, do the work, and prove what actually moved. You decide what ships.
14-Day Trial for $1, credited to your first payment.
SEOmatic's SEO MCP server is a hosted Model Context Protocol server that exposes SEOmatic's SEO tools to any MCP client: your Search Console data, site audits, AI visibility and approval-gated fixes. Connect over OAuth 2.1, or with a workspace API key as a Bearer token. Tools are annotated read-only or acting, and in hosts that support MCP Apps (ChatGPT, Claude) key tools render interactive UI right in the conversation: file upload, live scan progress, one-click connects, approval cards, and charts.
Most SEO MCP servers only read. Here, agents stage real fixes, you approve them (approval cards render right in the chat), and approved work executes on your live site within seconds, with the full pre-edit state stored so any edit to an existing page can be rolled back. In Approval mode every change waits for your approval; autonomy settings can let small reversible fixes go ahead on their own.
Every tool description says whether it is free or bills AI credits. Reading your own data - tasks, evidence, Search Console, audits, AI visibility - is free and never triggers paid re-analysis, and get_credit_usage shows exactly where credits went.
An MCP chat stops when you close the window. SEOmatic's agents don't: diagnosis, planning, visibility scans and approved fixes run on schedule server-side. The chat is a window onto a team that is already working, and changes follow the approval rules you set.
In ChatGPT and Claude, key tools render interactive widgets (MCP Apps): upload a CSV where the protocol has no file transport, watch a scan progress live, connect Search Console with one click, approve work with a button, read a trend as a chart. Where the host cannot render them, everything degrades to plain text.
You do not call tools by hand. You ask your assistant a question in plain language, and it picks the tool. Some questions and the tool that answers each one:
| Ask your assistant | Tool it calls | Plan |
|---|---|---|
| How did my site do on Google this month? | gsc_performance (compare_periods) | Free |
| Which pages get impressions but few clicks? | gsc_insights (ctr_outliers) | Free |
| Are two of my pages competing for the same keyword? | gsc_insights (cannibalization) | Free |
| Is this page indexed, and if not, why? | gsc_indexing (inspect) | Free |
| Audit my site and rank the fixes by impact. | site_audit | Free |
| Do ChatGPT and Claude mention my brand? | get_ai_visibility | Free |
| What is the search volume and difficulty for these keywords? | keyword_research (metrics) | Paid |
| Where do I rank today for my tracked searches, city by city? | rank_tracking_read (tracked) | Paid |
| Show my new Google reviews and the replies you drafted. | business_profile (reviews) | Paid |
| Stage new titles for my pages with the worst CTR. | task_manage (create) | Paid |
Guides per assistant, with prompts to paste: Claude SEO, ChatGPT SEO, Claude Code and Cursor.
| Field | Value |
|---|---|
| Endpoint | https://app.seomatic.ai/api/mcp |
| Transport | Streamable HTTP (stateless, POST JSON-RPC 2.0) |
| Protocol | 2026-07-28 (per-request _meta, server/discover) and 2024-11-05 through 2025-11-25 (initialize) |
| Extensions | MCP Apps (widgets), Tasks (long jobs), Events (draft: webhook delivery and events/poll) |
| Fewer tools | ?tools=essentials or ?toolsets=gsc,act,events on the endpoint URL |
| Server | seomatic v1.0.0 |
| Auth | OAuth 2.1 (interactive clients) or Authorization: Bearer smk_live_... |
| OAuth token lifetime | 30 days, with a refresh token for assistant connectors |
Fastest way: let your agent do it. Copy the prompt below, paste it into whichever AI you want connected, and send it. Agents that can edit config or run commands (Claude Code, Cursor, Cline, Devin) will install the server themselves. Chat assistants (Claude, ChatGPT, Gemini) cannot edit their own settings, so they hand you the exact clicks for their app instead.
Install the SEOmatic MCP server for me.
Server: https://app.seomatic.ai/api/mcp
Transport: Streamable HTTP (stateless JSON-RPC 2.0)
Auth: OAuth 2.1 - the client discovers it automatically, no API key needed.
(Headless setups can instead send: Authorization: Bearer smk_live_...)
What to do:
1. If you can edit MCP config or run commands in this client, install it
yourself now. Reference configs:
- Claude Code: claude mcp add --transport http seomatic https://app.seomatic.ai/api/mcp
- Cursor (mcp.json):
{ "mcpServers": { "seomatic": { "url": "https://app.seomatic.ai/api/mcp" } } }
- Cline (cline_mcp_settings.json; the type is required):
{ "mcpServers": { "seomatic": { "type": "streamableHttp", "url": "https://app.seomatic.ai/api/mcp" } } }
- Devin Desktop / CLI (mcp_config.json, or: devin mcp add seomatic https://app.seomatic.ai/api/mcp):
{ "mcpServers": { "seomatic": { "url": "https://app.seomatic.ai/api/mcp" } } }
2. If you cannot, give me the exact clicks for THIS client instead
(for Claude: Customize, then Connectors, then + Add, then Add custom
connector with the URL above, and switch it on in a chat from the +
button under Connectors; for ChatGPT on the web (Business, Enterprise
or Edu for full use, read-only on Pro): Plugins, then +, then Add
custom MCP server with the URL above, OAuth, tick I understand and
want to continue, Create as a plugin, then type @ in a chat and pick
SEOmatic; for the Gemini app: Settings, then Connected Apps, then Custom apps,
then Add a custom app with the URL above. Gemini custom apps need a
personal Google account in the US; elsewhere use Gemini CLI or
Antigravity, see the docs link below).
3. Tell me to finish the OAuth login when the SEOmatic screen appears, and
to pick the site I want connected.
4. In a NEW chat, check the tools menu and confirm SEOmatic is enabled for
that conversation (in the Gemini app, type @ and pick SEOmatic). This
step is the one people miss.
5. Then prove it works by calling tools/list and running one read-only tool,
and show me what came back.
Docs if you need them: https://seomatic.ai/developers/mcpPrefer to do it by hand? Three steps, same everywhere: open your assistant's connector settings, paste the SEOmatic URL, then log in and pick your site when the SEOmatic screen appears. No API key to copy. After installing, one step people miss: in a NEW chat, open the tools menu in the message box and make sure SEOmatic is enabled for that conversation.
Two things that look like problems but are not: the consent screen asks you to log in or create a SEOmatic account (free works), and the connector is separate from any SEOmatic skill you may have installed. The skill needs the connector to reach your data.
Find your client:
Requires: Any Claude plan. Free allows one custom connector. On Team and Enterprise an Owner adds it under Organization settings.
Customize -> Connectors -> + Add -> Add custom connector Name: SEOmatic URL: https://app.seomatic.ai/api/mcp Then click Add, Connect, and approve in the SEOmatic consent screen. In a chat: + (lower left) -> Connectors -> switch SEOmatic on.
Headless? The custom connector form also takes a fixed Authorization header: Bearer smk_live_... instead of OAuth, never both.
Requires: Nothing extra.
claude mcp add --transport http seomatic https://app.seomatic.ai/api/mcp # then inside a session: /mcp -> seomatic -> Authenticate
Requires: ChatGPT Business, Enterprise or Edu for the full connector with write actions. Pro connects read-only. Plus is not listed in OpenAI's current help article. Web only.
Plugins -> + -> Add custom MCP server (ChatGPT on the web) Name: SEOmatic URL: https://app.seomatic.ai/api/mcp Auth: OAuth -> tick "I understand and want to continue" -> Create as a plugin Then approve in the SEOmatic consent screen. In a chat, type @ and pick SEOmatic.
On Business only an admin or owner can create and publish the plugin; on Enterprise and Edu an admin grants the permission first. No Developer mode is needed.
Requires: A free SEOmatic account (you can create it during sign-in). Muse is available in the US and Canada to people 18 and over.
Tell Muse: "Build a custom connector to SEOmatic. Its MCP server is https://app.seomatic.ai/api/mcp (public HTTPS, streamable HTTP). Prefer OAuth: send me the sign-in link. If you need a key, ask me through your secure credential prompt and send it as Authorization: Bearer <key>. Save a skill so SEO questions use SEOmatic first, then list my workspaces." Open the link and approve in the SEOmatic consent screen, or paste a key from Settings, AI Agents, API Keys into Muse's credential prompt.
Meta documents custom connectors through chat; if your Settings, Connectors page also offers an add-custom option, the same URL works there. Never send a key as a chat message: Muse keeps it in its secure credentials store. Meta does not review custom connectors, so Muse asks you to confirm, and it asks before anything that changes or spends.
Requires: Nothing extra. Use OAuth, not an API key.
// ~/.cursor/mcp.json (or .cursor/mcp.json in one repo),
// or Customize > MCP in the sidebar
{
"mcpServers": {
"seomatic": { "url": "https://app.seomatic.ai/api/mcp" }
}
}
# one click: cursor://anysphere.cursor-deeplink/mcp/install?name=seomatic&config=eyJ1cmwiOiJodHRwczovL2FwcC5zZW9tYXRpYy5haS9hcGkvbWNwIn0=
# Cursor CLI: agent mcp login seomaticSEOmatic advertises OAuth, and Cursor starts that sign-in before it sends any configured Authorization header, so a key here is not used. Approve the browser prompt; if the server shows a yellow dot in Customize > MCP, click Authenticate. Cloud Agents read Dashboard > Plugins & MCPs, not this file.
Requires: Nothing extra. Sign in from the server card; a key header only for headless machines.
// ~/.cline/data/settings/cline_mcp_settings.json
// (MCP Servers icon > Configure > Configure MCP Servers)
{
"mcpServers": {
"seomatic": {
"type": "streamableHttp",
"url": "https://app.seomatic.ai/api/mcp",
"disabled": false,
"autoApprove": []
}
}
}
# then click Authenticate on the seomatic card
# CLI: cline mcp add seomatic https://app.seomatic.ai/api/mcp --transport http --yesKeep "type": "streamableHttp": without it Cline falls back to legacy SSE. No browser? Add "headers": { "Authorization": "Bearer smk_live_..." } instead and skip the sign-in. One file serves the VS Code extension, the JetBrains plugin and the CLI.
Requires: Grok Bot (x.ai/bot): a paid individual Cursor plan, Cursor Teams, or a SuperGrok, SuperGrok Plus or SuperGrok Heavy subscription linked to your Cursor account. Bearer fallback: create an API key in Settings, AI Agents, API Keys.
In chat, tell your Bot: "Add a custom MCP server named SEOmatic at https://app.seomatic.ai/api/mcp (remote server, OAuth)" Confirm the card, click Authorize, sign in to SEOmatic. Type @ in chat to attach SEOmatic to a task. # Token-only? Ask the Bot to send Authorization: Bearer <key> # and hand it the key through the secure secret card, not in chat. # Manage later: composer + menu -> MCP Servers # If SEOmatic shows in Connect apps: search -> Add -> Authorize
The Bot runs in the cloud, so it only reaches public HTTPS servers. One stuck custom server can block tool discovery for all: remove it from the composer + menu -> MCP Servers. Full always-on template (instructions plus weekly routines): github.com/Minh42/seomatic-mcp/tree/main/grok-bot
Requires: Copilot enabled in VS Code. On Business or Enterprise, an admin must turn on the MCP servers in Copilot policy.
// .mcp.json at the repo root (VS Code and Copilot CLI both read it)
{
"mcpServers": {
"seomatic": {
"type": "http",
"url": "https://app.seomatic.ai/api/mcp"
}
}
}
// older VS Code-only form: .vscode/mcp.json with "servers"
# no file? Chat: Open Customizations > MCP Servers > Add Server > HTTP
# Copilot CLI: copilot mcp add --transport http seomatic https://app.seomatic.ai/api/mcp
# registry: https://github.com/mcp/ai.seomatic/seomaticStart the server from the code lens if VS Code has not already, confirm the trust prompt and sign in in the browser. Then open Configure Tools in the chat input and tick the SEOmatic tools (128 tools max per request).
Requires: A personal Google account, 18 or over, in the US, with Gemini in English and Keep Activity on. Work or school accounts, and accounts outside the US, do not see the Custom apps section yet.
Settings -> Connected Apps -> Custom apps -> Add a custom app URL: https://app.seomatic.ai/api/mcp Next -> sign in to SEOmatic and pick your site In a chat, type @ and pick SEOmatic so Gemini uses it.
The Gemini chat cannot add a server itself: pasting the setup prompt into Gemini only returns these clicks. Set it up on the web; the app then appears in the Gemini mobile app too. Outside the US or on a Workspace account, use Gemini CLI below or Antigravity (/ai-assistants/antigravity).
Requires: A Google Workspace account or a Gemini API key. Personal Google accounts moved to Antigravity.
gemini mcp add --transport http seomatic https://app.seomatic.ai/api/mcp # or as an extension (server plus SEO context in one install): gemini extensions install https://github.com/Minh42/seomatic-mcp # headless or container? use a key instead of the browser flow: gemini mcp add --transport http seomatic https://app.seomatic.ai/api/mcp \ --header "Authorization: Bearer smk_live_..."
Google retired Gemini CLI for personal (free, Pro and Ultra) accounts on June 18, 2026; Workspace and API-key users keep it, and personal accounts use Antigravity (/ai-assistants/antigravity). The OAuth flow needs a local browser and a localhost redirect, so it will not complete over SSH or inside a container. Use the Bearer form there.
Requires: A Devin account. Windsurf became Devin Desktop in June 2026; the old Cascade agent and its serverUrl key are gone.
// ~/.config/devin/mcp_config.json (or .devin/mcp_config.json in one repo)
{
"mcpServers": {
"seomatic": { "url": "https://app.seomatic.ai/api/mcp" }
}
}
# or: devin mcp add seomatic https://app.seomatic.ai/api/mcp
# Devin on the web: Customize > MCPs > Add custom MCP > HTTP > OAuth > Save > ConnectDevin prompts for the sign-in the first time it uses the server, not when you save the config. Give it a SEOmatic task, or run devin mcp login seomatic; if the server shows Needs auth, click Authenticate.
Requires: Nothing extra. Zed's agent is free with your own model key.
// settings.json -> context_servers
// (or Settings > AI > MCP Servers > Add Server > Add Remote Server)
{
"seomatic": {
"url": "https://app.seomatic.ai/api/mcp"
}
}Click Authenticate if the server asks; Zed opens the sign-in. Setting an Authorization header makes Zed skip OAuth entirely, so use one or the other. The Ask profile has MCP servers off by default; Write has them on.
Discovery follows the MCP spec: the endpoint returns 401 with a WWW-Authenticate pointing at /.well-known/oauth-protected-resource (RFC 9728), whose authorization server metadata lives at /.well-known/oauth-authorization-server (RFC 8414). PKCE (S256) is required; tokens are bound to this resource. Dynamic client registration and client-id metadata documents are both supported. Access tokens last 30 days, and assistant connectors also get a refresh token, so clients that support refresh renew without a new sign-in. After you upgrade and want the acting tools, reconnect the connector so the new token carries them. The metadata also lists the RFC 8628 device grant, which is reserved for the SEOmatic CLI.
Once connected, the server ships three ready workflows. In Claude they appear in the prompt picker (the / menu or the plus button); other clients surface them wherever they list MCP prompts. Picking one is the fastest way to get a real answer out of your own data on day one.
| Prompt | What it does |
|---|---|
seo-audit | Run a complete, data-grounded SEO audit of the connected site and rank the fixes by impact. |
striking-distance | Find the keywords the connected site is one push away from ranking on page 1 for. |
traffic-drop | Work out why organic traffic dropped, who took the clicks, and what to fix first. |
Listing and expanding a prompt costs nothing: no credits, no free questions. Only the tool calls it then makes are metered. The server also exposes two static reference documents over resources/list that an agent can attach for context: seomatic://guides/connect (how to connect Search Console, Analytics, Ads, Business Profile and a CMS) and seomatic://guides/audit-method (the audit sequence the tools are built around). Neither contains workspace data.
For headless agents and clients that take a static token, mint a workspace API key and send it as a Bearer token. This is also how the Claude Messages API connector authenticates, via its authorization_token field.
Mint it under Settings → AI Agents → API Keys. The section needs the admin role on that workspace, so if you do not see it, check which workspace is selected and whether you are an admin on it rather than a member.
{
"mcpServers": {
"seomatic": {
"url": "https://app.seomatic.ai/api/mcp",
"headers": { "Authorization": "Bearer smk_live_..." }
}
}
}Two requests prove the whole surface: list the tools your key can call, then call one. The example reads your top Search Console queries, which costs no credits (on a free workspace it uses one question). Failures come back as isError results with a plain-language reason, never opaque transport errors.
curl -s https://app.seomatic.ai/api/mcp \
-H "Authorization: Bearer smk_live_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'curl -s https://app.seomatic.ai/api/mcp \
-H "Authorization: Bearer smk_live_..." \
-H "Content-Type: application/json" \
-d '{"jsonrpc":"2.0","id":2,"method":"tools/call","params":{
"name":"gsc_performance",
"arguments":{"action":"top_queries","days":28,"limit":10}}}'Every successful call returns the payload twice: content (text, for every client) and structuredContent (a JSON object conforming to the declared outputSchema, for clients that want typed data).
| Method | What it does |
|---|---|
server/discover | 2026-07-28 clients: supported versions, capabilities (incl. the Apps, Tasks and Events extensions) and serverInfo. Answers without auth; with auth it also returns instructions for this key. |
initialize | Negotiate the protocol version and get serverInfo. Answers 200 without auth (version, capabilities, serverInfo only); with auth it also returns instructions for this key. |
tools/list | The scope-filtered tool roster this key can call. |
tools/call | Invoke a tool. Failures return as an isError result, not a transport error, so the agent can react. |
prompts/list | The starter workflows below. Free: no quota, no credits. |
prompts/get | Expand one prompt into the user message that triggers its tool flow. |
resources/list | The static guides plus the ui:// widget templates that MCP Apps hosts render. |
resources/read | Fetch one by URI. Same content for every caller: no workspace data. |
ping | Liveness check. Returns an empty result. |
notifications/initialized | Accepted and acknowledged with 202. No body, per the spec. |
events/list | Every event SEOmatic emits, with its filters (inputSchema) and data (payloadSchema). |
events/subscribe | Webhook subscription to one event: callback URL plus your whsec_ secret. The callback must echo a signed challenge first; returns id and refreshBefore. Refresh with the same arguments; send your last cursor to replay what you missed. |
events/unsubscribe | Stop a subscription, matched by event name, arguments and callback URL. Idempotent. |
events/poll | Events after a cursor (or within maxAgeMs), filtered by the event's arguments. |
tasks/get | Poll a task handle: working, completed (with the tool result), failed or cancelled. |
tasks/cancel | Ask a task to stop. Cooperative: a scan or article already running may still finish. |
The tools/listroster follows the key's scopes, with two deliberate exceptions so an agent can discover what is available. A free key also sees the acting tools, described as needing a paid plan: calling one returns the upgrade path instead of running. And while the workspace has no Search Console connection, the Search Console tools are listed as needing it: calling one returns the one-click connect link.
| Scope | Lane | Tools it unlocks |
|---|---|---|
read:gsc | Free | Direct Search Console reads. |
chat:ask | Free | All insight tools: GSC, keywords, backlinks, SERP, analytics, ads, Business Profile, datasets, templates. |
agents:act | Paid | The acting tools: SEO tasks, campaigns, bulk edits, blog authoring, skills. Works on any paid plan over MCP. |
Acting over MCP works on any paid plan; the same acting tools over the REST API require Infrastructure.
In hosts that support MCP Apps (ChatGPT and Claude), 10 tools render interactive UI directly in the conversation instead of describing what to do. Each widget exists because the protocol alone cannot do the job: MCP has no file transport, no navigation, and no way to show progress on async work. Hosts without MCP Apps support get the same tools with plain text results; nothing requires the widgets.
| Tool | What renders |
|---|---|
get_started | The site verdict and top 3 actions with their numbers, plus a one-click Search Console connect when it is missing. |
upload_csv | File picker that reads a CSV in your browser and stages it as a dataset - the file transport MCP itself lacks. |
run_ai_visibility_scan | Live scan progress that polls until results land, then renders per-engine visibility. |
generate_article | Article progress card that polls until the article is ready, with a buy button when prepaid units run out. |
connections_read | One-click connect buttons that open Search Console, Analytics, or CMS OAuth in your browser (the connect action). |
agent_settings | Explicit Confirm/Cancel when autonomy is set to 'auto' without the user's confirmation; the click is the sign-off. |
show_approval_cards | Approve/Dismiss cards for proposed tasks and campaigns - the button click is the human decision. |
show_trust_facts_card | One-tap Confirm buttons for the business facts found on your own pages - confirmed facts are the only credentials the agents may claim. |
task_manage | A confirm card before any destructive execution, showing the exact target and consequence. |
gsc_performance | An inline clicks-and-impressions trend chart when a date breakdown is returned. |
SEOmatic keeps a 30-day log of what happens in your workspace: a ranking that slipped, a fix waiting for your approval, a fix seen live on your page, AI answers gained or lost, a new Google review. Your agent can read that log, or SEOmatic can start your agent the moment it happens. The events tool lists the events, polls them and manages where they go; MCP Events clients use events/subscribe directly.
| Event | When it fires | Filters |
|---|---|---|
ranking.dropped | A query the site earns clicks on slipped in Google (Search Console average position, last 2 complete weeks against the 4 before), with the page, how much of the site's clicks it carries, who passed it when known, and the defense fix staged for approval. Checked daily for workspaces with the SEO agents on. The Rank Tracker fires it too: a tracked search that held 3 or more places below its usual place for 2 days, or left the Google Maps top 3, with its city and device. | min_positions_lost, min_click_share |
ranking.page_changed | Google now shows a different page of the site for a tracked search than the one that held it the 3 checks before: two of the site's pages compete for it. Says the search, its city and device, both pages, and the fix staged for approval when there is one. From the Rank Tracker's daily checks. | none |
review.received | A new review arrived on the connected Google Business Profile: stars, reviewer, text, and the reply SEOmatic drafted in your brand voice with its approval task. Replies to 1 to 3 star reviews always wait for a person; 4 and 5 star replies go out on their own only if you turned auto-reply on. | max_stars |
business_profile.calls_report | Every Monday: calls, direction requests and website clicks from the Google Business Profile over the last 7 days, with the week before for comparison. Google's numbers run about 2 days behind. | none |
business_profile.update_due | On your update day, when no update was drafted this week. Send a job photo with one line about the job and SEOmatic drafts the update for approval. | none |
business_profile.duplicate_found | Another Google Maps listing looks like this business. Duplicates can get a profile suspended. A flag only: nothing is changed. | none |
site_audit.completed | A deep site audit finished: health score, pages crawled, issues by severity, and how many issues are new or fixed since the previous audit. | only_with_new_issues |
task.awaiting_approval | An agent staged a fix that runs once a person approves it. | type |
task.decided | A person approved or dismissed a fix, from the dashboard, an email, Slack, a client approval link or an assistant. Says the decision and where it was made. Automatic approvals do not fire it. | type, decision |
task.completed | An approved fix finished: whether it changed the site, and whether the change was already seen live. | type |
task.live | A change SEOmatic made was seen on the live page; its effect is now measured against its own baseline. | type |
ai_visibility.scan_completed | Per-engine visibility, plus the AI answers gained and lost since the previous scan and who is cited where you were lost. | only_with_changes |
campaign.completed | Every task in a page set, content sweep or bulk edit has finished. | none |
page.published | A generated page was published to your site. | project_id |
page.publish_failed | Publishing a generated page failed, with the reason. | project_id |
| Your agent | How events reach it |
|---|---|
| ChatGPT (Work chats and dots) | Native MCP Events: ChatGPT subscribes with events/subscribe and SEOmatic posts each event to it, signed (Standard Webhooks). Ask ChatGPT to watch for an event and say what to do when it arrives. |
| Claude Code routines | Add an API trigger to a routine, then ask your agent: "send fixes waiting for approval to my Claude routine" with the routine URL and token. Each event starts a run; write the routine prompt to act on the routine-fire-payload. |
| Grok Bot routines and Cursor Automations | Give the routine a webhook trigger, then ask your agent to send events to it with the webhook URL and its crsr_ key. The event arrives as the run's JSON input. |
| Any agent on a schedule (Claude Cowork, ChatGPT Tasks, Gemini CLI, Grok) | Start the scheduled prompt with "check SEOmatic events since my last run". The events tool returns what happened since that connection last asked, so nothing is missed between runs. |
| Zapier, n8n, Make, your own code | The same events as named triggers in Zapier, Make (Watch Events) and n8n (SEOmatic Trigger), or as REST webhooks to your own code, signed with X-Seomatic-Signature (register them with the REST API, or with the events tool and kind webhook). |
MCP Events is a draft extension of the protocol (the MCP Triggers and Events working group); ChatGPT is the first client to support it. Event data carries facts and ids, never instructions: your prompt decides what happens next, and fixes still wait for your approval.
An AI visibility scan and an article take a few minutes. Clients that support the MCP Tasks extension get a task handle back and poll tasks/get until it completes; the completed task carries the same result the read tool returns. Other clients get the scan or article id and poll get_ai_visibility or get_article, as before.
Every tool definition takes room in your assistant's context before you ask anything. Add a query to the endpoint URL to load only what you use; calling a tool by name still works.
| Endpoint URL | Loads |
|---|---|
https://app.seomatic.ai/api/mcp | Every tool (the default). |
https://app.seomatic.ai/api/mcp?tools=essentials | Search Console, page checks and audits, the approval loop, cost estimates and events. |
https://app.seomatic.ai/api/mcp?toolsets=gsc,research,act | Any mix of: gsc, research, ai, site, act, analytics, strategy, data, trust, events, account. |
The server serves 60 tools: 34 consolidated outcome tools documented in this section, plus 26 single-purpose tools listed in the next one. Each consolidated tool takes an action that selects the operation. Every tool carries MCP annotations, so a client knows at a glance whether it only reads (readOnlyHint) or can stage a change. Nothing is destructive by default: acting tools stage proposals that follow your approval settings in SEOmatic. This reference is generated from the server's real catalog, so it is exactly what tools/list serves. Every tool is already scoped to the connected workspace and its site; the few tools that accept a domain default to your own site when it is omitted, and analyze a competitor when you pass one.
gsc_performanceRead-onlyFreeInteractiveGoogle Search Console performance for the connected site: clicks, impressions, CTR and position by query, page or period (data lags 2 to 3 days). Use for 'how is my site / this page / this query doing in Google'. One page's queries: dimension_breakdown with filterPage. Diagnosis (cannibalization, CTR outliers) is gsc_insights; weekly position history is rank_tracking_read.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
top_queries | top search queries | days, limit |
top_pages | top pages | days, limit |
dimension_breakdown | by device/country/date, or one page's queries (query + filterPage) / one query's pages (page + filterQuery) | dimension*, days, filterQuery, filterPage, limit |
query_page_matrix | cannibalization / query-to-page map | days, maxRows |
query_pages | which pages rank for given queries, with each page's own numbers | queries*, page, days |
compare_periods | decay/growth vs the prior period | dimension, days, limit |
trend | daily clicks/impressions over time | days |
discover_news | Discover / News / Image / Video surfaces | surface, days |
folder_rollup | performance by URL folder / site section | days, depth |
fresh | provisional today/yesterday numbers (hours-old data) | none |
custom_query | flexible query: 1-3 dimensions, regex/exclusion filters, search type, fresh data, dates, paging to 25,000 rows | dimensions, filters, searchType, dataState, startDate, endDate, days, rowLimit, startRow, aggregationType |
days (number) Look-back window in days (defaults ~28). 1-90 for most actions; 7-90 for trend; custom_query up to 486 (about 16 months).limit (number) Row cap. top_queries/top_pages/dimension_breakdown default 50; compare_periods rows per period default 500. Ignored by query_page_matrix (use maxRows), trend and custom_query (use rowLimit).dimension (string) REQUIRED for dimension_breakdown: device|country|date|query|page (query + filterPage = the queries one page ranks for, with that page's own numbers; page + filterQuery = the pages ranking for one query). For compare_periods: query|page (default page). Ignored otherwise. One of: device, country, date, query, page.filterQuery (string) dimension_breakdown only: restrict to one exact query (pair with dimension=page to see which pages rank for it).filterPage (string) dimension_breakdown only: restrict to one exact page URL, as Search Console records it (pair with dimension=query to see the queries that page ranks for).maxRows (number) query_page_matrix only: max query-page pairs (100-1000, default 200).queries (array) REQUIRED for query_pages: 1-5 exact search queries. Page rows are that page's own numbers; queryTotal is site-wide and never a page's number.page (string) query_pages only: a full page URL to check - returns its own row for each query, or null when it does not rank.surface (string) discover_news only: which surface (default discover). One of: discover, news, image, video.depth (number) folder_rollup only: path depth to group by (1-3, default 1).dimensions (array) custom_query only: 1-3 dimensions to group by (default query).filters (array) custom_query only: filters applied together (AND). Regex is RE2 (no lookarounds). Country is a 3-letter code (usa); device is DESKTOP, MOBILE or TABLET.searchType (string) custom_query only: which search results (default web). Discover and googleNews report no queries. One of: web, image, video, news, discover, googleNews.dataState (string) custom_query only: final (default) or all (adds fresh data from the last 2-3 days, which can still change). One of: final, all.startDate (string) custom_query only: YYYY-MM-DD, with endDate (overrides days).endDate (string) custom_query only: YYYY-MM-DD, with startDate.rowLimit (integer) custom_query only: rows per page (1-25,000, default 1,000).startRow (integer) custom_query only: zero-based row offset; pass the nextStartRow a previous answer gave.aggregationType (string) custom_query only: auto (default), byPage or byProperty (not with the page dimension or a page filter). One of: auto, byPage, byProperty.gsc_indexingRead-onlyFreeIs a URL in Google's index, and why not (coverage, crawl, robots, canonical). Use this for any 'is this page indexed' question; batch_inspect takes up to 50 URLs. To get a page indexed, follow next_step in the result (stage an index_request with task_manage). Google cannot be made to crawl a normal page: never promise it.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
inspect | one URL, full diagnostics | url* |
batch_inspect | many URLs, summary each | urls* |
url (string) inspect only: the fully-qualified URL to inspect.urls (array) batch_inspect only: the URLs to inspect.gsc_insightsRead-onlyFreeDiagnoses over the site's Search Console history: cannibalization, brand vs non-brand, CTR outliers (pages under-earning their position), rich results, seasonality, sitemap health. Use to find what to fix; raw numbers are gsc_performance.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
cannibalization | queries split across competing pages | days, minImpressions |
brand_split | brand vs non-brand performance | days, brandTerms |
ctr_outliers | pages under-earning their position (title/meta candidates) | days, minImpressions |
search_appearance | rich results / enhanced appearance breakdown | days |
seasonality | 16-month YoY verdict: real change vs seasonal dip | none |
sitemaps | sitemap errors, warnings, pending, staleness | none |
days (number) Look-back window in days (7-90, default 28).minImpressions (number) cannibalization/ctr_outliers: minimum impression volume to judge (defaults 100/200).brandTerms (array) brand_split only: brand words/variants, lowercase. Defaults to the domain name.rank_trackingCan stage changesBills AI creditsThe Rank Tracker: track searches daily from a city on mobile/desktop (track, quoted first, confirm: true after the user's yes), stop tracking (untrack, deletes history: confirm: true), run a city grid for one tracked search (grid, billed: quoted first, confirm: true after the user's yes), ranking alerts (alerts); also a blog project's keyword list (add_keywords, remove_keywords). Reads, including the latest grid (grid_latest), are rank_tracking_read.
Cost: reads are FREE (stored data), grid_latest included. track adds daily checks paid from the AI credit pool at vendor cost (about 350 to 550 credits a check): it quotes the monthly credits and saves only with confirm: true. grid bills one run from the AI credit pool (200 credits a point plus 700 to place the business: about 2,500 for 3x3, 5,700 for 5x5, 10,500 for 7x7): without confirm it only returns the latest grid and the quote. untrack, add_keywords and remove_keywords are FREE configuration changes.
| Action | What it does | Parameters |
|---|---|---|
history | weekly position per query (target terms by default), up to 52 weeks | queries, weeks |
movers | biggest position gains and losses between two weeks | dimension, fromWeek, toWeek, minImpressions, limit |
serp_history | who held the top 10 each week for one of the site's own queries, and competitor title changes | query*, weeks |
tracked | daily positions of the tracked searches, Google Maps top 3, AI Overview, what moved and the staged fix | city, service |
suggest | searches worth tracking, from the site's own data | none |
trackstages | track searches daily from a city (quotes the monthly credits; confirm: true after the yes) | keywords*, city, devices, service, confirm |
untrackstages | stop tracking searches (history deleted; confirm: true) | searchIds*, confirm, confirmDestructive |
gridstages | run a city grid: the business's Google Maps place across a square around it (bills about 2,500 to 10,500 credits; without confirm: latest + quote; confirm: true runs one) | searchId*, size, confirm |
grid_latest | the latest city grid for one tracked search (stored, free) | searchId* |
alertsstages | ranking alerts: smart or custom thresholds, same day / weekly / off | alertsMode, cadence, dropPositions, holdDays, mapsExit, groupMovePct |
add_keywordsstages | add up to 100 keywords to a blog project (plan-capped per call; a refusal states the cap) | projectId*, keywords*, locationCode, languageCode |
remove_keywordsstages | remove keywords from a blog project by id, or all of them (confirm: true after the user's yes) | projectId*, keywordIds, all, confirm, confirmDestructive |
projectId (string) add_keywords/remove_keywords (required): the blog project id (dataset_library list_page_projects lists projects with their type; posts = blog).keywords (array) add_keywords (required): 1 to 100 keywords for the blog project; a duplicate refuses the call. track (required): 1 to 100 searches to check daily.city (string) track: where customers search from ("Georgetown, TX", "Lyon"); omit for the whole country. tracked: only searches from this city.devices (array) track: mobile and/or desktop (default mobile; desktop doubles the credits).service (string) track: a service group, so a whole service moving shows as one alert. tracked: only this group.searchIds (array) untrack (required): tracked search ids from tracked.searchId (string) grid / grid_latest (required): one tracked search id from tracked.size (integer) grid: 3, 5 or 7 points a side (default 5).alertsMode (string) alerts: smart defaults or custom numbers. One of: smart, custom.cadence (string) alerts: when alerts are sent (off still stages the fixes). One of: same_day, weekly, off.dropPositions (integer) alerts (custom): places lost before it counts (1-20).holdDays (integer) alerts (custom): days the drop must hold (1-7).mapsExit (boolean) alerts (custom): alert when a search leaves the Google Maps top 3.groupMovePct (integer) alerts (custom): % of a service moving together that alerts (10-100).keywordIds (array) remove_keywords: the keyword ids to remove (1 to 100). Pass this or all: true.all (boolean) remove_keywords: true removes every keyword of the project.confirm (boolean) remove_keywords / untrack (required true): the user explicitly asked to remove exactly these (untrack deletes their history). track: true only after the user saw the quoted monthly credits and said yes. grid: true only after the user saw the quoted credits for one grid run and said yes; without it grid only returns the latest grid and the quote. Never set it on your own judgment.confirmDestructive (boolean) remove_keywords / untrack: the same attestation, as the confirm widget and the elicitation retry send it. Not used by grid (grid takes confirm).locationCode (integer) add_keywords: locale location code (default: the workspace market).languageCode (string) add_keywords: two-letter language code (default: the workspace market).queries (array) history only: up to 20 exact queries. Omit for the target terms (or the top 10 queries by impressions when none are set).weeks (integer) history/serp_history: complete weeks back (2-52, default 12).dimension (string) movers only: compare queries (default) or pages. One of: query, page.fromWeek (string) movers only: earlier week, any date in it (YYYY-MM-DD). Default: the week before toWeek.toWeek (string) movers only: later week, any date in it (YYYY-MM-DD). Default: the latest complete stored week.minImpressions (integer) movers only: minimum impressions in BOTH weeks for a move to count (default 20).limit (integer) movers only: rows per list (1-50, default 15).query (string) serp_history only (required): a target term or a query from the site's Search Console history.keyword_researchRead-onlyBills AI creditsKeyword demand: volume, difficulty, CPC, intent, ideas, Google Trends and Google Ads keyword data, from a live vendor (never invented; a gap is said plainly). Use to decide what to target; who ranks today is serp_competitors.
Cost: metrics and suggestions bill AI credits (live vendor data at actual cost); trends, related_queries, compare and performance are FREE (Google Trends / your connected Google Ads).
| Action | What it does | Parameters |
|---|---|---|
metrics | volume/difficulty/CPC/intent | keywords* |
suggestions | keyword ideas from seeds | keywords*, limit |
compare_trends | Trends interest, keywords side by side | keywords* |
trend | Trends interest over time for one keyword | keyword* |
related | Trends related queries | keyword* |
ads_performance | Google Ads keyword performance | days, limit |
keywords (array) metrics/suggestions/compare_trends: the seed or target keywords.keyword (string) trend/related: the single keyword to analyze.days (number) ads_performance: look-back window in days.limit (number) suggestions/ads_performance: max results.keyword_clustersRead-onlyFreeThe site's stored keyword-cluster map from its Search Console queries (pillar, cannibalization, gap, covered). Use for topic structure; live demand is keyword_research.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
list | none |
backlink_profileRead-onlyBills AI creditsBacklinks of the site or any competitor: referring domains, anchors, velocity, links gained or lost, link prospects. Use for authority and link questions.
Cost: bills AI credits per call (live vendor data at actual cost); reads of your own stored data elsewhere are free.
| Action | What it does | Parameters |
|---|---|---|
summary | totals, referring domains, rank/spam | domain |
anchors | anchor-text distribution | domain, limit |
velocity | monthly new vs lost referring domains | domain, months |
referring_domains | top linking domains | domain, limit |
new_lost_links | the individual links gained or lost since a date | domain, status, since, perDomain, limit |
link_prospects | link intersect: linking to competitors but not to us | competitors*, limit |
domain (string) The domain to analyze, e.g. "example.com". Omit it to analyze the connected workspace's own site (the server fills it in); pass it only to analyze a competitor.limit (number) anchors (default 25), referring_domains (default 50), new_lost_links (1-500, default 100).months (number) velocity only: months back (default 6).status (string) new_lost_links only: new (default) or lost links. One of: new, lost.since (string) new_lost_links only: YYYY-MM-DD, default 30 days ago.perDomain (boolean) new_lost_links only: true = one link per referring domain.competitors (array) link_prospects only: 1-3 competitor domains to intersect against.serp_competitorsRead-onlyBills AI creditsThe live search results landscape: SERP features for a keyword, a domain's rankings and visibility, its competitors and top pages. Use for who ranks and why.
Cost: bills AI credits per call (live vendor data at actual cost); reads of your own stored data elsewhere are free.
| Action | What it does | Parameters |
|---|---|---|
features | which SERP features appear for a keyword | keywords* |
domain_rankings | top keywords a domain ranks for | domain, limit |
domain_overview | organic visibility distribution | domain |
domain_competitors | domains ranking for similar keywords | domain, limit |
top_pages | a domain's top pages by estimated organic traffic | domain, limit |
keywords (array) features only: the keyword(s) to inspect.domain (string) domain_rankings/domain_overview/domain_competitors/top_pages: the domain. Omit for the connected workspace's own site (the server fills it in); pass only for a competitor.limit (number) max results where applicable (top_pages 1-500, default 50).ai_citationsRead-onlyFreeHow AI engines cite this site: citations seen in real logged-in AI answers (observed_citations), the brand facts the site publishes for AI (brand_facts), and the latest AI-visibility scan (scan_results: where the brand was missed and who won). Use for AI search visibility questions.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
observed_citations | real logged-in AI answers that cited this site | days |
brand_facts | declared canonical facts + internal-link health | none |
scan_results | latest scan: per-engine visibility, missed prompts, competitors, cited sources | scanId |
days (number) look-back window in days (1-90, default 28).scanId (string) scan_results only: a specific scan id from recentScans. Omit for the latest completed scan.traffic_analyticsRead-onlyFreeGoogle Analytics 4 traffic and Google Ads performance: overview, sources, landing pages, any GA4 report, realtime, key events (conversions), Ads campaigns and search terms, plus AI-referred visits per page. Each action names a missing connection instead of returning empty data. Search clicks are gsc_performance.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
overview | GA4 sessions/users/pageviews/bounce | days |
sources | GA4 sessions by channel | days |
landing_pages | GA4 top entry pages | days, limit |
top_pages | GA4 most-viewed pages | days, limit |
ads_account | Google Ads account totals | days |
ad_campaigns | Google Ads campaign performance | days, limit |
ads_search_terms | actual search terms that triggered Ads | days, limit |
ai_pages | first-party AI engagement per page: crawler fetches + AI-referred visits | days, limit |
ga4_report | custom GA4 report: up to 9 dimensions and 10 metrics by API name, date ranges, filters, ordering | dimensions, metrics*, dateRanges, days, filters, orderBys, limit, offset |
realtime | GA4 activity in the last 30 minutes | dimensions, metrics, filters, limit |
key_events | GA4 key events (conversions) by landing page, source or channel | by, eventName, days, limit |
days (number) look-back window in days.limit (number) max rows where applicable (ga4_report up to 10,000).dimensions (array) ga4_report (0-9) / realtime (0-4): GA4 dimension API names, e.g. sessionDefaultChannelGroup, landingPage, pagePath, deviceCategory, country, customEvent:<parameter>. Realtime default unifiedScreenName.metrics (array) ga4_report (required, 1-10) / realtime: GA4 metric API names, e.g. sessions, totalUsers, engagementRate, keyEvents, totalRevenue. Realtime default activeUsers.dateRanges (array) ga4_report only: up to 4 ranges; dates are YYYY-MM-DD, today, yesterday or NdaysAgo. Overrides days.filters (array) ga4_report/realtime: dimension filters applied together: field + value (matchType default exact) or values (in-list); not:true excludes matches.orderBys (array) ga4_report only: sort by requested metrics or dimensions (default first metric, descending).offset (integer) ga4_report only: row offset for paging (use nextOffset).by (string) key_events only: group by landing page (default), source / medium, or channel. One of: landing_page, source, channel.eventName (string) key_events only: one key event name (e.g. purchase, generate_lead); omit for all.local_presenceRead-onlyBills AI creditsLocal search presence: Business Profile locations, local rankings for money keywords, reviews. Use for map-pack and local questions.
Cost: list_locations and reviews read your connected Business Profile and are FREE; visibility bills AI credits (live local SERP data at actual cost).
| Action | What it does | Parameters |
|---|---|---|
list_locations | GBP locations on the account | none |
visibility | local organic position for keywords | keywords* |
reviews | average rating + review count | location* |
keywords (array) visibility only: the money keywords to measure.location (string) reviews only: the Business Profile location id.business_profileRead-onlyFreeThe Google Business Profile, read-only: calls, direction requests and website clicks with the agent's changes, the Google Maps top 3 vs the businesses above, category advice, Ask Maps readiness, duplicates (overview); reviews with drafted replies (reviews); completeness, edits waiting and updates (updates); the review link (review_link); drafted Ask Maps answers (ask_maps).
Cost: FREE. Stored data synced daily from Google; never calls Google per question.
| Action | What it does | Parameters |
|---|---|---|
overview | calls and checks, last 30 days vs the 30 before | location |
reviews | reviews with drafted replies, unhappy first | location, filter |
updates | completeness, edits waiting, this week's update, published ones (Google gives no views per update) | location |
review_link | the link to ask every customer for a review | location |
ask_maps | Ask Maps answers drafted from the site and profile, each with its question | location |
location (string) A listing ("locations/456"); omit for all listings.filter (string) reviews only: which reviews (default needs_reply). One of: needs_reply, replied, all.business_profile_manageCan stage changesBills AI creditsStage Google Business Profile work as approval cards (never published directly; approve with task_manage decide): this week's update from a job note and photo (draft_update), a review reply (redraft_reply), a profile edit (propose_edit; name, address and primary category only with confirm: true after the user asked for exactly that), settings (auto-reply to 4-5 star reviews, off by default), review requests by email to the customers the user lists (send_review_requests: preview, then confirm: true), a refresh from Google now with the Google Maps comparison (refresh: quote, then confirm: true). With several listings and none named, an action answers chooseListing: ask the user which one.
Cost: draft_update and redraft_reply bill a small AI credit charge for the draft; refresh bills about 700 credits per listing, up to 4,700 per listing (quoted first, runs only with confirm: true); propose_edit, settings and send_review_requests are FREE.
| Action | What it does | Parameters |
|---|---|---|
draft_updatestages | draft this week's update for approval | note*, photoUrl, location |
redraft_replystages | draft the reply to one review for approval | reviewId* |
propose_editstages | stage a profile edit (high-risk fields need confirm: true); returns taskId for task_manage decide | field*, proposed*, reason*, location, confirm, answers |
send_review_requestsstages | email the Google review link to listed customers (preview without confirm; send with confirm: true after a yes) | emails*, location, confirm |
refreshstages | sync from Google now with the Google Maps comparison (quote without confirm; runs with confirm: true) | confirm |
settingsstages | auto-reply (4-5 star, confirm: true), review alerts, update day | autoReplyPositive, reviewAlerts, updateDay, confirm |
note (string) draft_update (required): one line about the job, what and where.photoUrl (string) draft_update: a public URL of the job photo (JPG or PNG).location (string) A listing ("locations/456" or its name). Required when the workspace has several listings: without it the action answers chooseListing.reviewId (string) redraft_reply (required): from business_profile reviews.field (string) propose_edit (required): the profile field. special_hours = holiday hours, one day per line (2026-12-24 closed, or 2026-12-31 09:00-14:00). One of: description, services, service_area, hours, special_hours, additional_categories, title, address, primary_category.proposed (object) propose_edit (required): the new value, text or a list (services, cities, categories).reason (string) propose_edit (required): why, in one or two sentences.emails (object) send_review_requests (required): customer emails, one per entry or line ("jane@example.com" or "jane@example.com, Jane"). Up to 20.answers (array) propose_edit (field description): Ask Maps answers from business_profile ask_maps, added to the description, each kept with its question.confirm (boolean) propose_edit (title, address, primary_category) / settings (autoReplyPositive true) / send_review_requests (sends the emails) / refresh (spends the quoted credits): only after the user explicitly asked for exactly this. Never on your own judgment.autoReplyPositive (boolean) settings: send 4-5 star replies without asking.reviewAlerts (boolean) settings: emails about new reviews (reply approval cards still reach the board and Slack).updateDay (integer) settings: weekday of the update reminder (0 Sunday ... 6 Saturday).visibility_manageCan stage changesBills AI creditsChange the AI-visibility monitor: create it (scans bill credits: confirm: true after the user agreed to the quoted cost), add, edit or remove tracked prompts, set cadence and engines (spend levers, only on the user's ask). Reading the monitor and crawler setup is visibility_manage_read; results are ai_citations.
Cost: all actions are FREE config changes; create_monitor starts scans that bill credits (it quotes the per-scan cost first), each ACTIVE prompt raises the recurring scan cost when scans run, cadence 'daily' is ~7x weekly spend, and each tracked engine adds its per-question cost - disclose before setting.
| Action | What it does | Parameters |
|---|---|---|
create_monitorstages | set up the monitor when there is none (quotes the per-scan cost; confirm: true) | domain, cadence, engines, locationCode, languageCode, confirm, confirmDestructive |
crawler_setup | AI-crawler tracking endpoint + Cloudflare Worker code (admin or owner) | none |
list | tracked prompts + plan allowance + cadence | locationCode, languageCode |
addstages | track a new buyer question (plan-capped) | prompt*, locationCode, languageCode |
updatestages | rename / pin / (de)activate a prompt | promptId*, text, pinned, active |
removestages | delete a prompt permanently (confirm: true after the user's yes) | promptId*, confirm, confirmDestructive |
set_cadencestages | weekly / daily / manual - daily is ~7x spend, explicit user ask only | cadence*, locationCode, languageCode |
set_enginesstages | choose tracked AI engines (full list) or reset to defaults - each engine adds scan cost, quote it first | engines, reset, locationCode, languageCode |
domain (string) create_monitor: the site to monitor; default: this workspace's own site.confirm (boolean) create_monitor: true only after the user agreed to the per-scan cost it quoted; remove: true only after the user said yes to deleting the prompt. Never on your own judgment.confirmDestructive (boolean) create_monitor and remove: the same attestation as confirm, as the elicitation retry carries it.prompt (string) add: the buyer question to track, in the customer voice.promptId (string) update/remove: the prompt id from list.text (string) update: new prompt wording.pinned (boolean) update: pin the prompt.active (boolean) update: false pauses scanning (keeps history), true re-activates (re-checks the plan cap).cadence (string) set_cadence / create_monitor: how often scans run. 'daily' ~7x weekly spend. One of: weekly, daily, manual.engines (array) set_engines / create_monitor: the FULL list of engine ids to track (see list for ids and per-engine cost).reset (boolean) set_engines: true tracks the default engines.locationCode (integer) Locale location code (default: primary monitor).languageCode (string) Locale language code, e.g. "en".site_pagesRead-onlyFreePage-level analysis of the live site: on-page SEO score and issues for a URL, crawl metadata, PageSpeed (lab and field), structured-data validation, and the stored page inventory. Use to diagnose a page before proposing a fix.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
score_draft | score a pasted DRAFT pre-publish (deterministic, free) | content*, contentType |
analyze | SEO score + critical issues | url* |
crawl | title/meta/headings/links | url* |
inventory | the user's real synced pages | limit |
pagespeed | Google PageSpeed now: lab metrics (score, LCP, CLS, TBT) and real-user field data (LCP, INP, CLS) | url*, strategy |
validate_schema | structured data vs Google rich-result rules: parse errors, missing required/recommended, wrong types (URL or pasted JSON-LD) | url, jsonld |
content (string) score_draft: the draft HTML or plain text/markdown.contentType (string) score_draft: guide|tutorial|listicle|review|roundup|comparison|case_study|research|opinion (default guide).url (string) analyze/crawl/pagespeed: the URL to inspect. validate_schema: the page to fetch (or pass jsonld instead).strategy (string) pagespeed only: mobile (default) or desktop. One of: mobile, desktop.jsonld (string) validate_schema only: raw JSON-LD (a JSON document or <script type="application/ld+json"> blocks) to validate instead of a URL.limit (integer) inventory only: max pages to return.dataset_libraryRead-onlyFreeRead the dataset library and page templates behind programmatic pages (datasets, sample rows, templates). Editing is dataset_manage.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
find_page_set_patterns | keyword research for a page set: the repeated query templates with a varying slot, entities ranked by demand (a seed term adds the keyword provider and costs credits) | seed, minEntities |
list_datasets | available datasets | none |
dataset_rows | sample rows from one dataset | datasetId*, limit |
list_templates | built-in page templates | none |
get_template | one template in full | templateId* |
seed (string) find_page_set_patterns: a head term to research with the keyword provider ('signage'); omit for Search Console only.minEntities (integer) find_page_set_patterns: smallest set worth showing (default 5).datasetId (string) dataset_rows only: the dataset to sample.templateId (string) get_template only: the template to read.limit (integer) dataset_rows only: how many rows to sample.strategy_insightsRead-onlyFreeThe agent's own diagnosis for this site: snapshot, current strategy, raw signals, AI-search content scores, the monthly client report and proof links. Use to explain what the agent sees and plans.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
snapshot | compact brief of cached signals | none |
strategy | themes + ranked big plays | none |
signal | one cached signal in full | signal* |
content_scores | AI-search scores for generated articles | none |
client_report | the monthly client report: summary, search detail or work history | view, month |
proof_links | the proof certificate links (search or AI); admin or owner | kind |
signal (string) signal only: which cached signal to read (e.g. index_coverage, backlink_profile).view (string) client_report only: summary (default), search detail, or work history. One of: summary, search, work.month (string) client_report only: YYYY-MM (default the latest month).kind (string) proof_links only: which certificate (default search). One of: search, ai.task_manageCan stage changesBills AI creditsInteractiveAct on the task board: stage proposals (create, up to 5; nothing runs), approve or dismiss them (decide, decide_batch), run an approved task (execute), undo live changes (rollback, undo_all), and the related site changes. Every decision is the user's: never approve, confirm or undo on your own judgment. Reading tasks is the tasks tool.
Cost: every action but preview is FREE to call (preview drafts with AI credits: the estimate first, confirm: true); approved work (decide, decide_batch, execute) bills AI credits when it runs (a title/meta/H1 fix is typically a few hundred credits). rollback, undo_all and apply_site_change change the live site. Inspecting tasks never triggers re-analysis.
| Action | What it does | Parameters |
|---|---|---|
list | the plan board (filterable) | status, type |
get | one task in full detail | taskId* |
createstages | stage up to 5 task proposals | tasks* |
savestages | free plan: save one fix the person asked for, waiting for their approval (nothing changes on the site) | type*, targetKey*, title*, rationale*, change*, queries |
decidestages | approve or dismiss a staged proposal (the approval loop) | taskId*, decision*, confirmDestructive |
executestages | run an approved task now; a staged hold (first rewrite, protected page) is released by the user's own confirmation, which SEOmatic asks for; refresh_pull_request updates an open GitHub pull request, or opens a new one if someone else changed its branch | taskId*, reviewToken, confirmDestructive, refresh_pull_request |
rollbackstages | undo an executed task's live change (drift-guarded) | taskId*, force |
paste_donestages | the user pasted a handed-over change; SEOmatic looks for it on the live page before measuring | taskId* |
decide_batchstages | approve or dismiss up to 50 staged tasks in one call, same rails as decide; skipped ids come back with a reason | taskIds*, decision*, confirmDestructive |
undo_allstages | undo EVERYTHING the agent has live, a few per call (confirm: true after the user's explicit ask; admin only) | confirm*, confirmDestructive, force |
donestages | the user made the change themselves; the task moves into measurement | taskId*, suggestion |
to_campaignstages | hand a proposed content sweep to the Agent campaigns (the direct task is dismissed) | taskId* |
dismiss_reasonstages | record why the user dismissed a task (closed set) | taskId*, reason* |
apply_site_changestages | apply a staged redirect, robots.txt or prune change the user saw (get's siteChange.shownHash, confirm: true; admin only) | taskId*, shownHash, confirm, confirmDestructive |
resolve_site_changestages | resolve an earlier site change whose undo was never confirmed: undo it (confirm: true after the user's yes), or record the admin's 'I resolved it' | taskId*, mode*, confirm, confirmDestructive |
protected_pages | the money pages the agent never writes unattended | none |
protect_pagesstages | add, remove or replace the protected pages (admin or owner; removing a URL needs confirm: true) | pagesMode, pages*, confirm, confirmDestructive |
suggest_protected_pages | money pages to protect, suggested from converting Google Ads landing pages | none |
previewstages | draft the exact change of a proposed snippet task before approving (estimate, then confirm: true) | taskId*, confirm, confirmDestructive |
pagesMode (string) protect_pages only: add (default), remove, or replace the whole list. One of: add, remove, replace.pages (array) protect_pages only: full URLs on the site or /path/* prefixes, each with an optional reason (max 200).status (string) list only: filter by task status (proposed, approved, ...).type (string) list: filter by task type. save (required): the fix type, e.g. ctr_fix.targetKey (string) save only (required): the full URL of the page.title (string) save only (required): the goal in plain words.rationale (string) save only (required): why the fix is worth doing.change (string) save only (required): the exact change in plain words, as the person will read it.queries (array) save only: Search Console queries the fix is for.taskId (string) Every single-task action: the task to act on.taskIds (array) decide_batch only (required): up to 50 task ids; more come back skipped over_limit.confirm (boolean) undo_all and apply_site_change: must be true, attesting the user explicitly asked for this exact action in this conversation. preview: true after the user agreed to the credit estimate. Never set it on your own judgment.suggestion (string) done only: what the user applied (e.g. the new title), kept for the verification report.reason (string) dismiss_reason only (required): why the user dismissed it. One of: wrong_page, not_priority, avoid_topic, felt_risky.shownHash (string) apply_site_change only (required): siteChange.shownHash from get, the hash of the change the user saw; a mismatch is refused.mode (string) resolve_site_change only (required): undo removes the change if still ours; confirm_resolved records the admin's own resolution. One of: undo, confirm_resolved.decision (string) decide/decide_batch: approve releases the task(s) to the gated pipeline; dismiss archives. Approving is confirmed by the USER through the question SEOmatic asks them (or the approveUrl the refusal gives); you cannot confirm for them. One of: approve, dismiss.confirmDestructive (boolean) preview: the same attestation as confirm. decide/decide_batch/execute: the attestation for indexation-destructive types (noindex, redirect). On this surface it is not yours to set: SEOmatic asks the user and verifies their answer itself; a value you set completes nothing.reviewToken (string) execute only, dashboard path. Not given to an assistant: a staged hold (first rewrite / money page) is released by the user's own confirmation, which SEOmatic asks for when execute is called.refresh_pull_request (boolean) execute only, GitHub: rewrite the task's OPEN pull request against the site's latest version (the dashboard's Refresh): updates the pull request, or opens a new one if someone else changed its branch. Runs the task again, so it uses AI credits like the first run - set it ONLY when the user asked for the refresh.force (boolean) rollback/undo_all: undo even though the live page drifted from what the agent wrote (undo_all lists the skipped pages first). Set ONLY after the user explicitly confirmed overwriting their newer edit.tasks (array) create only: up to 5 task objects to stage as proposals (see the SEOmatic docs for the task shape).slack_settingsCan stage changesFreeSlack notifications for this site: connection, card mode, weekly report, the channel it posts to; change them or get the install link. Organization owner only.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
get | connection, card mode, switches and the channel this site uses | none |
setstages | change cardMode (each | digest), weeklyReport, mentionsEnabled | cardMode, weeklyReport, mentionsEnabled |
channels | the channels SEOmatic can post to | none |
set_channelstages | route this site (or the default) to a channel; null = default | channelId*, forAllSites |
install | the Slack app install link (browser step) | none |
cardMode (string) set: each = one card per decision; digest = one message per burst. One of: each, digest.weeklyReport (boolean) set: post the weekly SEO report in Slack.mentionsEnabled (boolean) set: allow @mentions on urgent cards (at most once per 6 hours per person).channelId (stringnull) set_channel: a channel id from channels, or null to use the default channel again.forAllSites (boolean) set_channel: true = make it the organization's default channel for every site without its own.workspacesRead-onlyFreeThe workspaces (sites) the user can open: list them, the steps to switch this connection to another one, and white-label clients. Creating or renaming is workspaces_manage.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
list | every workspace the user can access, with plan and site | none |
switch | the connect steps for another workspace | workspace* |
clients | this site's clients, pending invitations, allowance and report cadence | none |
workspace (string) switch (required): the workspace id, name or site host from list.workspaces_manageCan stage changesFreeCreate or rename a workspace, and manage white-label clients (invite, allowance, reports), each after the user confirms. Deleting a workspace stays in Settings. Admins and the owner.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
createstages | create a workspace within the plan limit, after the user confirms | name*, confirm |
renamestages | rename this or another workspace, after the user confirms | name*, workspace, confirm |
invite_clientstages | invite a client by email under the agency brand, after the user confirms | email*, access, role, confirm |
revoke_client | who would lose access, and the White-label tab link to revoke it | client* |
client_allowancestages | set this site's monthly AI-credit allowance, after the user confirms | credits, noLimit, confirm |
client_reportsstages | the client report email: off, weekly or monthly, after the user confirms | cadence*, confirm |
name (string) create and rename (required): the workspace name, 3 to 50 characters.workspace (string) rename: the workspace id, name or site host from workspaces list; defaults to this workspace.email (string) invite_client (required): the client's email address.access (string) invite_client: portal (default) is the branded reports portal, app the full product under the agency brand. One of: portal, app.role (string) invite_client: client_viewer looks only, client_member can approve. One of: client_viewer, client_member.client (string) revoke_client (required): the client email or id from workspaces clients.credits (integer) client_allowance: the monthly allowance in AI credits.noLimit (boolean) client_allowance: true removes the limit.cadence (string) client_reports (required): how often the clients get the report email. One of: off, weekly, monthly.confirm (boolean) create, rename, invite_client, client_allowance, client_reports: true only after the user said yes to this exact change; never set it on your own judgment.eventsCan stage changesFreeWhat happened in this workspace: the event list, poll for new events, wait for the next one, and register targets (a routine or webhook) that receive them.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
list | the event catalog with filters and fields | none |
poll | events since a cursor, a time, or the last poll | cursor, since, names, limit |
wait | wait up to 45 s for the next matching event | names, filters, cursor, timeout_seconds |
targetsstages | list / create / test / delete where events go (Claude routine, Grok Bot or Cursor routine, webhook) | targetAction*, kind, url, token, events, filters, id |
cursor (string) poll/wait: continue after this cursor (from a previous call or an event delivery).since (string) poll: ISO 8601 time; events at or after it.names (array) poll/wait: only these event names (see list).limit (integer) poll: max events (default 50, max 100).filters (object) wait (one event name) / targets create (one event): that event's filters, see list.timeout_seconds (integer) wait: seconds to wait (default 30, max 45).targetAction (string) targets: what to do with event targets. One of: list, create, test, delete.kind (string) targets create: where events go. One of: claude_routine, grok_routine, cursor_automation, webhook.url (string) targets create: the Claude routine /fire URL, the routine webhook URL, or an https URL.token (string) targets create, routine kinds: the routine API token or crsr_ key (stored encrypted, never shown again).events (array) targets create: which events to send.id (string) targets test/delete: the target id from targets list.campaign_manageCan stage changesBills AI creditsAct on campaigns: approve, pause, resume or abandon (manage), release held waves (expand), revert a campaign's live changes (undo), and stage new campaigns (page scale, location pages, content sweeps, bulk edits, articles). Approving, expanding, undoing and publishing are the user's decision, never yours. Reading campaigns is the campaigns tool.
Cost: list is FREE and staging spends nothing. Approving or expanding bills AI credits per page as the work runs; expand without confirm: true spends nothing. undo is FREE but changes the live site.
| Action | What it does | Parameters |
|---|---|---|
list | campaigns with status + task counts | status |
managestages | approve/pause/resume/abandon/update a campaign | campaignId*, manageAction*, confirm, confirmDestructive, brief |
expandstages | release a bulk sweep's held later waves: estimate only without confirm: true | campaignId*, confirm, confirmDestructive |
undostages | undo every live change the campaign applied (confirm: true after the user's explicit ask) | campaignId*, confirm*, confirmDestructive, force |
propose_page_scalestages | a set of pages on the site own page or own template | title*, kind*, brief*, exemplarUrl, projectId, rowSourceKind, rows, libraryDatasetId, rowTarget, allowGenText, publishAsDraft |
propose_location_pagesstages | location pages on the site own layout (drafts), or existing ones improved | locationMode*, exemplarUrl, exemplarPlace, title, rows* |
propose_content_sweepstages | N distinct blog articles as a campaign | title*, topics*, brief |
propose_bulk_editstages | one instruction across many pages | taskType*, instruction, title, selectorKind, urls, pathPrefix, segments, maxPages |
write_articlesstages | direct N-article staging | topics*, autoPublish |
save_articlestages | save a full article draft (pass title/content/slug) for one-click publish, or publish it to the CMS when the user says so (publish + confirm) | title*, content*, slug*, excerpt*, metaTitle, metaDescription, publish, publishAsDraft, confirm, confirmDestructive |
status (string) list only: filter campaigns by status. One of: proposed, approved, active, paused, done, abandoned.campaignId (string) manage/expand/undo: the campaign to act on.manageAction (string) manage only: what to do to the campaign. approve releases the campaign to execution (the USER must have explicitly said yes first). One of: approve, pause, resume, abandon, update_brief.confirm (boolean) manage (approve, abandon), expand, undo, and save_article with publish: true: must be true, attesting the user explicitly asked for this (approve releases work and spend; abandon is irreversible; publish sends the article to the CMS). Without it expand returns the estimate only.confirmDestructive (boolean) save_article with publish: the same attestation as confirm, the spelling the confirm widget sends.publish (boolean) save_article only: true sends the article to the connected CMS now through the same path as the dashboard Publish button (needs confirm: true). Only when the user asked.publishAsDraft (boolean) save_article with publish: default true (a draft in the CMS); false = live. In approval mode the article is always a draft. Also propose_page_scale: publish pages as drafts.force (boolean) undo only: also restore pages a person edited since. Set ONLY after the user saw the skipped list and chose to overwrite those edits.brief (string) manage+update_brief: replacement brief. Also propose_page_scale (template brief) and propose_content_sweep (shared direction).title (string) propose_page_scale (required), propose_content_sweep (required), propose_bulk_edit and propose_location_pages (optional).locationMode (string) propose_location_pages only (required): create = new draft pages modelled on exemplarUrl; enrich = rewrite existing location pages (rows carry pageUrl). One of: create, enrich.exemplarUrl (string) propose_location_pages (create) and propose_page_scale: the customer's own page the new pages copy (layout, embeds, page type). propose_page_scale needs exemplarUrl or projectId.projectId (string) propose_page_scale: the customer's own project whose fields hold their {{Column}} template. Needs projectId or exemplarUrl.exemplarPlace (string) propose_location_pages, create: the place the model page is about, when its title does not say.kind (string) propose_page_scale only (required): page kind, e.g. "location pages".rowSourceKind (string) propose_page_scale only: where page rows come from (required with exemplarUrl; with projectId defaults to the project dataset). No AI source: an invented row list is refused. One of: user, library, gbp_locations.rows (array) propose_page_scale, rowSourceKind=user: one object per page. propose_location_pages (required): one object per location (name + the facts the user gave; enrich: pageUrl).libraryDatasetId (string) propose_page_scale, rowSourceKind=library: dataset id to attach.rowTarget (integer) propose_page_scale only: target number of rows/pages.allowGenText (boolean) propose_page_scale only: allow per-row AI text (costs credits).topics (array) propose_content_sweep (required, up to 50) and write_articles (required, 2-50). One distinct article per topic.taskType (string) propose_bulk_edit only (required): the sweep type, e.g. ctr_fix, schema, content_refresh.instruction (string) propose_bulk_edit only: shared per-page brief.selectorKind (string) propose_bulk_edit only: how to select pages. One of: urls, path_prefix, all_pages.urls (array) propose_bulk_edit, selectorKind=urls: the pages.pathPrefix (string) propose_bulk_edit, selectorKind=path_prefix: the prefix.segments (array) propose_bulk_edit: advanced mixed-template selectors (overrides selectorKind/instruction).maxPages (integer) propose_bulk_edit only: cap the sweep size.autoPublish (boolean) write_articles only: default true (articles that pass our checks publish on their own, with undo); false keeps them as drafts.content (string) save_article only (required): full Markdown body.slug (string) save_article only (required): the URL slug.excerpt (string) save_article only (required): the excerpt.metaTitle (string) save_article only: meta title.metaDescription (string) save_article only: meta description.connectionsCan stage changesFreeChange connections (the connect link itself comes from connections_read connect: show it to the user VERBATIM, a one-time browser step), choose the Search Console, Analytics, Ads or Business Profile property, test or disconnect, and set publishing, sitemaps, market, IndexNow and vendor keys (confirm: true where the user must say yes). Checking what is connected is connections_read.
Cost: FREE - reads stored status and changes settings, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
status | every source with connected true/false, plus connect links for the missing ones | none |
connect | the connect link (or button) for each listed source the user has not linked | integrations* |
check | one source: connected yet? (poll after the user connected) | integration* |
property_choices | the user's Search Console properties / Analytics properties / Ads accounts / Business Profile listings, with the current and suggested pick | source* |
select_propertystages | use this property / account (property) or these listings (locations); replacing a set one needs confirm: true | source*, property, locations, confirm, confirmDestructive |
teststages | test the site connection with its stored credentials | connectionId |
disconnectstages | remove a source: cms deletes the site connection, a Google source revokes the user's own grant (confirm: true after the user's yes) | source*, connectionId, confirm, confirmDestructive |
publish_settings | where new blog posts land in the CMS (collection + field mapping) | connectionId |
set_publish_settingsstages | set the blog collection and field mapping | connectionId, collectionId*, collectionName*, fieldMapping |
sitemaps | custom sitemap URLs (added to auto-discovery) | none |
set_sitemapsstages | replace the custom sitemap URLs (the inventory re-syncs) | sitemapUrls* |
market | the search market in use, the suggestion, and every market offered | none |
set_marketstages | set the search market (locationCode + languageCode from market) | locationCode*, languageCode* |
indexing | IndexNow instant indexing settings (NOT whether Google indexed a page: use gsc_indexing inspect) | none |
set_indexingstages | turn instant indexing on or off (changes the live site; confirm: true) | enabled*, confirm, confirmDestructive |
vendor_keys | which own API keys are set (last 4 only, never the key) | none |
set_vendor_keystages | save an Ahrefs / Semrush / IndexMeNow / IndexNow key the user gave (IndexNow: omit apiKey to generate one) | provider*, apiKey, keyLocation |
integrations (array) connect only: the sources to offer - cms (website/CMS), gsc (Google Search Console), ga4 (Google Analytics), google_ads (Google Ads), gbp (Google Business Profile). Only the ones the question needs.integration (string) check only: the one source to check. One of: cms, gsc, ga4, google_ads, gbp.source (string) property_choices / select_property / disconnect: gsc (Search Console), ga4 (Analytics), google_ads (Ads), gbp (Business Profile); cms (the website connection) for disconnect only. One of: cms, gsc, ga4, google_ads, gbp.property (string) select_property: gsc the property siteUrl, ga4 the propertyId, google_ads the customerId (from property_choices).locations (array) select_property, gbp only: the listing location names to use (empty = none).connectionId (string) test / disconnect (cms) / publish_settings / set_publish_settings: the connection id; omit for this workspace's site connection.collectionId (string) set_publish_settings: the CMS collection or table id.collectionName (string) set_publish_settings: its display name.fieldMapping (object) set_publish_settings: CMS field ids for title, content, slug, excerpt, featuredImage (required in it) and metaTitle, metaDescription (optional).sitemapUrls (array) set_sitemaps: the FULL list of http(s) sitemap URLs to keep (max 20; empty clears).locationCode (integer) set_market: the market location code (from market).languageCode (string) set_market: the market language code, e.g. "en".enabled (boolean) set_indexing: true turns instant indexing on, false off.provider (string) set_vendor_key: whose key this is. One of: ahrefs, semrush, indexmenow, indexnow.apiKey (string) set_vendor_key: the key the user gave in this conversation (optional for indexnow: one is generated).keyLocation (string) set_vendor_key, indexnow only: a custom key-file URL.confirm (boolean) select_property (replacing a set one) / disconnect / set_indexing: true only after the user explicitly said yes to this exact change - never on your own judgment.confirmDestructive (boolean) The same attestation as confirm, as the elicitation retry carries it.agent_settingsCan stage changesBills AI creditsInteractiveChange the agent controls: on or off, autonomy mode (approval, assisted, auto), daily credit cap and publish-gate floors. Anything that lets work run or spend with less approval needs confirm: true after the user explicitly asked. Admin or owner. Reading them is agent_settings_read.
Cost: get and set are FREE config changes; a wider mode or a higher cap lets approved work spend more credits later - disclose before setting.
| Action | What it does | Parameters |
|---|---|---|
get | current mode, on/off, daily cap and spend | none |
setstages | change autonomyMode / enabled / dailyCreditCap / publishGate ('auto', 'assisted', a higher cap and a lowered floor need confirm: true from the user) | autonomyMode, enabled, dailyCreditCap, publishGate, confirm, confirmDestructive |
autonomyMode (string) set only: how the agents decide. 'auto' and 'assisted' need confirm: true. One of: approval, assisted, auto.enabled (boolean) set only: false turns the agents off (kill switch); true turns them on and starts the first plan run.dailyCreditCap (integernull) set only: the most credits agent work may spend per day (1 to 1,000,000); null restores the default cap.publishGate (object) set only: publish-gate floors, only those that change (scores 0-100, aiSearchBlock at or below aiSearchWarn; minBaselineCompetitors 1-20).confirm (boolean) set only: required true for autonomyMode 'auto' or 'assisted', a higher dailyCreditCap and a lowered publishGate floor. Attestation that the user explicitly asked for unattended execution after hearing the consequence - never set it on your own judgment.confirmDestructive (boolean) set only: the same attestation as confirm, as the elicitation retry carries it.dataset_manageCan stage changesBills AI creditsEdit datasets as the dashboard does: rows, cells and columns, find and replace, AI fill, generate rows, create, attach, fork, copy, share, rename, delete and restore a snapshot. Long work returns a job id to poll.
Cost: reads and edits are FREE. ai_fill, add_fill_column and generate_rows bill AI credits: without confirm they return the estimate, with confirm: true they reserve it and run.
| Action | What it does | Parameters |
|---|---|---|
get | one dataset: columns, row count, status | datasetId* |
rows | rows, 100 per page (cursor) | datasetId*, cursor, limit |
search | matching cells for a query | datasetId*, query* |
export | rows as JSON or CSV text | datasetId*, format, offset, limit |
createstages | a dataset from the user's rows (optionally attached to a project) | name*, columns*, rows*, projectId, confirm, confirmDestructive |
add_rowsstages | append rows the user gave (over 100 rows needs confirm: true) | datasetId*, rows*, projectId, confirm, confirmDestructive |
update_rowstages | change cells of one row | datasetId*, rowId*, data*, merge, projectId |
bulk_updatestages | set many cells at once (confirm: true after the user's yes) | datasetId*, updates*, projectId, confirm, confirmDestructive |
delete_rowsstages | delete rows (confirm: true after the user's yes) | datasetId*, rowIds*, projectId, confirm, confirmDestructive |
columnsstages | add, rename or delete a column (rename and delete need confirm: true) | datasetId*, op*, columnName, newName, columnType, defaultValue, projectId, confirm, confirmDestructive |
column_job | progress of a background column change | jobId* |
find_replacestages | find and replace as a job: start (confirm: true), status, cancel | op*, projectId*, datasetId*, findText, replaceText, matchCase, matchWholeWord, selectedCells, jobId, confirm, confirmDestructive |
ai_fillstages | fill chosen cells with AI (estimate, then confirm: true) | projectId*, prompt*, targets*, confirm, confirmDestructive |
add_fill_columnstages | add a column and fill every row with AI (estimate, then confirm: true) | projectId*, columnName*, prompt*, confirm, confirmDestructive |
generate_rowsstages | generate new rows with AI into one column (estimate, then confirm: true) | projectId*, prompt*, columnKey*, confirm, confirmDestructive |
ai_jobstages | status or cancel of an AI fill / row-generation job | op*, projectId*, jobId* |
attachstages | attach a dataset to a project by reference, with compatibility warnings | datasetId*, projectId*, confirm, confirmDestructive |
forkstages | private editable copy attached to a project (confirm: true) | datasetId*, projectId*, confirm, confirmDestructive |
copystages | copy into the user's library (confirm: true) | datasetId*, confirm, confirmDestructive |
sharestages | submit to the public library, or withdraw (confirm: true) | datasetId*, withdraw, title, description, category, confirm, confirmDestructive |
update_metadatastages | rename, description, category, tags | datasetId*, title, description, category, tags |
deletestages | delete a dataset, or detach it from a project (confirm: true; admin) | datasetId*, projectId, confirm, confirmDestructive |
restore_snapshotstages | replace a project dataset's rows with a snapshot (confirm: true) | datasetId*, projectId*, snapshotRows*, columnSchema, confirm, confirmDestructive |
datasetId (string) The dataset (from dataset_library list_datasets or page_projects get).projectId (string) The project the dataset is attached to. Required for find_replace, ai_fill, add_fill_column, generate_rows, ai_job, attach, fork; optional on row/column edits (edits the project's own dataset) and delete (detaches instead).cursor (integer) rows only: the nextCursor from the previous page.limit (integer) rows (max 100) / export (max 2000): rows per call.offset (integer) export only: row offset.query (string) search only: the text to find.format (string) export only: default json. One of: json, csv.name (string) create only: the dataset name.columns (array) create only: the columns (type default single_line).rows (array) create / add_rows: row objects keyed by column name, the user's own data (max 500).rowId (string) update_row only: the _rowId from rows.rowIds (array) delete_rows only: the _rowId values to delete.data (object) update_row only: column name -> new value.merge (boolean) update_row only: default true (only the given cells change); false replaces the row.updates (array) bulk_update only: cells to set (max 2000).op (string) columns: add | rename | delete. find_replace: start | status | cancel. ai_job: status | cancel.columnName (string) columns (add/delete, or the current name for rename) and add_fill_column.newName (string) columns rename only.columnType (string) columns add only (default single_line).defaultValue (string) columns add only.jobId (string) column_job, find_replace status/cancel, ai_job: the job to read.findText (string) find_replace start only (required).replaceText (string) find_replace start only (default empty).matchCase (boolean) find_replace start only.matchWholeWord (boolean) find_replace start only.selectedCells (array) find_replace start only: limit to these cells.prompt (string) ai_fill / add_fill_column / generate_rows: what to generate.targets (array) ai_fill only: cells to fill (rowPk = the _id from rows).columnKey (string) generate_rows only: the data column the values land in.withdraw (boolean) share only: true withdraws from the public library.title (string) share (required) / update_metadata: the public title.description (string) share (required) / update_metadata.category (string) share (required) / update_metadata: e.g. locations, saas, health.tags (array) update_metadata only (max 10).snapshotRows (array) restore_snapshot only (required): every row of the snapshot, keyed by column name (e.g. from export); replaces all current rows.columnSchema (array) restore_snapshot only: the columns to restore with the rows.confirm (boolean) delete_rows, bulk_update, add_rows over 100 rows, columns rename and delete, delete, restore_snapshot, find_replace start, fork, copy, share, and create / attach that replace the project's own dataset: true attests the user's explicit yes after seeing what changes. ai_fill, add_fill_column, generate_rows: true attests the user approved the quoted credits.confirmDestructive (boolean) The same attestation as confirm, the spelling the confirm widget and the elicitation retry send.site_audit_deepCan stage changesFreeStart or cancel a whole-site technical audit that crawls in the background (up to 2,000 pages). Reading its progress, results, comparisons and history is site_audit_deep_read. A quick 30-page audit inside one call is site_audit.
Cost: FREE - crawls with SEOmatic's own crawler in the background, no AI credits. start creates an audit run; nothing on the site changes.
| Action | What it does | Parameters |
|---|---|---|
startstages | start a background crawl (or get the one already running); returns runId | maxPages, urls |
status | progress while running; score + issues when done; issueType drills in (paged) | runId, issueType, page, pageSize |
compare | new / fixed / persisting issues vs the previous completed run | runId, baseRunId |
list | recent runs with score and issue counts | limit |
cancelstages | stop a queued or running audit (keeps partial results) | runId* |
maxPages (integer) start: most pages to crawl (default 500, max 2000).urls (array) start: list mode, audit exactly these pages of the workspace's own site and follow no links.runId (string) status/compare: the run (default newest; compare: newest completed). cancel (required): the run to stop.issueType (string) status only: drill into one issue type, as named in the results (e.g. broken_internal_link, duplicate_title).page (integer) status with issueType: page number (default 1).pageSize (integer) status with issueType: page size (default 25, max 100).baseRunId (string) compare only: the older run (default: the completed run before runId).limit (integer) list only: how many runs (default 10).brand_profileCan stage changesFreeChange the brand profile and Trust Profile: company facts, voices and references, brand kit, autofill from the site, copy from another workspace, trust facts and expertise questions. Writers omit what is empty instead of inventing it. Deletes, copy, kit and autofill need the user's yes (confirm: true). Reading it is brand_profile_read.
Cost: FREE except autofill, which bills AI credits (the estimate first, confirm: true); an expertise answer queues a page upgrade that bills when it runs.
| Action | What it does | Parameters |
|---|---|---|
get | the profile and the brand voices | none |
setstages | save the fields the user stated (admin or owner; never guessed values) | companyName, companyDescription, industry, elevatorPitch, targetAudience, products |
voicesstages | list, create or update brand voices | op*, voiceId, voice |
voice_referencesstages | a voice's reference pages and notes: list, add, delete | voiceId*, op*, type, url, content, title, referenceId |
kitstages | the visual brand kit: get, or set (confirm: true) | op*, kit, confirm, confirmDestructive |
autofillstages | fill empty brand fields from the site (estimate, then confirm: true; poll with op status) | op, jobId, confirm, confirmDestructive |
copystages | copy another workspace's brand style here (confirm: true) | sourceWorkspaceId*, confirm, confirmDestructive |
trust_fact_editstages | confirm, unconfirm or mark wrong one Trust Profile fact | factId*, confirmed, wrong |
trust_fact_deletestages | delete one Trust Profile fact (confirm: true) | factId*, confirm, confirmDestructive |
expertise_questionsstages | the writer's expertise questions: list, answer, dismiss | op*, openOnly, questionId, answer |
op (string) voices: list | create | update. voice_references: list | add | delete. kit: get | set. autofill: start (default) | status. expertise_questions: list | answer | dismiss.voiceId (string) voices update, voice_references (required): from voices list.voice (object) voices create/update: name (required on create), description, toneFormality/toneHumor/toneRespect/toneEnthusiasm (1-5), structuralRules, approvedTerms, bannedTerms, carefulTerms, dos, donts, pointOfView, customInstructions, language, copyBank, excludedTopics.type (string) voice_references add only (required). One of: url, text.url (string) voice_references add, type url: a public page.content (string) voice_references add, type text: the note.title (string) voice_references add: a title.referenceId (string) voice_references delete only (required).kit (object) kit set only (required): the fields to save (hex colours like #1a2b3c).jobId (string) autofill status only (required): the jobId start returned.sourceWorkspaceId (string) copy only (required): the workspace to copy from (the workspaces tool lists them).factId (string) trust_fact_edit / trust_fact_delete (required): from get_trust_facts.confirmed (boolean) trust_fact_edit: true lets the writers claim the fact, false takes that back.wrong (boolean) trust_fact_edit: true marks the fact not true (never cited, never re-harvested).openOnly (boolean) expertise_questions list: only unanswered questions.questionId (string) expertise_questions answer/dismiss (required): from list.answer (string) expertise_questions answer: the user's own words (2-500 chars).confirm (boolean) trust_fact_delete, copy and kit set: true after the user's explicit yes to what changes. autofill: true after the user agreed to the credit estimate. Never set it on your own judgment.confirmDestructive (boolean) The same attestation as confirm, as the confirm widget and the elicitation retry send it.companyName (string) set only: the business name (max 200).companyDescription (string) set only: what the company does (max 2000).industry (string) set only: the industry (max 200).elevatorPitch (string) set only: the one-paragraph pitch (max 1000).targetAudience (string) set only: who the content is for (max 3000).products (array) set only: up to 20 products or services, each with a name and description (replaces the stored list).page_projectsCan stage changesBills AI creditsPage and blog projects as the dashboard runs them: configure projects and fields, edit and regenerate pages, generate content, and publish (one page, bulk or drip). Credit-billing actions return the estimate until confirm: true; publishing and deletes need the user's yes.
Cost: reads, settings, fields, keywords, exports, deletes and publishing are FREE in AI credits (a metrics retry uses the keyword data allowance). regenerate, generate, generate_posts, preview, spin_content, regenerate_outline and refresh_baseline bill AI credits: the estimate first, run only with confirm: true.
| Action | What it does | Parameters |
|---|---|---|
list | the projects, with ids, type, step, dataset and status | projectType |
get | one project: fields and pages, or one page in full (pageId) | projectId*, pageId, status, limit, page |
add_fieldstages | add a template column | projectId*, label*, fieldName, type*, category, placeholder, helpText, isRequired, maxLength, options, order |
edit_fieldstages | change a column label, help text, placeholder or options | projectId*, fieldId*, label, helpText, placeholder, options |
edit_pagestages | save one page's field values (stored page only) | projectId*, pageId*, fieldValues* |
regeneratestages | rewrite one blog page through the full pipeline (AI credits; confirm: true) | projectId*, pageId*, confirm, confirmDestructive |
publish_pagestages | send one page to the CMS, live or as a draft (confirm: true) | projectId*, pageId*, publishAsDraft, confirm, confirmDestructive |
createstages | create a project (built-in template is Scale+) | name*, description, projectType, templateType, pageTemplate |
updatestages | change settings (name, type, step, connection, template, blog settings) | projectId*, name, description, projectType, templateType, currentStep, status, connectionId, cmsCollectionId, pageTemplate, blogSettings |
duplicatestages | copy a project | projectId*, newName |
deletestages | delete a project (confirm: true; admin) | projectId*, confirm, confirmDestructive |
save_field_valuesstages | save field templates (applyFieldIds re-renders pages) | projectId*, fieldValues*, applyFieldIds, confirm, confirmDestructive |
sync_fieldsstages | pull the CMS field schema from a connection | projectId*, connectionId*, postType |
validate_fields | are the required fields filled | projectId* |
pages_grid | dataset rows joined to their pages (cursor paged) | projectId*, cursor, limit |
ensure_pagestages | create the draft page behind a dataset row | projectId*, datasetRowPk* |
previewstages | render 3 preview pages (estimate, then confirm: true; poll job) | projectId*, confirm, confirmDestructive |
spin_contentstages | add spin syntax to template HTML (estimate, then confirm: true; poll job) | projectId*, htmlContent*, confirm, confirmDestructive |
job | result of a preview, spin-syntax or render job | jobId*, projectId |
generatestages | generate the pages (plan and estimate, then confirm: true) | projectId*, maxRows, confirm, confirmDestructive |
generationstages | generation job: status, pause, resume, cancel, retry | projectId*, op* |
generation_run | telemetry of one run (runId or subjectId) | projectId*, runId, subjectId, surface |
hostingstages | hosted delivery on (Scale+; detaches the CMS, confirm: true after the user's yes) or off | projectId*, op*, confirm, confirmDestructive |
content_briefstages | edit a post's content brief or outline | projectId*, contentBriefId*, outline, updates |
keywords | a blog project's keywords | projectId*, status, search, limit, page |
generate_postsstages | write posts for keywords (estimate, then confirm: true) | projectId*, keywordIds*, maxKeywords, confirm, confirmDestructive |
posts_generationstages | blog generation job: status or cancel | projectId*, op* |
publishstages | publish ready pages or posts to the CMS (confirm: true) | projectId*, pageIds, publishAsDraft, drip, confirm, confirmDestructive |
publish_jobstages | a publish run: status, or cancel (confirm: true) | projectId*, jobId*, op*, confirm, confirmDestructive |
delete_pagesstages | delete pages, optionally from the CMS too (confirm: true) | projectId*, pageIds*, removeFromCms, confirm, confirmDestructive |
delete_fieldstages | delete a column (confirm: true) | projectId*, fieldId*, confirm, confirmDestructive |
reorder_fieldsstages | set the column order (confirm: true when pages are live) | projectId*, fieldUpdates*, confirm, confirmDestructive |
clear_fieldsstages | clear columns, pages and setup data (wizard step back; confirm: true) | projectId*, confirm, confirmDestructive |
regenerate_outlinestages | rewrite a brief's outline with AI (estimate, then confirm: true) | projectId*, contentBriefId*, confirm, confirmDestructive |
retry_keyword_metricsstages | fetch a failed keyword's metrics again | projectId*, keywordId* |
refresh_baselinestages | rebuild a keyword's SERP baseline (estimate, then confirm: true; returns a jobId) | projectId*, keywordId*, device, confirm, confirmDestructive |
export | pages (or one page) as CSV or JSON, with the download link | projectId*, pageId, format, status |
projectId (string) The project (from list). Required by every action but list and create.pageId (string) get: one page in full. edit_page/regenerate/publish_page (required): the page, from get. export: one page instead of all.status (string) get: only pages in this status (draft, ready, in_progress, published, error, pr_staged, deploying). update: draft | published. keywords: pending | processing | completed | failed | no_data. export: ready | published | draft | error.limit (integer) get: pages per page (default 25, max 100). pages_grid: rows (max 500). keywords: per page (max 500).page (integer) get / keywords: page number (default 1).fieldId (string) edit_field / delete_field (required): the column, from get.label (string) add_field (required) / edit_field: the column label; the CMS key follows it.fieldName (string) add_field only: the CMS key, when it must differ from the label.type (string) add_field only (required): single_line, multiline, rich_text, number, image_url, link, dropdown, multiselect, switch, date, json, ... (the wizard field types).category (string) add_field only: default optional. One of: required, optional, acf, meta, advanced.placeholder (string) add_field/edit_field: the placeholder text.helpText (string) add_field/edit_field: the help text.isRequired (boolean) add_field only: whether every page must fill it.maxLength (integer) add_field only: a length cap.options (array) add_field/edit_field: dropdown / multiselect choices (strings, or { value, label } objects).order (integer) add_field only: a position; appended after the last column when absent.fieldValues (object) edit_page (required): one page's values keyed by field id, each { value, category, fieldName }, in the shape get returns; fields not passed keep their value. save_field_values (required): the project's templates, field id -> template value.publishAsDraft (boolean) publish_page / publish: true = drafts in the CMS where supported; default false = live.confirm (boolean) Must be true only after the user's explicit yes in this conversation: delete, delete_pages, delete_field, clear_fields (after seeing what goes), publish_job cancel, reorder_fields on a project with live pages, regenerate, generate, generate_posts, preview, spin_content, regenerate_outline, refresh_baseline (after hearing the credit estimate), publish_page, publish (after asking to publish). Never set it on your own judgment.confirmDestructive (boolean) The same attestation as confirm, the spelling the confirm widget and the elicitation retry send.name (string) create (required) / update: the project name.newName (string) duplicate only.description (string) create / update.templateType (string) create / update. One of: seomatic, cms, custom.pageTemplate (string) create / update: a built-in template id (Scale+); null clears.currentStep (integer) update only: 1-3.connectionId (string) update: a CMS connection of this workspace. sync_fields (required).cmsCollectionId (string) update only.blogSettings (object) update only.applyFieldIds (array) save_field_values only: re-render existing pages for these fields.postType (string) sync_fields only: the post type, resource or collection where the CMS needs it.cursor (integer) pages_grid only: the nextCursor from the previous page.datasetRowPk (string) ensure_page only: the row's _id.htmlContent (string) spin_content only: the template HTML.jobId (string) job: from preview, spin_content, or save_field_values applyJobs. publish_job: the jobId publish returned.maxRows (integer) generate only: cap the rows generated.op (string) generation: status | pause | resume | cancel | retry. posts_generation and publish_job: status | cancel. hosting: enable | disable.runId (string) generation_run: the run id.subjectId (string) generation_run: a page, keyword or row id (newest run).surface (string) generation_run: preview | wizard | chat | agentic.contentBriefId (string) content_brief / regenerate_outline (required): from keywords.outline (array) content_brief only: the new outline.updates (object) content_brief only: other brief fields (searchIntent, narrative, targetAudience, questionsToCover, callToAction, tone, articleLength, language, competitorUrls, requiredKeywords, primaryGoal, contentType).search (string) keywords only: filter by text.keywordIds (array) generate_posts only (required): keyword ids, from keywords.maxKeywords (integer) generate_posts only: cap the batch.pageIds (array) publish: specific pages (omit for every ready page). delete_pages (required): the pages to delete (max 500).removeFromCms (boolean) delete_pages only: also remove published pages from the CMS first (25 per call; the rest come back as deferredPageIds).fieldUpdates (array) reorder_fields only (required): each column id with its new position (max 100).keywordId (string) retry_keyword_metrics / refresh_baseline (required): from keywords.device (string) refresh_baseline only: default desktop. One of: desktop, mobile.format (string) export only: default csv (json for one page). One of: csv, json.drip (object) publish only: batches over time; omit to publish at once.projectType (string) list: only this project type. create / update: pages, posts, or a CMS post type (sent as the raw type).articlesCan stage changesBills AI creditsChange articles: edit a pay-as-you-go article, schedule weekly articles, run auto-optimize on a blog article, and leave feedback. Reading scores and downloads is articles_read; writing a new one is generate_article.
Cost: edit, download, scores and feedback are FREE. schedule is free to set; each weekly run uses one prepaid unit. auto_optimize start bills AI credits: the estimate first, confirm: true.
| Action | What it does | Parameters |
|---|---|---|
editstages | change the title and/or replace the markdown | article_id*, title, markdown |
download | the article as a file (md or html) with the download link | article_id*, format |
schedulestages | read the weekly schedule, or set enabled + topics (admin or owner; turning it on or changing topics needs confirm: true) | enabled, topics, confirm, confirmDestructive |
scores | a blog article's content, AI search, structure or term score | blogArticleId*, kind, device |
auto_optimizestages | Auto Optimize a blog article: start (estimate, then confirm: true) or status | blogArticleId*, op*, jobId, confirm, confirmDestructive |
feedbackstages | record the user's like or dislike of a blog article | blogArticleId*, feedback* |
article_id (string) edit/download (required): from get_article.title (string) edit only: the new title (max 500).markdown (string) edit only: the complete replacement markdown.format (string) download only: default md. One of: md, html.enabled (boolean) schedule only: true runs weekly; false pauses.topics (array) schedule only: the ordered topics, one per week (up to 104); replaces the stored list.blogArticleId (string) scores / auto_optimize / feedback (required): a blog project article id.kind (string) scores only: default content. One of: content, ai_search, structure, term.device (string) scores only: the baseline device, default desktop. One of: desktop, mobile.op (string) auto_optimize (required): start a run, or status. One of: start, status.jobId (string) auto_optimize status: the jobId start returned; omit for the run history.feedback (stringnull) feedback only (required): like, dislike, or null to clear. One of: like, dislike, .confirm (boolean) schedule: required true to turn the schedule on or change its topics (it spends the prepaid balance weekly). auto_optimize start: true after the user agreed to the credit estimate. Never on your own judgment.confirmDestructive (boolean) schedule / auto_optimize: the same attestation, as the elicitation retry sends it.billingRead-onlyFreeThe owner's plan as on the Billing tab: status, renewal date, free questions left, invoices and invoice details. Owner only; the payment method stays on the billing page. Plan changes and credit packs are billing_manage.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
status | plan, status, renewal and the billing page link | none |
invoices | invoices with hosted invoice page and PDF links | limit |
billing_details | the name, address and tax ID on invoices | none |
limit (integer) invoices: how many, newest first (default 12, at most 50).billing_manageCan stage changesFreePlan changes and credits for the owner: take the save offer, buy a credit pack (a Stripe Checkout link paid in the browser), set invoice details after the owner says yes. Previews of plan changes, pause, cancel and resume are billing_manage_read; they always finish in the browser.
Cost: FREE. Nothing is charged from the chat: plan changes are confirmed on the Plans or Billing page, and a credit pack is paid on its checkout page.
| Action | What it does | Parameters |
|---|---|---|
change_plan | the price and what is charged today, plus the Plans page where the owner confirms it | plan* |
pause | what a 1 to 3 month pause does, plus the Billing page where the owner pauses | duration* |
cancel | the two questions the cancel flow asks, the one save offer this plan gets, plus the Billing page where the owner cancels | reason, switchedTo |
resume | what resuming changes, and the Billing page link to do it | none |
start_now | what ending the trial today charges, and the Plans link to do it | none |
workspace_addon | extra workspaces: in use, allowed, the price of a quantity, and the Plans link | quantity |
savestages | the owner takes the one save offer from cancel instead of cancelling: remind turns on "ask me first" for the trial (nothing cancelled) | reason, offer* |
buy_credit_packstages | the pack catalogue, then a checkout link with pack and confirm | pack, confirm |
set_billing_detailsstages | change the invoice name, address and tax ID, after the owner answers yes | name*, line1*, line2, city*, state, postalCode, country*, taxId, confirm |
plan (string) change_plan (required): the target plan by name ("launch", "scale yearly") or id.duration (integer) pause (required): months to pause, 1 to 3.reason (string) Accepted for older callers; no longer picks the offer (cancel asks two open questions instead). One of: no_results, too_expensive, missing_feature, too_hard, switched, no_longer_needed, avoid_charge, other.switchedTo (string) cancel, reason switched: the tool or agency they moved to.offer (string) save (required): the offer_kind cancel returned. remind turns on "ask me first" for the trial; a pause is taken on the Billing page. One of: remind, help, recap, cheaper, pause, wish, switched.quantity (integer) workspace_addon: the total extra workspaces wanted (0 to 20), to price; omit for the current state.pack (string) buy_credit_pack: which pack. One of: small, medium, large.name (string) set_billing_details (required): the name on invoices.line1 (string) set_billing_details (required): street address.line2 (string) set_billing_details: address line 2.city (string) set_billing_details (required): city.state (string) set_billing_details: state, region or province.postalCode (string) set_billing_details: postal code.country (string) set_billing_details (required): two-letter country code (US, FR, GB).taxId (string) set_billing_details: business tax number (VAT, GST, EIN); empty removes it.confirm (boolean) buy_credit_pack and set_billing_details: must be true. Attests the user explicitly chose that pack or answered yes to those exact invoice details; never set it on your own judgment.teamRead-onlyFreeThe team as the Team tab shows it: members and invitations, redacted API keys (keys are created and revoked on the dashboard; a secret is never returned), and the person's own email preferences. Ownership transfer stays in Settings. Changes are team_manage.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
members | who is on the team and the seats in use | none |
api_keys | the redacted API key list | none |
email_preferences | the person's own email families and whether each is on | none |
team_manageCan stage changesFreeChange the team (admins and the owner): invite, change roles, resend or revoke invitations, email preferences, each after the user confirms; removals and admin changes return the Team tab link.
Cost: FREE - reads your connected/stored data, no AI credits.
| Action | What it does | Parameters |
|---|---|---|
invitestages | invite one member or viewer by email (sends an email, confirm required); admin invites link the Team tab | email*, role*, confirm |
change_rolestages | change a role (to member or viewer after the user confirms; to admin, the Team tab link) | member*, role*, confirm |
remove | who would lose access, and the Team tab link to remove them | member* |
reactivate | a suspended teammate: what reactivating does, and the Team tab link | member* |
resend_invitestages | send a pending invitation again, after the user confirms | member*, confirm |
revoke_invitestages | cancel a pending invitation, after the user confirms | member*, confirm |
set_email_preferencesstages | turn one of your own email families on or off, after you confirm | category*, on*, confirm |
email (string) invite (required): the address to invite.role (string) invite and change_role (required): viewer reads reports (no seat), member works on the site, admin also manages the team and keys (an admin is made on the Team tab only). One of: viewer, member, admin.member (string) change_role, remove, reactivate, resend_invite, revoke_invite (required): the email or id from team members.category (string) set_email_preferences (required): reports (weekly report, recaps), tips (setup help, reminders) or news (research, new features). One of: reports, tips, news.on (boolean) set_email_preferences (required): true to receive them, false to stop them.confirm (boolean) invite, change_role, resend_invite, revoke_invite, set_email_preferences: true only after the user said yes to this exact change; never set it on your own judgment.* = required for that action. The complete fine-grained tool list behind these, with each input schema, is in the REST reference.
Alongside the consolidated set, the server serves these single-purpose tools. They take direct parameters instead of an action, and the same annotations apply: read-only tools never change anything, and cost is stated per tool.
get_startedRead-onlyFreeInteractiveThe first answer about your own site: whether Google can index it, Search Console clicks and the near-page-one queries worth pushing (when connected), market data in the site's own country, a one-line verdict, the top 3 actions ranked by impact with the numbers behind them, what could not be checked, and one next step. The same answer on free and paid plans.
Cost: FREE for the reads; the one market-data lookup uses the free monthly allowance or AI credits, like any keyword question.
get_ai_visibilityRead-onlyFreeRead the latest completed AI-search visibility scan: per-engine brand visibility (ChatGPT, Claude and Google AI Overviews by default, plus any engine the monitor tracks: Perplexity, Google AI Mode, Copilot, Gemini, Grok), the prompts where the brand was missed and who won them, top competitors, and the sources engines cite.
Cost: FREE - reads your connected/stored data, no AI credits.
run_ai_visibility_scanActs or spendsPaidInteractiveStart a fresh AI-search visibility scan: queries the live AI engines with buyer-intent prompts and measures whether the brand appears. Scans your own site by default, or any competitor domain via the domain parameter. Returns a scanId immediately; results arrive in a few minutes via get_ai_visibility. Limited to one assistant-triggered scan per hour.
Cost: bills AI credits from the workspace pool (comparable to generating a few articles). Reading an existing scan with get_ai_visibility is free.
site_auditRead-onlyFreeSite-wide technical SEO audit: crawls up to 30 pages and aggregates cross-page issues a single-page check cannot see - duplicate titles and metas, thin content, noindex leaks, canonical mismatches, slow pages, broken internal links, HTTPS and mixed content, and the mobile viewport. For the whole site (up to 2000 pages, in the background, with history and comparison) use site_audit_deep.
Cost: FREE - crawls with SEOmatic’s own crawler at call time, no AI credits.
get_credit_usageRead-onlyFreeWhere the workspace’s AI credits went in the current billing period: customer-language groups plus the raw per-feature ledger with event counts. Totals reconcile with the plan meter; refunds show as negative credits.
Cost: FREE - reads your connected/stored data, no AI credits.
estimate_costRead-onlyFreeWhat a tool call will cost before you make it: free, credits at the actual vendor cost (with the ceiling the product reserves), credits, or one prepaid unit, plus the remaining balance and, on the free plan, the free questions left. Pass the tool and action you plan to call.
Cost: FREE - reads your connected/stored data, no AI credits.
get_referral_linkRead-onlyFreeYour personal SEOmatic Refer and earn link: the share URL, how many people you referred and how many became paying, and the extra AI credits you get every month from friends who pay. Give credits, get credits. Your friend gets 500K extra AI credits every month, and you get 500K more every month once they become a customer. Nothing is earned at signup.
Cost: FREE - reads your connected/stored data, no AI credits.
generate_articleActs or spendsPaidInteractiveWrite one in-depth SEO article on a topic, research-grounded against live rankings, quality-gated, delivered as markdown and HTML. Generation is async: returns an article_id to poll with get_article. With no prepaid units it returns the price and a buy link instead of failing.
Cost: consumes 1 prepaid pay-as-you-go article unit ($9 each, never expires); no subscription required.
get_articleRead-onlyFreeFetch a pay-as-you-go article by id (poll after generate_article), or omit the id to list recent articles and the prepaid balance. A ready article carries both markdown and HTML.
Cost: FREE - reads your connected/stored data, no AI credits.
pay_for_articlesActs or spendsPaidPay for prepaid units with a Stripe Shared Payment Token, for agent platforms whose users approve spends in a Link wallet (Meta Muse, ChatGPT agentic checkout). Products: articles ($9, default), question packs ($5 for 50 assistant questions), AI-visibility scans of your own site ($19), and competitor scans ($19). The token is single-use and amount-capped by Stripe; prices are fixed server-side. Hosts that cannot mint SPTs use the buy links from the payment_required payloads instead.
Cost: charges the approved payment method (product-priced); consumes no AI credits.
upload_csvActs or spendsFreeInteractiveStage CSV text so it can be imported as a dataset. Exists because MCP has no file transport: in MCP Apps hosts a file-picker widget reads the file in the browser and passes its text here, minting the same attachmentId a chat upload would. Pass that id to import_attachment_as_dataset.
Cost: FREE - stages the file text, no AI credits.
show_trust_facts_cardRead-onlyFreeInteractiveRender the Trust Profile card: harvested-but-unconfirmed business facts with one-tap Confirm buttons (MCP Apps hosts), or an Open-settings link when the profile is empty. Confirmed facts are the only credentials/experience/review claims the agent's writers may make - an empty profile means humbler content, never invented authority.
Cost: FREE - reads your connected/stored data, no AI credits.
confirm_trust_factActs or spendsFreeRecord the USER'S confirmation of one harvested trust fact, allowing writers to claim it. The click is the consent: call ONLY when the user explicitly confirmed that exact fact (the widget's Confirm button is the intended caller). Never confirm on your own judgment.
Cost: FREE - reads your connected/stored data, no AI credits.
add_trust_factActs or spendsFreeAdd a business fact the user stated in their own words (a credential, years of experience, an award, a review count, a guarantee) to the Trust Profile, confirmed by construction, so the agent's writers may claim it. Admin or owner; the same as adding one in Settings.
Cost: FREE - saves the fact, no AI credits.
get_trust_factsRead-onlyFreeThe workspace's Trust Profile: the provenance-tracked, verifiable business facts (credentials, experience, awards, review counts, guarantees) the agent's writers are allowed to claim in E-E-A-T work, each with its source URL and confirmation status. An empty profile means the agent writes around trust claims rather than inventing them.
Cost: FREE - reads your connected/stored data, no AI credits.
import_attachment_as_datasetActs or spendsFreePromote a spreadsheet uploaded in the conversation (CSV/Excel) into a private dataset in the workspace library, ready to drive a pages-at-scale campaign. Also accepts the Pages export of Search Console's generative AI performance report (Google has no API for it) with its date range, which then shows as Google's own AI Overviews and AI Mode impressions per page in the AI funnel and the diagnosis.
Cost: FREE - writes the dataset, no AI credits.
get_ai_crawler_activityRead-onlyFreeWhich AI bots (GPTBot, ChatGPT-User, PerplexityBot, ClaudeBot and more) visited the site, classified by purpose (answer-time retrieval, AI-search indexing, model training), with per-bot trends, top crawled pages, and the crawl-to-citation funnel.
Cost: FREE - reads your connected/stored data, no AI credits.
get_trust_entitiesRead-onlyFreeThe trust entities AI engines consult when answering questions about the market, mined from the actual fan-out queries scans capture. Every entity carries the cross of queried vs cited, surfacing the outreach list of sources engines check but never cite the brand from.
Cost: FREE - reads your connected/stored data, no AI credits.
get_ai_funnelRead-onlyFreeThe full AI-search funnel per page, joined across the measurements: cited (engines named the page as a source), crawled (AI bots actually fetched it), referred (GA4-measured assistant-referred visitors), and Google's own AI Overviews and AI Mode impressions when a Search Console generative AI report export was uploaded (with its date range), with unmeasured columns flagged honestly rather than shown as zero.
Cost: FREE - reads your connected/stored data, no AI credits.
show_approval_cardsActs or spendsFreeInteractiveRender inline Approve/Dismiss cards for existing proposed tasks and campaigns, bringing the approval decision into the conversation instead of sending the user to the dashboard.
Cost: FREE - reads your connected/stored data, no AI credits.
get_task_rollbackRead-onlyFreeWhat the pipeline can restore for an executed task: every live edit stores the page’s full pre-edit state before writing. Returns which fields are recoverable, original embed code verbatim, and how to trigger the one-click restore.
Cost: FREE - reads your connected/stored data, no AI credits.
resume_page_publishingActs or spendsPaidResume a page campaign paused by the scale governor (the drip stops itself when the first published pages earn essentially no search appearances). Requires the resumeToken from the hold, so resuming is always an explicit, informed decision.
Cost: resuming is free; each released page bills AI credits as it generates and publishes, same as campaign execution.
get_target_termsRead-onlyFreeThe searches your business says bring it customers, each with the page that should show for it and a priority. Your agents plan around them: when Google shows a different page for a term, the chosen page gets the fix, and low-volume terms are worked too.
Cost: FREE - reads your connected/stored data, no AI credits.
set_target_termsActs or spendsFreeAdd, update or remove the searches that bring your business customers, each with the page on your own site that should show for it and a priority. Pages on another site are refused; up to 50 terms per site.
Cost: FREE - saves your settings, no AI credits.
get_store_policiesRead-onlyFreeYour store's return and shipping policy as you stated it, and the summary the agents write into your homepage's Organization markup, Google's recommended place for a store-wide policy. Empty means no policy markup is written.
Cost: FREE - reads your connected/stored data, no AI credits.
set_store_policiesActs or spendsFreeSave or clear your return policy (countries, window in days, method, who pays) and shipping rates (price per country, free-shipping threshold, handling and transit days). Only values you state are saved; the agents never guess a return window or a shipping price. The markup change is then proposed like any other.
Cost: FREE - saves your settings, no AI credits.
A free workspace gets 5 questions a month, one meter shared across SEOmatic chat, MCP, the REST tool bridge and the CLI. Only market-data lookups (keywords, search results, backlinks) and get_started are metered, and metered calls within 90 seconds of each other count as one question, up to 5 lookups. Search Console and site reads are free, and initialize, tools/list, prompts, resources and get_credit_usage never use a question. The first OAuth connect of a free workspace adds 10 bonus questions, and connecting Search Console adds 10 more, enough for a full first audit. When the questions run out, the call returns an isError result with the next step to relay: connecting Search Console when that bonus is still unclaimed, otherwise the ways to get more questions or upgrade. Paid workspaces are not question-metered.
Independent of plan, each key is rate-limited to 60 tool calls per minute and 1,000 per hour, enough for any real session and a backstop against runaway loops. To revoke access: remove the connector in your assistant, or revoke the key or OAuth grant in SEOmatic Settings. Either kills the connection immediately.
domain default to your own site when it is omitted.agents:act: the acting tools are listed so the agent knows they exist, and calling one returns the upgrade path. They run on any paid plan.agents:act. With an API key, create a new key that includes agents:act.isError results with a plain-language reason the model can act on, never as opaque transport errors.An MCP server gives AI assistants tools they can call over the Model Context Protocol. An SEO MCP server gives them SEO tools. SEOmatic's reads your own Search Console data, audits your pages and checks your AI visibility, and on paid plans stages fixes on your site for you to approve.
Any client that supports remote MCP servers over Streamable HTTP. This page has setup steps for Claude, ChatGPT, the Gemini app, Claude Code, Cursor, GitHub Copilot, Gemini CLI, Devin, Cline, Zed and others. Clients that sign in with OAuth need no API key; headless clients send a workspace key as a Bearer token.
Connecting is free, and a free workspace gets 5 questions a month, where one message to your assistant uses at most one (only keyword, search result and backlink lookups count; your own Search Console and site data are free), plus bonus questions for the first connect and for connecting Search Console. Paid plans remove the limit and unlock the tools that stage changes. Each tool says whether it is free or bills AI credits.
Only on a paid plan, and only by staging proposals. Each staged change follows the approval rules you set in SEOmatic: in Approval mode it waits for your approval, the page's previous state is stored, and an applied edit can be rolled back.
Most SEO MCP servers only read data. This one also acts, with your approval: agents stage real fixes, you approve them in the chat, and approved work goes live on your site through your connected CMS. It also keeps working after the chat ends, because diagnosis, planning and scans run on schedule in SEOmatic.