SearchChampSearchChamp
MCP Documentation

MCP tool reference

Parameters, returned data, scopes, costs, and availability for every SearchChamp MCP tool.

SearchChamp publishes 54 tools from one versioned registry. OAuth clients receive the full catalog; each call still checks scope and role. User-generated tokens receive only the tools marked in the Token column, filtered by the organization's current plan and the token's scope.

Input and result rules

  • Inputs are strict: unknown fields, wrong types, out-of-range numbers, and malformed UUIDs return invalid_input before the handler runs.
  • A site accepts a domain or display name. Call list_sites when unsure. A foreign/missing site returns site_not_found; an ambiguous name returns only your own matching candidates.
  • Tool results contain human-readable content and machine-readable structuredContent.
  • A missing product prerequisite is normally a valid { setup_required: true, reason, next_step } result, not an exception.
  • Credits are debited after a handler runs. Denied/invalid calls do not debit a successful tool call.

Core SEO reads

ToolRequired input and optional boundsReturned dataScopeCreditsToken
list_sitesNoneAddressable sites: slug, domain, workspacemcp:read1All paid plans
get_daily_briefsite; date? as YYYY-MM-DDHeadline, findings, open actions, or setup guidancemcp:read1OAuth only
get_site_snapshotsiteRank/AI Visibility/audit/credit rollup plus open actions, goals, and strategy cardsmcp:read1OAuth only
get_rank_moverssite; days? 1–90 (default 7), limit? 1–100 (default 10)Keywords ordered by movement, including baseline/current ranks and deltamcp:read1OAuth only
get_rankingsSame as get_rank_moversSame rank-mover data under the token-catalog namemcp:read1All paid plans
get_ai_visibilitysiteScore, prompt coverage, appearance/share-of-voice summary, or setup guidancemcp:read1All paid plans
get_opportunitiessite; limit? 1–100 (default 10)Top active opportunities with title, lane, and impactmcp:read1OAuth only
get_audit_summarysiteLatest completed audit scores and severity counts, or setup guidancemcp:read1OAuth only
get_audit_issuessite; limit? 1–100 (default 20)Actual severity-ordered findings: title, page URL, description, kind/lens, and fix availabilitymcp:read1Business/Pro+ token
get_backlinks_summarysiteActive total, 30-day gained/lost, spam count, top referring domainsmcp:read1Business/Pro+ token
get_tracked_keywordssite; limit? 1–500 (default 50)Current positions, unranked flags, volumes, and cluster labelsmcp:read1OAuth only
get_bot_access_reportsiteLatest AI Access Score, per-bot verdict/evidence, grouped coverage, recent history; { report: null } if no scanmcp:read1OAuth only
get_volatilitysite; days? 1–90 (default 30)Volatility score and most-volatile keywords, or setup guidancemcp:read1Business/Pro+ token

Evidence and keyword research

These tools let an agent diagnose a page and propose keywords from the evidence SearchChamp already holds, without opening the app. Every read names its source and reporting range, and an unavailable integration is a named state (not_connected, needs_reconnect, read_failed), never an empty success. Nothing in this lane adds keywords, changes tracking, edits a page, publishes, or starts an integration sync; the single spending tool is run_keyword_research, and it starts nothing without the user's explicit confirmation of a previewed scope.

ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
get_integration_healthsiteWhether Search Console and GA4 are connected, their latest reportable dates, the last manual Search Console sync outcome, and what the nightly keyword join has storedmcp:read1Business/Pro+ token
get_search_console_performancesite; dimension? site/page/query/country/device/date, days? 1–480 (default 28) or start_date+end_date, page?, query_contains?, country? alpha-3, device?, limit? 1–500 (default 50)Live, finalised clicks, impressions, CTR and position at the chosen grain; totals match the Search Console UImcp:read1Business/Pro+ token
get_ga4_performancesite; report? overview/pages/channels/trend, days? 1–365 (default 28), page_path?, limit? 1–250 (default 25)Live GA4 sessions, page views, engagement, channels or daily trend for the authorised property; the range ends yesterdaymcp:read1Business/Pro+ token
get_keyword_inventorysite; cluster_id?, search?, source?, tracking? daily/weekly/any/none, limit?, offset?Stored keywords with cluster, market, metrics and their data date, provenance, Search Console evidence, tracking state and mapped-page count; exact total with pagingmcp:read1Business/Pro+ token
get_keyword_clusterssiteClusters with keyword count, stored volume, tracked counts and a per-source breakdown, plus the ungrouped countmcp:read1Business/Pro+ token
get_page_keyword_coveragesite, url on the site's domain; limit? 1–200 (default 50)Keywords mapped to one page (and how), plus stored Search Console queries for that page flagged as in or out of the keyword librarymcp:read1Business/Pro+ token
get_keyword_page_coveragesite; keyword text or keyword_idFor one keyword: the pages carrying evidence for it with verbatim stored excerpts and how each matched (exact wording, normalized phrase, all terms in one sentence, similar meaning), Search Console figures per page and query, each page's stored title and main heading, the single suggested target with its basis (similar meaning, or stored page evidence when meaning cannot be compared) and the reasons for it, or the exact abstention reason (tied, conflicting or insufficient evidence), every saved page mapping with its provenance and any user confirmation, and the cannibalization pairs touching those pages. Read-only: nothing is written, embedded or fetched from a providermcp:read1Business/Pro+ token
get_page_diagnosissite, url on the site's domain; days? 1–365 (default 28)One-call page diagnosis: live Search Console and GA4 performance, latest audit findings, internal-link opportunities, backlinks and keyword coverage, each section reporting its own availabilitymcp:read1Business/Pro+ token
preview_keyword_researchsite, seeds; country?/language? or location_code?/language_code?, url?The exact scope a run would use, its cost, balance, remaining daily runs, seeds already in the library, blockers, and a scope_hash; spends nothingmcp:read1Business/Pro+ token
run_keyword_researchThe previewed scope plus user_confirmed: true, scope_hash, idempotency_keyStarts the research job and returns a job_id; requires a signed-in Editor and the user's explicit confirmation; candidates are reviewable only and nothing is added to the librarymcp:spend1 + the research run's own creditsOAuth only
get_keyword_research_resultsite, job_idReviewable candidates and the reasons any were rejected, or the job's current statemcp:read1Business/Pro+ token

run_keyword_research is a confirmed spend: the preview shows the scope and cost, and the run refuses a scope_hash that does not match it.

Content and publishing

ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
get_content_draftssite; limit? 1–100 (default 25)Draft/ready article identifiers, slugs, statuses, and titlesmcp:read1Business/Pro+ token
list_draft_articlessite; limit? 1–100 (default 25)Drafts plus MCP claim state: unclaimed, claimed/lease, or published/verificationmcp:read1Business/Pro+ token
get_article_contentarticle_idMarkdown/HTML body, SEO metadata, slug, hero image, and publisher JSON-LD graphmcp:read1Business/Pro+ token
get_page_recommendationssite; url?Audit issues and opportunities reshaped as rewrite guidancemcp:read1OAuth only
get_brand_voicesiteComposed tone, do/don't lists, banned phrases, audience, and available named voicesmcp:read1OAuth only
start_publisharticle_idClaims a draft for 30 minutes; returns claimed/reclaimed/already-claimed statemcp:act10OAuth only
report_publisharticle_id, canonical_url on the site's domainRecords the external publish and queues independent verification; idempotent for article+URLmcp:act10OAuth only
publish_articlearticle_id, provider (wordpress or shopify); as_draft? default falseSearchChamp enqueues its standard CMS publisher and returns job_id; feature-enable and CMS gates applymcp:act10OAuth only

start_publish/report_publish are for a coding agent that performs the site write itself. publish_article asks SearchChamp to perform the CMS write. Poll get_job after publish_article.

Content Writer and Research Studio editorial tools

These five tools give an AI client the same editorial feed the public REST routes expose, backed by the identical query and authorization code — there is one implementation per capability, so REST and MCP can never drift apart.

These tools read existing content and flip status only

list_content_articles, list_research_sessions, and get_research_session read content SearchChamp has already generated. set_content_article_status and set_research_session_status change a status value in SearchChamp's own database and nothing else.

None of them starts a Content Writer generation run or a Research Studio research run, and neither status tool pushes anything to WordPress, Shopify, or any other connected CMS. Starting a run is a SearchChamp app workflow. For a real CMS publish, use publish_article, which is a different tool with a different scope and a different cost.

ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
list_content_articlessite; status? exactly draft or published; limit? 1–100 (default 25); offset? ≥ 0{ articles[], total, returnedCount, limit, offset } — a stable editorial feed. Each article carries its raw status alongside the draft/published grouping. Archived articles are never returned.mcp:read1Business/Pro+ token
list_research_sessionssite; status? exactly draft or published; limit? 1–100 (default 25); offset? ≥ 0{ sessions[], total, returnedCount, limit, offset }. Each session carries its raw status. Archived and failed sessions are never returned.mcp:read1Business/Pro+ token
get_research_sessionsession_id UUIDOne session with its latest generated brief, pinned sources, and keywords. brief is null when the session has not been synthesized yet — that is a valid result, not an error. Large sessions report pinsTruncated / keywordsTruncated instead of silently capping.mcp:read1Business/Pro+ token
set_content_article_statusarticle_id UUID, status — only "published" is acceptedMarks the article published in SearchChamp's database. Idempotent: a repeat reports already_published and does not re-stamp the publish time. Returns the article as the database holds it after the write.mcp:act5Business/Pro+ token
set_research_session_statussession_id UUID, status — only "published" is acceptedMarks the session published in SearchChamp's database. A draft session needs a completed brief; a reviewing session needs nothing further. Idempotent.mcp:act5Business/Pro+ token

status is enforced at the schema boundary, not just inside the handler, so a value outside the documented vocabulary is rejected as invalid_input before anything runs. The accepted target is an allow-list of exactly published: when SearchChamp's internal state machines gain new values, those values do not silently become remotely settable.

Status grouping and what is hidden

status=draft / status=published is a deliberate, stable grouping over internal state machines that have more values and keep growing. Each item's raw value always comes back in its status field.

FilterArticle statusesResearch session statuses
draftdraft, generating, brief_ready, ready_for_review, approved, faileddraft, researching, reviewing, brief_ready, handed_off
publishedpublishedpublished
omittedboth groupsboth groups
never returnedarchivedarchived, failed

Research sessions with no site are not visible to MCP clients

A Research Studio session whose site is unset is not readable and not publishable through any external surface.

research_sessions carries no organization column, so a session's tenancy is proven through its site. A session with no site cannot be proven to belong to the calling organization, and SearchChamp treats an unprovable authorization as a failure rather than a pass. Such a session is absent from list_research_sessions and get_research_session reports it as not found. Assign the session a site in the SearchChamp app to make it addressable.

publishedAt is a SearchChamp timestamp, not a CMS one

Both feeds and both status tools return publishedAt — for research sessions this is research_sessions.published_at, a real column with a real producer. It is null for anything not published, and also null for a session that was published before the column existed.

It records when the status was flipped inside SearchChamp. It is not a CMS publication time, because nothing on this surface talks to a CMS.

Worked example — list drafts, then publish one

Example prompt

Show me the draft articles for example.com, then mark "How to choose SEO tools" as published in SearchChamp. Don't publish it to WordPress.

The client would call list_content_articles to find the id, then set_content_article_status with it.

Step 1 — list_content_articles

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "list_content_articles",
      "arguments": {
        "site": "example.com",
        "status": "draft",
        "limit": 25,
        "offset": 0
      }
    }
  }'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{ "type": "text", "text": "37 articles for example.com" }],
    "structuredContent": {
      "articles": [
        {
          "id": "0f2c9c2a-5f6f-4a53-9a1e-2b2a1f5f0c11",
          "title": "How to choose SEO tools",
          "slug": "how-to-choose-seo-tools",
          "status": "ready_for_review",
          "locale": "en",
          "wordCount": 1420,
          "targetKeyword": "seo tools",
          "createdAt": "2026-08-20T09:14:00.000Z",
          "updatedAt": "2026-08-27T16:02:00.000Z",
          "publishedAt": null
        }
      ],
      "total": 37,
      "returnedCount": 1,
      "limit": 25,
      "offset": 0
    }
  }
}

Step 2 — set_content_article_status

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "set_content_article_status",
      "arguments": {
        "article_id": "0f2c9c2a-5f6f-4a53-9a1e-2b2a1f5f0c11",
        "status": "published"
      }
    }
  }'
{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "content": [{ "type": "text", "text": "Article marked published in SearchChamp." }],
    "structuredContent": {
      "article": {
        "id": "0f2c9c2a-5f6f-4a53-9a1e-2b2a1f5f0c11",
        "status": "published",
        "publishedAt": "2026-08-29T11:02:41.000Z"
      },
      "already_published": false
    }
  }
}

Worked example — read a research session and publish it

Example prompt

Pull up the published research sessions for example.com, read the brief for the Q4 competitor one, and publish the draft session that already has a completed brief.

get_research_session

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_research_session",
      "arguments": { "session_id": "9c1b6f3e-77d4-4c2a-b0aa-3e5c9f2d1a44" }
    }
  }'
{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "content": [{ "type": "text", "text": "Q4 competitor landscape" }],
    "structuredContent": {
      "session": {
        "id": "9c1b6f3e-77d4-4c2a-b0aa-3e5c9f2d1a44",
        "title": "Q4 competitor landscape",
        "status": "reviewing",
        "publishedAt": null,
        "brief": {
          "briefDocVersion": 1,
          "contentMd": "## Summary\n…",
          "generatedAt": "2026-08-26T13:30:00.000Z",
          "exportedToContentWriter": false
        },
        "pins": [],
        "pinsTruncated": false,
        "keywords": [],
        "keywordsTruncated": false
      }
    }
  }
}

set_research_session_status

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 4,
    "method": "tools/call",
    "params": {
      "name": "set_research_session_status",
      "arguments": {
        "session_id": "9c1b6f3e-77d4-4c2a-b0aa-3e5c9f2d1a44",
        "status": "published"
      }
    }
  }'

When a status change is refused

Both status tools accept only a resource already in a publishable state.

ResourcePublishable fromAnything else
Articleapproved, ready_for_review, or draft with a bodyinvalid_status, reporting the current status
Research sessionreviewing, or draft with a completed briefinvalid_status, reporting the current status

A refusal names the current state as data rather than prose, and adds a reason when the status alone does not explain it: empty_body for an article, no_brief for a session. Calling again on an already-published resource is not a refusal — it succeeds, reports already_published, and leaves the original publish time untouched.

Search Console, GA4, and keyword research

These ten tools let an AI client diagnose a page and propose keywords from evidence, without the user switching to the SearchChamp app. Nine are read-only. One — run_keyword_research — spends credits, and only after the end user explicitly confirms a scope they were shown.

What these tools will and will not do

  • Read-only by default. No tool here adds a keyword to the library, changes rank tracking, edits or publishes a page, or starts an integration sync.
  • Research is review-only. run_keyword_research returns candidates for the user to review. Keeping any of them is a separate action the user takes on the Keywords page in the SearchChamp app.
  • Research needs explicit consent. Call preview_keyword_research, show the user the scope and cost, and call run_keyword_research only after they say yes. An AI client must not set user_confirmed on the user's behalf.
  • A Search Console sync is never started from MCP. get_integration_health reports whether a manual sync is possible; the user runs it in the app.
ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
get_integration_healthsiteWhether Search Console and GA4 are connected, the connected property, the latest date each can report, the last manual Search Console sync and its outcome, and what the nightly keyword join has stored. Connection is read from the stored integration, not verified against Google.mcp:read1Business/Pro+ token
get_search_console_performancesite; dimension? one of site (default), page, query, country, device, date; either days? 1–480 (default 28) or start_date + end_date as YYYY-MM-DD; filters page? (a URL on this site, matched across http/https, www, and trailing-slash variants), query_contains?, country? (ISO alpha-3, e.g. are), device? (desktop, mobile, tablet); limit? 1–500 (default 50)Live clicks, impressions, CTR, and average position with the source, property, exact reporting range, and latest available date. Totals come from a property-level query, so they match the Search Console UI.mcp:read1Business/Pro+ token
get_ga4_performancesite; report? one of overview (default), pages, channels, trend; days? 1–365 (default 28); page_path? starting with / (matched with or without its trailing slash); limit? 1–250 (default 25)Live sessions, page views, engaged sessions, engagement rate, and average session duration — overall, per page, per default channel group, or per day — with the source, property, and exact reporting range.mcp:read1Business/Pro+ token
get_keyword_inventorysite; cluster_id? UUID; search?; source?; tracking? one of daily, weekly, any, none; limit? 1–200 (default 50); offset? ≥ 0The keywords the site already has: cluster, market, stored volume/difficulty/CPC/intent, provenance, the data date of those metrics and a stale flag, joined Search Console evidence, tracked state and cadence, and mapped-page count. Exact filtered total.mcp:read1Business/Pro+ token
get_keyword_clusterssiteEach cluster's keyword count, total stored volume, tracked and daily-tracked counts, and keyword count per provenance source; plus the ungrouped keyword count.mcp:read1Business/Pro+ token
get_page_keyword_coveragesite, url (a page on this site); limit? 1–100 (default 50)The keywords mapped to that page and how, plus the Search Console queries stored for it (trailing 28 days as of dataDate), each flagged inInventory.mcp:read1Business/Pro+ token
get_page_diagnosissite, url (a page on this site); days? 1–365 (default 28)One call combining the page's live Search Console performance and top queries, live GA4 engagement, latest audit findings, pending internal-link opportunities, backlinks, and keyword coverage. Each section reports its own availability.mcp:read1Business/Pro+ token
preview_keyword_researchsite, seeds (1–10 phrases, each ≤ 120 chars); market as either country + language (ISO codes, e.g. AE + en) or location_code + language_code, or omit both to use the site's stored keyword market; url? (a page on this site)Spends nothing. The resolved scope, the cost to start and what else a run can cost, credit balance, research runs remaining today, whether each seed is already in the library, any blockers, and a confirmation.scope_hash.mcp:read1Business/Pro+ token
run_keyword_researchThe same scope fields as the preview, plus user_confirmed: true, scope_hash from the preview, and idempotency_key 1–128 charsSpends credits. Starts the same research the Keywords page runs and returns a job_id. Refused unless user_confirmed is true and scope_hash matches this exact scope. Needs a signed-in user and the Editor role.mcp:spend1OAuth only
get_keyword_research_resultsite, job_id UUIDStatus while running. When finished, result is candidates, empty, failed, or canceled. With candidates: new_opportunities and already_earning_impressions as separate lists, each with metrics and provenance. Always an outcome with counts at every stage, a sample of rejected terms with reasons, and a plain-language reason when nothing is returned.mcp:read1Business/Pro+ token

Data sources, freshness, and "no data"

Every Search Console and GA4 result names its source, the property, and the exact reporting_range, so a client can always say where a number came from and which dates it covers.

DataWhere it comes fromHow fresh
get_search_console_performanceGoogle Search Console, read liveFinalised data only. Google finalises on a two-day lag, so latest_available_date is two days ago. Cached for 30 minutes per site (served_from_cache).
get_ga4_performanceGoogle Analytics 4, read liveThe newest whole day is yesterday — today is incomplete in GA4. Cached for 30 minutes per site.
get_keyword_inventory, get_keyword_clustersSearchChamp's stored keyword libraryStored figures, not a fresh lookup. metrics.dataDate says when volume and difficulty were pulled. metrics.stale: true means they were measured for a different market than the keyword now sits in. In get_keyword_inventory, provenance.research.basis: "keyword_suggestions" marks a keyword saved from keyword-suggestions research — search data, not model inference — even though its source bucket reads AI-Inference; requestedMarket is the market that research ran for. research: null means no basis was recorded, and nothing is inferred.
get_page_keyword_coverageThe nightly Search Console join SearchChamp storesA trailing 28 days as of dataDate.

A connection problem is always a named state, never an empty result:

stateMeaning
okConnected and read.
not_connectedThe integration is not connected for this site. Connect it in the SearchChamp app.
needs_reconnectIt is connected, but the stored authorisation is no longer valid. Reconnect it in the app.
read_failedIt is connected, but Google did not return the data just now. Try again later.

A metric of null means the provider had no data for it. Never read null as zero.

Search Console sync

Search Console performance is read live, so it does not depend on a sync. get_integration_health reports the last manual sync as never_synced, in_progress, ok, partial, or failed, and whether another is possible. A manual sync calls Google on the workspace's quota, so it stays a user-approved action: an Editor or above chooses Sync now on the Search Console page in the app. No MCP tool starts one.

The keyword research workflow

Candidate provenance. A recorded originating provider stays attached when keyword suggestions are reused from cache. A suggestion served through SearchChamp's data gateway returns provenance.provider: "DataForSEO" only when the gateway reports that item's own source as DataForSEO. Gateway results without a per-item source, an unknown source, and older cached suggestions without originating-provider metadata return provenance.provider: null; the app shows provider unavailable. A source label such as “Keyword suggestions” or a transport label such as “cache” is not provider attribution. A cache fetch time is not a measurement date: missing reporting dates remain data_date: null. Re-reading an existing research result preserves its recorded evidence; it does not retroactively infer a provider or refresh its data.

Research is a two-step workflow so that a credit is never spent without the user's agreement.

  1. Check what exists. Call get_keyword_inventory (and get_page_keyword_coverage for a specific page) so you do not research what the site already has.
  2. Preview. Call preview_keyword_research with the seeds, target market, and optional page URL. Nothing is spent.
  3. Ask the user. Show them the scope and the cost (see What research costs).
  4. Run, only on a yes. Call run_keyword_research with the same seeds, market, and URL, user_confirmed: true, and the preview's scope_hash. If anything changed since the preview, the call returns confirmation_mismatch and spends nothing — preview again. A scope_hash is valid only on the UTC day it was previewed.
  5. Review. Poll get_keyword_research_result with the job_id, and read its result field.

What research costs

The preview's estimated_cost separates three charges, because they are not all known in advance:

FieldWhat it is
start_creditsCharged when the run starts. Returned if the run fails or finds no new candidates.
tool_call_creditsThe MCP charge for the run_keyword_research call itself.
minimum_total_creditsstart_credits + tool_call_credits — what starting a run costs.
recent_usage_creditsA run that returns candidates also records usage-based credits for the research itself. The amount varies, so the preview reports this site's recent completed runs (count, average, maximum) as a guide. null means the site has no recent history — not that the usage is zero.

Tell the user both parts: the credits to start, and that a successful run records additional usage-based credits.

The target market is never guessed. Give a country and language, or leave both out to use the site's stored keyword market. If the site has no keyword market set, the preview returns market_required rather than researching a default country. English, Spanish, and Arabic markets are supported; any other market returns unsupported_market, and that research is run from the Keywords page in the app instead.

Relevance and location checks. The research uses the same rules as the Keywords page in the app. A term that does not match the seed topic is rejected as off_topic. A term that names a place outside the target market — for example a New York term in a United Arab Emirates run — is rejected as off_market, unless the user named that place in a seed. Rejected terms are listed in outcome.rejected_sample with their reason; they are never returned as recommendations.

An empty result always has a reason. Read result, not status: a run that finds nothing new is recorded as failed internally so that its start credit is returned, and it comes back as result: "empty". outcome.reason and outcome.explanation say which of these happened:

outcome.reasonMeaning
candidates_availableNew candidates are ready for review.
duplicate_onlyEvery relevant term is already in the keyword library.
rejected_onlyThe provider returned terms, but none passed the relevance and target-market checks.
provider_emptyThe provider returned no keyword data for these seeds in this market.
provider_unavailable / provider_errorThe provider could not be reached or returned an error.
research_incompleteThe run did not finish cleanly. Do not read this as "no keywords exist".

outcome.stage_counts reports how many terms were proposed, unique, rejected (unobserved, off-topic, off-market), duplicated (within the run, or already in the library), and accepted.

Worked example — preview, confirm, and run research

Example prompt

Find new keywords for our iOS app development page in Dubai. Tell me what it costs before you run anything.

Step 1 — preview_keyword_research

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "preview_keyword_research",
      "arguments": {
        "site": "example.ae",
        "seeds": ["iOS app development Dubai"],
        "country": "AE",
        "language": "en",
        "url": "https://example.ae/ios-app-development-dubai"
      }
    }
  }'
{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "content": [{ "type": "text", "text": "Preview only — nothing was spent. Researching 1 seed(s) for AE / en costs 2 credit(s) to start (the start credit is returned if nothing new is found), plus usage-based credits if candidates are found. Ask the user to confirm this scope and cost before calling run_keyword_research." }],
    "structuredContent": {
      "action": "preview",
      "scope": {
        "site": "example.ae",
        "seeds": ["iOS app development Dubai"],
        "market": { "country": "AE", "location_code": 2784, "language_code": "en", "source": "explicit" },
        "target_url": "https://example.ae/ios-app-development-dubai"
      },
      "estimated_cost": {
        "start_credits": 1,
        "tool_call_credits": 1,
        "minimum_total_credits": 2,
        "recent_usage_credits": { "completed_runs_last_90_days": 4, "average": 3.6, "maximum": 5.2 }
      },
      "daily_runs": { "limit": 20, "used": 3, "remaining": 17 },
      "existing_coverage": {
        "keywords_in_this_market": 57,
        "seeds": [{ "seed": "iOS app development Dubai", "already_in_library": true }]
      },
      "can_run": true,
      "blockers": [],
      "confirmation": { "scope_hash": "5f0c9c2a5f6f4a539a1e2b2a1f5f0c11" }
    }
  }
}

The client now tells the user the scope, the 2 credits to start, and that a run returning candidates also records usage-based credits (recently about 3.6 on this site) — and waits for a yes.

Step 2 — run_keyword_research, after the user confirms

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "tools/call",
    "params": {
      "name": "run_keyword_research",
      "arguments": {
        "site": "example.ae",
        "seeds": ["iOS app development Dubai"],
        "country": "AE",
        "language": "en",
        "url": "https://example.ae/ios-app-development-dubai",
        "user_confirmed": true,
        "scope_hash": "5f0c9c2a5f6f4a539a1e2b2a1f5f0c11",
        "idempotency_key": "ios-dubai-2026-10-06"
      }
    }
  }'

Step 3 — get_keyword_research_result

curl --fail-with-body 'https://mcp.searchchamp.com/mcp' \
  --header "Authorization: Bearer $SEARCHCHAMP_MCP_TOKEN" \
  --header 'Content-Type: application/json' \
  --data '{
    "jsonrpc": "2.0",
    "id": 3,
    "method": "tools/call",
    "params": {
      "name": "get_keyword_research_result",
      "arguments": { "site": "example.ae", "job_id": "9c1b6f3e-77d4-4c2a-b0aa-3e5c9f2d1a44" }
    }
  }'

Limits

  • run_keyword_research is OAuth only. A user-generated token can preview research and read a result, but cannot start a run, because a token has no signed-in user to give the confirmation.
  • Research runs are capped per site per day; the preview reports how many remain.
  • get_integration_health does not contact Google, so it cannot tell that an authorisation was revoked. A performance read reports that as needs_reconnect.
  • get_page_keyword_coverage reads stored data. status: "no_stored_data" means nothing is stored for that page — the integration may not be connected, the nightly join may not have run yet, or the page may have no impressions. Use get_integration_health and get_search_console_performance to tell which.
  • Page tools accept only a URL on the addressed site's own domain. Anything else returns url_not_on_site.

Custom-site publication artifacts

ToolRequired input and optional boundsReturned dataScopeCreditsToken
list_pending_publication_pagessite; limit? 1–100 (default 25), offset? 0–10,000Exact total and bounded page of Content Writer pages awaiting custom-site publicationmcp:read1Business/Pro+ token
get_pending_publication_pagesite, article_id UUIDSource/proposed versions and a drift-safe ChangeArtifactV1mcp:read1Business/Pro+ token
list_internal_link_editssite; limit? 1–100 (default 25), offset? 0–10,000Exact total and bounded pending edits without full page bodiesmcp:read1Business/Pro+ token
get_internal_link_editsite, suggestion_id UUIDExact-context, drift-safe ChangeArtifactV1mcp:read1Business/Pro+ token

Page Optimizer apply and verification

ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
list_approved_changessite; approved status?; limit? 1–100 (default 25)Approved changes with page/section identity, summary, lifecycle status, and verification timestampsmcp:read1Business/Pro+ token
get_changeidExact approved before/after HTML, page URL, anchor, heading, kind, summary, selector hints, and statusmcp:read1Business/Pro+ token
mark_appliedidReports a live application and triggers an independent re-crawl; settles verified or applied-unverifiedmcp:act10OAuth only

list_approved_changes defaults to approved but not conclusively verified work (accepted, applied, and applied_unverified). mark_applied never accepts HTML from the caller and is rate-bounded/idempotent; the agent's report is not the final verification.

llms.txt

ToolRequired input and optional boundsReturned data / effectScopeCreditsToken
get_llms_txtsiteCurrent configuration/content and latest generation statemcp:read1Business/Pro+ token
generate_llms_txtsite, idempotency_key 1–128 charsCreates or reuses a generation jobmcp:spend20Business/Pro+ Full token
get_llms_txt_jobsite, run_id UUIDOne site-scoped generation jobmcp:read1Business/Pro+ token
list_llms_txt_versionssite; limit? 1–100 (default 25), offset? 0–10,000Exact total and bounded generated-version listmcp:read1Business/Pro+ token
diff_llms_txt_versionssite, from_version_id, to_version_id UUIDsExact unified diff between two versions from the same sitemcp:read1Business/Pro+ token

The caller supplies a stable idempotency_key so reconnects/retries do not enqueue equivalent generation work twice.

Actions, natural-language answers, and jobs

ToolRequired inputReturned data / effectScopeCreditsToken
list_actionssite; status?Site agent actions, optionally filteredmcp:read1OAuth only
approve_actionaction_idAudited, idempotent approval. Eligible CMS meta writes can execute only when mcp:act is also granted and execution is enabled; spending runs otherwise remain proposed for in-app approvalmcp:approve5OAuth only
decline_actionaction_idAudited, idempotent declinemcp:approve5OAuth only
ask_atliosite, messageGrounded answer plus suggested actions (capability, params, billing preview, action class); spending commands are proposed, not silently runmcp:read20OAuth only
get_jobjob_idStatus, stage, percent, partial summary, and poll_after_ms; poll until succeeded/failed/canceledmcp:read1OAuth only

ask_atlio requires editor-or-higher access to the addressed site. Although it requires the read scope, it is LLM-backed and costs 20 credits. The server's published cost is authoritative if this table and a live tools/list ever differ.

Token catalog summary

User-generated tokens intentionally expose a smaller catalog:

  • Every paid plan: list_sites, get_rankings, get_ai_visibility.
  • Business/Pro and higher: also get_audit_issues, get_backlinks_summary, get_content_drafts, get_volatility, the approved-change read tools, custom-publication artifact reads, llms.txt reads, the editorial reads list_draft_articles, get_article_content, list_content_articles, list_research_sessions, and get_research_session, and — with mcp:act — the two status tools set_content_article_status and set_research_session_status.
  • Business/Pro and higher: also the ten Search Console, GA4, and keyword read tools — get_integration_health, get_search_console_performance, get_ga4_performance, get_keyword_inventory, get_keyword_clusters, get_page_keyword_coverage, get_keyword_page_coverage, get_page_diagnosis, preview_keyword_research, and get_keyword_research_result.
  • Business/Pro and higher Full tokens: also generate_llms_txt through mcp:spend.
  • run_keyword_research remains OAuth-only even for a Full token: it spends on the end user's explicit confirmation, and a token has no signed-in user.
  • Approval, action-decision, ask_atlio, mark_applied, and CMS publishing tools (start_publish, report_publish, publish_article) remain OAuth-only. The two set_*_status tools are not CMS publishing and are available to Business/Pro+ tokens holding mcp:act.

The organization plan is evaluated at call time. Downgrading can immediately reduce a token's visible catalog; upgrading expands it without reminting the token.

On this page