Bing Webmaster Tools MCP Server
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Bing Webmaster Tools MCP Server show my top search queries from last month"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Bing Webmaster Tools MCP Server
An MCP (Model Context Protocol) server that provides access to Bing Webmaster Tools functionality through Claude and other MCP-compatible AI assistants.
This is a hardened fork of isiahw1/mcp-server-bing-webmaster (MIT License, copyright (c) 2025 Isiah Wheeler — see LICENSE), maintained by Synectus for internal agency use across multiple client Bing Webmaster accounts. All credit for the original implementation and the full BWT API surface goes to the upstream author; this fork adds the production-hardening described below on top of it.
Changes from upstream
The upstream server runs over stdio only, with all 60 tools always registered against a single global API key and no access controls. This fork adds:
Read-only by default (
BWT_READ_ONLY, defaultstrue). The 26 tools that mutate state on Bing's side (submit_url,add_site,remove_sitemap, crawl settings, site roles, etc.) simply don't register as MCP tools under the default — an agent can't see or attempt to call a tool it can't use. SetBWT_READ_ONLY=falseto register all 60.Site allowlist (
BWT_ALLOWED_SITES), enforced centrally in the API client before any HTTP call reaches Bing, not per-tool. Asite_url-shaped argument for a site outside the allowlist raises immediately, on both read and write tools.Streamable HTTP transport alongside the original stdio, selected by
MCP_TRANSPORT=stdio|http. HTTP binds0.0.0.0:$PORT(default8080) and exposesGET /health(200, unauthenticated) for hosting platforms.Bearer auth with per-tenant API key routing for HTTP. A single
MCP_AUTH_TOKENcovers the simple case (one deployment, one Bing account).BWT_TENANTScovers this agency's actual shape — one shared deployment serving multiple client sites, several under different Bing Webmaster accounts — by mapping each client's own bearer token to its own API key and site allowlist. The key is bound to the authenticated connection, not looked up per tool call, because tools likeget_sites(no site argument) andadd_site(the site isn't in any map yet — it's being created) have no site to route a lookup on.Production Docker image:
python:3.13-slim, uv-based build, non-root user. Replaces the previousmcp-proxy/Glama.ai scaffolding, which cloned from GitHub at build time instead of using the local tree.Renamed package (
synectus-bing-webmaster-mcpon PyPI-style naming,@synectus/bing-webmaster-mcpfor npm), version reset to0.1.0to mark this as a new release line separate from upstream's versioning.
None of this changes what the 60 tools do against the Bing Webmaster API — only what's registered, what's reachable, and how the server is deployed.
Related MCP server: Bing Webmaster MCP Server
Installation
Prerequisites
Python 3.10+ (python.org)
uv for local/dev use, or Docker for hosted deployment
A Bing Webmaster API key (Settings → API Access) — one per Bing Webmaster account you intend to expose
Local development install
git clone <this-repo-url>
cd bing-webmaster-mcp
uv syncThis resolves against the pins in pyproject.toml (notably mcp[cli]>=1.10.0,<2.0.0 — the mcp SDK's 2.x line renamed FastMCP and removed the module this server is built on, so don't lift that upper bound without adapting the code). No uv.lock is committed; uv sync resolves fresh each time.
npm package
This fork is not yet published to npm under @synectus/bing-webmaster-mcp — package.json and the version-sync tooling are in place, but publishing is a separate decision (the existing .github/workflows/publish.yml still targets the old @isiahw1/... package name and needs updating before it's used). Until that's resolved, use the local uv install above or the Docker image.
Security: the API key leaks into logs
mcp_server_bwt/main.py calls logging.basicConfig(level=logging.INFO) at import time, which sets the root Python logger to INFO. The Bing Webmaster API key is sent as a query parameter (apikey=...) on every single request to Bing, and httpx's own request logger — which propagates to the root logger since nothing stops it — logs the full request URL, key included, at INFO:
INFO:httpx:HTTP Request: GET https://ssl.bing.com/webmaster/api.svc/json/GetUserSites?apikey=<LIVE KEY> "HTTP/1.1 200 OK"This is not specific to Docker or to BWT_READ_ONLY=false — it happens on every tool call, read or write, on either transport. In a container it lands in docker logs; on stdio it goes to stderr, which most MCP clients capture and persist. Under BWT_TENANTS multi-tenant HTTP, every tenant's key lands in the same shared log stream, so one leaked log file exposes every client's key at once.
Mitigation (deliberately not implemented in this change — land it separately and review it on its own): raise the httpx logger's level above INFO (logging.getLogger("httpx").setLevel(logging.WARNING)), or add a logging filter that strips the apikey query parameter before the record is emitted. Do not flip BWT_READ_ONLY=false or ship this to a deployment whose logs are retained or shipped anywhere until one of those is in place.
Configuration
Every variable below can be set directly in the environment or via a .env file (see .env.example for a fully commented copy).
Variable | Default | Applies to | Purpose |
| (required)* | both | Bing Webmaster API key. Required for stdio; required for HTTP unless running a pure |
|
| both |
|
| (empty = allow all) | both | Comma-separated site origins. A |
|
| both |
|
|
| http | Bound on |
| (unset) | http | Single static bearer token, routes to the global |
| (unset) | http | JSON object mapping bearer token → |
At least one of MCP_AUTH_TOKEN / BWT_TENANTS must be set for HTTP transport to start — it fails closed rather than serving unauthenticated.
Local (stdio)
export BING_WEBMASTER_API_KEY=your_api_key_here
uv run mcp-server-bing-webmasterClaude Desktop / Claude Code config:
{
"mcpServers": {
"bing-webmaster": {
"command": "uv",
"args": ["run", "--directory", "/path/to/bing-webmaster-mcp", "mcp-server-bing-webmaster"],
"env": {
"BING_WEBMASTER_API_KEY": "your_api_key_here"
}
}
}
}Remote (Streamable HTTP)
Run the server (or the Docker image) with MCP_TRANSPORT=http, then point any MCP client that supports remote Streamable HTTP servers with a custom header at it:
{
"mcpServers": {
"bing-webmaster": {
"type": "http",
"url": "https://your-deployment-host/mcp",
"headers": {
"Authorization": "Bearer your_token_here"
}
}
}
}Single-tenant example (one Bing account):
export BING_WEBMASTER_API_KEY=your_api_key_here
export MCP_TRANSPORT=http
export MCP_AUTH_TOKEN=a_long_random_token
uv run mcp-server-bing-webmasterMulti-tenant example (one deployment, several client sites/accounts — each client gets their own bearer token, mapped to their own Bing API key and allowed sites):
export MCP_TRANSPORT=http
export BWT_TENANTS='{"tok_client1":{"api_key":"CLIENT1_BING_KEY","allowed_sites":["https://client1.com"]},"tok_client2":{"api_key":"CLIENT2_BING_KEY","allowed_sites":["https://client2.com"]}}'
uv run mcp-server-bing-webmasterHealth check (no auth required):
curl https://your-deployment-host/healthDocker
docker build -t bing-webmaster-mcp .
docker run -p 8080:8080 \
-e MCP_AUTH_TOKEN=a_long_random_token \
-e BING_WEBMASTER_API_KEY=your_api_key_here \
bing-webmaster-mcpThe image defaults MCP_TRANSPORT=http and binds 0.0.0.0:8080. Runs as a non-root user; GET /health is wired up as the container HEALTHCHECK.
Available Tools
34 read tools are always registered. The 26 write/mutating tools below are marked write and require BWT_READ_ONLY=false to appear in tools/list at all.
Site Management
get_sites- List all verified sites in your accountadd_sitewrite - Add a new site to Bing Webmaster Toolsverify_sitewrite - Verify ownership of a siteremove_sitewrite - Remove a site from your accountget_site_roles- Get list of users with access to the siteadd_site_roleswrite - Delegate site access to another userremove_site_rolewrite - Revoke a user's site access
Traffic Analysis
get_query_stats- Get search query performance dataget_page_stats- Get page-level traffic statisticsget_rank_and_traffic_stats- Get overall ranking and traffic dataget_query_page_stats- Get detailed traffic statistics for a specific queryget_query_page_detail_stats- Get statistics for specific query-page combinationsget_url_traffic_info- Get traffic information for specific URLsget_children_url_traffic_info- Get traffic information for child URLsget_page_query_stats- Get query stats for one pageget_query_traffic_stats- Get traffic-over-time for a query
Crawling & Indexing
get_crawl_stats- View crawl statistics and bot activityget_crawl_issues- Get crawl errors and issuesget_crawl_settings- Get crawl settings for a siteupdate_crawl_settingswrite - Update crawl settings (slow/normal/fast)get_url_info- Get detailed index information for a specific URLget_children_url_info- Get information about child URLs under a parent URLfetch_urlwrite - Request Bing crawl a specific URL (consumes quota)get_fetched_urls- List URLs previously fetchedget_fetched_url_details- Details of a fetched URL
URL Management
submit_urlwrite - Submit a single URL for indexingsubmit_url_batchwrite - Submit multiple URLs at onceget_url_submission_quota- Check your URL submission limits
Content Submission
submit_contentwrite - Submit page content directly without crawlingget_content_submission_quota- Get content submission quota information
Sitemaps & Feeds
submit_sitemapwrite - Submit a new sitemapremove_sitemapwrite - Remove a sitemapremove_feedwrite - Remove a feedget_feeds- Get all RSS/Atom feeds for a siteget_feed_details- Details of one feed
Keyword Analysis
get_keyword_data- Get detailed data for specific keywordsget_related_keywords- Find related search termsget_keyword_stats- Get historical statistics for a specific keyword
Link Analysis
get_link_counts- Get inbound link statisticsget_url_links- Get inbound links for specific site URL (requires link and page parameters)add_connected_pagewrite - Add a page that has a link to your websiteget_connected_pages- List pages linking to the site
Content Blocking
get_blocked_urls- View blocked URLsadd_blocked_urlwrite - Block URLs from crawlingremove_blocked_urlwrite - Unblock URLs
Deep Link Management
get_deep_link_blocks- Get list of blocked deep linksadd_deep_link_blockwrite - Block deep links for specific URL patternsremove_deep_link_blockwrite - Remove a deep link block
URL Parameters
get_query_parameters- Get URL normalization parameters (may require special permissions)add_query_parameterwrite - Add URL normalization parameterremove_query_parameterwrite - Remove a URL normalization parameterenable_disable_query_parameterwrite - Toggle a query param on/off
Geographic Settings
get_country_region_settings- Get country/region targeting settings (may require special permissions)add_country_region_settingswrite - Add country/region targeting settingsremove_country_region_settingswrite - Remove country/region targeting settings
Page Preview Management
add_page_preview_blockwrite - Add a page preview block to prevent rich snippetsget_active_page_preview_blocks- Get list of active page preview blocksremove_page_preview_blockwrite - Remove a page preview block
Site Migration
get_site_moves- Get history of site moves/migrationssubmit_site_movewrite - Submit a site move/migration notification (validates both the old and new site against the allowlist)
Write Tools by Risk
The 26 write tools aren't hidden by accident — BWT_READ_ONLY=true is the default precisely because some of them are low-stakes and some are not, and tools/list doesn't distinguish between the two. This table does. Before setting BWT_READ_ONLY=false on a real deployment, read it.
Rule applied: a tool is Consequential if it changes who has access to the site, changes how Bing treats the entire property (not one URL), or cannot be undone by another API call at all. Everything else — scoped to a single URL, parameter, or pattern, with a paired add/remove call or a metered Bing-side allowance that resets on its own — is Reversible.
Reversible — undone by another call, or by time
Tool | What actually happens |
| Submits one URL to Bing's crawl/index queue. Draws against the daily URL submission quota (see |
| Same as |
| Registers a sitemap with Bing ( |
| Unregisters a sitemap. Hits the same |
| Unregisters a feed. Same |
| Adds a URL or directory to the crawl blocklist. |
| Removes a URL from the crawl blocklist — direct undo of |
| Pushes page HTML to Bing directly, skipping a crawl. Draws against the content submission quota ( |
| Records that another page links to yours. No |
| Blocks Bing from surfacing deep links matching a URL pattern in search results. |
| Removes a deep-link block — direct undo of |
| Tells Bing to ignore a URL query parameter for normalization/dedup. |
| Removes a normalization parameter — direct undo of |
| Toggles an existing normalization parameter on or off — call again with the opposite value to undo. |
| Blocks Bing from generating a rich-snippet preview for a URL/pattern. |
| Removes a preview block — direct undo of |
| Asks Bing to crawl one URL immediately. Draws against a Bing-side fetch allowance rather than changing configuration — there's nothing to undo, the effect is a queued crawl. |
fetch_url and submit_content are both write-shaped for the same reason: neither edits site configuration, both spend a metered Bing-side allowance instead (submit_url/submit_url_batch spend the same kind of allowance, against the URL submission quota). They're gated as writes because they cost Bing-side quota that an unsupervised agent could burn through, not because they change how the site is configured.
Consequential — hard or impossible to undo, changes access, or changes how Bing treats the whole site
Tool | What actually happens | How you undo it |
| Adds a site to the account's managed-sites list. |
|
| Attempts to verify domain ownership using whatever verification method Bing has on file for the site. | You can't retract a verification attempt through this API — it's Bing's record, not this tool's. |
| Removes the site from the Bing Webmaster account entirely — settings, blocked URLs, roles, and history for that property go with it. |
|
| Grants another user access to the site. Takes a raw |
|
| Revokes a user's access to the site. |
|
| Tells Bing the site has moved to a new domain/subdomain, which redirects Bing's ranking signal from the old property toward the new one. Both | No undo call exists. Submitting another move back to the original domain is possible, but signal already transferred is not guaranteed to fully return. |
| Sets geo-targeting for the whole property to a country/region. |
|
| Removes geo-targeting for the whole property. |
|
| Changes Bing's crawl rate (Slow/Normal/Fast) for the entire site, affecting how fast every page on it gets crawled. |
|
Usage Examples
Once configured, you can use these tools in Claude:
"Show me all my verified sites in Bing Webmaster Tools"
"What are the top search queries for example.com?"
"Show me crawl errors for my site"
"What's my daily URL submission quota?"
"Get detailed stats for the query 'best products' on my site"
"Show me traffic info for my top 10 pages"
"Get historical data for the keyword 'seo tools'"Anything that mutates state ("Submit this URL for indexing", "Add a new site", "Block this URL from crawling") requires BWT_READ_ONLY=false — under the default, those tools aren't visible to the agent at all.
Development
uv sync
uv run pytest tests/ -vThe test suite (tests/test_read_only_gate.py, tests/test_site_allowlist.py, tests/test_http_transport.py) covers the read-only gate, the site allowlist (including origin normalization), and the HTTP transport's auth/tenant-routing behavior — including an end-to-end check that a tenant's API key actually reaches BingWebmasterAPI._make_request during a real tools/call, not just at the auth middleware layer.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
MIT License — see LICENSE. Original work copyright (c) 2025 Isiah Wheeler.
Support
For issues with the upstream BWT tool implementations, see the original repository. For issues with the hardening in this fork (read-only gate, allowlist, HTTP transport, tenant routing, Docker), open an issue in this repository.
Available Tools
34 toolsget_active_page_preview_blocksC
Get list of active page preview blocks.
Inputs: site_url (required). Returns: result
get_blocked_urlsC
Get list of blocked URLs for a site.
Inputs: site_url (required). Returns: result
get_children_url_infoC
Get information about child URLs under a parent URL.
Inputs: site_url (required), parent_url (required). Returns: result
get_children_url_traffic_infoC
Get traffic information for child URLs.
Inputs: site_url (required), parent_url (required), limit. Returns: result
get_connected_pagesB
Get list of connected pages that link to your site.
Inputs: site_url (required). Returns: result
get_content_submission_quotaC
Get content submission quota information.
Inputs: site_url (required). Returns: result
get_country_region_settingsA
Get country/region targeting settings. Note: May require special permissions.
Inputs: site_url (required). Returns: result
get_crawl_issuesB
Get crawl issues and errors for a site.
Inputs: site_url (required). Returns: result
get_crawl_settingsC
Get crawl settings for a site.
Inputs: site_url (required). Returns: result
get_crawl_statsC
Retrieve crawl statistics for a specific site.
Inputs: site_url (required). Returns: result
get_deep_link_blocksB
Get list of blocked deep links.
Inputs: site_url (required). Returns: result
get_feed_detailsC
Get detailed information about a specific feed.
Inputs: feed_url (required), site_url (required). Returns: result
get_feedsC
Get all RSS/Atom feeds for a site.
Inputs: site_url (required). Returns: result
get_fetched_url_detailsD
Get detailed information about a fetched URL.
Inputs: url (required), site_url (required). Returns: result
get_fetched_urlsC
Get list of URLs that have been fetched.
Inputs: site_url (required). Returns: result
get_keyword_dataC
Get detailed data for a specific keyword/query.
Inputs: query (required), site_url (required). Returns: result
get_keyword_statsC
Get historical statistics for a specific keyword.
Inputs: query (required), site_url (required), country, language. Returns: result
get_link_countsB
Get inbound link counts for a site.
Inputs: site_url (required). Returns: result
get_page_query_statsC
Get query statistics for a specific page.
Inputs: page (required), site_url (required). Returns: result
get_page_statsC
Get traffic statistics for top pages.
Inputs: site_url (required). Returns: result
get_query_page_detail_statsC
Get detailed statistics for a specific query and page combination.
Inputs: page (required), query (required), site_url (required). Returns: result
get_query_page_statsC
Get detailed traffic statistics for a specific query.
Inputs: query (required), site_url (required). Returns: result
get_query_parametersC
Get URL normalization parameters. Note: May require special permissions.
Inputs: site_url (required). Returns: result
get_query_statsC
Get detailed traffic statistics for top queries.
Inputs: site_url (required). Returns: result
get_query_traffic_statsC
Get traffic statistics for queries over time.
Inputs: query (required), site_url (required), period. Returns: result
get_rank_and_traffic_statsC
Get overall ranking and traffic statistics.
Inputs: site_url (required). Returns: result
get_site_movesC
Get history of site moves/migrations.
Inputs: site_url (required). Returns: result
get_site_rolesC
Get list of users with access to the site.
Inputs: site_url (required). Returns: result
get_sitesA
Retrieve all sites in the user's Bing Webmaster Tools account
Inputs: no named parameters. Returns: result
get_url_infoC
Get detailed index information for a specific URL.
Inputs: url (required), site_url (required). Returns: result
get_url_linksC
Get inbound links for specific site URL.
Inputs: link (required), site_url (required), page. Returns: result
get_url_submission_quotaC
Get information about URL submission quota and usage.
Inputs: site_url (required). Returns: result
get_url_traffic_infoC
Get traffic information for specific URLs.
Inputs: urls (required), site_url (required). Returns: result
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 34 tools
Many tools have heavily overlapping purposes, such as get_keyword_stats, get_keyword_data, get_related_keywords, get_query_stats, get_query_page_stats, get_query_page_detail_stats, get_page_query_stats, and get_query_traffic_stats. An agent would struggle to choose the correct tool without deep knowledge of the API's internal distinctions.
All tools follow a get_ prefix, which is consistent, but the suffixes are unpredictable: info, stats, details, data, and settings are used interchangeably. The naming also swaps word order in confusing ways, e.g., get_page_query_stats vs get_query_page_stats, making the pattern unreliable.
34 tools is excessive for a coherent MCP server surface, especially since almost all of them are read-only variations on the same underlying domain. The large count increases selection difficulty without providing meaningful functional variety.
The server is almost entirely read-only: every tool begins with get_, and there are no tools for submitting URLs, blocking/unblocking URLs, managing feeds, updating crawl settings, or handling site moves. This creates major dead ends for common Webmaster Tools workflows.
Related MCP Connectors
Google Search Console for AI assistants: traffic, rankings, indexing and page checks. Read-only.
Google Search Console, GA4 and Bing Webmaster data for SEO and AI-search work. 20 read-only tools.
Read-only Google Search Console and Google Analytics for AI agents.
Read-only Google Search Console, Bing, Google Analytics and privacy-friendly analytics for your AI.
Related MCP Servers
- AlicenseBqualityCmaintenanceProvides AI agents full access to Bing Webmaster Tools API for site management, URL submission, sitemaps, traffic stats, keyword research, and URL blocking.2410 npm1MIT
- AlicenseAqualityBmaintenanceBing Webmaster Tools and IndexNow for AI agents: traffic, indexing, crawl issues, inbound links, keywords. Direct writes are off by default; changes go through a plan a person applies.6356 PyPI1MIT
- AlicenseCqualityCmaintenanceEnables AI assistants to manage Bing Webmaster Tools, including site verification, URL submissions, traffic analytics, crawl monitoring, and keyword analysis through natural language.62MIT
- AlicenseAqualityBmaintenanceEnables AI assistants to access search analytics from Google Search Console and Bing Webmaster Tools, inspect URL indexing, monitor sitemaps, and submit URLs to search engines via IndexNow.7MIT