deen
Alle Projekte
2026Konzept, Umsetzung, Betrieb (plus ein externer Beitrag)

MCP Migration Check

Prüfer für den MCP-Break: Skill, CLI, Action, Demo

mcp-migration-check.alpaycelik.workers.dev

Überblick

Die MCP-Revision 2026-07-28 macht das Protokoll zustandslos und bricht damit fast jeden bestehenden Server. Eine Regel-Engine mit vier Zugängen: Web-Demo, `npx`-Befehl, GitHub Action und ein Agenten-Skill, der nicht bei der Diagnose aufhört, sondern den Umbau Regel für Regel abarbeitet. Den Skill installiert man inzwischen als Claude-Code-Plugin aus dem Repository, damit er nicht gegen die Regeln veraltet, die er mitbringt; die CLI liegt als abhängigkeitsfreies Paket auf npm. Mit derselben Engine habe ich 13.380 registrierte Endpunkte geprüft: 60,1 % sprechen nur das alte Protokoll.

Das Problem

Eine Protokollrevision, die Sessions abschafft, bricht Server lautlos: lokal mit einem Prozess läuft alles, hinter einem Load Balancer schlägt jede zweite Anfrage fehl. Wer wissen will, ob es ihn trifft, liest ein Changelog mit neun Hauptänderungen und rät. Das Erkennen ist dabei nur die halbe Miete. Ein Agent, den man einfach auf den Code loslässt, findet zwar Treffer, kann aber nicht unterscheiden, welche davon echt sind, und baut dann eine `sessionId` um, die in Wahrheit zu einer Express-Session für ein Admin-Panel gehört. Gesucht war also nicht „ein Werkzeug, das Funde ausspuckt“, sondern eine Anleitung, die einem Agenten Diagnose, Triage und Reihenfolge vorgibt. Und wie schlimm es tatsächlich steht, hatte niemand beantwortet. Es gibt Tausende registrierter Server, aber keine Zahl dazu, wie viele der Bruch wirklich trifft, also habe ich sie mit derselben Engine gezählt. Die erste Fassung dieser Zählung konnte gepflegte Server, die beide Epochen bedienen, nicht von reinen Altservern unterscheiden. Der Report trennt das jetzt: 60,1 % sprechen nur alt, 5,5 % bedienen beides, und unter den 6.191 Servern, an denen seit der Revision überhaupt noch jemand gearbeitet hat, sind es 63,8 %.

Randbedingungen

  • Die Spec war vier Tage alt: kaum Sekundärquellen, alles selbst nachprüfen
  • Der Dienst ruft eine URL auf, die ein Fremder eintippt
  • Cloudflare Free Tier: 10 ms CPU pro Anfrage
  • Skill, CLI und Action laufen auf Maschinen, auf denen nie ein npm install lief
  • Ein Report über fremde Server, der keinen davon beim Namen nennt

Entscheidungen

Ein Skill mit Prozedur statt nur eines Werkzeugs

Skill, der Diagnose, Triage, Umbau und Verifikation vorgibt

Den Checker veröffentlichen und den Agenten machen lassen

Der offizielle Codemod deckt nur die SDK-Umbenennung ab und sagt selbst, dass die Protokollumstellung „architectural and not codemod-automatable“ ist. Der Scanner wiederum arbeitet mit regulären Ausdrücken, meldet also Signale und keine Beweise. Ein Agent, der die Liste ungeprüft abarbeitet, baut Fehlalarme um, und ein Umbau, der nicht nötig war, ist teurer als der Fund wert war. Der Skill schiebt deshalb einen Triage-Schritt dazwischen, der jeden Treffer an seiner Fundstelle begründen muss, bevor irgendetwas geändert wird. Danach gibt er die Reihenfolge vor: SDK zuerst, dann der Session-State, dann der Handshake, sonst refactort man zweimal. Die Engine liegt ihm als eine abhängigkeitsfreie Datei bei, damit der Diagnoseschritt auch dort läuft, wo nie ein npm install stattfand; dieselbe generierte Datei trägt die CLI.

Feste Regeln statt eines Sprachmodells

Regel-Engine mit 13 Regeln und einem HTTP-Probe

Ein Modell den Code lesen und urteilen lassen

Ein Modell liefert bei jedem Lauf eine andere Antwort und keine Möglichkeit, ihm zu widersprechen. Die Engine gibt bei gleicher Eingabe dasselbe Ergebnis und nennt zu jedem Fund die Spec-Seite, an der man sie widerlegen kann. Das Modell bekommt danach den Teil, der wirklich Urteilsvermögen braucht: zu entscheiden, ob ein Treffer echt ist, und den Umbau zu machen. Dass die Engine deterministisch ist, war später die Voraussetzung dafür, sie auf 13.380 fremde Endpunkte loszulassen. Mit einem Modell wäre das weder bezahlbar noch nachvollziehbar gewesen.

Erst modern fragen, dann legacy

Der Probe eröffnet als moderner Client; „akzeptiert legacy noch“ kostet null Punkte

Jeden Server melden, der den alten Handshake beantwortet

Meine erste Fassung dieser Regel feuerte auf jeden Endpunkt, der `initialize` beantwortet, und riet, den Handshake zu entfernen. Das hätte jeden v1-Client abgeschnitten, der noch auf den Server zeigt, und zwar für null Compliance-Gewinn: die Spec erlaubt einem Server ausdrücklich, beide Verhalten zu bedienen. Schlimmer war, dass der Probe selbst nur als alter Client sprach: Er konnte einen gepflegten Server, der beide Epochen bedient, nicht von einem toten v1-Server unterscheiden. Heute fragt er zuerst modern, wertet `-32601` ausdrücklich nicht als Beleg (den schickt jeder JSON-RPC-Server bei unbekannter Methode) und trennt „akzeptiert legacy noch“ von „kann nur legacy“. Nur das Zweite ist ein Fund. Ein Test hält fest, dass der Fix-Text nie wieder zum Entfernen des Handshakes rät.

Auf den Paketnamen prüfen, nicht auf die Versionsnummer

Regel feuert, sobald @modelcontextprotocol/sdk überhaupt vorkommt

Die Version gegen eine 2.0-Schwelle vergleichen

Die ursprüngliche Regel tat genau das und riet zu `@modelcontextprotocol/sdk@^2`, eine Version, die es nie gab. Die v2 erschien als Paketumbenennung auf @modelcontextprotocol/server und /client. Ein Versionsvergleich ist dort bedeutungslos, der Paketname ist das Signal. Meine erste Korrektur überschoss und löschte die Regel ganz, weil eine Umbenennung von außen aussieht wie „es gibt keine v2“. Zwei Tests halten heute beide Fehler fest. Go zeigt inzwischen die Gegenrichtung: dort lief der Bruch über einen Minor-Sprung von v1.6.1 auf v1.7.0, gleicher Modulpfad, kein /v2. Deshalb vergleicht die Go-Regel volle Release-Tripel und rät nie zu einem neuen Import-Pfad. Ein Signal, das für alle vier SDKs gilt, gibt es nicht.

Lieber gar nicht prüfen als sauber melden

C# steht als ungeprüft im README, mit dem Verweis auf den Live-Probe

Eine flache Regel für C# dazunehmen, damit die Liste vollständig aussieht

Der Scanner liest keine `.cs`-Dateien und es gibt keine C#-SDK-Regel. Ein Quellscan eines C#-Servers meldet also nichts, und dieses Nichts liest sich wie ein sauberes Ergebnis. Das ist der gefährlichere Fehler von beiden: ein Fund, den man widerlegen kann, kostet eine Minute, ein grünes Ergebnis, das nichts geprüft hat, kostet die Migration. Dazu kommt, dass das C#-SDK auf eine 2.x der `ModelContextProtocol`-Pakete gewechselt ist, die Ratschläge für TypeScript und Python dort also gar nicht greifen. Im README steht deshalb der Satz, dass C# nicht gescannt wird, und daneben der Weg, der ohne Sprache auskommt: der Live-Probe spricht nur HTTP.

Zählen, nicht beim Namen nennen

Der veröffentlichte Report zählt Server; die Namen bleiben in einer lokalen Datei

Eine öffentliche Rangliste der kaputten Server

Eine Liste namentlich genannter kaputter Server wäre ein anderes Projekt mit einer anderen Ethik und würde genau die Maintainer vergraulen, denen das Werkzeug helfen soll. Die zweite Entscheidung war unbequemer: „antwortet“ ist nicht „migriert“. Der Probe setzt `reachable` bei jeder HTTP-Antwort, was für den einen Server richtig ist, den man selbst betreibt. Über mehrere tausend fremde gerechnet ist es falsch: ein 403 von einer WAF, ein 404 von einem verschobenen Pfad und ein Captive Proxy antworten alle mit etwas, das kein MCP ist, und kamen naiv gewertet als sauberes A zurück. Der Report hätte das Gegenteil der Wahrheit behauptet. Diese Fälle liegen jetzt in einem eigenen Topf, außerhalb des Nenners.

Gebaut

  • Vier Oberflächen über einem Kern: Demo, npx-CLI, GitHub Action, Agenten-Skill
  • 13 Regeln für TypeScript, Python, Rust und Go, jede mit der Spec-Stelle, die sie widerlegen kann
  • State of MCP: 13.380 Endpunkte geprobt, 10.890 davon bewertbar, 60,1 % nur altes Protokoll
  • Über 170 Testfälle; die Engine wird generiert statt kopiert, und CI schlägt fehl, sobald eine Kopie abweicht