mcp-microsoft-ads

mcp-microsoft-ads

Enables AI assistants to manage Microsoft Advertising accounts, including campaigns, ad groups, keywords, audiences, and reporting, with safety-first write controls such as opt-in mutations, draft-and-confirm workflows, spend ceilings, and audit logging.

Category
访问服务器

README

mcp-microsoft-ads

Unofficial — not affiliated with, endorsed by, or supported by Microsoft. This is a third-party MCP (Model Context Protocol) server for Microsoft Advertising. "MCP" is the open protocol that lets an AI assistant (Claude, or any other MCP client) call tools against a real system — here, your Microsoft Ads account.

The safety-first Microsoft Ads MCP: 47 tools covering campaign, ad group, keyword, negative-keyword, geo-targeting, ad-schedule, extension, media, audience, and conversion-goal management, plus performance reporting and Ad Insight keyword research — built so that giving an AI assistant write access to a live ad account doesn't mean giving it a blank check.

Why "safety-first"

Every mutating tool is off by default. Turning writes on is one env var, and even then every write goes through the same layered gate before a single call reaches Microsoft's API:

  1. MS_ADS_ENABLE_WRITES=true — without it, every write tool refuses to run. Out of the box this is a read-only server.
  2. Draft → confirm. A write tool never mutates on its own call. It returns a preview (a draft_id and exactly what would change); nothing lands until you — or your MCP client — calls confirm_and_apply(draft_id).
  3. Spend ceilings. Draft creation and apply both reject amounts above MS_ADS_MAX_DAILY_BUDGET (default 1000) or MS_ADS_MAX_CPC (default 50), in the account's own currency, not USD.
  4. Smart Bidding fail-closed guards. Bid/adjustment writes are allowlisted to manual bidding strategies (ManualCpc, EnhancedCpc, ManualCpv, ManualCpm, ManualCpa); an unrecognized or automated strategy (MaxConversions, TargetCpa, TargetRoas, …) is refused rather than assumed safe.
  5. JSONL audit log. Every draft and every apply is appended to a local, append-only JSONL file — a plain-text paper trail of what this server actually did.

Backed by 380+ offline tests (no live API calls) that exercise the rails, the SOAP plumbing quirks, and the draft/confirm lifecycle against fakes.

Be honest about what "draft → confirm" is not

Draft → confirm is a preview gate against single-call accidents — a typo in a bid, a copy-paste mistake, calling the wrong tool. It is not human-approval access control: the same MCP client that created the draft can call confirm_and_apply immediately afterward, with no human in the loop required by the server. If you want a human to review every write, that has to be enforced by your own workflow (a separate approval step, a human-only client, etc.) — this server doesn't do it for you.

One write is called out separately because the layered story above can't fully bound it: apply_recommendation hands off to a Microsoft-decided mutation — you preview only the recommendation ID, not the change itself, so the actual monetary effect isn't something this server's spend ceilings can check in advance. It's kept (Microsoft's recommendations can be useful), loudly labeled as the exception it is, and gated behind both MS_ADS_ENABLE_WRITES and its own separate flag, MS_ADS_ALLOW_APPLY_RECOMMENDATION — so turning on writes generally does not turn this one on.

What this server does not do

  • No Quality Score diagnostics.
  • No automatic retry/backoff on transient API failures (a failed call fails; you retry).
  • Built on Microsoft's SOAP Bing Ads SDK, which Microsoft has announced end-of-life — see below.

SOAP end-of-life and the REST roadmap

This server is built on the bingads SOAP SDK. Microsoft has announced that SOAP is end-of-life on 2027-01-31, and recommends migrating before 2026-10-01 (new API features ship REST-only from then). See Microsoft's Migrate to REST API guide and the Python SDK SOAP-to-REST migration guide. Porting this server's tools to REST is the roadmap item — SOAP still works today and isn't going away until the EOL date, but don't plan around it long-term.

How this compares

write access write safety layer notes
mcp-microsoft-ads (this project) yes, opt-in draft→confirm + spend ceilings + Smart-Bidding guards + audit log SOAP today, REST planned
mharnett/mcp-bing-ads see their repo for current scope
bit-of-a-shambles Bing Ads MCP server see that project's repo for current scope
CData Microsoft Ads MCP connector read-only n/a no write path
Microsoft's official hosted MCP see Microsoft's docs for current scope

Comparison last checked 2026-08-24. This project doesn't claim to know the exact current feature set of the other rows beyond what's read-only vs. not — check each project's own repo/docs for details. The differentiators above (opt-in writes, two-phase draft→confirm, spend ceilings, Smart-Bidding fail-closed guards, JSONL audit log, 380+ offline tests) are what this project is built around.

Install

git clone https://github.com/wvuhskr/mcp-microsoft-ads.git
cd mcp-microsoft-ads
python3 -m venv .venv  # requires Python >= 3.12
.venv/bin/pip install -e ".[dev]"

Full setup — Azure app registration, developer token, first OAuth sign-in — is in docs/setup.md. This section only covers running the server once credentials already exist.

Credentials

Credentials live outside the repo, in a YAML file (default ~/.mcp-microsoft-ads/credentials.yaml, override with MS_ADS_CREDENTIALS_PATH): developer_token, client_id, client_secret, refresh_token, customer_id, account_id, tenant.

The six static fields (everything except refresh_token) can instead be set as MS_ADS_DEVELOPER_TOKEN, MS_ADS_CLIENT_ID, MS_ADS_CLIENT_SECRET, MS_ADS_CUSTOMER_ID, MS_ADS_ACCOUNT_ID, MS_ADS_TENANT env vars — env wins over the file when both are present. refresh_token is file-only: Microsoft rotates it on every use, and a rotated token has to be persisted somewhere for the next run, which an env var can't do. The server persists each rotation back to the credentials file atomically (a .bak is kept).

First-run walkthrough

  1. Bootstrap sign-in:
    .venv/bin/python -m mcp_microsoft_ads.reauth
    
    Walks an interactive OAuth sign-in in your browser and writes the resulting refresh_token into the credentials file. See docs/setup.md for the Azure app registration and developer token this step depends on.
  2. Start the server read-only (don't set MS_ADS_ENABLE_WRITES yet) and, from your MCP client, call health_check, then list_accounts and/or get_account_info.
  3. Confirm the account is the one you mean — check the account ID, account name, and account currency returned by those calls against the account you intend to let this server touch. The spend ceilings below are enforced in that account's currency, so a currency mismatch is worth catching before writes are ever on.
  4. Only then set MS_ADS_ENABLE_WRITES=true (and, if you want it, MS_ADS_ALLOW_APPLY_RECOMMENDATION=true) and restart the server.

MCP client configuration

Both configs assume the venv above lives at ~/mcp-microsoft-ads/.venv — replace that with the actual absolute path on your machine (both clients need an absolute path, not ~).

Claude Code (.mcp.json in your project, or via claude mcp add):

{
  "mcpServers": {
    "microsoft-ads": {
      "command": "/home/you/mcp-microsoft-ads/.venv/bin/python",
      "args": ["-m", "mcp_microsoft_ads.server"]
    }
  }
}

Claude Desktop (claude_desktop_config.json):

{
  "mcpServers": {
    "microsoft-ads": {
      "command": "/home/you/mcp-microsoft-ads/.venv/bin/python",
      "args": ["-m", "mcp_microsoft_ads.server"]
    }
  }
}

Don't point two concurrent clients at the same credentials file

Sharing one credentials file between concurrent clients is unsupported. The refresh_token is a rotating, shared, mutable file: every refresh mints a new token and immediately invalidates the old one, and the read-modify-write that persists the rotation can't be safely serialized across two separate processes at this layer. Two clients racing to refresh from the same file can strand each other with an invalidated token. If you want more than one concurrent client (e.g. Claude Code and Claude Desktop open at once), give each one its own credentials file and its own Azure app registration — set MS_ADS_CREDENTIALS_PATH differently per client and bootstrap each with its own reauth run.

Environment variables

Var Default Purpose
MS_ADS_CREDENTIALS_PATH ~/.mcp-microsoft-ads/credentials.yaml credentials file location
MS_ADS_ADVERTISER_CONFIG ~/.mcp-microsoft-ads/advertiser.yaml optional advertiser settings (blocked terms, advertiser domain, keyword-research defaults) — missing file means defaults
MS_ADS_AUDIT_PATH ~/.mcp-microsoft-ads/audit.jsonl JSONL audit log location
MS_ADS_ENABLE_WRITES false master switch for all mutating tools
MS_ADS_ALLOW_APPLY_RECOMMENDATION false second, separate switch required (in addition to MS_ADS_ENABLE_WRITES) for apply_recommendation specifically
MS_ADS_MAX_DAILY_BUDGET 1000 daily-budget rail ceiling, in the account's own currency
MS_ADS_MAX_CPC 50 bid/tCPA rail ceiling, in the account's own currency
MS_ADS_DRAFT_TTL_SECONDS 3600 how long a draft stays valid before confirm_and_apply refuses it as stale
MS_ADS_DEVELOPER_TOKEN, MS_ADS_CLIENT_ID, MS_ADS_CLIENT_SECRET, MS_ADS_CUSTOMER_ID, MS_ADS_ACCOUNT_ID, MS_ADS_TENANT the six static credential fields; env wins over the credentials file when both are set

Currency note: MS_ADS_MAX_DAILY_BUDGET and MS_ADS_MAX_CPC are compared directly against amounts in the account's own currency, not converted to or from USD. A 1000 ceiling means 1000 units of whatever currency the account is denominated in.

Test / lint

.venv/bin/python -m pytest -q     # offline test suite, ~370 tests, no live API calls
.venv/bin/python -m ruff check .  # lint

Documentation

License and support

MIT-licensed — see LICENSE. This is a best-effort, unpaid open-source project: no SLA, no guaranteed response time. Issues are watched and triaged on a best-effort basis.

推荐服务器

Baidu Map

Baidu Map

百度地图核心API现已全面兼容MCP协议,是国内首家兼容MCP协议的地图服务商。

官方
精选
JavaScript
Playwright MCP Server

Playwright MCP Server

一个模型上下文协议服务器,它使大型语言模型能够通过结构化的可访问性快照与网页进行交互,而无需视觉模型或屏幕截图。

官方
精选
TypeScript
Magic Component Platform (MCP)

Magic Component Platform (MCP)

一个由人工智能驱动的工具,可以从自然语言描述生成现代化的用户界面组件,并与流行的集成开发环境(IDE)集成,从而简化用户界面开发流程。

官方
精选
本地
TypeScript
Audiense Insights MCP Server

Audiense Insights MCP Server

通过模型上下文协议启用与 Audiense Insights 账户的交互,从而促进营销洞察和受众数据的提取和分析,包括人口统计信息、行为和影响者互动。

官方
精选
本地
TypeScript
VeyraX

VeyraX

一个单一的 MCP 工具,连接你所有喜爱的工具:Gmail、日历以及其他 40 多个工具。

官方
精选
本地
graphlit-mcp-server

graphlit-mcp-server

模型上下文协议 (MCP) 服务器实现了 MCP 客户端与 Graphlit 服务之间的集成。 除了网络爬取之外,还可以将任何内容(从 Slack 到 Gmail 再到播客订阅源)导入到 Graphlit 项目中,然后从 MCP 客户端检索相关内容。

官方
精选
TypeScript
Kagi MCP Server

Kagi MCP Server

一个 MCP 服务器,集成了 Kagi 搜索功能和 Claude AI,使 Claude 能够在回答需要最新信息的问题时执行实时网络搜索。

官方
精选
Python
e2b-mcp-server

e2b-mcp-server

使用 MCP 通过 e2b 运行代码。

官方
精选
Neon MCP Server

Neon MCP Server

用于与 Neon 管理 API 和数据库交互的 MCP 服务器

官方
精选
Exa MCP Server

Exa MCP Server

模型上下文协议(MCP)服务器允许像 Claude 这样的 AI 助手使用 Exa AI 搜索 API 进行网络搜索。这种设置允许 AI 模型以安全和受控的方式获取实时的网络信息。

官方
精选