mcp-microsoft-ads (wvuhskr/mcp-microsoft-ads) is an MCP server listed on the M8ven Trust Index. It scores 45 out of 100, grade D. It declares 47 tools. No publisher has claimed this listing.
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.
Warning. Serious findings were identified. Review the full report before connecting. Grades reflect the full trust pyramid: code, verification depth, and reputation. New projects cap at C until adoption is earned.
How we verified
Verified is a snapshot. Live keeps it current, and builds your track record.
⚡ Connect GitHub → continuous verification on every pushwhy connect →Who stands behind it
wvuhskr
Source: Glama
Claim it to get a verified publisher badge, a free copy of our full audit findings, and direct contact for any high-priority issues we find. Or connect your repo for our deepest verification, Live Monitored: read-only, revoke anytime. What we access →
Install from
The grade above is for the source repository. Registries can serve a different version, so we mark the ones we were not able to read.
These names and descriptions are the publisher's own, read from the source code. We print them as written. Our assessment is the findings above, not this list.
update_ad_groupDraft an ad-group update. target_cpa sets an explicit MaxConversions tCPA on the ad group (MS Search campaigns on the development account run MaxConversions with no target — this INTRODUCES one). cpc_bid is allowed ONLY when the ad group's effective bid strategy is in the MANUAL_BIDDING allowlist (r…
draft_responsive_search_adDraft a Responsive Search Ad. 3-15 headlines, 2-4 descriptions. Ad copy claims MUST be verified against the advertiser's website before use — don't claim anything not actually present on the site (site-verified-claims policy). Blocklist (settings-configured blocked_terms) enforced on every headline/…
create_custom_audienceDraft a remarketing list targeting site visitors (needs the account's UET tag; errors if none exists — create one in the MS Ads UI first). url_contains: substring the visited page URL must contain; defaults to the configured advertiser_domain setting when omitted — error naming both if neither is se…
add_audience_targetingDraft audience targeting on a campaign. audience_type disambiguates which id namespace audience_id is in — one of: RemarketingList, Custom, InMarket, Product, SimilarRemarketingList, CombinedList, CustomerList, ImpressionBasedRemarketingList, CustomSegment (WSDL AudienceType enum). bid_adjustment_pc…
update_campaignDraft a campaign update (budget / status Active|Paused / tCPA). tCPA at campaign level is only operative on PMax — for Search use update_ad_group. Returns a draft; apply with confirm_and_apply.
draft_campaignDraft a new campaign — ALWAYS created Paused. campaign_type: Search | PerformanceMax. time_zone/language default to EasternTimeUSCanada/English (US-centric defaults) — override for other markets.
confirm_and_applyExecute a previously drafted write. The ONLY path that mutates the account.
create_conversion_actionDraft a conversion goal. goal_type: Event | Url | Duration (only supported values on the development account). Each goal_type REQUIRES its matching match-criteria arg — without one the goal creates "successfully" but can never record a conversion: - Url: url_expression (matched with UrlOperator="Con…
set_conversion_action_primary_statusDraft a campaign-goal association. MS models 'primary for this campaign' as a campaign conversion goal association (associate = campaign optimizes to it; disassociate = falls back to account-level goals).
get_entitiesFetch entity state. entity: campaigns | ad_groups | keywords | ads | asset_groups | campaign_criterions. parent_id required for all but campaigns. campaign_criterions returns DayTime, Location, LocationIntent, Radius criterion types (Audience not readable via this API). NOTE: campaign BiddingScheme …
draft_sitelinksDraft sitelinks on a campaign. sitelinks: [{text, url, description1?, description2?}]. Copy claims must be site-verified (the advertiser's website).
create_calloutsDraft callout extensions (max 25 chars each).
create_structured_snippetsDraft a structured snippet (header must be an MS-supported header, e.g. 'Services'; 3+ values required).
remove_extensionDraft removal: disassociate from campaign, then delete from library.
search_geo_targetsSearch targetable/excludable locations by name (MS ships a file, not a query API; cached locally 30 days). Returns location ids for geo write tools.
exclude_geo_targetDraft a location EXCLUSION on a campaign. location_id from search_geo_targets.
remove_geo_targetDraft removal of a campaign criterion by id, via DeleteCampaignCriterions with CriterionType="Targets" — the Targets group covers Location, DayTime, Radius, and other campaign-criterion types, so this deletes whatever criterion id is passed, not Location only. ids from get_entities('campaign_criteri…
health_checkVerify auth chain: token refresh + Customer Management GetUser round-trip.
list_accountsList ALL advertiser accounts visible to the authenticated user (paged SearchAccounts under the hood; `truncated` is true only if the 1000-account safety cap was hit — raise MAX_PAGES if that ever happens for real).
get_account_infoAuthenticated user + roles + configured account/customer ids.
discover_keywordsKeyword ideas from seed keywords and/or a landing-page URL (Ad Insight GetKeywordIdeas). Scoped to the location/language/network configured via advertiser settings' keyword_research block (defaults: US/English/Owned&Operated+Syndicated).
get_keyword_forecastsTraffic estimates (clicks/impressions/CPC/cost) for candidate keywords at a given max CPC (defaults to the account's MS_ADS_MAX_CPC cap). Scoped to the location/language/network configured via advertiser settings (see discover_keywords).
list_recommendationsAccount recommendations (MS Ad Insight GetRecommendations). recommendation_type is passed through as-is to MS — live probing found the API rejects a null type but every documented RecommendationType enum value also faulted (607, account/feature gating, not a code issue); pass whatever type MS has en…
apply_recommendationDraft applying an MS recommendation (mutates the account — rails apply).
dismiss_recommendationDraft dismissing an MS recommendation.
draft_keywordsDraft new keywords under an ad group — created Paused. keywords: [{text, match_type: Broad|Phrase|Exact, bid: optional float}]. Blocklist (settings-configured blocked_terms) + bid cap (MS_ADS_MAX_CPC) enforced.
update_keyword_bidDraft a keyword CPC bid change (MS_ADS_MAX_CPC cap enforced). Allowed ONLY when the ad group's effective bid strategy is in the MANUAL_BIDDING allowlist (rails.py). Pre-rejected for Smart Bidding: UpdateKeywords silently ignores Bid there instead of erroring (live-verified — empty PartialErrors, bid…
remove_keywordsDraft keyword deletion (irreversible — pause_entity is the reversible lever).
upload_image_assetDraft an image upload to the account media library (for image extensions / PMax asset groups). Returns media id on apply. PNG/JPEG.
get_negative_keywordsCampaign-level negatives + ALL shared negative keyword lists (with items and campaign associations). Always call before recommending/adding negatives.
add_negative_keywordsDraft negatives. scope: campaign | ad_group | shared_list. keywords: [{text, match_type: Phrase|Exact}]. Checks existing negatives first and skips duplicates (check-existing-lists-first rule). Blocklist NOT applied — negating a settings-blocked term is desired. scope='ad_group' REQUIRES campaign_id …
remove_negative_keywordsDraft negative removal by id. scope: campaign | ad_group | shared_list. keyword_ids come from get_negative_keywords. scope='ad_group' REQUIRES campaign_id for consistency with add_negative_keywords — validation only, DeleteNegativeKeywordsFromEntities has no parent field per WSDL.
create_pmax_campaignDraft a Performance Max campaign + first asset group — created PAUSED. time_zone defaults to EasternTimeUSCanada (US-centric default) — override for other markets. target_cpa is required by default (require_pmax_target_cpa setting, default true) — never create PMax without a target; removing one lat…
create_portfolio_bidding_strategyDraft a portfolio bid strategy (account library, shared across campaigns). strategy_type: MaxConversions | MaxClicks | TargetImpressionShare. Returns a draft; apply with confirm_and_apply.
list_extensionsAd extensions. campaign_id=None: full account library (sitelinks, callouts, structured snippets...). campaign_id set: only extensions associated with that campaign.
get_conversion_actionsConversion goals (nil ids returns all goals of the given types).
get_policy_issuesDisapproved ads + keywords in an ad group (editorial review failures).
remove_entityDraft PERMANENT deletion of campaign | ad_group | keyword | ad. Irreversible — prefer pause_entity. ad_group needs parent_id=campaign id; keyword/ad need parent_id=ad group id.
get_campaign_performanceCampaign performance (impressions/clicks/spend/conversions/CPA).
get_ad_performancePer-ad performance.
get_keyword_performancePer-keyword performance incl. QualityScore.
get_geo_performanceGeographic performance.
get_search_termsSearch query report.
run_reportArbitrary report (replaces Google run_gaql for metrics pulls). report_type = exact v13 request type name e.g. 'AgeGenderAudienceReportRequest'.
set_campaign_scheduleREPLACE a campaign's ad schedule. week = 7 dicts {day, from_hour, to_hour} (0-23 hour clock; to_hour is the hour service stops, e.g. to_hour=22 serves until 22:00). MUST cover all 7 days — a campaign with any DayTime rows serves only inside them, so a partial week silently narrows delivery. Deletes …
pause_entityDraft a pause. entity_type: campaign | ad_group | keyword | ad. keyword/ad need parent_id = ad group id; ad_group needs parent_id = campaign id.
enable_entityDraft an enable (Status=Active). Same shape as pause_entity.
MS_ADS_AUDIT_PATHJSONL audit log locationMS_ADS_CREDENTIALS_PATH~/.mcp-microsoft-ads/credentials.yaml, override with ):Tool annotations
No tools have read-only/destructive annotations
Add readOnlyHint or destructiveHint annotations to every tool so hosts can warn users before invoking.
All four hints declared on every tool
47/47 tools missing one or more hints — update_ad_group (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); draft_responsive_search_ad (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint); create_custom_audience (missing: readOnlyHint, destructiveHint, idempotentHint, openWorldHint), +44 more. OpenAI's directory rejects tools where any of the four hints are missing or non-boolean.
For every tool, set all four hints (readOnlyHint, destructiveHint, idempotentHint, openWorldHint) to explicit true/false values that match the handler’s actual behaviour.
No access to sensitive paths
Reads sensitive paths: ~/.mcp-microsoft-ads/credentials.yaml
Remove reads of sensitive system paths. If you genuinely need them, document why in the README.
Claim the listing to review these findings one by one and send us a correction where you disagree, straight to the team. Claiming also means we tell you when the grade moves, and reach you first if we find anything urgent.
[](https://m8ven.ai/mcp/wvuhskr/mcp-microsoft-ads)?variant=verified from the URL.Vetting this one by hand? Tool Check is an MCP that scores other MCPs. Add it once and ask Claude, ChatGPT, or any MCP client to grade a server, surface CVEs, check the publisher, and suggest safer alternatives — before you install.
https://m8ven.ai/api/mcp/tool-check