Announcing CIMD support for MCP Client registration
Learn more

MCP vs API for Integrating Semrush to AI Agents

Shri Mithran
Director of Marketing

Semrush hosts an official MCP server that reaches every SEO report through a discover, describe and execute pattern, and keeps the API agencies have built reporting on for years. Both read the same data and spend the same API units. They diverge on writes, on Local SEO, on which plan unlocks them and on whose key every request runs under. This guide compares both for an SEO agent, shows why units make spend a production risk, and how to run a key per client.

TL;DR

  • Semrush hosts an official remote MCP server at https://mcp.semrush.com/v2/mcp over Streamable HTTP. It exposes 14 tools: 12 discovery tools such as domain_overview, keyword_research, and backlinks_research, plus get_report_schema and execute_report, which together reach every SEO API report, Trends API reports your plan includes, and read-only Projects API (v3) data. It has no write path and no Local API coverage. Semrush's docs mark the page "new" and don't publish a GA or beta label.
  • The MCP server takes OAuth 2.1 by default, or Authorization: Apikey YOUR_API_KEY for clients without OAuth. The REST API takes API keys only for SEO, Trends, and Projects: a v3 key passed as the key query parameter (one per account, auto-generated, and it "can't be revoked or deleted"), or v4 keys in Authorization: Apikey, up to 100 per account, each with a read-only or read-and-write permission and its own expiration.
  • Both paths spend the same API units. MCP access comes with Semrush One Starter and Pro+ and SEO Classic Pro and Guru, with 50,000 units that refresh on renewal; direct Standard API keys require the Business subscription, which starts with zero units until you buy a package. One loose execute_report call on domain_organic at 10 units per line can eat a fifth of a Pro allowance.
  • MCP is the faster path for an SEO lead asking Claude or ChatGPT which keywords a competitor gained last month. The API is the right path for scheduled client reporting, backlink monitoring across many customer domains, and anything that writes: Position Tracking projects, Map Rank Tracker campaigns, listings, and review replies.
  • Scalekit's semrush connector is a REST connector built by Scalekit with 54 tools (35 read-only, 14 write, 5 destructive) over backlinks, keyword metrics, projects, Map Rank Tracker, Listing Management, Google Business Profile, and reviews. Each user connects their own Semrush API key once, Scalekit stores it encrypted, and the agent never sees it, so the MCP vs API decision doesn't change your auth infrastructure.

The decision your Semrush agent forces first

Your agent does SEO work for your customers. It needs to explain why a client's organic traffic dropped after a core update, find the referring domains that link to three competitors but not to the client, pull search volume for a list of keywords before a content brief goes out, or check how a dentist's practice ranks on Google Maps across a five-mile grid. Semrush now hosts an official Model Context Protocol (MCP) server and ships connectors for Claude, ChatGPT, Perplexity, Copilot, and Notion on top of it. It also has the API that agencies have built reporting on for years. They read the same data and bill the same API units. They diverge on writes, on Local SEO, on which plan unlocks them, and on whose key every request runs under. Here's how to pick.

What Semrush MCP and Semrush API actually are

Semrush MCP

The Semrush MCP server is hosted by Semrush at https://mcp.semrush.com/v2/mcp and supports Streamable HTTP only. Nothing runs locally. Earlier third-party setup guides point at /v1/mcp; Semrush's current docs list only /v2/mcp. Connecting Claude Code is one line: claude mcp add semrush https://mcp.semrush.com/v2/mcp -t http, then /mcp to sign in. Semrush also lists official apps or connectors for Claude, ChatGPT, Microsoft Copilot, Perplexity, Lovable, and Notion, and config snippets for Cursor, VS Code, and Antigravity. Semrush announced the Perplexity connector on June 3, 2026, and PPC Land reported the Claude connector on August 26, 2026.

The server's 14 tools follow a discover, describe, execute pattern. Twelve discovery tools map to Semrush report families: domain_overview, organic_research, keyword_research, competitors_research, backlinks_research, audience_research, traffic_overview, paid_search_research, shopping_research, position_tracking, site_audit, and projects. The model picks a report, calls get_report_schema for its parameters, and runs it with execute_report. Semrush describes the data scope as all SEO API endpoints, all Trends API endpoints subject to your subscription, and read-only Projects API (v3) methods: "users can read project data but cannot create projects, change settings, or take other actions."

Access needs an eligible plan. The SEO data comes with Semrush One Starter, Semrush One Pro+, SEO Classic Pro, or SEO Classic Guru, which include 50,000 API units refreshed on renewal; SEO Classic Business and Semrush One Advanced get MCP with a units package of 2M, 5M, 10M, or 20M. Traffic and market data needs a Trends API Basic or Premium plan. Semrush says there are no MCP usage fees beyond units.

Semrush API

The Semrush API is several APIs under one key system (API overview):

  • Standard API: SEO (v3 and v4): domain, keyword, and backlink analytics. The v3 analytics reports are GET requests to https://api.semrush.com/ with a type such as domain_organic and return semicolon-separated CSV. The v4 resources live under https://api.semrush.com/apis/v4/, for example /keywords/v1/metrics and /backlinks/v1/overview, and return JSON. Semrush marks the v3 keyword and backlink methods deprecated in favor of v4.
  • Standard API: Projects (v3 and v4): Position Tracking and Site Audit campaigns, keywords, competitors, tags, and audit runs, read and write.
  • Trends API (v3): clickstream traffic and market data, Basic or Premium, with a default of 10,000 requests per month and no Standard API units.
  • Local API (v4): Listing Management, Review Management, Google Business Profile Tool, and Map Rank Tracker. Review Management, GBP Tool, and Map Rank Tracker use no API units.

Auth is an API key. The v3 key goes in the key query parameter, there is "only one v3 key in your account that's generated automatically," and it "can't be revoked or deleted." v4 keys go in Authorization: Apikey <YOUR_API_KEY>; you can create up to 100, each "Read-only" (GET only) or "Read and write", each with its own TTL. OAuth 2.0 survives only for the deprecated Projects and Listing Management APIs, through a Device Authorization Grant (RFC 8628) or a Support-issued client, with 7-day access tokens.

Standard API access is gated harder than MCP. Semrush's how to get the API page says to "Upgrade to the Business subscription to buy API units and generate an API key," and after upgrading, "the number of units will still be zero."

Comparing them where it matters for agents

What your agent can actually do

Capability
Semrush MCP
Semrush API
Domain overview, organic and paid keywords
Yes
Yes: Domain reports at 10 to 100 units per line
Keyword volume, difficulty, and ideas
Yes
Yes: Keyword metrics at 20 units per request
Competitor and gap analysis
Yes
Yes: Domain comparison reports and backlink competitor and gap reports
Backlink profiles, anchors, and history
Yes
Yes
Traffic and audience data
Limited: Only with a Trends API plan
Limited: Trends API, Basic or Premium, 10,000 requests per month by default
Read Position Tracking and Site Audit results
Yes
Yes
Create projects, add keywords, run audits
No
Yes: Projects API write methods; Scalekit includes project deletion
Map Rank Tracker grid rankings
No: Not in MCP data scope
Yes: Map Rank Tracker campaigns, scans, heatmaps and metrics
Business listings and GBP
No
Yes: Listing Management and GBP Tool
Review replies
No
Yes
Change notifications
No: Semrush says MCP "doesn't monitor anything or send alerts"
No: No webhooks in Semrush's API docs; agents poll on a schedule

The read side is close to parity. Because execute_report can run any SEO API report, the MCP server reaches the same domain, keyword, and backlink data the Standard API does, and on Pro and Guru plans it reaches it without a Business upgrade. Everything else splits cleanly. The MCP server cannot change anything in Semrush, and it doesn't touch the Local API at all. An agent that manages Position Tracking campaigns, runs Map Rank Tracker scans for multi-location clients, or replies to Google reviews is an API agent.

What the MCP path makes easier

Semrush's API is wide and terse. "Which keywords does competitor.com rank for in the top 10 that we don't" on the raw API means knowing the report is domain_organic (or domain_organic_organic for the comparison), knowing the database code, building export_columns=Ph,Po,Nq,Cp,Ur,Tr from two-letter column codes, encoding a display_filter, and parsing semicolon-separated CSV. The v4 backlink resources are JSON, but scope must be one of ROOT_DOMAIN, SUBDOMAIN, SUBFOLDER, or PAGE, and not every method accepts every value.

On MCP, the model calls organic_research to find the right report, get_report_schema to learn its parameters, and execute_report to run it. Semrush owns the mapping from intent to report to parameters, across v3 and v4. Writing the schema is the hard part. Not the API call.

The tradeoff is that Semrush owns the surface, and the surface is a meta-tool. Two tools decide everything the model does, so tool selection tells you little about cost or scope until the execute_report arguments land. The endpoint path has already moved from /v1/mcp to /v2/mcp. An agent tuned against today's report schemas can change behavior without a release on your side.

The auth path each one puts you on

On the MCP path, OAuth 2.1 is the default: the client redirects the user to Semrush's login page and the grant carries that user's Semrush account and plan. Semrush's troubleshooting note says a "redirect URI ... is not allowed" or 400 error during OAuth means contacting Semrush Support, so a custom MCP client in your own product should expect a redirect allowlisting step, not self-service registration. Clients that can't do OAuth send Authorization: Apikey YOUR_API_KEY. For Claude Team and Enterprise, Semrush also supports enterprise-managed authorization, where a corporate account owner trusts exactly one issuer, either Claude or Okta, and members sign in through it.

On the direct API path, every credential is an account key. The v3 key is the sharp edge for agents: one per account, generated automatically, never revocable. A leaked v3 key is a permanent liability until Semrush Support intervenes. v4 keys fix most of that. You can mint a key per integration, mark it "Read-only" so POST, PUT, PATCH, and DELETE fail, and give it a TTL so it expires on its own. Map Rank Tracker "requires a Version 4 API key," and Scalekit's own quickstart for the semrush connector calls semrush_get_map_rank_limits, so a v4 key is the one to hand the connector.

Semrush adds a twist that matters for agents: every key is an account, and units are an account balance. There is no per-user scope inside a Semrush account. Two people at the same agency sharing a Semrush login share one key's reach, one 10-requests-per-second limit, and one unit balance. What the user can't do, the agent can't do, but in Semrush "the user" is the account.

Both paths still need per-user isolation

In a multi-tenant B2B agent, MCP's OAuth flow gives you a token per user and the direct API gives you a key per user or per customer account. In neither case does the path itself solve storage, rotation, or revocation; those are infrastructure problems regardless of which path you choose.

Semrush makes the boundary financial as well as about access. If your agent runs every customer's queries through one Semrush key, every customer's backlink audit spends your units, every customer's loop counts against your 10 simultaneous requests, and every customer can see whatever your projects contain if the prompt lets a project_id through. With a key per customer, each customer's agent spends that customer's units and sees that customer's projects. That multiplies the keys you hold.

Recommended reading: OAuth vs API keys for AI agents

What you own in production

On the MCP path, Semrush hosts the server, owns the report schemas, and enforces the account's plan. You own each user's OAuth session if your product is the MCP client, or a key per account if it runs headless. You also own the unit budget, which is the real production risk. A model that runs execute_report on domain_organic without a display_limit can return thousands of lines at 10 units each, or 50 each for historical data. A 100-row backlink gap at 40 units per row is 4,000 units. On a 50,000-unit Pro allowance, a few curious conversations exhaust the month, and Semrush's own guidance is to specify result counts, databases, and filters in the prompt.

On the API path, you own report selection, CSV and JSON parsing, pagination, retries, and the key lifecycle. Semrush's usage restrictions cap every account at 10 requests per second and 10 simultaneous requests, and forbid caching data for more than a month without written consent. When units run out, per-line SEO and Trends reports return only the lines your balance covers, then ERROR 132; Projects and Local APIs return 403 (API unit balance). A partial result that looks complete is the failure mode to guard against. GET https://www.semrush.com/users/countapiunits.html?key=YOUR_API_KEY returns the remaining balance, so a pipeline can check before it spends. Requests that return no data cost nothing.

There are no webhooks to react to. On both paths, a rank drop or a new toxic backlink is something your agent discovers on a schedule.

When to use MCP, when to use the API

Use Semrush MCP when:

  • An SEO lead in Claude or ChatGPT asks "which of our top 20 keywords lost positions since the March core update, and who took them," and organic_research plus execute_report answer it in one conversation.
  • A content strategist wants keyword volume, difficulty, and related terms for a brief, with a human deciding how many rows are worth the units.
  • Your team is on SEO Classic Pro or Guru, or Semrush One Starter or Pro+, and needs agent access to SEO data without upgrading to Business to get a Standard API key.
  • A marketer is exploring a competitor's traffic and audience in Perplexity, Copilot, or Notion, where Semrush already ships the connector.

Use the Semrush API when:

  • The agent produces monthly client reports for 40 agency clients as a deterministic pipeline, with fixed reports, fixed display_limit values, and a unit check before each run.
  • The workflow writes: creating Position Tracking projects, adding keywords and competitors, running Site Audits, or creating and collecting Map Rank Tracker campaigns.
  • The agent manages Local SEO for multi-location businesses: updating listings, reading GBP metrics, and replying to reviews through Review Management, none of which the MCP server exposes.
  • You need a key you can scope and expire: a v4 "Read-only" key with a TTL for a reporting agent, separate from the read-and-write key a provisioning job uses.

The credential problem that exists on both paths

Both paths hand you a Semrush credential. Neither hands you a vault. An agency platform serving 120 client businesses, each with its own Semrush account, holds 120 keys on the API path, or 120 OAuth grants on the MCP path if your product is the client. On the API path, each key is a unit balance and a 10-requests-per-second budget, not just a secret. If a customer gives you their v3 key, it can never be revoked; if they give you a v4 key, it may expire on a TTL you didn't set, and your agent finds out when a scheduled report returns 403. Each must be stored encrypted, kept out of logs and LLM context, mapped to exactly one customer, and deleted when that customer churns.

The tempting shortcut is your own Business account and one key for everyone. Fewer secrets, larger blast radius per secret: one leaked key spends your whole unit balance, one runaway loop throttles every customer at once, and every customer's agent can read every project in your account.

Scalekit's semrush connector stores each user's Semrush API key encrypted in the token vault and injects it into every call, so the MCP vs API decision doesn't change your auth infrastructure. Your agent passes an identifier; credentials never touch the agent runtime or the LLM context.

Recommended reading: why a token vault matters for AI agent workflows

How to connect a Semrush agent with Scalekit

Scalekit's semrush connector is an API-path connector built by Scalekit with 54 tools: 35 read-only, 14 write, and 5 destructive. It covers v4 backlink analytics, keyword metrics, projects, Map Rank Tracker, Listing Management, the Google Business Profile tool, and Review Management. It authenticates with API keys: each user connects their own Semrush API key once, and Scalekit sends it with every call. The core set for SEO analysis:

Tool
What it does
semrush_get_backlinks_overview
Aggregated backlink metrics for a domain, subdomain, subfolder, or page; 45 units per request
semrush_get_authority_score_distribution
Referring domains grouped by authority score from 0 to 100
semrush_list_backlink_competitors
Competitor domains ranked by shared referring domains
semrush_get_backlink_gap
Referring domains shared across up to 6 targets; 40 units per row
semrush_list_anchors
Anchor texts used in backlinks to a target
semrush_get_backlinks_history
Monthly authority score, backlinks, and referring domains; 40 units per row
semrush_get_keyword_metrics
Search metrics for one keyword in one country; 20 units per request
semrush_get_map_rank_limits
Map Rank Tracker campaign slots and remaining credits

Prerequisites and the connection name

In the Scalekit dashboard, go to AgentKit > Connections and create a Semrush connection. The name you give it is the connection_name your code passes, and the string must match the dashboard exactly. This is the most common integration error.

Ask each customer for a v4 key generated for your integration, not their account's v3 key. A v4 key can be deleted when they leave, given a TTL, and marked "Read-only" if your agent only reports. Copy SCALEKIT_ENVIRONMENT_URL, SCALEKIT_CLIENT_ID, and SCALEKIT_CLIENT_SECRET from Developers > API Credentials into .env.

pip install scalekit-sdk-python python-dotenv langchain-openai

Authorize each user once

get_or_create_connected_account returns the connected account for an identifier. If it is not ACTIVE, get_authorization_link returns a link to Scalekit's Hosted Connect Widget. For an API-key connection like Semrush, the widget shows a form where the user enters their key instead of an OAuth consent screen. Scalekit encrypts and stores it; your code never receives it. The identifier should map to one Semrush account, because a key acts as exactly one account and spends exactly one unit balance. semrush_get_map_rank_limits then confirms the key works and is a v4 key.

import os from dotenv import load_dotenv from scalekit import ScalekitClient load_dotenv() scalekit_client = ScalekitClient( env_url=os.environ["SCALEKIT_ENVIRONMENT_URL"], client_id=os.environ["SCALEKIT_CLIENT_ID"], client_secret=os.environ["SCALEKIT_CLIENT_SECRET"], ) actions = scalekit_client.actions CONNECTION_NAME = "semrush" # must match the connection name in AgentKit > Connections identifier = "client_acme_dental" # your app's stable ID for this customer's Semrush account account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name=CONNECTION_NAME, identifier=identifier, ) print("Open this link and enter your Semrush API key:", link.link) input("Press Enter after submitting the form...") account = actions.get_or_create_connected_account( connection_name=CONNECTION_NAME, identifier=identifier, ) if account.connected_account.status != "ACTIVE": raise RuntimeError(f"Semrush is {account.connected_account.status}, not ACTIVE") limits = actions.execute_tool( tool_name="semrush_get_map_rank_limits", tool_input={}, connection_name=CONNECTION_NAME, identifier=identifier, ) print(limits.execution_id, limits.data)

Retrieve the Semrush tools this account can call

This is not a catalog load. The agent asks for the tools this connected account is authorized to call, then narrows them to the seven a backlink analyst needs. Loading all 54 Semrush tools would put semrush_delete_project, semrush_delete_location, and semrush_add_review_comment in front of a model whose job is to compare link profiles. None of the seven below changes anything in Semrush.

tools = actions.langchain.get_tools( identifier=identifier, connection_names=[CONNECTION_NAME], tool_names=[ "semrush_get_backlinks_overview", "semrush_get_authority_score_distribution", "semrush_list_backlink_competitors", "semrush_get_backlink_gap", "semrush_list_anchors", "semrush_get_backlinks_history", "semrush_get_keyword_metrics", ], page_size=100, ) tool_map = {t.name: t for t in tools} print(sorted(tool_map))

Run the agent loop

The loop runs until the model stops requesting tools. Every call spends this customer's API units, so the system prompt sets row limits the way Semrush recommends, and the loop stops the model after a fixed number of tool calls.

from langchain_core.messages import HumanMessage, SystemMessage, ToolMessage from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-4o").bind_tools(tools) messages = [ SystemMessage( "You analyze backlink profiles in Semrush. Every call spends the customer's " "API units, so keep limit at 20 or less on any per-row tool and never page " "past the first result set. Use scope ROOT_DOMAIN for domains such as " "example.com. Start with semrush_get_backlinks_overview for the client, then " "semrush_list_backlink_competitors, then semrush_get_backlink_gap with the " "client first in urls. Country codes are two letters and the United Kingdom " "is UK. Report numbers exactly as returned and never invent domains." ), HumanMessage( "Our domain is acmedental.com. Which referring domains link to at least two " "of our top three backlink competitors but not to us? Rank them by authority " "score and tell me what search volume 'emergency dentist' has in the US." ), ] MAX_TOOL_CALLS = 12 tool_calls_made = 0 while True: response = llm.invoke(messages) messages.append(response) if not response.tool_calls: print(response.content) break for tc in response.tool_calls: tool_calls_made += 1 tool = tool_map.get(tc["name"]) if tool_calls_made > MAX_TOOL_CALLS: result = "Tool budget reached for this run. Answer with what you have." elif tool: result = tool.invoke(tc["args"]) else: result = f"Unknown tool: {tc['name']}" messages.append(ToolMessage(content=str(result), tool_call_id=tc["id"]))

Deterministic calls with execute_tool

For pipelines, skip the model. execute_tool runs one tool with a fixed input and returns data plus an execution_id you can log. This monthly job runs per client: it reads the backlink overview at 45 units, the last six months of history at 40 units per row, and the keyword metrics for the client's tracked head terms at 20 units each. The unit cost is fixed before it runs, which is the property an agency billing model needs and an open-ended MCP conversation can't give you.

from datetime import date client_domain = os.environ.get("CLIENT_DOMAIN", "acmedental.com") head_terms = ["emergency dentist", "teeth whitening", "dental implants"] this_month = date.today().strftime("%Y-%m") overview = actions.execute_tool( tool_name="semrush_get_backlinks_overview", tool_input={ "scope": "ROOT_DOMAIN", "url": client_domain, "fields": "backlinks_count,domains_count,score", }, connection_name=CONNECTION_NAME, identifier=identifier, ) print(overview.execution_id, overview.data) history = actions.execute_tool( tool_name="semrush_get_backlinks_history", tool_input={ "scope": "ROOT_DOMAIN", "url": client_domain, "fields": "score,backlinks_count,domains_count", "limit": 6, }, connection_name=CONNECTION_NAME, identifier=identifier, ) print(history.execution_id, history.data) for term in head_terms: metrics = actions.execute_tool( tool_name="semrush_get_keyword_metrics", tool_input={"keyword": term, "country": "US", "month": this_month}, connection_name=CONNECTION_NAME, identifier=identifier, ) print(metrics.execution_id, term, metrics.data) # Budget: 45 + (6 x 40) + (3 x 20) = 345 API units per client per month

The writes are where the API path earns its place. semrush_create_map_rank_campaign and semrush_collect_map_rank_campaign set up and run a Google Maps grid scan, and collection spends Map Rank Tracker credits equal to grid points times keywords, which semrush_get_map_rank_limits reports before you start. semrush_add_review_comment posts a reply to a Google review. Neither belongs in a model's default tool set; both fit a pipeline with a human approval step in front of them, and neither exists on the Semrush MCP server.

Reaching Semrush reports outside the connector

The tools we could verify in Scalekit's semrush connector cover v4 resources. For a v4 endpoint the connector doesn't wrap, Scalekit's proxied API calls keep the customer's key in the vault. v3 analytics reports such as domain_organic are different: the v3 key travels in the key query parameter, so that call and that key stay in your code. The raw shape, including the two failure modes that matter, looks like this:

import csv import io import os import requests SEMRUSH_API = "https://api.semrush.com/" api_key = os.environ["SEMRUSH_API_KEY"] balance = requests.get( "https://www.semrush.com/users/countapiunits.html", params={"key": api_key}, timeout=30, ) balance.raise_for_status() remaining = int(balance.text.strip()) display_limit = 50 cost = display_limit * 10 # domain_organic: 10 units per line, 50 for historical data if remaining < cost: raise RuntimeError(f"Need {cost} units, {remaining} left; skip this run") resp = requests.get( SEMRUSH_API, params={ "type": "domain_organic", "key": api_key, "domain": "competitor.com", "database": "us", "display_limit": display_limit, "display_sort": "tr_desc", "export_columns": "Ph,Po,Nq,Cp,Ur,Tr", }, timeout=60, ) resp.raise_for_status() if resp.text.startswith("ERROR"): # ERROR 132 means the unit balance hit zero; rows before it may be partial raise RuntimeError(resp.text.strip()) rows = list(csv.DictReader(io.StringIO(resp.text), delimiter=";")) if len(rows) < display_limit: print(f"Got {len(rows)} of {display_limit} rows; check units before trusting totals") for row in rows: print(row)

The v3 key in that key parameter ends up in request URLs, which is where proxies and access logs keep it. That's one more reason to prefer v4 keys in the Authorization: Apikey header for anything new.

Multi-tool, multi-tenant Semrush agents on a virtual MCP server

The semrush connector has 54 tools. At roughly 200 tokens each, that is about 10,800 tokens of tool definitions before the agent does any work. A model choosing among semrush_get_backlinks_overview, semrush_compare_backlink_profiles, semrush_get_backlinks_history, and semrush_get_authority_score_distribution picks the wrong report more often than a model holding only the one it needs, and in Semrush the wrong report costs units. Overreach is the bigger risk: a reporting assistant that also holds semrush_delete_project and semrush_update_location can remove a client's tracking history or change a business's hours on a bad inference. The fix is not better prompting. It is surface reduction. A Scalekit virtual MCP server declares exactly which tools an agent role can see, and session tokens keep each run bound to one user's connected accounts. Docs: set up a virtual MCP server.

Create the server once per agent role

from scalekit.actions.models.mcp_config import McpConfigConnectionToolMapping vmcp = actions.mcp.create_config( name="semrush-backlink-reporter", description="Reports backlink and keyword changes for a client from Semrush and posts a Slack summary", connection_tool_mappings=[ McpConfigConnectionToolMapping( connection_name="semrush", tools=[ "semrush_get_backlinks_overview", "semrush_get_backlinks_history", "semrush_list_backlink_competitors", "semrush_get_backlink_gap", "semrush_get_keyword_metrics", ], ), McpConfigConnectionToolMapping( connection_name="slack", tools=["slack_send_message"], ), ], ) print(vmcp.config.id, vmcp.config.mcp_server_url)

Mint a session token per user, per run

One server definition serves every customer. Before each run, check that the customer's accounts are active and mint a short-lived session token scoped to them. Any MCP client that speaks Streamable HTTP can connect; this example uses langchain-mcp-adapters (pip install langchain-mcp-adapters) and passes the token as a Bearer header.

import asyncio from datetime import timedelta from langchain_mcp_adapters.client import MultiServerMCPClient config_id = vmcp.config.id mcp_server_url = vmcp.config.mcp_server_url user_id = "client_acme_dental" accounts = actions.mcp.list_mcp_connected_accounts( config_id=config_id, identifier=user_id, include_auth_link=True, ) not_ready = [ a for a in accounts.connected_accounts if str(a.connected_account_status).upper() != "ACTIVE" ] for a in not_ready: print(f"{a.connection_name} is {a.connected_account_status}: {a.authentication_link}") if not_ready: raise RuntimeError("Connect the accounts above before starting this run") session_token = actions.mcp.create_session_token( mcp_config_id=config_id, identifier=user_id, expiry=timedelta(minutes=30), ).token async def load_tools(): client = MultiServerMCPClient( { "scalekit": { "transport": "streamable_http", "url": mcp_server_url, "headers": {"Authorization": f"Bearer {session_token}"}, } } ) return await client.get_tools() mcp_tools = asyncio.run(load_tools()) print([t.name for t in mcp_tools])

The agent sees six tools instead of 54 plus everything Slack exposes. The endpoint is static; the identity is per user. Semrush's MCP docs describe no way to narrow its server like this: every client gets the same 14 tools, and execute_report can run any report the account's plan allows.

Observability: every Semrush action tied to a user

Every execute_tool call returns an execution_id, and every execution is attributed to a connected account, which maps to one customer and one Semrush account. When a client asks why their API units ran out on the 9th, or who deleted a Position Tracking project, the answer is a lookup, not an investigation. Because each tool's unit cost is published per request or per row, your execution log is also a spend log you can reconcile against the balance from countapiunits.html.

Attribution is where the paths differ. Semrush records usage against the account behind the key. If one key serves every user of your product, Semrush sees one account doing everything, and your execution log is the only place that records which user and which prompt spent the units. Shared credentials work for a single user. They do not survive a second user.

Recommended reading: audit trails for agent auth

Which one to build against

If your agent is an SEO lead's or content strategist's assistant in Claude, ChatGPT, or Perplexity, answering questions about keywords, competitors, and backlinks with a person deciding what's worth the units, Semrush's hosted MCP server is a good fit, and on Pro or Guru plans it's the only way to reach Standard API data without a Business upgrade. If your agent runs on a schedule for many clients, needs a fixed unit cost per run, writes projects or Map Rank Tracker campaigns, or manages listings and reviews, build against the Semrush API, where you choose the report, the row limit, and a v4 key you can scope and expire. Either way, you hold a Semrush key per customer that is also that customer's unit balance, and that's what needs production-grade infrastructure.

FAQs

Does Semrush have an official MCP server?

Yes. Semrush hosts a remote MCP server over Streamable HTTP with 14 tools: 12 discovery tools for report families plus a schema tool and an execute tool that together reach every SEO API report, the Trends reports your plan includes and read-only project data. Semrush also ships connectors for Claude, ChatGPT, Perplexity, Copilot and Notion.

Can the Semrush MCP server change anything?

No. Semrush says users can read project data but cannot create projects, change settings or take other actions, and the server has no Local API coverage. Creating Position Tracking projects, running Map Rank Tracker scans, updating listings and replying to reviews all require the API.

How do Semrush API units affect an agent?

Both paths spend the same units, often per returned line. A loose report request without a row limit can return thousands of lines at 10 or more units each, so a few curious conversations can exhaust a 50,000-unit monthly allowance. Set row limits, cap tool calls per run and check the balance before scheduled jobs.

How do Semrush API keys work?

The v3 key is one per account, generated automatically, passed as a query parameter and cannot be revoked or deleted. Version 4 keys go in a request header, up to 100 per account, each read-only or read and write with its own expiration. Prefer v4 keys for any agent integration.

Which Semrush plans include MCP and API access?

MCP access comes with Semrush One Starter and Pro+ and SEO Classic Pro and Guru, with 50,000 units refreshed on renewal, while higher plans buy larger unit packages. Standard API keys require the Business subscription, which starts with zero units until you buy a package. Traffic data needs a Trends API plan.

How does Scalekit connect an AI agent to Semrush?

Each customer enters a Semrush API key once on a hosted page, and Scalekit stores it encrypted in a vault and sends it with every call. The connector exposes 54 tools, 35 read, 14 write and 5 destructive, covering backlinks, keyword metrics, projects, Map Rank Tracker, listings, Business Profile and reviews.

Build your Semrush agent with Scalekit

Browse the Scalekit Semrush connector and the Semrush connector docs with the full tool list. See Scalekit pricing, or talk to us.

No items found.
On this page
Share this article
Scalekit
Find us on ProductHunt

Acquire enterprise customers with
‍zero upfront cost.

Every feature unlocked. No hidden fees.