Keyword research for AI agents: search volume, CPC and difficulty over MCP
AI-generated: an AI agent built this Actor with me and drafted this post from its code and test runs. The numbers, outputs and code come from the published Actor, and I checked them before publishing. Ask an AI agent how many people search for "keyword research" each month and it will guess. For SE

AI-generated: an AI agent built this Actor with me and drafted this post from its code and test runs. The numbers, outputs and code come from the published Actor, and I checked them before publishing.
Ask an AI agent how many people search for "keyword research" each month and it will guess. For SEO work a guess is worse than nothing, so I built a tool the agent can call instead: Keyword Research API. It is an Apify Actor that returns Google keyword data, and it works as an MCP tool in Claude, Cursor or any other MCP client.
This post covers what it returns, how an agent uses it, and four things I learned building a pay-per-event Actor.
You send keywords and a country. Each keyword comes back as one flat row. This is a real row from a test run this morning (US, English):
{ "keyword": "keyword research", "search_volume": 135000, "cpc": 16.68, "competition_level": "LOW", "low_top_of_page_bid": 3.63, "high_top_of_page_bid": 26.33, "keyword_difficulty": 88, "search_intent": "informational", "trend": { "monthly": 233, "quarterly": 233, "yearly": 508 }, "data_status": "ok", "source_endpoint": "dataforseo_labs/google/keyword_overview/live" } Enter fullscreen mode Exit fullscreen mode The row also holds monthly_searches for the last 12 months. Keywords the source has no data for come back with data_status: "no_data" and are not charged.
{ "mode": "domain", "domain": "example.com", "location": "GB", "maxIdeas": 50 } Enter fullscreen mode Exit fullscreen mode It works for every country Google Ads serves, by ISO code or by country name. 94 countries get every metric; the others get the Google Ads metrics (volume, CPC, competition and bids).
Apify exposes Actors through its MCP server, so there is nothing to host. In Claude Code:
claude mcp add --transport http apify "https://mcp.apify.com/?tools=gaelasao/keyword-research-api" --header "Authorization: Bearer $APIFY_TOKEN " Enter fullscreen mode Exit fullscreen mode Clients that support OAuth, such as Claude, Cursor or VS Code, can use https://mcp.apify.com/?tools=gaelasao/keyword-research-api without a token: you sign in to Apify on first use.
Get search volume, CPC, difficulty and intent for these 40 keywords in Germany, and sort them by volume.
Which keywords bring competitor.com the most traffic in the UK? Show the top 30 with their ranking pages.
The agent sends the same JSON input as above and gets the same rows back. The price per keyword is fixed, so the agent can work out the cost before it runs.
Apify users set a maximum cost per run. The data comes from DataForSEO, which bills me per request, so the Actor must never buy data it cannot charge for. Before each batch it books budget for the rows it can still bill (simplified from src/billing.js ):
// How many more rows the user's spending limit can pay for, keeping room for the start event. rowsAffordable () { const remaining = this. maxTotalChargeUsd - this. chargedUsd () - ( this. startCharged? 0: this. startPrice ); const byPrice = Math. max ( 0, Math. floor ( Number (( remaining / this. rowPrice ). toFixed ( 4 )))); return Math. min ( byPrice, this. manager. calculateMaxEventChargeCountWithinLimit ( EVENTS. row )); } // Books budget before buying data, so concurrent batches never buy more than can be billed. reserve ( count ) { const granted = Math. max ( 0, Math. min ( count, this. rowsAffordable () - this. reserved )); this. reserved += granted; return granted; } Enter fullscreen mode Exit fullscreen mode When the cap is reached, the run stops cleanly, keeps every row already delivered and says what the rest would cost, for example: "Stopped at your $1.00 maximum cost per run: 495 keywords with data. Raise it to $2.01 to get the other 505."
On Apify, only paying users generate revenue. Runs from free accounts bring nothing, yet each one still costs me data. So free accounts can try the Actor on 20 keywords per run. The platform tells the Actor who is paying through an environment variable (simplified; the real check also exempts my own account so I can test):
export function isFreePlanRun ( env ) { return env. APIFY_IS_AT_HOME === ' 1 ' && env. APIFY_USER_IS_PAYING!== ' 1 '; } Enter fullscreen mode Exit fullscreen mode 3. The daily Store test runs your prefilled input Apify tests every public Actor once a day with the values prefilled in its input form. If more than half of the runs in three days fail, the Actor is labelled "under maintenance". My prefill is five US keywords: the test passes and costs about one cent of data a day.
I renamed the Actor through the API to put "search volume" in the title. The Store page changed at once, but Store search still showed the old title more than 13 hours later. Pushing a new build refreshed it immediately, and the Actor went from outside the top 250 to 59th for "search volume". If you edit your listing through the API, push a build afterwards.
$2 per 1,000 keywords with data, plus $0.01 per run that returns data, with lower prices on higher Apify plans. Keywords without data, duplicates and failed batches are free.
Bing volumes and "AI search volume" are the two features other keyword tools offer that this one doesn't have yet. If you would use either, tell me in the comments.