DEV Community

Cover image for "Our MCP directory said \"active\". The publisher had deprecated it five days earlier."

"Our MCP directory said \"active\". The publisher had deprecated it five days earlier."

md sultan mahamud on October 29, 2026

I run ProtocolProbe, a directory of facts about every server in the official MCP Registry: each server gets a page, read from public records (the r...
Collapse
 
gautamtalksdev profile image
Gautam K •

The 53 deprecated entries still showing as active is a useful find, and showing a date range on the leaderboard is a nice honest touch. The same version, different record problem goes one level deeper for remote servers: the endpoint can change what tools/list returns with no new version and no registry change at all. Do you record anything about the tool list itself, like a hash per server, or only the registry and package facts?

Collapse
 
sultan57git profile image
md sultan mahamud •

Yes, the tool list itself. Every read-only listing we capture is stored as hashes: one for the whole list, and one per tool for its title, description, input schema and annotations. Each server's reads are compared in order, and the hosted endpoint and the package are tracked separately so they're never mixed up. The server page then shows tools added, removed or changed between two reads, and flags "changed without a new version". When we first measured it on 2026-10-25, 0 of the changed pairs had the same version, so we haven't caught that case yet, but it's flagged when it happens. We never call the tools, and a read we don't have counts as unknown, never as "unchanged".

Collapse
 
gautamtalksdev profile image
Gautam K •

Counting a missing read as unknown, not unchanged, is the part I like most. That's the honest default. And 0 same-version changes so far is still a useful number to publish, it tells people the check is armed. Will keep an eye on the server pages.

Thread Thread
 
sultan57git profile image
md sultan mahamud •

Thanks, glad the unknown-vs-unchanged choice reads right. One caution on the 0: it is out of only 11 same-version pairs we could compare (as of 2026-10-31), so it shows the check ran and found nothing there, not that silent swaps don't happen. Our daily job only re-reads new or new-version listings, so a same-version change is mostly invisible to us today. We state that on the site as a coverage limit.

Thread Thread
 
gautamtalksdev profile image
Gautam K •

Stating the 11-pair limit on the site is the honest version, thanks for spelling it out. If you ever widen it, a slow weekly re-read of a random sample of unchanged listings would give you a real rate for same-version swaps instead of a blind spot.

Thread Thread
 
sultan57git profile image
md sultan mahamud •

Thanks, that's a good suggestion. You're right that today it's a blind spot: we only see a tool list on the days we read it, so a same-version swap shows up only if two of our reads happen to straddle it. A random sample of unchanged listings, re-read on a schedule, would turn that into a rate with a stated base. I'm noting it as the way to widen this. I won't promise a date, and I'd publish the sample size and the read dates with any rate, since a small sample could mislead.

Collapse
 
alexshev profile image
Alex Shev •

Registry freshness is a security and reliability property, not housekeeping. An entry should carry its publisher, last verified timestamp, supported protocol version, and a clear expiry policy. Clients can then warn or fail closed on stale integrations instead of silently treating a directory as ground truth.

Collapse
 
sultan57git profile image
md sultan mahamud •

Agreed, and it's measurable. Today a registry entry carries status, statusChangedAt, statusMessage, publishedAt and updatedAt, but no expiry and no "last verified" time (I checked the live OpenAPI spec). So a client can't tell "active, checked yesterday" from "active, nobody has looked in a year". That's why every fact on our pages carries the date we read it.

Collapse
 
alexshev profile image
Alex Shev •

Freshness needs an owner and a failure mode. Expose last verified time, upstream deprecation status, and a TTL that blocks automatic use after expiry; a stale directory entry should degrade to review, not remain silently selectable.

Thread Thread
 
sultan57git profile image
md sultan mahamud •

Agreed on the failure mode. A directory like ours can't block a client, so that has to live in the client or the registry. Today we expose the date we last read each fact, and the status exactly as the registry reports it (we reconcile it against the registry every day). The registry schema itself has no last-verified or expiry field.

One thing we can add on our side, and are considering: a machine-readable "last verified" and "stale after" in our API, so a client can degrade a stale entry to review without scraping pages. I'd only ship it once the refresh behind it runs on a schedule, so the number is one we can keep.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

A job that reports ok while the page stays wrong is a nasty kind of bug.

Collapse
 
sultan57git profile image
md sultan mahamud •

Exactly, and the nasty part is that every check we had was green: the job exited ok, and a version comparison found 0 mismatches across all 51,834 records. The bug lived in a field the check never compared (status, which the registry lets a publisher change without a new version).

Two things changed for us: we now compare every field the source owns, not just the version, and "ok" no longer comes from the exit code. After each run we sample changed servers and read the public page's own marker (version, status, a hash of the status message). It only warns and doesn't roll back, and when our own lookup fails we log "not checked" rather than pass it. The first full compare found 53 stale pages; the next one found 0.

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

The 'not checked' rather than pass distinction is the part most teams skip — a failed lookup that reads green is worse than a loud failure. When the public page itself is down, does the sample count that as not checked too, or does it warn?

Collapse
 
robertpaschal profile image
Odinaka Robert Nnamani •

The not checked label is the useful part. A failed lookup should not pass as a clean run.

Thread Thread
 
sultan57git profile image
md sultan mahamud •

Agreed. A failed lookup counted as a pass would have hidden the same bug again, so "not checked" is its own state and never counted as clean.

Thread Thread
 
robertpaschal profile image
Odinaka Robert Nnamani •

Treating 'not checked' as its own state is the fix. Counting it as clean is how the same bug hides twice.