Skip to main content
Glama
administrator-prog

DataForSEO MCP Server

DataForSEO MCP Server

A production-ready remote MCP server that exposes the DataForSEO API v3 to Claude over the Streamable HTTP transport, designed to run on Railway.

It gives Claude access to essentially the whole DataForSEO surface — SERP, DataForSEO Labs, Keywords Data, Backlinks, OnPage, Business Data, Content Analysis, Merchant, App Data, Domain Analytics, Content Generation and AI Optimization — through 51 tools rather than several hundred, with cost controls, response normalisation and a strictly bounded generic request layer.

  • Endpoint: POST https://<your-app>.up.railway.app/mcp

  • Transport: Streamable HTTP (@modelcontextprotocol/sdk 1.30, stateless by default)

  • Stack: Node 20+, TypeScript, Express 5, Zod 4


Contents


Related MCP server: oncrawl-mcp-server

Architecture

src/
  server.ts              entry point: listen, graceful shutdown
  app.ts                 Express app: /, /health, /mcp, limits, error handling
  config.ts              env parsing; the only place credentials live

  mcp/
    server.ts            McpServer factory + model-facing instructions
    transport.ts         Streamable HTTP wiring, auth gate, origin gate, sessions
    context.ts           ToolContext (config, client, metadata, result builder)
    tools/               tool definitions, one module per domain
      discovery.ts keywords.ts domain.ts serp.ts backlinks.ts
      onpage.ts business.ts content.ts account.ts generic.ts helpers.ts

  dataforseo/
    client.ts            the single outbound HTTP path (auth, retries, logging)
    auth.ts              HTTP Basic header construction, forbidden headers
    endpoints.ts         family registry, allow-list, endpoint catalog, metadata sources
    errors.ts            DataForSEO status-code model → typed errors
    types.ts             response envelope types

  services/              per-family request building + normalisation
    serp.ts labs.ts keywords.ts backlinks.ts onpage.ts business.ts
    content.ts account.ts generic.ts metadata.ts types.ts

  normalizers/           DataForSEO response → concise SEO objects
    serp.ts keywords.ts labs.ts backlinks.ts onpage.ts business.ts content.ts common.ts

  schemas/common.ts      shared Zod fields, filter/sort validation, target normalisation
  utils/                 logger (redacting), redaction, TTL cache, semaphore, result builder

tests/                   vitest suite; all DataForSEO calls are mocked
scripts/
  verify-mcp.mjs         local Streamable HTTP + tools/list verification
  smoke.mjs              MANUAL smoke test against real DataForSEO credentials

Data flows in one direction: tool → service → client → DataForSEO, and back client → normaliser → result builder → tool. Only dataforseo/client.ts performs network I/O, and every request it makes passes validateEndpointPath() first.

Tool layers

Layer 1 — discovery. dataforseo_capabilities, dataforseo_locations, dataforseo_languages, dataforseo_endpoint_info. These let Claude learn what exists, resolve identifiers and confirm a path before spending money. dataforseo_capabilities and dataforseo_endpoint_info make no DataForSEO call at all.

Layer 2 — curated tools. 46 tools covering the common SEO workflows with strict Zod schemas, friendly parameters, resolved locations/languages and normalised output.

Layer 3 — the generic request. dataforseo_request reaches any documented endpoint under an allowed /v3/<family>/ prefix. New DataForSEO endpoints are usable the day they ship, without changing this server.

Available tools

Tool

What it does

DataForSEO endpoint

dataforseo_capabilities

Families, coverage, limits, workflow hints

(local)

dataforseo_locations

Search location codes by name

*/locations, dataforseo_labs/locations_and_languages

dataforseo_languages

Search language codes

*/languages

dataforseo_endpoint_info

Explain/validate an endpoint, live vs async

(local)

account_status

Balance, limits, prices

appendix/user_data

keyword_overview

Volume, CPC, competition, difficulty, intent

dataforseo_labs/google/keyword_overview/live

keyword_suggestions

Long-tail keywords containing a seed

dataforseo_labs/google/keyword_suggestions/live

related_keywords

"Searches related to" expansion (depth 0–4)

dataforseo_labs/google/related_keywords/live

keyword_ideas

Category-based keyword ideas

dataforseo_labs/google/keyword_ideas/live

search_intent

Informational/commercial/etc. classification

dataforseo_labs/google/search_intent/live

keyword_historical_volume

Monthly history per keyword

dataforseo_labs/google/historical_keyword_data/live

keywords_search_volume

Google Ads / Bing Ads volumes

keywords_data/{google_ads,bing}/search_volume/live

keyword_gap

Keywords a competitor has and you don't

dataforseo_labs/google/domain_intersection/live (intersections:false)

domain_overview

Organic/paid metrics for a domain

dataforseo_labs/google/domain_rank_overview/live

domain_ranked_keywords

Every keyword a domain ranks for

dataforseo_labs/google/ranked_keywords/live

page_ranked_keywords

Keywords for one URL

dataforseo_labs/google/ranked_keywords/live

domain_competitors

Organic competitors

dataforseo_labs/google/competitors_domain/live

domain_intersection

Keywords two domains share

dataforseo_labs/google/domain_intersection/live

page_intersection

Keywords where pages rank together

dataforseo_labs/google/page_intersection/live

relevant_pages

Best pages of a domain

dataforseo_labs/google/relevant_pages/live

serp_competitors

Domains ranking for a keyword set

dataforseo_labs/google/serp_competitors/live

bulk_traffic_estimation

Traffic for up to 1000 targets

dataforseo_labs/google/bulk_traffic_estimation/live

live_serp

Live SERP, 7 engines, many search types

serp/{engine}/{type}/live/advanced

rank_check

Where a domain/URL ranks for a keyword

serp/{engine}/organic/live/advanced

maps_serp

Google Maps / Local Finder results

serp/google/{maps,local_finder}/live/advanced

serp_task_post

Queue a SERP task (cheaper)

serp/{engine}/{type}/task_post

serp_task_get

Collect a SERP task

serp/{engine}/{type}/task_get/advanced/{id}

serp_tasks_ready

List finished SERP tasks

serp/{engine}/organic/tasks_ready

backlinks_summary

Backlink profile summary

backlinks/summary/live

backlinks

Individual backlinks

backlinks/backlinks/live

referring_domains

Referring domains

backlinks/referring_domains/live

backlink_anchors

Anchor text distribution

backlinks/anchors/live

backlink_competitors

Shared-referrer competitors

backlinks/competitors/live

backlinks_history

Monthly link history

backlinks/history/live

backlinks_bulk_metrics

Bulk rank/backlinks/spam/refdomains

backlinks/bulk_*/live

onpage_start_audit

Start a crawl (async)

on_page/task_post

onpage_audit_status

Crawl progress / finished crawls

on_page/summary/{id}, on_page/tasks_ready

onpage_summary

Site-level technical SEO results

on_page/summary/{id}

onpage_pages

Crawled pages + per-page checks

on_page/pages

onpage_issues

Duplicate tags/content, non-indexable, redirects, links

on_page/{issue_type}

onpage_resources

Images/scripts/stylesheets

on_page/resources

onpage_instant_page

Analyse one URL immediately

on_page/instant_pages

onpage_lighthouse

Lighthouse scores

on_page/lighthouse/live/json

onpage_force_stop

Stop a running crawl

on_page/force_stop

business_search

Search local business listings

business_data/business_listings/search/live

business_info

Google Business Profile (async)

business_data/google/my_business_info/task_*

business_reviews

Google reviews (async)

business_data/google/reviews/task_*

content_mentions

Brand/keyword citations

content_analysis/search/live

content_summary

Mention volume aggregation

content_analysis/summary/live

content_sentiment

Sentiment of mentions

content_analysis/sentiment_analysis/live

dataforseo_request

Any allowed /v3/ endpoint

(generic)

API family coverage

Family

Coverage

Notes

SERP

Direct + generic

Google (organic, maps, local finder, news, images, jobs, events, shopping, autocomplete, ai_mode…), Bing, Yahoo, YouTube, Baidu, Naver, Seznam. Live and task-based flows are first class. Less common Google verticals (finance, ads_search, dataset_search, screenshot, search-by-image) go through dataforseo_request.

DataForSEO Labs

Direct + generic

13 dedicated tools. keywords_for_site, subdomains, bulk_keyword_difficulty, historical_serps, categories, top_searches, and the Amazon / Google Play / App Store Labs datasets via dataforseo_request.

Keywords Data

Direct + generic

search_volume for Google Ads and Bing directly; keywords_for_site, keywords_for_keywords, ad_traffic_by_keywords, Google Trends, DataForSEO Trends and clickstream via dataforseo_request.

Backlinks

Direct + generic

7 tools cover the common profile work; referring_networks, intersections, timeseries, domain_pages*, remaining bulk endpoints via dataforseo_request.

OnPage

Direct + generic

Full async crawl lifecycle, pages, resources, links, duplicates, non-indexable, redirects, instant pages, Lighthouse. waterfall, keyword_density, microdata, raw_html, content_parsing, page_screenshot via dataforseo_request.

Business Data

Direct + generic

Listings search, Business Profile, reviews. Q&A, hotel searches/info, Trustpilot, Tripadvisor, social media via dataforseo_request.

Content Analysis

Direct + generic

Search, summary, sentiment directly; rating distribution, phrase/category trends via dataforseo_request.

Merchant

Generic

Google Shopping and Amazon products/ASIN/sellers.

App Data

Generic

Google Play and App Store searches, info, listings, reviews.

Domain Analytics

Generic

Technology detection and Whois with filters.

Content Generation

Generic

Generate, paraphrase, grammar check, meta tags, text summary.

AI Optimization

Generic

LLM responses/scrapers (ChatGPT, Claude, Gemini, Perplexity), LLM mentions, AI keyword volume.

Appendix

Direct + generic

account_status; errors/status via dataforseo_request.

Not reachable through this server: DataForSEO features that are not v3 REST endpoints — the client dashboards, webhook delivery to this server (you can still set postback_url / pingback_url on a task, but nothing here receives them), and any endpoint outside the thirteen /v3/ families above.

Local development

npm install
cp .env.example .env        # fill in DATAFORSEO_LOGIN / DATAFORSEO_PASSWORD
npm run dev                 # tsx watch on http://localhost:3000

npm run typecheck
npm test                    # mocked, no network, no cost
npm run build && npm run verify:mcp   # boots the built server and drives real MCP calls

Point any MCP client at http://localhost:3000/mcp, or use the MCP Inspector:

npx @modelcontextprotocol/inspector

Environment variables

Required:

Variable

Purpose

DATAFORSEO_LOGIN

DataForSEO API login (server-side only)

DATAFORSEO_PASSWORD

DataForSEO API password (server-side only)

PORT

HTTP port — Railway injects this automatically

Optional:

Variable

Default

Purpose

DATAFORSEO_SANDBOX

false

Route everything to sandbox.dataforseo.com (free, dummy data)

DATAFORSEO_BASE_URL

https://api.dataforseo.com

Override; must be an https *.dataforseo.com host

DATAFORSEO_TIMEOUT_MS

60000

Per-request timeout (max 180000)

DATAFORSEO_MAX_RETRIES

2

Retries for transient failures (never for task_post)

DATAFORSEO_MAX_CONCURRENCY

8

Max in-flight DataForSEO requests

MCP_AUTH_TOKEN

(unset)

Comma-separated bearer tokens required on /mcp

MCP_SESSION_MODE

stateless

stateless or stateful

MCP_SESSION_IDLE_TIMEOUT_MS

1800000

Stateful mode only: reap sessions idle this long

MCP_ALLOWED_ORIGINS

(unset)

Comma-separated allowed Origin values

PUBLIC_URL

(unset)

Public base URL, echoed on /

MAX_RESULT_ITEMS

50

Default rows per tool call

MAX_RESULT_ITEMS_HARD_CAP

1000

Absolute row ceiling

MAX_RESPONSE_CHARS

100000

Character budget per tool response

MAX_BATCH_ITEMS

100

Max keywords/targets per batched call

RATE_LIMIT_WINDOW_MS / RATE_LIMIT_MAX

60000 / 120

Rate limit on this server

MAX_REQUEST_BODY_SIZE

1mb

JSON body limit on /mcp

METADATA_CACHE_TTL_MS

21600000

Locations/languages cache TTL (6h)

LOG_LEVEL

info

debug/info/warn/error/silent

TRUST_PROXY

1

Express trust proxy setting

.env.example contains names only — never commit real values.

Railway deployment

  1. Push this repository to GitHub and create a Railway project from it.

  2. Railway detects Node via Nixpacks; railway.json pins the commands:

    • build: npm ci && npm run build

    • start: npm run start

    • healthcheck: /health

  3. Set variables in the Railway service:

    • DATAFORSEO_LOGIN, DATAFORSEO_PASSWORD (required)

    • optionally MCP_AUTH_TOKEN, PUBLIC_URL, LOG_LEVEL, limit overrides

    • do not set PORT manually; Railway provides it

  4. Deploy, then check https://<app>.up.railway.app/health.

Notes: /health returns 503 while credentials are missing, so a misconfigured deploy fails its healthcheck by design. trust proxy is on for Railway's proxy. SIGTERM triggers graceful shutdown (open MCP sessions closed, then the HTTP server). Nothing is written to disk — state is in memory only, so replicas and restarts are safe (stateless session mode is the default for exactly this reason). Docker is not required.

Connecting Claude

Claude.ai / Claude Desktop → Settings → Connectors → Add custom connector:

  • URL: https://<your-app>.up.railway.app/mcp

  • If MCP_AUTH_TOKEN is set, supply the token as a bearer token in the connector's authentication settings.

Claude Code:

claude mcp add --transport http dataforseo https://<your-app>.up.railway.app/mcp \
  --header "Authorization: Bearer <token>"

Ask Claude to call dataforseo_capabilities first — it returns the map of families, tools and limits.

DataForSEO authentication

DataForSEO uses HTTP Basic auth. This server:

  • builds the Authorization: Basic base64(login:password) header in dataforseo/auth.ts

  • attaches it inside DataForSeoClient.send() immediately before fetch

  • never places it on any object that is logged or serialised

  • never returns login, password, encoded credentials or authorization headers to the MCP client — account_status deliberately omits the account login, and /health reports only whether credentials are configured

Tool callers cannot supply headers at all, and dataforseo_request rejects bodies containing login, password, authorization, headers, credentials or api_key at any depth.

Asynchronous DataForSEO jobs

Task-based DataForSEO endpoints are exposed honestly — no request is ever held open waiting for a long job.

Workflow

Start

Poll / collect

SERP tasks

serp_task_posttask_id

serp_tasks_ready, then serp_task_get

Site crawls

onpage_start_audittask_id

onpage_audit_status until crawl_progress: "finished", then onpage_summary / onpage_pages / onpage_issues

Business Profile / reviews

business_info / business_reviews with action: "start"

same tool with action: "collect" and the task_id

Anything else

dataforseo_request on a task_post path

dataforseo_request on the matching task_get path

While DataForSEO is still working (status codes 40601/40602) the collect tools return ready: false with a note, rather than an error or a hanging request.

Cost controls

DataForSEO is usage-priced, so the defaults are deliberately conservative:

  • default limit is 50 rows (MAX_RESULT_ITEMS), hard-capped at 1000

  • keyword/target batches are capped at MAX_BATCH_ITEMS (100) with an explicit error rather than silent truncation

  • crawls default to max_crawl_pages: 100; SERP depth defaults to 100 elements

  • nothing recursively pages: next_offset is returned and Claude must ask for the next page

  • no tool fans out into multiple DataForSEO calls; bulk endpoints are preferred and documented in the tool descriptions

  • task_post is never retried, so a task cannot be created (and billed) twice

  • concurrency is bounded by a semaphore (DATAFORSEO_MAX_CONCURRENCY)

  • every response preserves DataForSEO's own accounting:

"usage": { "dataforseo_cost": 0.0123, "tasks_count": 1, "result_count": 100, "duration_ms": 812 }

Every outbound call is logged as one structured line (dataforseo_request) with endpoint, method, status, duration, cost and result counts — and never any credential.

Response modes and pagination

Every list-returning tool accepts:

  • response_mode: summary (headline fields) · standard (default; the useful SEO fields) · full (raw DataForSEO fields, still subject to MAX_RESPONSE_CHARS)

  • limit / offset, with pagination.next_offset returned when a full page came back

If a response would still exceed the character budget, rows are dropped from the end and an output_truncated block explains exactly what was omitted and how to narrow the request.

Locations, languages, filters and sorting

Pass natural values — "United Kingdom", "London,England,United Kingdom", "Marbella, Andalusia, Spain", "English", "Spanish" — and they are resolved against the correct per-family DataForSEO metadata list (SERP, Labs and Keywords Data use different location code sets). Numeric location codes and ISO language codes are accepted verbatim and skip the lookup entirely. Ambiguous names produce an error listing the candidates; metadata lists are cached in memory for METADATA_CACHE_TTL_MS.

DataForSEO's filtering power is preserved, not removed: filters accepts documented expressions such as

[["keyword_data.keyword_info.search_volume", ">", 1000], "and", ["keyword_data.keyword_info.cpc", "<", 5]]

Field paths, operators, value types and nesting depth are validated before the request is sent. order_by accepts up to 3 rules of the form "field,asc" / "field,desc".

The generic request layer

{
  "endpoint": "/v3/domain_analytics/technologies/domain_technologies/live",
  "method": "POST",
  "body": { "target": "example.com" },
  "response_mode": "standard",
  "item_limit": 50
}

Guarantees enforced by validateEndpointPath() and services/generic.ts:

  • the host is always the configured DataForSEO base URL; callers supply a path, never a URL

  • the path must start with /v3/ and sit under one of the thirteen allowed families

  • absolute URLs, protocol-relative paths, .., query strings, fragments, @, backslashes, whitespace and control characters are rejected

  • only GET and POST are possible

  • no header input is accepted, so authentication cannot be injected or overridden

  • credential-shaped body keys are rejected at any depth

  • bodies are capped at 128 KB and 100 task objects

It is an escape hatch for DataForSEO, not an HTTP proxy.

Security model

  • Credentials stay in config.credentials and the Authorization header; they are registered with the redaction layer so any accidental appearance in logs or tool output is masked.

  • MCP authentication is optional and pluggable: set MCP_AUTH_TOKEN for bearer auth (constant-time comparison, multiple tokens for rotation). The gate is one middleware in mcp/transport.ts, so OAuth can replace it without touching the DataForSEO integration. /health stays open for platform probes.

  • Origin validation (MCP_ALLOWED_ORIGINS) protects browser-originated callers against DNS rebinding; requests with no Origin (Claude, curl) are unaffected.

  • Rate limiting on /mcp via express-rate-limit, plus a JSON body size limit.

  • Error sanitisation: DataForSEO and internal errors become structured payloads (kind, message, hint, retryable); stack traces never reach the client.

  • No filesystem persistence, no eval, no dynamic endpoint construction from caller input beyond the validated path.

Adding a new high-level wrapper

  1. Add the endpoint to ENDPOINT_CATALOG in src/dataforseo/endpoints.ts (this powers discovery).

  2. Add a normaliser in src/normalizers/<family>.ts using byMode() so summary / standard / full all behave.

  3. Add a service function in src/services/<family>.ts that builds the task object, calls ctx.client.post(...) and returns { data, meta: metaFrom(response), notes?, pagination? }.

  4. Register the tool in src/mcp/tools/<family>.ts with defineTool() and a strict Zod schema (reuse schemas/common.ts fields).

  5. Add tests: schema rejection, a mocked happy path, and the normaliser.

Until a wrapper exists, the endpoint is already usable through dataforseo_request.

Testing

npm test          # 109 tests: credentials, allow-list, error parsing, location/language
                  # resolution, generic-request protection, normalisers, tool schemas, HTTP
npm run verify:mcp # Streamable HTTP initialize + tools/list against the built server
npm run smoke      # MANUAL only — real credentials; defaults to the sandbox

The automated suite mocks every DataForSEO call and never makes a paid request. scripts/smoke.mjs is the only script that talks to DataForSEO; it uses the sandbox unless you pass --production, and only makes a billed call with --production --paid.

Sandbox mode

DataForSEO offers a free sandbox at https://sandbox.dataforseo.com that mirrors the production response structure with dummy data. Set DATAFORSEO_SANDBOX=true to route every call there — useful for development and for verifying a deployment without spending credits. Responses are tagged with "sandbox": true so Claude knows the data is not real. Production behaviour is unchanged when the flag is unset.


Built against DataForSEO API v3 documentation and the Model Context Protocol specification as published in August 2026.

A
license - permissive license
-
quality - not tested
C
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Servers

  • A
    license
    B
    quality
    B
    maintenance
    A Model Context Protocol server that enables Claude to interact with DataForSEO APIs, allowing access to SEO data including SERPs, keyword research, on-page metrics, and domain analytics.
    17
    4,882
    238
    Apache 2.0
  • A
    license
    -
    quality
    F
    maintenance
    MCP server that exposes OnCrawl's API for use with Claude Code and Claude Desktop. Enables Claude to perform deep technical SEO analysis by querying crawl data, Google Search Console metrics, and crawl-over-crawl comparisons.
    2
    MIT
  • A
    license
    -
    quality
    A
    maintenance
    Production-grade MCP server for Microsoft Advertising (Bing Ads) API. Enables Claude to manage Bing/Microsoft Ads accounts with full campaign, ad group, keyword, and performance analysis capabilities.
    148
    4
    MIT
  • A
    license
    -
    quality
    D
    maintenance
    A Model Context Protocol (MCP) server that provides comprehensive SEO analysis tools with actionable fix instructions for AI assistants like Claude Code and Claude Desktop.
    MIT

View all related MCP servers

Related MCP Connectors

  • Hosted MCP with 91 agent tools: X, domains, SEO, Maps, Trends, Search, YouTube, TikTok, and more.

  • Live SEO workflow tools for Claude Code, Codex, and AI agents.

  • Hosted Amazon Seller Central and Amazon Ads MCP server for Claude, ChatGPT, Cursor, and agents.

View all MCP Connectors

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/administrator-prog/data-for-seo'

If you have feedback or need assistance with the MCP directory API, please join our Discord server