Documentation » Tool Reference

Tool Reference

Every tool the Kafkai MCP server exposes, grouped by what it does. Tool names are stable identifiers — your agent sees exactly these names.

To see the tools in use before reading them one by one, start with the Example Prompts page; each prompt there lists the tools the agent calls behind it.

Conventions

  • Responses are JSON. Every tool returns a JSON document. Successful responses include a next_step_suggestion field: advice the server computes for the agent's next move (which tool to call, or what to search the web for). Agents follow these hints without special prompting.
  • Usage reporting. Metered tools append a _usage object showing what the call cost and your remaining balance. See Credits and Billing.
  • Limits. limit arguments are capped server-side (100 for keyword lists, 50 for clusters). Asking for more returns the cap, not an error. Lists longer than the cap are read a page at a time — see Reading a long list below.
  • Identifiers. Projects are addressed by project_id (from kafkai_list_projects), competitors by competitor_domain (from kafkai_list_competitors), and publishing destinations by destination_id (from kafkai_list_publishing_destinations).

Reading a long list

A research run can return far more keywords than one call should carry, so the list tools return one page at a time. Every paged response says where its page sits:

  • count — rows in this response.
  • total_matching — rows in the whole list the page came from.
  • offset — rows skipped to reach this page.

To read the next page, call the same tool again with offset raised by your limit. While rows remain, next_step_suggestion names the exact offset to use, so an agent walks a long list without being told how. A count smaller than your limit means the page is the last one. An offset past the end returns no rows and reports how many there are, rather than failing.

The keyword, cluster, backlink, Search Console and analytics list tools all take offset. The tools that return one short list — projects, competitors, publishing destinations — do not.

Each page is a separate call carrying its own flat call fee, so one call of 100 rows costs less than five calls of 20. Read in the largest pages a tool allows, and stop once you have what you need. See Credits and Billing.

Projects and competitors

kafkai_list_projects

Lists your projects with id, site URL, status, location, and keyword and competitor counts. This is the usual first call — later tools need the project_id it returns.

Arguments: none.

kafkai_get_project_summary

A full overview of one project: site metadata, niche, location, keyword counts per 4C strategy and for your own ranking baseline, the competitor list, and three blocks that say what data exists — authority (your site's strength next to each competitor's), backlinks (whether backlink data exists for your site and each competitor, with the whole-profile totals, and a next_step_suggestion naming which backlink tool to call) and search_console (whether Kafkai can read your site's Google Search Console property, whether the domain is verified for your account (domain_verified) and the window its data covers, with a next_step_suggestion that names the two Search Console tools or the step still missing: verifying the domain, or granting access). The response also names a recommended_strategy — the strategy with the most keyword opportunities — with the reason. last_research is the project's latest research run — a full update, or the research an added competitor bought: pending while it is still running, then its verdict (success, partial or failed) with the reason when something failed.

Arguments:

  • project_id — the project to summarise.

kafkai_list_competitors

Lists the competitor sites tracked in a project, with each competitor's keyword count and research status. A competitor whose research failed reads failed, with the reason in error; its keyword lists are incomplete, and the response's next_step_suggestion says how to retry — kafkai_update_keywords researches every domain again, or remove the competitor and add it again for the competitor fee. The response highlights the top_competitor by keyword count and carries last_research, the project's latest research run.

Arguments:

  • project_id

kafkai_find_competitors

Finds the sites a project's site competes with in search, from the keywords the site actually ranks for — not from a guess about its homepage. Kafkai takes the domains that rank for the same keywords in the project's country (the 1,000 largest sites on the web excluded), scores each by how much of the two keyword footprints overlap, sizes it against your site with the same winnability rule the 4C tools use, and drops review sites, marketplaces, listicle publishers and unrelated domains. Competitors the project already tracks are flagged already_tracked, so the list reads as "who else".

Each row carries domain, relationship (direct, adjacent, or unknown when it could not be judged), winnability, rank (0–1000), intersections (the keywords you share), overlap (that count as a share of both footprints, 0–1), avg_position, etv, keywords_count, sample_keywords and already_tracked. filtered_out counts the domains the judge dropped, and site gives your own keyword count, traffic estimate and rank. Rows are ordered direct competitors first, then winnable before avoid, then by overlap.

Two things to know when reading the rows:

  • A site Google does not rank for anything yet is answered from the searches its customers make (method is customer_searches, and seed_keywords lists them): who ranks on page one for those, smallest sites first. overlap, etv and keywords_count are empty on that path and winnability is unknown.
  • Kafkai returns the candidates and the evidence; which of them matter is your agent's reading. Adding one is a separate, priced step: kafkai_add_competitor.

Carries its own call fee, higher than a plain read, because the tool buys fresh competitor, authority and judgement data rather than returning what the project already holds; the per-row amount is the same as every other read. The answer is cached for a day, so a repeat call returns the same list. See Credits and Billing.

Arguments:

  • project_id
  • limit — max competitors to return (default 10, max 20).

kafkai_get_competitor_analysis

A focused analysis of one competitor: its brand description, the keywords it ranks for that you do not (Catch-up), and the keywords you both rank for (Compete). Higher base cost than a plain list.

Every keyword carries competitor_previous_rank and competitor_rank_change (and our_previous_rank and our_rank_change on Compete rows): the move since Kafkai's previous measurement.

Arguments:

  • project_id
  • competitor_domain — from kafkai_list_competitors.
  • include_history — set to true to include each keyword's dated positions: competitor_history for this competitor, our_history where you rank too.

Keyword research — the 4C strategies

The four strategy tools share their shape: each returns keyword objects with search volume, keyword difficulty, CPC, ranks, the ranking page's SERP title and description where relevant, tags, and freshness timestamps (first_seen, last_updated). A recommended subset highlights the strongest starting keywords by volume and difficulty.

Every rank is dated. Each keyword also carries the move of each side since Kafkai's previous measurement: our_previous_rank and our_rank_change where you rank, competitor_previous_rank and competitor_rank_change where the competitor does. A positive change means the position moved up. Catch-up, Consolidate and Compete also accept include_history: set it and each keyword carries the dated positions Kafkai has recorded for every side that ranks (our_history, competitor_history), oldest first, with unchanged positions collapsed. For "what moved over the last three months", use kafkai_get_ranking_changes below instead.

Catch-up, Consolidate and Compete each measure your site against a competitor, so they stay empty until the project has at least one. Complement does not — it works from your own topics, with or without competitors. To see what your site ranks for when no competitor is registered, use kafkai_get_ranked_keywords below.

All four take the same arguments:

  • project_id
  • limit — max keywords to return (default 20, max 100).
  • offset — rows to skip, for paging (default 0). The response's next_step_suggestion names the next offset while more rows remain, and total_matching says how many rows there are in all.
  • include_history — Catch-up, Consolidate and Compete only. Set to true to include the dated positions of each side that ranks.

kafkai_get_catchup_keywords

Catch-up: keywords competitors rank for that you do not — your content gaps. Each keyword shows which competitor ranks and with what title, so the agent knows exactly what page it is up against.

kafkai_get_consolidate_keywords

Consolidate: keywords you already rank for that competitors do not — the territory that is working and worth strengthening.

kafkai_get_compete_keywords

Compete: keywords where both you and a competitor rank — head-to-head battles. Both ranks are returned, so the agent can pick fights where the gap is small.

kafkai_get_complement_keywords

Complement: related keywords that neither you nor your competitors target yet — what to add next to the topic map. Each keyword is returned once, however many of your topics suggested it, so limit counts distinct keywords.

kafkai_get_keyword_clusters

Semantic clusters: groups of related keywords that one comprehensive article can cover together. Each cluster carries its average search volume, difficulty, and CPC, plus its member keywords. The response recommends the highest-volume cluster.

Arguments:

  • project_id
  • limit — max clusters (default 10, max 50).
  • offset — clusters to skip, for paging (default 0). The response's next_step_suggestion names the next offset while more clusters remain, and total_matching says how many there are in all.

Your own rankings

kafkai_get_ranked_keywords

Every keyword your site already ranks for, and how each position has moved. This is not one of the 4C strategies: those compare your site against a competitor, while this one reads your own positions directly. It works on a project with no competitors at all, which makes it the first useful call on a brand-new project.

Each keyword returns your current position, the previous one, the change since the last measurement, whether the keyword is newly ranking, plus search volume, difficulty, CPC and the page that ranks. A progress object tallies what improved, declined, stayed flat and is new, and how many keywords sit in the top 3 and top 10.

Set include_history and each keyword also carries the positions Kafkai has recorded over time, oldest first — enough to chart a trend. Unchanged positions are collapsed, so you get the moves rather than one point per update.

Three things to know when reading the numbers:

  • A keyword here may also appear under Consolidate or Compete. This is your whole ranking picture, not a slice of it.
  • progress counts only the keywords this call returned, not the whole project. The project-wide figure is total_ranked_keywords.
  • On the first call for a new project there is no earlier Kafkai measurement to compare against, so the change is counted from the position first seen.

Positions refresh when you run kafkai_update_keywords — that is what adds the next point to each keyword's history.

Arguments:

  • project_id
  • limit — max keywords to return (default 20, max 100).
  • offset — rows to skip, for paging (default 0). The response's next_step_suggestion names the next offset while more rows remain, and total_matching says how many rows there are in all.
  • include_history — set to true to include past positions for each keyword.

Ranking changes over time

kafkai_get_ranking_changes

Which keywords gained or lost positions over a period — for your own site, one competitor, or every competitor at once. Every rank Kafkai measures is dated, so the tool compares each keyword's position at the start of the period with its position now and sorts the biggest moves first. It answers "what moved in the last three months", "where is this competitor slipping", "which keywords did I lose", and "what are my opportunities from competitors' falling rankings".

Each keyword returns its movement — improved, declined, new (ranks now, did not at the period start) or lost (ranked at the period start, does not now) — with current_rank and measured_at, baseline_rank and baseline_measured_at, rank_change (positive when the position moved up), first_seen, search volume, difficulty, CPC and the ranking page. Competitor reports add competitor_domain and our_rank: where your site sits on the same keyword right now. A competitor sliding on a keyword you sit close behind, or do not rank for yet, is the opening to write for.

A summary counts what improved, declined, stayed unchanged, is new and is lost across every keyword measured for the site, not just the rows returned. Unchanged keywords are counted there and left out of the list.

Three things to know when reading the numbers:

  • Updates run on demand, so there is no measurement for "exactly 90 days ago". The baseline is the latest measurement at or before the period start, and baseline_measured_at says when that was.
  • When tracking began inside the period (period.tracked_since), the first measurement stands in for the period start, and the keywords from that first run are not "new".
  • Rows are merged per keyword, so a keyword that moved between strategies keeps one continuous history.

Positions refresh when you run kafkai_update_keywords — that is what adds the next dated measurement.

Arguments:

  • project_id
  • competitor_domain — empty for your own site, a competitor's domain (from kafkai_list_competitors) for that competitor, or all for every competitor merged into one list (the response then also carries competitor_domains and a by_competitor breakdown).
  • days — length of the period in days (default 90, max 365).
  • movement — all (default; every kind of move but unchanged), improved, declined, new or lost.
  • limit — max keywords to return (default 20, max 100).
  • offset — rows to skip, for paging (default 0). total_matching counts the rows that match movement; summary still counts the whole site.

Who links to your site and to each competitor, how strong those sites are, when each link was last seen, and how many links each site gained and lost over time. Kafkai returns the data; the reading — what the linking sites have in common, which lost link is worth chasing — is your agent's.

Kafkai fetches backlinks as part of every research run: for the site and each competitor when a project is created, for the new competitor when one is added, and for every site on kafkai_update_keywords. The three read tools below answer from that snapshot; kafkai_update_backlinks refreshes backlinks alone, without re-buying keyword data. Every response says when the snapshot was taken (as_of), and a site that has not been fetched yet says so instead of returning empty rows.

The sites linking to your site or to one competitor — one row per referring domain, its strongest link, strongest first. It answers "who links to competitor X", "how strong are the sites linking to me", and, with status set to lost, "which links did competitor X lose that I could win": every lost row names a site that once linked to a page like target_page and stopped, with last_seen dating the loss.

Each row carries referring_domain, referring_page, target_page, page_title, anchor, link_type, dofollow, link_rank, referring_page_rank and referring_domain_rank (0–1000, higher is stronger), spam_score, platform_types, country, first_seen, last_seen, is_lost, is_new, is_broken and links_from_domain.

Two things to know when reading the numbers:

  • profile holds the whole link profile: domain_rank, backlinks_total, referring_domains_total, the nofollow and broken counts, and the link type, platform, country and TLD mixes. Quote those totals for the size of the profile.
  • The rows are a sample of it. Kafkai stores the strongest link from up to 1,000 referring domains, and the strongest links lost within the last year. coverage says how many rows are stored and whether the live sample is complete, so an agent can say "the strongest 1,000 of 18,452" rather than imply it saw everything.

Arguments:

  • project_id
  • competitor_domain — empty for your own site, or a competitor's domain (from kafkai_list_competitors). One site per call.
  • status — live (default), lost (links that disappeared within the last year) or all.
  • limit — max rows to return (default 20, max 100).
  • offset — rows to skip, for paging (default 0). The response's next_step_suggestion names the next offset while more rows remain.

How many backlinks and referring domains a site gained and lost over a period — your own site, one competitor, or every site in the project side by side. Kafkai keeps a daily new/lost count for each site (a year of history from the first fetch), so the period is summed from that, with a month-by-month breakdown. It answers "how many links did competitor X win in the last three months", "is their link building accelerating", and "am I keeping pace".

Each site row carries status and as_of, totals_now (backlinks, referring_domains, domain_rank), period_totals (new_backlinks, lost_backlinks, net_backlinks, new_referring_domains, lost_referring_domains, net_referring_domains), by_month, and data_from / data_to — the days the stored history actually covers. A site whose status is not ready has no counts yet.

Arguments:

  • project_id
  • competitor_domain — empty for your own site, a competitor's domain (from kafkai_list_competitors), or all for your site and every competitor, one row each.
  • days — length of the period in days (default 90, max 365).

The sites that link to two or more of your competitors but not to you — the link gap. One row per referring domain, strongest first, with the link it gives each competitor (referring_page, target_page, anchor, dofollow, link_rank, last_seen). A site that already links to several competitors covers your topic and accepts links to sites like yours, so it is the first place to ask for one. Kafkai returns the rows; which sites to approach, and what to offer them, is your agent's reading.

Each row carries referring_domain, competitor_count, referring_domain_rank (0–1000, higher is stronger), spam_score, country and links. competitors_with_data and competitors_without_data say which competitors the answer covers.

Two things to know when reading the rows:

  • It needs backlink data for your own site — that is how "not linking to you" is decided — and for at least min_competitors competitors. Until then the response names the sites still missing and how to fetch them.
  • "Not linking to you" is judged against the stored sample of your live links (own_site_coverage, the same shape as coverage above), so a site outside that sample can appear in the list although it links to you.

Arguments:

  • project_id
  • min_competitors — how many competitors a site must link to before it counts as a gap (default 2, minimum 1). Pass 1 to see every site that links to any competitor but not to you.
  • limit — max rows to return (default 20, max 100).
  • offset — rows to skip, for paging (default 0). The response's next_step_suggestion names the next offset while more rows remain.

Fetches fresh backlink data for your site and every competitor in a project: the linking sites and their strength, the links lost in the last year with the date each was last seen, and a year of daily gained/lost counts. This is what the three read tools above answer from.

Backlinks are already fetched by kafkai_create_project, kafkai_add_competitor and kafkai_update_keywords. Use this tool to refresh them without re-buying keyword data — for a project created before backlinks existed, after a failed fetch, or when a day-old snapshot is not fresh enough.

The fetch runs in the background and takes about a minute per site. A site fetched within the last day is skipped, and a site whose fetch is still running is not fetched twice, so calling this twice in a row costs nothing extra. The response lists the sites it is fetching now (domains), the ones it skipped (skipped_fresh) and the ones already running (in_flight).

Charges a backlinks-only fee once per site actually fetched — smaller than a full update, because no keyword data is bought; see Credits and Billing.

Arguments:

  • project_id

Domain verification

Kafkai serves a site's own private data — its Search Console queries, pages and clicks today, other sources later — only to an account that has proved it controls the domain. The proof is one DNS TXT record on the project's registered (apex) domain — a project on blog.example.com is proved at example.com, and example.co.jp is proved at example.co.jp (the Public Suffix List decides what "registered" means, so a two-label country suffix is kept whole). One record opens every subdomain project for your account. The code is unique to your account and that domain. Two accounts can both verify one domain — a site owner and their agency, say — each with their own record. Both tools are free.

  1. Call kafkai_verify_domain with the project_id. The response's dns_record gives the record to add: type (TXT), name (the domain) and value (kafkai-verification= followed by the code).
  2. Add that record at the DNS provider for the domain.
  3. Call kafkai_check_domain_verification. Kafkai looks the record up; when it is there, status becomes verified. DNS changes usually show within minutes but can take up to 48 hours, so call again later if the record was not found yet.

Kafkai re-checks verified domains periodically. A record that is later removed stops the data until it is put back; the code stays the same, so there is nothing to redo but the record.

The same record, check button and status are on the Domains page of your account, one entry per domain — use it when you would rather copy the record from a browser than through the agent. Both paths share one code per domain.

kafkai_verify_domain

Starts verifying the project's domain, or returns the existing code, with the DNS record to add. Calling it again never changes the code.

Arguments:

  • project_id

The response carries domain (the project's registered domain, where the record goes), status (pending or verified), dns_record (type, name, value), verified_at, last_checked, last_error and a next_step_suggestion.

kafkai_check_domain_verification

Looks the record up now and reports the result in the same shape as kafkai_verify_domain. A missing record keeps status at pending and says in last_error what was looked for. A lookup that got no answer (a timeout) changes nothing; try again in a few minutes. Calling this before kafkai_verify_domain is fine: the code is created and the record to add is in the answer.

Arguments:

  • project_id

Search Console

Your own Google Search Console data, read by two tools. Kafkai's ranking data is a sample of search results; Search Console is what Google actually recorded for your site — every query it appeared for, with real clicks, impressions, click-through rate and average position. Together they answer what the rankings alone cannot: what people searched, which pages they clicked, and what changed.

Both tools describe one period: the latest 28-day window Kafkai has stored, compared with the 28 days before it. Every row and the property-wide totals carry clicks_change, impressions_change and position_change against that prior window. position_change is positive when your site moved up the page — the same sign the ranking tools use.

Two steps stand between a project and its data. While search_console.status is not_connected, both tools name the first one still missing in their next_step_suggestion, so your agent can pass it on to you.

  1. Verify the domain (see Domain verification above). Until then Kafkai serves nothing for the domain, not even whether a property exists.
  2. Grant Kafkai read access to the property. This is one step in Search Console, and shares nothing but an email address: open the property in Google Search Console, go to Settings > Users and permissions > Add user, enter the Kafkai reader address and choose the Restricted permission level. The address is in the next_step_suggestion once the domain is verified. For a walkthrough with screenshots, see Connect Google Search Console.

Kafkai picks the property up at the next research run (kafkai_update_keywords), backfills 16 months of history, and refreshes it at the end of every later run. Until the first sync finishes the status is syncing.

Two things to know when reading the numbers, both Google's doing:

  • Google leaves out the queries it anonymises, so the query rows add up to less than the property's true totals. totals are exact, and coverage reports the impressions the query rows carry (visible_impressions), the exact total (total_impressions) and the share between them (visible_impressions_share). The share is measured over the rows the call returns, so it describes what you can actually see.
  • Google Discover reports pages and totals but no queries, so search_type='discover' works with the pages and trend views only.

kafkai_get_search_console_data

The queries your site appears for, the pages that earn the traffic, or the daily totals — three views of one period.

  • view='queries' (default): one row per search query in the current window — query, clicks, impressions, ctr, position, the prior window's numbers under prior, and the three change fields.
  • view='pages': one row per page of your site, summed from Google's daily page figures, which are exact.
  • view='trend': one row per day, oldest first, taken from the recent end of the prior and current windows — enough to see the day traffic turned. Pass limit=100 for the whole series.

Every response carries search_console (property, status, domain_verified), window, prior_window and totals (current, prior and the change fields). Use it next to kafkai_get_ranked_keywords: a query here that the ranking data does not show is a real search Kafkai's sample missed.

Arguments:

  • project_id
  • view — queries (default), pages or trend.
  • order_by — for the queries view: impressions (default), clicks or position (best first). Pages are always ordered by impressions.
  • contains — only queries (or page URLs) containing this text, case-insensitive. The trend view has neither, so it ignores this and does not echo it back.
  • search_type — web (default) or discover.
  • limit — max rows to return (default 20, max 100). For the trend view it is a number of days counted back from the most recent, so limit=100 returns the whole series in one call. total_matching always says how many days the two windows hold.
  • offset — rows to skip, for paging (default 0). The trend view counts back from the most recent day, so offset steps further into the past. The response's next_step_suggestion names the next offset while more rows remain.

kafkai_get_search_console_insights

What to work on first, computed by Kafkai from your Search Console data. Five kinds of flag, each a query or page with the numbers behind it in evidence and a score to rank by within its kind:

  • striking_distance — queries ranking just off page one (positions 8–20 by default) with real impressions. Score: the extra clicks expected from reaching position 5.
  • ctr_gap — queries whose click-through rate is far below what their position normally earns on your site: usually a title or snippet problem, not a ranking problem. Score: clicks lost.
  • cannibalisation — one query split across two or more of your pages, each taking a real share of the impressions. Score: the impressions at stake.
  • new_query — queries your site newly appears for, compared with the prior window. Score: impressions.
  • decay — pages whose clicks dropped hard against the prior window, computed for web search and Google Discover separately. Score: clicks lost.

The response's definitions states each rule with the thresholds in force, and counts says how many flags of each kind exist. Scores compare within a kind only — the units differ. Kafkai computes the flags; deciding what to change is your agent's reading of the evidence, with kafkai_get_search_console_data for the surrounding rows.

Arguments:

  • project_id
  • insight_type — all (default) or one of striking_distance, ctr_gap, cannibalisation, new_query, decay. With all, limit and offset apply per kind.
  • limit — max rows to return per kind (default 20, max 100).
  • offset — rows to skip per kind, for paging (default 0).

Analytics

Your own traffic analytics, read by one tool. Search Console covers the search angle — what people searched for and what Google recorded. Analytics covers the whole visit: how many people came, which pages they opened, where they came from, and what they used to browse. It answers what the search data cannot: how much traffic the site gets overall, and what visitors do once they arrive.

Two steps stand between a project and its data, and the analytics.status block (not_verified, not_configured, unavailable, ready) names the one still missing in next_step_suggestion:

  1. Verify the domain (see Domain verification above). Until then Kafkai serves nothing for the domain, not even whether analytics tracking exists for it.
  2. Ask Kafkai support to set up tracking for the site. Kafkai sets it up on its own analytics instance; there is no customer-side setup, and nothing to connect afterwards: the first call finds the site automatically and keeps it. A site set up a moment ago can take up to ten minutes to appear. A project on a subdomain uses the site of its registered domain when it has none of its own.

unavailable means Kafkai could not reach its analytics service on this call; it says nothing about whether tracking exists. Try again in a minute.

Unlike Search Console there is nothing to wait for: the data is read live at call time, so once the status is ready the next call returns what the site holds right now.

kafkai_get_analytics_data

Traffic, pages, referrers, visitor location and devices, in 21 reports. By default it covers the last 30 days; pass period='day' and date='last30' for a daily time series.

Every response carries analytics (status, domain_verified, id_site, site_url), the report, a short description of the report, the period and date in force, count and rows. While more rows remain, next_step_suggestion names the offset for the next page.

Arguments:

  • project_id
  • report — one of: summary (default), pages, entry_pages, exit_pages, page_titles, outlinks, downloads, referrers, search_engines, keywords, social, websites, campaigns, countries, regions, cities, device_types, browsers, browser_versions, operating_systems, screen_resolutions. summary returns one metrics row — visits, unique visitors, actions, bounce rate and average visit duration; the rest return a list of rows.
  • period — day, week, month, year or range. Empty defaults to range.
  • date — empty defaults to the last 30 days. Examples: today, last30, 2024-01-01,2024-01-31 (for period='range').
  • segment — optional segment definition to filter visits.
  • limit — max rows to return for list reports (default 20, max 100). Ignored by summary.
  • offset — rows to skip, for paging (default 0).

kafkai_get_ga_analytics_data

The customer's own Google Analytics 4 data: traffic, pages, landing pages, channels, source/medium, countries, cities, devices, browsers, operating systems and key events. Read live from the customer's GA4 property — not stored, so there is nothing to sync or wait for once access is granted.

Same domain-verification gate as Search Console and analytics. The ga_analytics.status block (not_verified, not_connected, ambiguous, unavailable, ready) names the step still missing in next_step_suggestion:

  1. Verify the domain (see Domain verification above).
  2. In Google Analytics, go to Admin › Property access management › Add users, enter the Kafkai reader address and pick the Viewer role. Kafkai finds the property on the next tool call — no research run needed.

ambiguous means more than one GA4 property claims the site; contact Kafkai support with the property id to use.

Every response carries ga_analytics (status, domain_verified, property_id, property_name, stream_uri), the report, a short description, start_date and end_date in force, count, total, subject_to_thresholding and rows. GA4 can take 24-48 hours to process data, and may hide small rows for privacy — subject_to_thresholding says when that happened. Numbers will not match Search Console: GA4 counts sessions from all sources, Search Console counts clicks from Google Search.

Arguments:

  • project_id
  • report — one of: summary (default), daily, pages, landing_pages, channels, source_medium, organic_landing_pages, countries, cities, devices, browsers, operating_systems, key_events. summary returns one metrics row; the rest return a list of rows.
  • start_date — ISO date (2026-08-01) or GA4 relative date (30daysAgo, yesterday, today). Empty defaults to 30daysAgo.
  • end_date — ISO date or GA4 relative date. Empty defaults to yesterday.
  • limit — max rows to return (default 20, max 100). Ignored by summary.
  • offset — rows to skip, for paging (default 0).

SERP intelligence

kafkai_get_keyword_serp_data

Everything known about one keyword in a project: who ranks (domains, SERP titles, descriptions, URL types), your rank, competitor ranks, rank changes, search volume, difficulty, CPC, and tags. The response includes a ranking_context interpretation — for example, "competitor ranks #3, you don't rank — write content to capture this demand". If the exact keyword is not found, near matches are returned instead. Higher base cost.

Arguments:

  • project_id
  • keyword — the exact keyword to look up (falls back to a contains-match).

Project management

These tools change data. Research runs asynchronously — queue it, keep working, and check back with kafkai_get_project_summary.

kafkai_create_project

Creates a project for a site, adds any competitors you give, and queues the full keyword research — including the backlinks of the site and of each competitor (see Backlinks). Priced per site researched: a base fee for your site plus a competitor fee for each competitor you give; see Credits and Billing.

Arguments:

  • site_url — the site to analyse, for example https://example.com. Required.
  • site_name — a display name; defaults to the URL.
  • description — a short description of the site.
  • location_code — the country whose search results the project targets. Required, with no default. The code is 2 followed by the country's ISO 3166-1 numeric code: Japan is 2392, Malaysia 2458, the United States 2840. Call the tool without it and it fails for free, listing every market you can pick.
  • competitors_url — a list of competitor site URLs. Optional.

Competitors are optional, and you can add them later with kafkai_add_competitor. Without them, Catch-up, Consolidate and Compete stay empty — each needs a competitor to compare against — but Kafkai still collects your own ranking baseline and Complement keywords, so a project starts useful with nothing but a domain and a country.

A project is locked to one country. Research for the wrong country costs the same and tells you nothing, which is why Kafkai asks instead of guessing.

kafkai_add_competitor

Adds one competitor to an existing project and fetches only that competitor's data — its keywords and its backlinks. Existing competitors and the site itself are not re-fetched, so this is much cheaper than a full update: it charges the competitor fee once.

The research runs in the background and is logged like a full update; the response carries its update_log_id. Check kafkai_list_competitors a few minutes later: the competitor's status reads ready when its data is in, or failed with the reason in error. While the research runs, kafkai_update_keywords and the delete tools are refused for the project.

Arguments:

  • project_id
  • competitor_url

kafkai_delete_competitor

Removes one competitor from a project, together with every keyword Kafkai collected for it and that keyword's ranking history. Use it when a competitor was added by mistake and its unrelated keywords are polluting the Catch-up, Consolidate and Compete lists. Free.

The deletion is permanent, so the tool runs in two steps:

  1. Call it without confirmation_token. Nothing is deleted. The response lists what would be removed (keywords per strategy, research sessions, ranking history) and what would be kept, and includes a confirmation_token valid for 15 minutes.
  2. Your agent shows you that summary and asks you to confirm. Only then does it call the tool again with the same project_id and competitor_domain plus the token. The competitor is marked for deletion and its data is removed in the background; check with kafkai_list_competitors a few minutes later.

A token is bound to one competitor and one account. Reused for a different competitor, or after it expires, it is refused and nothing happens. The deletion is refused while a keyword update for the project is running; wait for it to finish and ask again.

Arguments:

  • project_id
  • competitor_domain — from kafkai_list_competitors; a full URL is accepted too.
  • confirmation_token — empty for the preview; the token from the preview to run the deletion.

kafkai_update_keywords

Queues a fresh ranking update for the whole project: all strategies and your own ranking baseline are re-fetched, ranks on existing keywords refresh, and keywords that dropped out are marked lost. This is what adds the next point to each keyword's position history, so run it before asking kafkai_get_ranked_keywords or kafkai_get_ranking_changes what moved. The backlinks of the site and of every competitor are refreshed in the same run (a site fetched within the last day is reused). Priced like creation: the base fee for your site plus the competitor fee for every competitor in the project.

Only one research run per project happens at a time; a second request while one is running — including the research an added competitor triggers — is refused. A project whose deletion you have confirmed cannot be updated either; that request is refused before anything is charged. Updates run on demand — Kafkai does not re-fetch rankings on its own schedule.

Arguments:

  • project_id

kafkai_delete_project

Deletes a project and everything in it: competitors, every keyword with its ranking history, and research sessions. Use it for a project you no longer need, or one that was set up with the wrong site. Free.

The deletion is permanent, so the tool runs in two steps:

  1. Call it without confirmation_token. Nothing is deleted. The response lists what would be removed (competitors, keywords per strategy, research sessions) and what is not touched, and includes a confirmation_token valid for 15 minutes.
  2. Your agent shows you that summary and asks you to confirm. Only then does it call the tool again with the same project_id plus the token. The project is marked as deleting and its data is removed in the background; check with kafkai_list_projects a few minutes later.

A token is bound to one project and one account. Reused for a different project, or after it expires, it is refused and nothing happens. Posts already published to your own site stay live, and publishing destinations and publication records belong to your account and are kept. The deletion is refused while a keyword update for the project is running; wait for it to finish and ask again.

Arguments:

  • project_id
  • confirmation_token — empty for the preview; the token from the preview to run the deletion.

Publishing

Kafkai does not write articles. Your agent writes the piece from the data above, then hands the finished text to Kafkai to publish. Kafkai keeps a snapshot of exactly what it sent — title, body, language — as the publication record; it holds no other copy of the article.

kafkai_list_publishing_destinations

Lists the active publishing destinations on your account — WordPress sites and webhooks — with each one's destination_id, name, type and URL. Destinations belong to the account, not to a project.

Arguments: none.

kafkai_add_publishing_destination

Adds a destination. For WordPress, pass the site URL and an application password; for a webhook, the endpoint URL and its credentials. The credentials are stored encrypted and never returned.

Arguments:

  • name — a label for the destination (unique on your account).
  • destination_type — wordpress (default) or webhook.
  • url — the site or endpoint URL.
  • auth_type — basic (default), api_key, bearer or oauth2.
  • credentials — the login details for that auth type.

kafkai_delete_publishing_destination

Removes a destination. Posts already published through it stay where they are, and their publication records are kept. Free.

Arguments:

  • destination_id

kafkai_publish_article

Publishes text your agent wrote to one destination and returns where the post went (external_url). Pass the body as HTML in content, or as Markdown in content_markdown — when content is empty, the Markdown is rendered to HTML for you, and webhook destinations also receive the Markdown as written. The post goes up as a draft unless you ask for it to go live, so you can review it on your own site first.

To update an existing post instead of creating a new one, pass its external_id (returned by a previous publish call). This edits the existing post on the destination rather than creating a duplicate.

Arguments:

  • project_id — the project the article was written for; its market sets the default language.
  • destination_id — from kafkai_list_publishing_destinations.
  • title
  • content — the body as HTML. Required unless content_markdown is given.
  • content_markdown — the body as Markdown.
  • language — e.g. en or ja. Defaults to the project's market language.
  • post_status — draft (default) or live.
  • categories — WordPress category names, e.g. ["Education", "Coffee"]. Categories that don't exist yet are created automatically. Ignored for webhook destinations (forwarded as-is).
  • slug — the URL slug for the post, e.g. my-first-article. Ignored for webhook destinations (forwarded as-is).
  • external_id — the ID of an existing post on the destination to update instead of creating a new one. Use the external_id returned by a previous publish call. When omitted, a new post is created.

Credits

kafkai_get_credit_balance

Your current balance, lifetime totals, and the last ten transactions with per-call cost breakdowns. Free — checking your balance never costs credits.

Credits are valid for 90 days from the day they are added, and the oldest are spent first. expiring lists every batch still unused with its valid_until — the last day those credits can be spent — soonest first, so an agent can tell you when to use what is left.

Arguments: none.