yandex-mcp
🇬🇧 English · [🇷🇺 Русский](README.ru.md)
# Yandex MCP
<!-- mcp-name: io.github.zai-one/yandex-mcp -->
**Bring Yandex advertising, analytics and search data into one conversation.**
> MCP server for Yandex Direct, Metrika (incl. Logs API and offline conversions), Webmaster, Wordstat, Search API and Audience: 127 tools in one server, with toolsets, read-only mode and guarded writes.
Review Direct campaigns, examine Metrika statistics, build bounded Audience segments, explore search demand and investigate Webmaster diagnostics with the same assistant. Yandex MCP connects six API groups; configure the services relevant to your work and add others as you need them.
**Default: every tool (`all`, 127 tools, ~22k tokens per session start).** To save tokens, pick platforms with `YANDEX_TOOLSETS` - the setup wizard (`yandex-mcp-setup`) or the `yandex_setup` prompt asks which you need and writes it for you. Measured tools/list + router cost (no Geosearch key):
| Preset | Platforms | Tools | ~Tokens |
|---|---|---|---|
| `everything` (default) | all | 127 | 21,986 |
| `seo` | webmaster, wordstat, serp | 55 | 8,971 |
| `direct-only` | direct | 40 | 8,055 |
| `analytics` | metrika, audience | 30 | 5,786 |
[Quick start](#quick-start) · [Connect your assistant](#connect-your-assistant) · [Issues](https://github.com/zai-one/yandex-mcp/issues)
Try asking your assistant:
> Show my Metrika counters. For the counter I choose, compare visits and goal conversions over two equal periods and highlight the largest changes.
## What you can do
| Your task | What the MCP server provides |
|---|---|
| Direct | Campaigns, supported inventory, portfolio strategies and statistics, including per-goal conversions and revenue; controlled changes when enabled. |
| Metrika | Counters, goals, filtered reports, period comparison and CSV with sampling metadata. |
| Search API | Asynchronous Yandex search-result jobs with saved results. |
| Wordstat | Top queries, demand trends, regional distribution and the region tree. |
| Webmaster | Indexing and site diagnostics, SQI history, important pages, search appearance/removal events, query statistics, sitemap and recrawl workflows. |
| Audience | Segments and pixels; guarded circle, polygon, pixel and pixel-viewer creates when explicitly enabled. |
[Report examples and local OAuth help](docs/METRIKA_REPORTS.md) explain how to compare periods, export rows and interpret partial results. [API coverage notes](docs/API_COVERAGE.md) list recently added tools with links to the Yandex documentation.
## Why this MCP
- Optional lazy tool loading: set `YANDEX_TOOL_LOADING=lazy` (or choose it in the setup wizard) to start with a small core and enable toolsets on demand; see [Lazy tool loading](#lazy-tool-loading).
- Six Yandex API groups in one process; enable only the toolsets you need (`YANDEX_TOOLSETS`, `YANDEX_READ_ONLY`).
- Writes (Direct changes, Audience creates, Metrika uploads and Logs requests) are off until enabled by an env flag and use confirmation hashes or idempotency keys.
- Agent layer: router instructions, 5 prompts (incl. `yandex_setup`), `yandex://playbook` and guide resources, self-contained skills, structured errors with `hint`.
- Compared with other Yandex MCP servers on GitHub: [SvechaPVL/yandex-mcp](https://github.com/SvechaPVL/yandex-mcp) (132 tools), [skiddgoddamn/yandex-marketing-mcp](https://github.com/skiddgoddamn/yandex-marketing-mcp) (153 tools) and [webkoth/yandex-mcp](https://github.com/webkoth/yandex-mcp) (125 tools) still expose more *total* endpoints (often one tool per add/update/delete); this server matches them on documented Direct+Webmaster **read** methods that matter, keeps writes behind per-service gates, and ships bounded typed responses with CI on Linux and Windows.
## Lazy tool loading
Optional lazy tool loading: `YANDEX_TOOL_LOADING=lazy` starts with a small core plus `yandex_enable_toolsets` and adds toolsets on demand (`tools/list_changed`). Startup cost (tools/list + instructions, ≈chars/4): eager ≈21872 tokens, lazy ≈2574 tokens (−88%). Default `eager` is unchanged; if your client ignores `tools/list_changed`, keep `eager` or reconnect after enabling. Scope: enablement is per MCP session (FastMCP session visibility), so one client's enabled toolsets never appear for another. The HTTP transport here is stateless (every request is its own session), so `lazy` is stdio only: an HTTP server refuses to start with it; use `eager` or `YANDEX_TOOLSETS` there.
Clients and `notifications/tools/list_changed` (verified against official docs, changelogs or maintainer statements, 2026-10):
| Client | `tools/list_changed` | Source |
|---|---|---|
| Claude Code | Supported (interactive: tools, prompts, resources; `-p`/Agent SDK: tools) | [docs: Dynamic tool updates](https://code.claude.com/docs/en/mcp) |
| VS Code (GitHub Copilot) | Supported (dynamic tool discovery); new tools may reach the agent only on the next turn | [docs](https://code.visualstudio.com/api/extension-guides/ai/mcp), [#303012](https://github.com/microsoft/vscode/issues/303012) |
| Gemini CLI | Supported (refreshes the tool registry) | [PR #14375](https://github.com/google-gemini/gemini-cli/pull/14375), [PR #21050](https://github.com/google-gemini/gemini-cli/pull/21050) |
| Cursor | Unreliable: staff confirm a regression in 3.12.x; restart Cursor after enabling | [forum](https://forum.cursor.com/t/mcp-server-regression-does-not-reload-tools-disconnect-does-nothing-ignores-mcp-json-changes-etc/166216) |
| Claude Desktop, Windsurf, Codex CLI, Cline, Zed, Continue | Unverified: no official statement found; use `eager` or reconnect after enabling | — |
## Maintained and up to date
- Actively maintained by ZAI.ONE: current version 0.7.0; release notes in [CHANGELOG.md](CHANGELOG.md) and [Releases](https://github.com/zai-one/yandex-mcp/releases).
- Built-in update check: ask the assistant to run `yandex_check_update` (public GitHub API, no credentials, cached; nothing is installed automatically; `YANDEX_DISABLE_UPDATE_CHECK=1` turns it off).
- Follows current MCP practice: tool annotations (read-only / destructive hints), toolsets and read-only mode, server `instructions`, prompts and resources, structured errors with recovery hints, secrets kept out of tool output, a token budget for tool descriptions enforced in tests, and a routing eval: messy RU/EN requests must reach the right skill, guide and tool from the short router.
- CI runs the test suite on Linux and Windows for every pull request.
## Quick start
**Zero config** (uv installed; no clone, no config file, no absolute paths):
```sh
claude mcp add yandex -- uvx --from "zai-yandex-mcp[standalone] @ git+https://github.com/zai-one/yandex-mcp@main" yandex-mcp
```
Then ask: *"Подключи Яндекс Метрику"*. The assistant runs `yandex_auth_start` (OAuth device flow: open the link, enter the code), then `yandex_auth_finish`; the token is stored in a private file under your user profile and used immediately and after restarts. It needs your Yandex OAuth app `client_id` once (pass it in chat or set `YANDEX_OAUTH_CLIENT_ID`; [OAuth guide](src/zai_yandex/resources/guide/oauth.md)). Without `--config` the server reads `YANDEX_MCP_CONFIG` or `mcp.local.json` in the per-user directory if present, and keeps state there (`%APPDATA%\zai-yandex-mcp` on Windows, `~/Library/Application Support/zai-yandex-mcp` on macOS, `~/.config/zai-yandex-mcp` elsewhere; override with `YANDEX_MCP_HOME`). The same `uvx` command works in Cursor, Codex and Claude Desktop.
**Wizard** (Python 3.12+ and uv installed, a Metrika OAuth token at hand):
```sh
git clone https://github.com/zai-one/yandex-mcp.git && cd yandex-mcp
uv sync --frozen --extra standalone
uv run --frozen --extra standalone python scripts/configure.py # paste the token into the hidden prompt
```
Merge the generated `mcp-client.json` into your client (Claude Desktop, Cursor...), restart it and ask: *"List my Metrika counters"*. Tip: add `"YANDEX_TOOLSETS": "default"` to the env for a smaller tool list; the assistant finds everything else through the router (`yandex://guide/tool-map`). Details below.
Prefer a ready package? [Install the release and generate your client configuration](INSTALL.md#install-a-release-package). No source checkout is required.
Install **Python 3.12–3.14** and [uv](https://docs.astral.sh/uv/getting-started/installation/). Clone with Git or [download the ZIP](https://github.com/zai-one/yandex-mcp/archive/refs/heads/main.zip). With a ZIP, open the extracted directory and skip the first two commands.
Each API group needs its own credentials. The wizard starts with Metrika; add Direct, Audience, Webmaster and Yandex Cloud credentials for the services you want to use. Cloud Search also needs a folder ID. Follow the [service-specific setup](INSTALL.md#from-a-clone-or-source-zip). Audience safety and status semantics are documented in [Yandex Audience](docs/AUDIENCE.md).
```sh
git clone https://github.com/zai-one/yandex-mcp.git
cd yandex-mcp
uv sync --frozen --extra standalone
uv run --frozen --extra standalone python scripts/configure.py
uv run --frozen --extra standalone yandex-mcp --config mcp.local.json --check-config
```
The wizard creates a local configuration and stores secrets in private files. It refuses to overwrite an existing setup. `--check-config` validates local settings; the first request below checks your account connection.
## Connect your assistant
Add this configuration to an MCP client that uses `mcpServers`, such as Claude Desktop or Cursor. Replace `/ABSOLUTE/PATH/` with your absolute path; Windows JSON paths can use forward slashes, such as `D:/Tools/`.
```json
{
"mcpServers": {
"yandex": {
"command": "uv",
"args": [
"--directory",
"/ABSOLUTE/PATH/yandex-mcp",
"run",
"--frozen",
"--extra",
"standalone",
"yandex-mcp",
"--config",
"/ABSOLUTE/PATH/yandex-mcp/mcp.local.json"
]
}
}
}
```
The client starts the MCP server for you. Refresh its tool list, then make your first request. For clients with a different config format, reuse the same `command` and `args`; `uv` must be available to the client process.
### First request
> List my Metrika counters and the goals of the counter I select.
The default setup starts with Metrika. Once its token is accepted, the assistant can list accessible counters and read their goals. Other API groups use separately configured credentials.
If tools do not appear, check the absolute path, whether the client can find `uv`, and the `--check-config` result. For access errors, check account credentials and permissions. [Installation and troubleshooting](INSTALL.md).
### Other clients
```bash
# Claude Code (MCP only); --config is optional (see Zero config above)
claude mcp add yandex -- uvx --from "zai-yandex-mcp[standalone] @ git+https://github.com/zai-one/yandex-mcp@v0.7.0" yandex-mcp --config /ABSOLUTE/PATH/mcp.local.json
# Claude Code plugin (MCP + skills) from this repository; set YANDEX_MCP_CONFIG to your mcp.local.json
/plugin marketplace add zai-one/yandex-mcp
/plugin install yandex@zai-yandex
```
Codex `~/.codex/config.toml`:
```toml
[mcp_servers.yandex]
command = "uvx"
args = ["--from", "zai-yandex-mcp[standalone] @ git+https://github.com/zai-one/yandex-mcp@v0.7.0", "yandex-mcp", "--config", "/ABSOLUTE/PATH/mcp.local.json"]
env = { YANDEX_TOOLSETS = "default" }
```
Cursor `.cursor/mcp.json` and Claude Desktop use the `mcpServers` block above (or `"command": "uvx"` with the Codex args).
## Toolsets and read-only mode
Unset = every tool (127; previous behaviour). Platforms: `yandex_setup_toolsets(platforms|preset, write=true)` (stdio) sets only `YANDEX_TOOLSETS` in the active `mcp.local.json` (it wins over client env; restart to apply) - opt-in toolsets below are opt-in only relative to `default`. `YANDEX_TOOLSETS=default` keeps the read toolsets (direct_read, direct_reports, metrika, webmaster, wordstat, audience) plus `account` - about 30% fewer tool tokens. It is not strictly read-only: `account` includes the OAuth self-setup tools `yandex_auth_start` / `yandex_auth_finish`, which write local token files (stdio only); add `YANDEX_READ_ONLY=1` (or `YANDEX_DISABLED_TOOLS=yandex_auth_start,yandex_auth_finish`) to hide them. The quota- and write-related `metrika_logs` and `metrika_offline` toolsets are opt-in: add them explicitly, e.g. `YANDEX_TOOLSETS=default,metrika_logs`. Rare reads live in opt-in `direct_extra` (client, dictionaries, Changes, keyword bids, bid modifiers, audience targets, retargeting lists, feeds, creatives, callouts, turbo pages, leads, videos, negative keyword sets) and `webmaster_extra` (owners, feeds, regions, query analytics). Administration lives in opt-in `metrika_manage`, `webmaster_manage` and `audience_manage` (grants, delegates, counters, filters, segments, labels, annotations, uploads, hosts, feeds, Audience segments; catalogue in `yandex://guide/management`), all writes through prepare -> approval -> apply. Yandex Maps organization search (`maps_geosearch`: `maps_search_organizations`, `maps_search_places`) is added only when `YANDEX_MAPS_GEOSEARCH_API_KEY` (or `YANDEX_MAPS_GEOSEARCH_API_KEY_FILE`, owner-private) is set - a separate Geosearch key from the developer cabinet; results are not cached and keep Yandex attribution per the Maps API terms (`yandex://guide/maps-geosearch`).
| Variable | Effect |
|---|---|
| `YANDEX_TOOLSETS` | `all`, `default` or a comma list of `account`, `direct_read`, `direct_extra`, `direct_reports`, `direct_write`, `metrika`, `metrika_logs`, `metrika_logs_write`, `metrika_offline`, `metrika_write`, `webmaster`, `webmaster_extra`, `webmaster_write`, `wordstat`, `search`, `audience`, `audience_write`, `audience_manage`, `metrika_manage`, `webmaster_manage`, `maps_geosearch` (needs its key). Also `--toolsets`. |
| `YANDEX_TOOLS` / `YANDEX_DISABLED_TOOLS` | Add or hide individual tools. |
| `YANDEX_READ_ONLY=1` | Hide every prepare/apply/write/paid-submit tool (also `--read-only`). |
Scopes, write flags, approvals and idempotency keys still apply to whatever is visible. The assistant can read `yandex://toolsets`. Errors are JSON with `code`, `retryable`, `hint` and `docs`.
## Multiple accounts and agencies
Set `YANDEX_ACCOUNTS_FILE` to a JSON file of named profiles. Unset fields inherit the base credentials, so an agency client is just a `direct_client_login`; a separate account points to its own owner-private token files (paths relative to the JSON file, tokens never inline).
```json
{
"default": "client-a",
"accounts": {
"client-a": {"direct_client_login": "client-a-login", "description": "Agency client A"},
"shop-b": {"direct_token_file": "shop-b.direct.token", "metrika_token_file": "shop-b.metrika.token"}
}
}
```
Every tool then gets an optional `account` argument (one of the names) and `yandex_list_accounts` shows the profiles without secrets. Omitted `account` = `default` (or the base credentials). Without the file nothing changes: no extra argument, no extra tokens in the tool list. Use `direct_list_agency_clients` to find client logins.
Writes are isolated per account: idempotency keys, the write ledger and approvals belong to the account resolved for the call (Direct, Metrika, Webmaster, Audience), so a key or an approval from one account never replays or applies on another. Writes without a resolved account keep their previous ledger keys.
## Direct sandbox
`YANDEX_DIRECT_SANDBOX=true` sends every Direct call to the official [Sandbox](https://yandex.ru/dev/direct/doc/ru/concepts/sandbox) (`api-sandbox.direct.yandex.com`, test data, same token; enable it once in Direct > API settings > Sandbox). Rehearse writes there first; write flags and approvals still apply. Per account: `"direct_sandbox": true` in `YANDEX_ACCOUNTS_FILE`. Sandbox writes, idempotency keys and approvals are recorded apart from production ones, so a rehearsal is never replayed or applied as a live change.
## Skills, prompts and guides
Self-contained skills in [`skills/`](skills/) (each with its own `references/` and `templates/`): `yandex-direct-audit`, `metrika-compare-periods`, `webmaster-seo-health`, `wordstat-demand-research`, `direct-safe-change`. Copy a folder into `~/.claude/skills/`, `.agents/skills/` or `.cursor/skills/`, or install the plugin. MCP prompts: `campaign_audit`, `weekly_report`, `seo_audit`, `budget_scaling`; resources `yandex://playbook`, `yandex://guide/{api-units|audit-checklist|strategies|metrics-dimensions|diagnostics-codes|wordstat-operators|prepare-apply|errors}`.
### Example tasks
- "Audit my Direct campaigns for the last 30 days and list the top 5 issues."
- "Compare organic traffic and goal reaches this week vs last week in Metrika."
- "Check SEO health of example.com in Webmaster and give me a fix list."
- "Collect Wordstat demand for 'купить диван' in Moscow and cluster it."
- "Which campaigns can take 20% more budget at CPA under 900 RUB? Prepare the change, do not apply."
## Access and limits
Search API jobs need a separate worker and a Cloud folder ID. Wordstat uses Cloud credentials and explicit cost limits. Write operations depend on service permissions and server policy. OAuth self-setup: `yandex_auth_start` / `yandex_auth_finish` (device-code flow, hot reload, no restart; local stdio only, never on an HTTP server; see `yandex://guide/oauth`) or `yandex-mcp-oauth --device`.
Authenticated HTTP is available for a server deployment. See [HTTP setup](INSTALL.md#http), [configuration and permissions](docs/RUNTIME.md) and [Python package integration](INSTALL.md#python-package-and-platform-integration).
<details>
<summary>For developers: project checks</summary>
```sh
uv sync --frozen --all-groups --extra standalone
uv run --frozen --extra standalone python scripts/verify.py
uv run --frozen --extra standalone python scripts/verify_install.py
```
Tests use synthetic fixtures. A passing test run does not establish live provider connectivity.
</details>
## Updates
Ask your assistant to run `yandex_check_update`. It compares the installed version with the
[latest release](https://github.com/zai-one/yandex-mcp/releases) through the public GitHub API
(no credentials, no Yandex API calls or quota, 3-second timeout, result cached for 24 hours next to the state file) and
returns the current and latest versions, the release notes link and the matching update command
(`git pull --ff-only && uv sync --frozen --extra standalone` for a checkout, `uv tool install --force ...` for a release package).
When a newer version is already known from the cache, the server mentions it once in its startup
instructions. Nothing is ever installed automatically. Offline, the check reports `status: unknown`
and the server keeps working. Set `YANDEX_DISABLE_UPDATE_CHECK=1` to turn it off.
## Built by ZAI.ONE
[ZAI.ONE](https://zai.one) is a digital agency working on websites, SEO, advertising and analytics. We also build tools that connect AI assistants to everyday work. [Talk to us on Telegram](https://t.me/zai_one) about setup, automation or an integration for your team.
## License, use and contributing
- **Use:** you may install and use this MCP server freely for yourself and your organisation, including commercial work. If it helps, please consider giving the repository a ⭐ — appreciated, never required.
- **Contribute:** [issues](https://github.com/zai-one/yandex-mcp/issues/new/choose) and pull requests are welcome; see [CONTRIBUTING.md](CONTRIBUTING.md). Never post tokens, cookies, sessions or account data.
- **Not allowed without written permission from ZAI.ONE:** copying code into other projects, forking for redistribution, embedding the server in other products or offering it as a competing service.
- License: [LicenseRef-ZAI-ONE 2.0](LICENSE) (source-available, not open source). Third-party notices and license history: [NOTICE](NOTICE).
TDQS
Scored across 127 tools
Many tools have near-overlapping purposes: generic readers like direct_get_inventory and *_manage_read duplicate specific list/get tools, while direct_prepare_write, direct_prepare_changes, direct_write, and direct_apply_changes create multiple write paths. Rich descriptions help, but with 127 tools the boundaries remain hard to keep straight.
Names are overwhelmingly snake_case with verb+noun patterns grouped by service (direct_*, metrika_*, webmaster_*, audience_*). Deviations such as the yandex_* prefix for Wordstat/SERP/auth/setup and occasional noun-style names (e.g., yandex_wordstat_dynamics) are minor but prevent a perfect score.
127 tools is an extreme mismatch for a single MCP server; it far exceeds the 50-tool threshold and will cause context bloat and selection errors. Even accounting for the multi-platform scope, the count is unreasonable.
Coverage across Direct, Metrika, Webmaster, Audience, and Wordstat is extensive, with read, write, approval, and reconciliation paths. Minor gaps remain: no maps tools appear despite being referenced in setup, and destructive operations are intentionally omitted or routed through approvals.