Yandex Webmaster MCP: Setup and Site Diagnostics

Connect Yandex Webmaster to Codex, Claude Code or Cursor with Docker, OAuth, ready-to-use prompts and a real opatsay.com report.

12.09.2026 · 9 min read

Yandex Webmaster MCP lets an agent check which pages are in search, inspect Yandex diagnostics and retrieve search-query reports. I built this open-source Go server for my SEO Agent. It fetches data through the Webmaster API so an agent can show the evidence behind a recommendation.

This guide takes you from a demo without credentials to connecting Codex, Claude Code, Cursor or VS Code and reading your first report. The project is independent and is not an official Yandex product. You run it on your computer or server. The Docker route requires Docker Compose; any AI-client subscription or hosting costs are separate.

Illustration: Yandex Webmaster reports connected to an AI agent through MCP

1. Run the demo without an OAuth token

Run these commands in order. The build uses the source code in your checkout.

git clone https://github.com/tenqz/webmaster-mcp.git
cd webmaster-mcp
docker compose -f compose.demo.yml up -d --build
docker compose -f compose.demo.yml exec mcp /mcp-server --smoke http://127.0.0.1:8080/mcp

The demo returns explicitly synthetic data and makes no Yandex requests. A successful smoke check verifies MCP and a representative set of tools. It does not yet establish access to your website.

  • MCP URL on this computer: http://localhost:8080/mcp.
  • Client header: Authorization: Bearer demo-token.
  • Demo host: https:example.invalid:443.

If the port is occupied, choose another one: HTTP_PORT=18080 docker compose -f compose.demo.yml up -d --build. Use port 18080 in the client; the smoke command inside the container still uses 8080.

2. Connect your AI client

Choose one client. These examples connect to the local demo. For a live installation, use its URL and MCP_AUTH_TOKEN. The Yandex OAuth token stays on the MCP server. A client running on another computer or in the cloud cannot reach your computer through its own localhost: it needs an HTTPS address it can access.

Codex

Add a section to ~/.codex/config.toml, keeping your existing settings:

[mcp_servers.yandex_webmaster]
url = "http://localhost:8080/mcp"
bearer_token_env_var = "MCP_AUTH_TOKEN"

For the demo, start Codex CLI from a terminal with this environment variable:

export MCP_AUTH_TOKEN=demo-token
codex

Use /mcp in the conversation to inspect connected servers. The app or IDE extension also needs the variable in its own environment: exporting it in a separate terminal does not update an already running application. See the official Codex MCP documentation for the configuration format.

Claude Code

For the local demo, run these commands in Bash:

export MCP_AUTH_TOKEN=demo-token
claude mcp add-json --scope user yandex-webmaster '{"type":"http","url":"http://localhost:8080/mcp","headers":{"Authorization":"Bearer ${MCP_AUTH_TOKEN}"}}'
claude

Single quotes around the JSON preserve the environment-variable reference; Claude Code resolves it from its own environment. Use your MCP token for a live installation. Check the connection with /mcp. This config is for Claude Code, not a Claude Desktop configuration file. See the Claude Code documentation.

Cursor

Add the server to your private ~/.cursor/mcp.json, merging it into any existing mcpServers object:

{
  "mcpServers": {
    "yandex-webmaster": {
      "url": "http://localhost:8080/mcp",
      "headers": {"Authorization": "Bearer ${env:MCP_AUTH_TOKEN}"}
    }
  }
}

Cursor must inherit MCP_AUTH_TOKEN=demo-token when it starts. Enable the server in MCP settings. For VS Code, the client guide provides a configuration that prompts privately for the token. It also explains client differences and Claude Desktop limitations.

Make your first request: “Call list_hosts through Webmaster MCP and show the exact identifiers of available sites.” The demo should return https:example.invalid:443. This verifies the path from your client to a tool result.

3. Connect your Yandex account

Your site must be added and verified in Webmaster under the appropriate Yandex account. Stop the demo and create the local settings file first:

docker compose -f compose.demo.yml down
test -f .env || cp .env.example .env

If you chose another demo port, add HTTP_PORT=18080 to .env, substituting your port number. Use that same port in the client. The command above preserves an existing .env.

  1. Open Yandex OAuth application registration. The step-by-step access guide explains the fields and permissions.
  2. Obtain a user OAuth token with webmaster:hostinfo and set YANDEX_WEBMASTER_TOKEN in .env.
  3. Generate a separate secret with openssl rand -hex 32 and set MCP_AUTH_TOKEN. Your AI client uses this secret.
  4. For automated collection, set MCP_READ_ONLY=true. Start the live server and verify access:
docker compose up -d --build
docker compose exec mcp /mcp-server --smoke http://127.0.0.1:8080/mcp

Replace the demo token in your client environment with the live MCP token and reconnect. The server has no built-in browser OAuth login. Mounted secrets are supported through YANDEX_WEBMASTER_TOKEN_FILE and MCP_AUTH_TOKEN_FILE; do not configure both a file and the corresponding inline value. The HTTPS and Docker deployment guide covers remote access.

4. Ask for a report you can verify

Call list_hosts and let me choose a site. Use host_id exactly as returned. Fetch get_summary and get_diagnostics. Show the source metrics, PRESENT problems and UNDEFINED checks separately. State the request time and any data dates supplied by the source. Do not submit URLs for recrawling.

https:example.com:443 and http:example.com:80 identify different hosts. Do not construct host_id from the domain yourself. In diagnostics, ABSENT means a particular problem is absent; UNDEFINED does not mean a check passed. The request time is also different from the time Yandex last updated a metric.

A real example: what Webmaster returned for opatsay.com

On 12 September 2026 at 14:29:23 UTC, I read reports for my site through a running Webmaster MCP instance. list_hosts returned the verified host https:opatsay.com:443. I then called get_summary, get_diagnostics and get_insearch_history. These are live account data, separate from the synthetic demo above.

The get_summary call used {"host_id":"https:opatsay.com:443"}. Here is its returned structuredContent:

{
  "excluded_pages_count": 4,
  "searchable_pages_count": 50,
  "site_problems": {},
  "sqi": 0
}

The summary reported 50 pages in search and 4 excluded pages. Diagnostics returned 32 ABSENT checks, no PRESENT problems and one UNDEFINED check: NOT_MOBILE_FRIENDLY. The empty site_problems object in the summary is therefore not a substitute for reading diagnostics.

I requested history with date_from=2026-08-29 and date_to=2026-09-11. The source returned only three observations:

{
  "history": [
    {
      "date": "2026-09-07T10:00:02.566+03:00",
      "value": 19
    },
    {
      "date": "2026-09-09T10:00:06.709+03:00",
      "value": 48
    },
    {
      "date": "2026-09-10T10:10:02.445+03:00",
      "value": 50
    }
  ]
}

The number of pages in search changed from 19 to 50 between these observations. This is not a traffic metric or evidence that new articles or a redesign caused the change. Three observations should not be presented as a complete daily series.

Next action: inspect the reasons for excluding the four pages in Webmaster, and assess mobile layout separately. UNDEFINED establishes neither a mobile-layout problem nor a passed check. This summary gives no basis for submitting every URL for recrawling.

14:29:23 UTC is the time of my request. Yandex supplied the dates of historical observations. The server did not provide a single freshness timestamp for the summary, so I do not invent one. How this workflow relates to the server design.

Five tasks for the next conversation

Specify your chosen site and requested period. Ask the agent to retain the actual available dates and sampling limitations in every answer.

Pages in search

Fetch get_insearch_history and get_insearch_samples for the selected host_id. Show how the page count changed and a few URLs from the sample. Do not present a sample as the complete index; state the available period.

Search queries

Fetch get_popular_queries. Show queries, impressions, clicks and available positions. Calculate CTR where both metrics exist and impressions are greater than zero. Suggest queries worth investigating; do not replace missing values with zeros.

Robot downloads

Compare get_indexing_history and get_insearch_history. Separate pages downloaded by the robot from pages present in search. State which changes are visible in the data and which explanations remain unconfirmed.

Sitemaps

Fetch get_sitemaps. Show known sitemap files and available processing information. Say when data is missing. Do not treat a sitemap as proof that every URL is indexed.

Recrawl status without submitting anything

Fetch get_recrawl_quota and get_recrawl_queue. Show the remaining quota and available tasks. Submit nothing. If a previous submission had an unknown outcome, explain what the queue establishes.

When an agent can submit a URL for recrawling

submit_recrawl is the only write tool. It consumes daily quota and does not promise immediate inclusion in search. With MCP_READ_ONLY=true, 33 tools are available: recrawl submission is hidden from discovery and direct calls are rejected too. The default mode provides 34 tools.

Submissions are never retried automatically. If a request may already have reached Yandex, outcome_unknown means uncertainty, not a confirmed failure. Inspect the queue before deciding whether another submission is necessary.

If the connection or report does not work

The server returns 401

If the MCP endpoint returns the error, check the URL, Authorization header and MCP_AUTH_TOKEN. The demo uses demo-token. If the Yandex token itself has expired, update YANDEX_WEBMASTER_TOKEN on the server and recreate the container.

Yandex returns 403, or the host list is empty

Read the tool error code first: unauthenticated may mean an invalid OAuth token even with HTTP 403; replace that token. For permission_denied, check the account, OAuth permissions and site verification. Use a host from list_hosts, including its scheme and port. Issuing a new token does not grant access to somebody else’s site or verify your own.

Queries or history are empty

Check the host, period and whether Webmaster has data. An empty report can be valid. It does not establish zero traffic, an empty index or successful diagnostics.

The client cannot see recrawl submission

Check MCP_READ_ONLY. Hiding this tool is expected for an automated reader.

Do I need a separate server?

A local client can use MCP on the same computer. Continuous SEO Agent collection needs a running service. A remote client needs an HTTPS endpoint it can reach; this project does not provide a shared hosted service holding your data.

See the README troubleshooting section for additional errors, quotas and timeouts.

How I use MCP in SEO Agent

Webmaster MCP retrieves reports. SEO Agent stores observations and dates in PostgreSQL, while SEO Version Control records page changes. GSC MCP and ahref provide additional sources. This history helps compare events, but does not by itself prove that a particular edit caused a change in search traffic.

The Webmaster MCP engineering case shows the system boundaries, request limits and tests for blocked writes and uncertain recrawl outcomes. It links the design decisions to source code you can inspect.

Source code and installation · Client configurations · What MCP does

Oleg Patsay

Engineering Leader — AI, Architecture & Complex Systems

I design and evolve complex software systems, from architecture and engineering practice to AI-enabled development.

GitHub LinkedIn Telegram Contact

Let's make the complex understandable.

Architecture, engineering leadership, and AI in development — when the system is too important to simplify, and too expensive not to own.

LinkedIn Telegram Email