Six of 16 common MCP servers can't be read from outside. One of the others changed 19 times in a month
We wrote down sixteen MCP servers that a software team could plausibly connect to its agents: the hosted servers of GitHub, Notion, Linear, Atlassian, Sentry and Stripe; Context7, DeepWiki, Hugging Face and Cloudflare's docs server for reading; Firecrawl, Brave Search and Tavily for the web; and three local packages, Playwright, MongoDB and Sentry.
It is a sample we picked, not a customer's setup and not a survey. Then we asked HISTOR, the public log of MCP tool definitions we run, what each of them had told agents over the last 30 days, 12 October to 11 November 2026. For six of the sixteen the answer was: nothing. HISTOR has never read a tool from them.
The six nobody outside can read
GitHub, Notion, Atlassian and Stripe answer an unauthenticated client with HTTP 401. Linear's and Sentry's hosted servers did the same on every read until 1 November. Since 2 November HISTOR honours robots.txt, and both sites disallow /mcp for all crawlers (Linear's disallows the whole site), so HISTOR no longer sends them a request.
Requiring sign-in is the right call for servers that reach a team's code, tickets, documents and payments. The consequence is that no public log, ours included, can tell you what these servers describe to your agent, or when that description changed.
The readable servers are not harmless by comparison - MongoDB's package has drop-database, Sentry's package now has delete_alert_rule - but at least their definitions are public.
The ten that can be read
Eight of the ten changed their tool definitions - descriptions or schemas - 28 times between them. Brave Search and Tavily did not change at all. Thirteen of the 28 changes came while the server kept reporting the same version, and all thirteen were Firecrawl's. Everywhere else, a change came with a new version number.
A changed definition does not mean a server misbehaved. It means the text and the schemas your model works from are not the ones somebody reviewed, and the workflows that use those tools deserve a re-run.
Three of the ten show three different kinds of change.
Sentry: from 9 tools to 73
Between the two versions HISTOR read, @sentry/mcp-server 0.42.0 and 0.49.0, the package went from 9 tools to 73. It dropped execute_sentry_tool, search_sentry_tools and search_events, kept six, and added 67. Among the new ones: delete_alert_rule, delete_metric_monitor, delete_monitor_environment, delete_uptime_monitor, seven create_* and five update_* tools.
The old design was deliberate. In 0.42.0, search_sentry_tools told the model: "Many Sentry operations are intentionally not exposed as top-level tools", and execute_sentry_tool ran them by name. In 0.49.0 those operations are tools of their own.
For a reviewer that is better: the four delete_* tools are now visible by name. But a config that starts npx -y @sentry/mcp-server without a version moved to 0.49.0 as soon as npx resolved it, and nobody had to approve the new tool list.
Firecrawl: changes the version did not announce
Each line is a new tool set: HISTOR hashes the tools' names, descriptions and input and output schemas, and a new digest is a change. The orange lines came with no new version. Some of what they carried:
- an
objectiveinput became required on 13 October, stopped being required with the3.30.1release on 15 October, and became required again on 18 October while the server still said3.30.3; - on 10 November
firecrawl_scrapegained an output field,retryable, and thezeroDataRetentionoption disappeared fromfirecrawl_search's scrape options - an object that rejects unknown keys, so a call that still sends the flag no longer validates; - at 03:21 UTC on 11 November
firecrawl_scrapedropped itsalexandriaargument, madeurlrequired, and its description namedalexandria_library_searchandalexandria_library_readwhere it had namedfirecrawl_find_tools. At 07:58 it was back, byte for byte, to the definition it had before;firecrawl_searchkept the new names. The server reported3.39.0throughout.
We don't know why any of these happened, and nothing about them is wrong. Firecrawl is under active development and its hosted server is where that shows. What they show is that the version string of a hosted server is not a record of what it serves. (Yesterday's post on signed manifest revisions is about who can vouch for such a change.)
MongoDB: a change that changes nothing
mongodb-mcp-server 3.2.2 โ 3.3.0 touched 10 input schemas and 8 output schemas. Most of its 47 edits rewrite additionalProperties: {} as additionalProperties: true or drop an empty items: {}. JSON Schema treats these forms as identical, so every call that validated before still validates.
The rest add guidance on embedding models to field descriptions and tighten one field mapping in create-index. A digest-based alarm fires on this exactly as loudly as on Firecrawl's zeroDataRetention. That is why a change alert alone is not enough: the person approving it needs the diff.
Checking your own servers
HISTOR's API is public and needs no key. This is the count behind the orange lines, cut down to one server; it runs on Python 3.9 or later with the standard library:
# usage: python3 same_version.py <server id> <since, e.g. 2026-10-12>
import json, sys, urllib.request
server_id, since = sys.argv[1], sys.argv[2]
api = "https://histor.modelmarket.dev/api/v1"
url = f"{api}/changes?watch={server_id}&limit=200" # newest first
rows = json.load(urllib.request.urlopen(url, timeout=30))["changes"]
window = [c for c in rows if c["observed_at"] >= since]
silent = [c for c in window if c["from_server_version"] == c["to_server_version"] and c["from_package_version"] == c["to_package_version"]]
print(f"{len(window)} changes since {since}, {len(silent)} at the same version")
for c in silent:
tools = [m["tool"] for m in c["summary"].get("modified", [])]
print(" ", c["observed_at"], c["to_server_version"], ", ".join(tools))
$ python3 same_version.py 0ae1ed4e4d5d8dd7 2026-10-12
19 changes since 2026-10-12, 13 at the same version
2026-11-11T07:58:19Z 3.39.0 firecrawl_scrape
2026-11-11T03:21:09Z 3.39.0 firecrawl_scrape, firecrawl_search
โฆ
A server's id is on its HISTOR page, or from https://histor.modelmarket.dev/api/v1/servers?q=<name>. The numbers move as servers change; the output above is from 11 November.
For what HISTOR cannot read, the check has to run with your credentials. WARDEN, our open-source MCP scanner, records the tool definitions of every server in a repository's .mcp.json into a lock file. It needs Node.js 20 or later, and it starts the local (stdio) servers in the config to read their tools, so run it where you would run those servers anyway:
npx -y @aimarket/warden@0.26.0 scan --project \
--lock warden.lock.json --update-lock
WARDEN scan 0.26.0 ยท ruleset 19 sha256-XfRh1+VZoAM6โฆ ยท block at high
read .mcp.json (claude-code, 2 servers)
โ allow deepwiki claude-code 3 tools ยท score 0.90 ยท lock: updated
โ allow context7 claude-code 2 tools ยท score 0.90 ยท lock: updated
โฆ
Lock written: warden.lock.json. Commit it; the diff is the review.
That run is from a test repository with two public servers, on 11 November. Committed, the lock makes CI fail when a remote server serves different definitions (TOOL_DEF_DRIFT, with a field-by-field diff) or when a server nobody approved appears (LOCK_MISSING); --project keeps your personal configs out of it.
It reaches a hosted server only with the headers written in the config: a server that takes a token in a header (GitHub's accepts a personal access token, for example) can be locked this way. A server you sign into through OAuth in the client answers WARDEN with 401, just as it answers HISTOR. For those, today, the review is the tool list your client shows you. We don't know of a tool that closes that gap, ours included.
For package servers the oldest fix still works: write the version you reviewed into the config, "args": ["-y", "@sentry/mcp-server@0.49.0"], and review again when you bump it.
Limits of this measurement
HISTOR reads remote servers on a six-hour target, and every 30 minutes once a server has changed twice in a week. At 14:44 UTC on 11 November the mean gap between reads was 13.7 hours. A change that is undone between two reads is not seen.
It reads what a server serves an unauthenticated client. Tools that appear only after sign-in, or only for another client or launch configuration, are outside what it can see.
Packages are read at whatever version is current when a crawl reaches them, every few days for the ones here. HISTOR never read Sentry 0.43-0.47, and its 0.48.0 install failed, so their changes are inside the 0.42 โ 0.49 difference.
Sixteen servers is a sample we chose. At 14:44 UTC on 11 November HISTOR counted 79,415 tool-set changes in the previous 30 days across the 91,847 registry entries it tracks; that total includes publishers whose servers change on almost every read, so it is not a rate for your stack.
The sixteen records as we read them at 14:20 UTC on 11 November, their SHA-256 sums, the stats snapshot and the scripts behind every number here are in one archive (1 MB).
If you'd rather someone else did this
We are starting to do this as an audit for teams: an inventory of the MCP servers your developers and agents use, a WARDEN scan of each tool, the lock and an allowlist in your CI, and 30 days of change alerts with a short note on each change that touches your workflows. The first three teams get it free in exchange for written feedback and a short, non-binding letter of intent. If that's you, write to qw*******@gmail.com with the MCP clients your team uses.
We run HISTOR and WARDEN. AI assistance was used for the analysis, the scripts, the figures and this article; the data, code and quoted outputs are reproducible from the linked files.
Comments
No comments yet. Start the discussion.