MARTECH

Webmaster MCP

Connecting Webmaster to my agent, with explicit boundaries for reads, quotas, cancellation and uncertain writes.

A self-hosted Go MCP server for my SEO Agent: indexing, diagnostics and search reports, a read-only mode and bounded access to the Yandex API.

Go · MCP · Yandex Webmaster · Docker

Role

Project author: architecture, Go development, Yandex API integration, MCP, testing and containerization.

Open source · September 2026. This case describes the published implementation. Examples and checks use commit fad9a869, with source links pinned to that version.

The working context

I am building SEO Agent for my own sites. It collects search metrics on a schedule and compares them with page history. I already have a separate MCP server for Google. Yandex Webmaster became the next source: I need its indexing, search inclusion and diagnostic reports so the agent can explain which evidence supports a conclusion.

I built Webmaster MCP in Go as a separate, self-hosted service using Streamable HTTP, MCP tools and the Yandex REST API. It retrieves data; interpretation and historical storage belong to SEO Agent. The MCP server has no persistent application database, which lets me verify the integration independently of the collector.

System boundaries
  1. SEO AgentScheduling, analysis and history in PostgreSQL
  2. Webmaster MCPGo, report access, permissions and request bounds
  3. Yandex APIWebmaster data and the recrawl queue

The agent uses an MCP bearer token. A separate Yandex OAuth token stays on the MCP server. SEO Agent records collection timestamps and history.

A workflow: check a site's indexing

I start with list_hosts. The agent receives the available sites and uses the returned host_id exactly, for example https:example.com:443. The protocol and port matter: constructing an identifier from the domain alone can select the wrong host.

  1. get_summary provides an overview of the site, its pages and reported problems.
  2. get_diagnostics provides diagnostic messages to inspect before proposing an explanation for a metric change.
  3. get_insearch_history provides the history of pages in search, while get_insearch_samples supplies a sample of URLs for further investigation.

I distinguish crawler downloads from search inclusion: the former use get_indexing_* tools, the latter get_insearch_*. A URL sample is not a complete index inventory, and an empty response alone does not prove that pages are absent. Reports need to retain the selected host, date range and source limitations.

Using it on opatsay.com: evidence before a recommendation

On 12 September 2026 at 14:29:23 UTC, I performed four read operations through a running Webmaster MCP instance: list_hosts, get_summary, get_diagnostics and get_insearch_history. Discovery returned https:opatsay.com:443 as a verified Yandex host.

The summary returned 50 pages in search and 4 excluded pages. For the requested period of 29 August–11 September, history contained three observations: 19 pages on 7 September, 48 on 9 September and 50 on 10 September. Diagnostics returned 32 ABSENT states, no PRESENT problems and UNDEFINED for NOT_MOBILE_FRIENDLY.

This example exercises the data boundaries: the agent can report a change in page counts, but cannot call it traffic growth, attribute it to a redesign or declare every check passed. The next steps are to investigate excluded URLs and check mobile layout separately. The report itself requires no write to Yandex.

Parameters, source responses and interpretation. This is a live observation of my own site, not demo data or a measured SEO impact of the product. Request time is kept separate from historical dates.

Decision 1: enforce the read-only boundary

The scheduled collector needs reports. Submitting a URL for recrawl changes external state and consumes daily quota, so I added MCP_READ_ONLY=true for SEO Agent.

This mode exposes 33 tools. It removes submit_recrawl from discovery and rejects a direct call using its known name. The second check matters: hiding a tool from a catalog does not enforce an access boundary. A dedicated MCP test covers that behavior. The default mode exposes 34 tools, including recrawl submission.

Decision 2: a write timeout is not a rejection

If a recrawl request reaches Yandex but its response times out, the service may already have accepted the URL. Automatically sending it again could create an unnecessary operation. The client therefore never automatically retries recrawl submissions.

A timeout or cancellation after dispatch produces outcome_unknown with retryable: false. This confirms neither success nor rejection. Before deciding to resubmit, inspect get_recrawl_queue and, when a task identifier is available, get_recrawl_task. I added a regression test for this case so a general retry policy cannot silently start replaying writes.

Decision 3: bound the entire read operation

Yandex work has a shared time budget: 30 seconds by default, including the wait for a concurrency slot and retry attempts. Reads can retry transient failures, but each attempt does not receive a fresh 30 seconds. Cancellation covers both queued work and upstream requests.

A process allows eight concurrent Yandex operations by default, and response bodies are capped at 8 MiB. These bounds constrain waiting and memory use. They do not replace provider quotas: adding replicas increases aggregate pressure because each replica has its own concurrency limiter.

How I verify the result

The public repository includes a reproducible demo with explicitly labelled synthetic data. It makes no Yandex requests and allows connection checks without an OAuth token. HTTP integration tests use the real MCP SDK, bearer authentication and a fake upstream transport to exercise successful calls, validation and integration failures.

The checks answer different questions. /health confirms that the process is running. The built-in smoke check verifies tool discovery and a representative set of calls; with a live configuration, it also checks access to Yandex data. A successful demo does not establish OAuth permissions, access to a particular site or correct HTTPS deployment.

The implemented and tested contract provides 33 tools for automated reading, 34 in the default mode, an explicit uncertain-write outcome and bounded upstream work. Search-traffic impact has not been measured here.

The public code exposes the tool catalog and registration, request bounds and retry policy, and an HTTP → authentication → MCP → API integration test.

While preparing this case, tests passed for internal/webmaster, internal/mcpserver and cmd/mcp-server, including targeted checks for direct recrawl rejection and write timeouts. An isolated demo passed the smoke check with nine tool calls. These checks ran on published commit fad9a869.

Limits and the next step

One installation uses one OAuth token. There is no isolation for unrelated users, distributed rate limiter or browser-based Yandex login. Separate owners need separate installations. The service also cannot establish that an article edit caused a change in search performance.

My next step is to improve how SEO Agent compares reports with page history: which material changed, which data has refreshed and where observations are still insufficient. Webmaster MCP remains the source of inspectable evidence that analysis can reference.

Try the public demo

You need Git and Docker with Compose. These commands build the published source. The demo uses synthetic data and makes no Yandex requests.

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

Connect to http://localhost:8080/mcp using Authorization: Bearer demo-token. This is a public demonstration token. The Compose demo exposes 34 tools by default. Its read_only setting applies to the container filesystem — MCP_READ_ONLY controls tool access.

Stop the demo after checking it:

docker compose -f compose.demo.yml down

For your own website, continue with the setup and usage article. Browse the full source in the Webmaster MCP repository.

GitHub Setup guide

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