Content
# Yandex.Direct MCP



**MCP server for Yandex.Direct API v5 (+ Wordstat).** 48 tools for managing contextual advertising right from Claude, Cursor, and any client that supports [Model Context Protocol](https://modelcontextprotocol.io).
Create and edit campaigns, groups, ads, keywords, bids, extensions, and negative keywords, collect reports, and Wordstat frequency — in natural language, without manual clicks on the Direct interface.
## Capabilities
- **Campaigns, groups, ads** — full CRUD + statuses (start/pause/archive/moderation)
- **Keywords and bids** — adding in batches, updating, bids, autotargeting
- **Negative keywords** — sets of negative phrases at the campaign level
- **Extensions** — quick links (sitelinks) and clarifications (callouts)
- **Reports** — campaign statistics, search query report, arbitrary reports
- **Wordstat** — keyword phrase frequency (via API v4)
- **Directories** — Direct regions and dictionaries
- **Multiple accounts** — switching between accounts at runtime
- **Sandbox and production mode** — one flag switches the environment
Full API and format documentation — in [`docs/yandex-direct-api.md`](docs/yandex-direct-api.md).
## Requirements
- **Python 3.10+**
- **Access to Yandex.Direct API** and OAuth token (how to obtain — below)
## Installation
```bash
git clone https://github.com/demokrat90/yandex-direct-mcp.git
cd yandex-direct-mcp
python -m venv .venv
# Windows (PowerShell):
.venv\Scripts\Activate.ps1
# Linux / macOS:
source .venv/bin/activate
pip install -r requirements.txt
```
## Obtaining OAuth Token
Yandex.Direct API works with an OAuth token. Obtaining it takes a couple of minutes:
1. **Create an OAuth application** on <https://oauth.yandex.ru/client/new>:
- in access rights, mark **Yandex.Direct** (campaign management);
- application type — «Web services», redirect can be left standard.
- After creation, copy **ClientID** and **Client secret**.
2. **Write them down** in `.env` (see below) in `YANDEX_DIRECT_CLIENT_ID` and `YANDEX_DIRECT_CLIENT_SECRET`.
3. **Run the script** — it will open the browser, you'll confirm access, insert the code, and the token will be saved in `.env`:
```bash
python scripts/get_yandex_token.py
```
> For the production API, you need approved access to Direct. Application and conditions: <https://yandex.ru/dev/direct/>. Sandbox (`YANDEX_DIRECT_SANDBOX=true`) works immediately and doesn't spend points.
## Configuration
```bash
cp .env.example .env # Windows: copy .env.example .env
```
Minimum required to fill in `YANDEX_DIRECT_TOKEN`. Other variables — in [`.env.example`](.env.example).
Check the connection:
```bash
python scripts/test_yandex_connection.py # sandbox
python scripts/test_yandex_connection.py --prod # production API
```
## Connecting to MCP Client
Add the server to your client's config (template — in [`.mcp.example.json`](.mcp.example.json)).
**Claude Desktop** — `claude_desktop_config.json`, **Cursor** — `.cursor/mcp.json`, **Claude Code** — `.mcp.json`:
```json
{
"mcpServers": {
"yandex-direct": {
"command": "python",
"args": ["/ABSOLUTE/PATH/TO/yandex-direct-mcp/run_server.py"],
"env": {
"YANDEX_DIRECT_TOKEN": "YOUR_OAUTH_TOKEN",
"YANDEX_DIRECT_SANDBOX": "false"
}
}
}
}
```
> **Windows:** in `command`, specify the path to Python from the virtual environment, for example
> `C:/path/to/yandex-direct-mcp/.venv/Scripts/python.exe`, and in `args` — the full path to `run_server.py`.
Restart the client — `yd_*` tools will appear in the list.
## Multiple Accounts
One server serves multiple accounts. Set them in `.env`:
```
YANDEX_DIRECT_ACCOUNTS=main,client2
YANDEX_DIRECT_ACCOUNT_MAIN_TOKEN=...
YANDEX_DIRECT_ACCOUNT_MAIN_DESC=Main account
YANDEX_DIRECT_ACCOUNT_CLIENT2_TOKEN=...
YANDEX_DIRECT_ACCOUNT_CLIENT2_DESC=Client 2
YANDEX_DIRECT_DEFAULT_ACCOUNT=main
```
At runtime: `yd_list_accounts` — list, `yd_switch_account` — switching.
## Tools (48)
| Category | Tools |
|---|---|
| **Accounts** (3) | `yd_list_accounts`, `yd_switch_account`, `yd_get_account_info` |
| **Campaigns** (9) | `yd_get_campaigns`, `yd_create_campaign`, `yd_create_campaigns`, `yd_update_campaigns`, `yd_delete_campaigns`, `yd_suspend_campaigns`, `yd_resume_campaigns`, `yd_archive_campaigns`, `yd_unarchive_campaigns` |
| **Groups** (5) | `yd_get_ad_groups`, `yd_create_ad_group`, `yd_create_ad_groups`, `yd_update_ad_group`, `yd_delete_ad_groups` |
| **Ads** (8) | `yd_get_ads`, `yd_create_text_ad`, `yd_create_text_ads`, `yd_update_ads`, `yd_delete_ads`, `yd_moderate_ads`, `yd_suspend_ads`, `yd_resume_ads` |
| **Keywords** (5) | `yd_get_keywords`, `yd_add_keywords`, `yd_add_keywords_bulk`, `yd_update_keywords`, `yd_delete_keywords` |
| **Bids** (2) | `yd_get_keyword_bids`, `yd_set_keyword_bids` |
| **Autotargeting** (1) | `yd_update_autotargeting` |
| **Negative keywords** (2) | `yd_get_negative_keyword_sets`, `yd_create_negative_keyword_set` |
| **Extensions** (6) | `yd_get_sitelinks`, `yd_create_sitelinks`, `yd_delete_sitelinks`, `yd_create_callouts`, `yd_get_ad_extensions`, `yd_delete_extensions` |
| **Reports** (3) | `yd_campaign_performance_report`, `yd_search_query_report`, `yd_custom_report` |
| **Wordstat** (1) | `yd_wordstat_report` |
| **Directories** (2) | `yd_get_regions`, `yd_get_dictionaries` |
| **Changes** (1) | `yd_check_changes` |
## Ad Format Limits
| Field | Limit |
|---|---|
| Headline 1 | 56 characters |
| Headline 2 | 30 characters |
| Text | 81 characters |
| Quick link headline | 30 characters |
| Clarification (callout) | 25 characters |
| Number of quick links in a set | up to 8 |
Useful region IDs: `225` — Russia, `213` — Moscow, `2` — St. Petersburg, `0` — worldwide. Full list — via `yd_get_regions`.
## Architecture
```
run_server.py # entry point: loads .env and starts the server
yandex_direct/
├── server.py # MCP server (list_tools / call_tool, multi-account)
├── tools.py # all 48 tools: definitions + handlers
├── api_client.py # HTTP client API v5 (JSON), sandbox/production
├── client.py # facade YandexDirectManager over services
└── *_service.py # services for campaigns/groups/ads/keys/extensions
scripts/
├── get_yandex_token.py # OAuth flow (browser → code → token)
└── test_yandex_connection.py # connection check
```
## Limitations and Support
The project is provided «as is». Issues and pull-requests are welcome, but regular support and SLA are not guaranteed. If something doesn't work — create an issue with reproduction steps.
## About the Author
Made in **Verkhozin Marketing** — setup and automation of contextual advertising (Google Ads, Yandex.Direct).
Need help with advertising or automation based on AI — write through [GitHub](https://github.com/demokrat90) or create an issue in the repository.
## License
[MIT](LICENSE) 2026 Verkhozin Marketing