Naver Search Ad MCP
# Naver Search Ad MCP
An [MCP](https://modelcontextprotocol.io) server for the **Naver Search Ad**
(네이버 검색광고) API — read/analytics focused. Query campaigns, ad groups,
keywords, stats, keyword research, and bid estimates through any MCP client.
- **Read-only** by default (safe): all tools are annotated `readOnlyHint`.
- **Multi-account**: one credential per user auto-discovers every advertiser
account it can access (agency-delegated + own) via `/ad-accounts` +
`child-ad-accounts`, addressed by `account_id` (= Naver `customerId`).
- **Two transports**: local `stdio` for a single account, or hosted
`streamable-http` (Google Workspace OAuth) for a team — see [DEPLOY.md](DEPLOY.md).
## Quick start (local, stdio)
Get your credentials at **searchad.naver.com → 관리 → 도구 → API 사용 관리**
(CUSTOMER_ID, access license, secret key).
```bash
uv venv --python 3.13
uv pip install -e .
export NAVER_API_KEY=... # access license
export NAVER_SECRET_KEY=... # secret key
export NAVER_CUSTOMER_ID=... # customer id (integer)
naver-searchad-mcp # stdio MCP server
```
Register with an MCP client (e.g. Claude Desktop):
```json
{
"mcpServers": {
"naver-searchad": {
"command": "/path/to/.venv/bin/naver-searchad-mcp",
"env": {
"NAVER_API_KEY": "...",
"NAVER_SECRET_KEY": "...",
"NAVER_CUSTOMER_ID": "..."
}
}
}
}
```
## Tools
**Accounts**
| Tool | Description |
|------|-------------|
| `list_accounts()` | All accessible ad accounts (`/ad-accounts` ∪ `child-ad-accounts`, deduped). Each `account_id` = customerId |
| `get_accounts_overview(...)` | Per-account campaign count + period performance summary |
| `whoami()` | Diagnostic: authenticated caller + linked credential (hosted mode) |
**Entities**
| Tool | Description |
|------|-------------|
| `list_campaigns(account_id, campaign_type?)` | Campaigns |
| `get_campaign(account_id, campaign_id)` | Campaign detail |
| `list_adgroups(account_id, campaign_id)` | Ad groups |
| `get_adgroup(account_id, adgroup_id)` | Ad group detail |
| `list_keywords(account_id, adgroup_id)` | Keywords |
| `list_ads(account_id, adgroup_id)` | Ads (creatives) |
| `list_business_channels(account_id)` | Business channels |
**Performance & analytics**
| Tool | Description |
|------|-------------|
| `get_stats(account_id, ids[], fields[], since/until\|date_preset, ...)` | Low-level `/stats` (≤92-day window, single entity level) |
| `get_campaign_performance(account_id, dates, fields?)` | All campaigns + names |
| `get_keyword_performance(account_id, adgroup_id, dates)` | Keyword performance + text |
| `get_related_keywords(account_id, hint_keywords[])` | Related keywords, search volume, competition (`/keywordstool`) |
| `get_performance_report(account_id, level, since, until, daily?, ...)` | Named report; auto-chunks >92 days; aggregate (ratios recomputed) or daily |
| `create_stat_report(account_id, report_tp, stat_dt)` | Async bulk StatReport job (1 job = 1 day) |
| `download_stat_report(account_id, download_url, max_rows?)` | Download StatReport TSV (raw, columns not interpreted) |
**Bid estimates**
| Tool | Description |
|------|-------------|
| `estimate_keyword_bid(account_id, keywords[], estimate_type, device, position)` | Target-position / min-exposure bid |
| `estimate_keyword_performance(account_id, keyword, bids[], device)` | Predicted impressions/clicks/cost per bid |
Metric field names are terse and sometimes misleading (`salesAmt` = **cost**,
`ror` = **ROAS %**); the server attaches clear aliases (`cost`, `roas_pct`, …)
and exposes a `naver://metric-glossary` resource.
## Hosted deployment (team, Google OAuth)
See [DEPLOY.md](DEPLOY.md) — Cloud Run + Secret Manager + Google Workspace
OAuth, per-email credential model, and a self-service admin console at `/admin`.
## Development
```bash
uv pip install -e ".[dev]"
pytest
```
## Notes
- This server covers **Search Ad** only. Naver GFA (성과형 디스플레이광고) is a
separate API (partner-only OAuth) and is out of scope.
- Signing rule: `base64(HMAC_SHA256(secret, "{timestamp}.{METHOD}.{path}"))` —
path only, query excluded, timestamp in ms.
## License
MIT — see [LICENSE](LICENSE).
TDQS
Scored across 19 tools
Each tool has a clear, distinct purpose. For example, create_stat_report and download_stat_report are sequential steps, and get_stats and get_performance_report serve different use cases (sync vs. named reports). No overlap or ambiguity.
All tools follow a consistent verb_noun snake_case pattern (create_, download_, estimate_, get_, list_). The only outlier is whoami, which is conventional for diagnostics. No mixing of styles.
19 tools cover account overview, campaign/adgroup/keyword details, performance reports, keyword estimation, and diagnostic tools. The number feels appropriate for the apparent scope of a search advertising management API.
The tool set is heavily read-oriented with only create_stat_report for report generation. There are no tools to create, update, or delete campaigns, adgroups, or keywords, which are critical for full management. This leaves significant gaps.