What 119,510 signed MCP server results show about uptime and tool-list drift
Updated 22 October 2026.
We have been probing public remote MCP servers on a schedule since 20 August 2026, without credentials, and signing what we observe since 22 August. This post summarises that data as of 21 October 2026, 23:00 UTC. Every figure comes from a read-only query against our production database, and each is defined where it appears.
We do not combine any of this into a score, and none of it is a verdict on a server. These are observations, together with the conditions they were made under.
The data set
At the cut-off our probe list held 5,916 remote MCP endpoints. Not all of them were signed, and not all were observed for the whole month. For each endpoint we took its most recent run in the seven days before the cut-off; 5,912 had one.
| Latest run | Endpoints | Share |
|---|---|---|
| Signed, full coverage | 3,564 | 60.3% |
| Signed, partial (auth-gated) coverage | 1,898 | 32.1% |
| Not signed | 450 | 7.6% |
Of the 450 unsigned runs:
- 412 did not complete the MCP handshake.
- 36 completed it but returned no tool list we could fingerprint.
- 2 were stopped by our outbound network guard.
For uptime we need at least seven days of observation. 951 endpoints had fewer, mostly because they were added in October, so the uptime section covers 4,961.
We store 194,352 probe runs against these endpoints, the first on 20 August. 119,510 of them carry a signed attestation: 114,398 with full coverage, and 5,112 with auth-gated coverage, which we introduced on 20 October. One of the 119,510, from a test run on 20 August, was signed with a development key that is not in our published key list, so our verifier rejects it.
"Full coverage" means every check was attempted, not that every check reached a verdict. A typical full-coverage run reaches a verdict on 10 of our 15 checks. The other 5 are UNVERIFIED with a reason:
- the TLS and latency checks, which are not run yet;
- authentication metadata, when the server showed no sign-in challenge;
- the two checks against an approved baseline, when no baseline exists.
Our homepage counts differently:
- Servers in the directory (3,770 when we checked on 22 October, 00:23 UTC) includes only servers that have returned a tool list at least once. This post counts every endpoint on the probe list, including those that ask for sign-in first or never complete a handshake.
- Runs and signed results are all-time totals, including runs our retention policy has since removed.
- "Tool set changed, last 30 days" compares tool names only, across all listed servers.
- The protocol panel counts the 3,564 servers whose latest result is signed with full coverage; this post counts the 3,602 that completed the handshake.
What a signature does and does not tell you
A signature shows that a record was issued by us and has not been altered since. It does not show that the server is good, that it will behave the same way tomorrow, or anything about what sits behind its sign-in. What a signed attestation proves goes into the details.
Uptime: how often a server answered
For each server we look at UTC days.
- Up: every run that day reached the server.
- Down: a run found the server unanswered. The host name did not resolve, the connection failed, no complete response arrived within the time budget, or the handshake got an HTTP 5xx.
- Left out: days on which only our probe could not reach a conclusion, for example because it was rate-limited.
A server's rate is its up days divided by its counted days.
The rule changed during the window. An HTTP 5xx during the handshake counts as down since 23 September, and a failed connection since 27 September. Before those dates, such a day may have counted as up or been left out, so the start of the window leans slightly towards "up".
We use the 29 full UTC days from 22 September to 20 October, and 4,961 servers had at least seven counted days in that period. We left out 21 September: 81 servers were recorded as unanswered that day, against 7 to 22 on the neighbouring days. We redeployed the probe three times that day, and the runs behind it have since been removed by our retention policy, so we cannot tell whether the cause was on our side. Including 21 September would lower the share of servers that answered on every counted day from 89.4% to 88.3%.
| Group (by latest run) | Servers | 100% | 95–99% | 80–94% | 50–79% | under 50% |
|---|---|---|---|---|---|---|
| Signed, full coverage | 2,967 | 2,692 (90.7%) | 118 | 130 | 21 | 6 |
| Signed, auth-gated | 1,593 | 1,485 (93.2%) | 63 | 41 | 4 | 0 |
| Latest run unsigned | 401 | 258 (64.3%) | 16 | 33 | 39 | 55 |
| All | 4,961 | 4,435 (89.4%) | 197 | 204 | 64 | 61 |
Rates are rounded to whole percent before bucketing.
Most servers answered on every counted day. The servers that require sign-in did slightly better than the open ones. For them, "answered" means they returned the 401 challenge; we cannot see whether the service behind sign-in worked. The long tail sits almost entirely among servers whose latest run was unsigned: 55 of the 61 servers below 50% are in that group. Some of that is selection, since a server whose latest run failed is one that had trouble recently.
Unclaimed servers are probed every 12 hours, so a day usually rests on two runs and a short outage between runs is invisible. This measures whether a server tends to be there when a client shows up, not minute-level availability.
Drift: how often tool lists change
Every run that gets a tool list compares it with the previous one for the same server. Each tool's name, description and input schema are part of the comparison. We apply the same exclusions as our earlier post, How often MCP toolsets change:
- Included: servers that already had a stored tool list when the window began, and whose tool list we actually read at least once during the window.
- Excluded: the 3 claimed servers, which we read more often than every 12 hours, and the 7 servers that return paged tool lists.
| Window | Servers | Any change | Tool added or removed | Schema changed, names unchanged | Description only | Potentially breaking |
|---|---|---|---|---|---|---|
| 7 days (14–21 Oct) | 3,029 | 780 (25.8%) | 376 (12.4%) | 234 (7.7%) | 170 (5.6%) | 115 (3.8%) |
| 30 days (21 Sep–21 Oct) | 815 | 398 (48.8%) | 261 (32.0%) | 91 (11.2%) | 46 (5.6%) | 115 (14.1%) |
The middle three columns are exclusive. Each server appears once, in the first column that applies.
Potentially breaking means that in at least one change during the window, one of the following happened:
- a tool disappeared;
- a parameter of a remaining tool was removed;
- a parameter's declared
typechanged; - a parameter became newly
required.
Each of these can make a previously valid call fail. Whether it does depends on the client and on the server's validation, so this is an upper bound, not a count of failures.
In any one week, about a quarter of these servers changed something, and about one in eight added or removed a tool. Those shares held steady over the last five weeks, between 26% and 29% for any change and between 12% and 14% for additions and removals, while the population grew from 171 to 3,029 servers.
Across every server we read during those 30 days, not only the 815 above (claimed and paged servers still excluded):
- Changes cluster. 5,054 changed lists were stored for 1,509 servers. 98 servers changed ten or more times and account for 29% of the changes.
- Changes rarely flip back. Only 41 changed lists exactly matched an earlier list of the same server.
- Descriptions move most, but rarely alone. We counted 12,951 description changes on individual tools, against 6,754 tools added, 2,500 removed and 9,154 schema changes. 764 description changes differed only in digits, such as counts, dates or versions, and 31 only in whitespace. Yet only 5.6% of servers changed nothing but descriptions in a given window.
- Type changes are mostly about precision. The most common type change was
numbertointeger: 319 parameter changes on 13 servers, most of them from a single server (case C below). Many others moved a parameter from a plaintypeto a composite such asanyOf. Our heuristic counts that as a type change, which overstates breakage.
Three cases
These are real servers from our data. We have left out names, exact dates and exact tool counts, because we have not asked their maintainers.
A server that grew in steps. Over the month, one server's tool count grew by about 60%, in ten separate steps. Between steps it also edited descriptions and schemas. We stored more than 40 changed lists for it. An agent that refreshed this server's tool list weekly would usually have been missing its newest tools.
Almost every tool gone. A server with several hundred tools had one run that did not complete the handshake. When it next answered, almost all of its earlier tool names were gone. Neither list carried a nextCursor, so this was not a paging effect. Any agent holding the earlier list would have been calling tools that no longer exist.
number becomes integer. In one update, a large server changed many of its numeric parameters from number to integer. Their descriptions did not change. A client that validates arguments against the new schema would now reject 2.5 where it accepted it the day before.
Protocol revisions
3,602 servers completed the handshake in their latest run and declared a protocol revision. The other 2,310 did not: 1,897 asked for sign-in at the handshake, 412 did not complete it, and 1 was stopped by our network guard. (One more auth-gated server completed the handshake and asked for sign-in only at tools/list.)
| Revision | Servers | Share |
|---|---|---|
| 2025-11-25 | 1,803 | 50.1% |
| 2026-07-28 | 1,043 | 29.0% |
| 2025-06-18 | 595 | 16.5% |
| 2024-11-05 | 85 | 2.4% |
| 2025-03-26 | 75 | 2.1% |
| other | 1 | <0.1% |
Our probe first tries server/discover and offers 2026-07-28. If the server does not support that, the probe falls back to initialize and offers 2025-11-25.
| Path | Answered | Offered revision | Earlier revision | Later revision | Unrecognised |
|---|---|---|---|---|---|
server/discover, offered 2026-07-28 |
1,059 | 1,039 | 20 | 0 | 0 |
initialize, offered 2025-11-25 |
2,543 | 1,797 | 741 | 4 | 1 |
| Total | 3,602 | 2,836 | 761 | 4 | 1 |
761 servers (21.1%) answered with an earlier revision than the one offered, most often 2025-06-18 (592). Answering with an earlier supported revision is how the protocol defines negotiation, so this is not a fault. It shows how much of the public surface still speaks revisions from 2024 and the first half of 2025.
Sign-in
In their latest run, 2,182 endpoints answered one of our requests with HTTP 401. They fall into two groups.
- 1,916 (87.8%) asked for sign-in at the handshake or at
tools/list.- 1,898 of them received a signed attestation with auth-gated coverage.
- 17 could not be signed because we got no tool list to fingerprint.
- 1 was stopped by our network guard.
- 266 (12.2%) listed their tools without credentials. They answered 401 only to the call we make to a tool name that does not exist, and they were signed with full coverage.
Of the 2,150 401s that carried a WWW-Authenticate challenge, 2,011 (93.5%) pointed to an OAuth protected-resource metadata document, as RFC 9728 describes. We fetched each document once:
- 1,997 were consistent with the challenge;
- 10 declared scopes that contradicted it;
- 4 returned an HTTP error.
139 challenges had no pointer, and 32 of the 401s carried no challenge at all.
An auth-gated attestation covers the four checks that are observable without credentials: reachability, redirect policy, transport and authentication metadata. Every other check is marked UNVERIFIED with a reason. The signed payload records the coverage, so a partial attestation cannot be mistaken for a full one. We started auth-gated signing on 20 October; before that, runs like these were left unsigned.
Method
-
Probing. Unclaimed servers are probed every 12 hours from Cloudflare Workers. The probe never sends credentials. It sends the handshake,
tools/list(first page only), and one call to a tool name that does not exist. That call is skipped when the first page has anextCursor. -
Check states. Each run records one state per check: VERIFIED, FAILED, OBSERVED_RISK, or UNVERIFIED with a reason.
-
Signing. A run that meets our signing conditions is canonicalised and signed with Ed25519 in a DSSE envelope. The signature binds the record to our key and makes any later change detectable. It is not a statement about the server's quality. Unsigned runs are shown as unsigned.
-
Published keys. The key list is at
https://mcpcheckup.com/.well-known/mcpcheckup-keys.json. The current key ID is70222b3a2c05e79a, valid from 22 August 2026. -
Checking a signature. mcpcheckup/checks holds the canonicaliser, the attestation schema and an offline verifier. It needs Node.js 22.18+ or 24+ and has no install step:
curl -fsS https://mcpcheckup.com/.well-known/mcpcheckup-keys.json -o keys.json node packages/verifier/verify-attestation.mjs --envelope <file> --keys keys.jsonThe verifier makes no network request. It checks that each signature's key ID is in the key list and not revoked, and that the payload's
observed_atfalls inside the key's validity window. A copy of the key list inkeys/allows fully offline checks.
Limits
- Two checks are not run yet. The TLS certificate and latency checks are UNVERIFIED in all 5,912 latest runs.
- Auth-gated attestations cover four checks only. Everything behind sign-in is outside what we observe.
- Transport is not recorded. We do not record whether a server answered over streamable HTTP or legacy SSE.
- Uptime is day-level, and its rule tightened during the window, as described above.
- We read only the first page of a tool list. Paged servers are excluded from the drift figures.
- Some description changes are dynamic text. "Potentially breaking" is a heuristic on top-level parameters; it skips nested schemas and counts moves to
anyOfas type changes. - One vantage point, no credentials. Signed-in users, or clients in other regions, may see different behaviour.
- The 7-day and 30-day populations differ. The list grew fast in October, so the 7-day population (3,029) and the 30-day one (815) are different sets. Do not read them as a trend.
About MCP Checkup
MCP Checkup publishes these observations per server, with the signed attestations behind them. The methodology page describes every check.
- Free check. The homepage runs a free check against any public MCP endpoint. That check is not signed and not stored.
- Indie plan. Maintainers who claim their server can add the Indie plan: $5.99 a month or $49.99 a year for 10 servers, checked every 15 minutes, with alert emails.