ADR: HTTP/1.1-Upgrade und Tunnelprotokoll v1
- Status: angenommen
- Upgrade-Protokoll:
private-proxy-mcp/1 - Wire-Version:
1.1(bevorzugt), Legacy1.0 - Normative Spezifikation: Connector- und Tunnelprotokoll v1
Kontext
Der private Host soll keine eingehenden Ports benötigen. Gleichzeitig muss der
öffentliche MCP-Prozess mehrere begrenzte Requests über eine langfristige,
authentisierte Verbindung senden und abbrechen können. HTTP/1.1 Upgrade kann
durch übliche TLS-Infrastruktur geleitet werden und übergibt danach einen
vollduplexfähigen Byte-Stream. HTTP/2 und HTTP/3 unterstützen Go
http.Hijacker absichtlich nicht und sind am Connector-Endpunkt ausgeschlossen.
Entscheidung
private-proxy öffnet ausgehend TCP/TLS und sendet bytegenau:
GET /connector HTTP/1.1\r
Host: proxy.example:9335\r
Authorization: Bearer <connector-key>\r
Connection: Upgrade\r
Upgrade: private-proxy-mcp/1\r
Private-Proxy-MCP-Version: 1.1, 1.0\r
Private-Proxy-MCP-Capabilities: <comma-separated capabilities>\r
\r
Der Erfolg ist bytegenau ein HTTP/1.1-Headerblock ohne Body:
HTTP/1.1 101 Switching Protocols\r
Connection: Upgrade\r
Upgrade: private-proxy-mcp/1\r
Private-Proxy-MCP-Version: 1.1\r
\r
Auf Wire 1.1 sendet der Proxy danach optional tools_announce und während
langer Jobs progress. Bidirektionales Ping hält den Tunnel auch bei
langen Media-Downloads (Deadline-Horizon 30m) stabil.
Danach folgt eine lückenlose Folge binärer Frames. Jeder Frame beginnt mit
einem 24-Byte-Header in Big Endian: Gesamtlänge uint32, Major uint8, Minor
uint8, Typ uint8, Flags uint8, Korrelations-ID uint64, absolute
Deadline in Unix-Millisekunden uint64. Die Gesamtlänge ist 24 bis 8 MiB.
Payload-Schemas, Nachrichtentypen, Zustandsmaschinen, Backpressure,
Fehlercodes und Golden-Vektoren sind normativ in der verlinkten Spezifikation
festgelegt.
Sicherheits- und Betriebsfolgen
- Der Bearer-Key wird vor Versionsauswahl geprüft und nur über TLS übertragen.
- Frame-Längen werden vor Allokation validiert; reservierte Flags und unbekannte kritische Typen beenden die Verbindung.
- Requests tragen monotone IDs und absolute Deadlines. Cancel, Ping/Pong und Goaway sind explizite Control-Frames.
- Das Protokoll wiederholt keine Requests. Reconnect geschieht auf Verbindungsebene; Wiederholung auf höherer Ebene muss Idempotenz beachten.
- Eine Major-Änderung darf inkompatibel sein. Minor-Erweiterungen müssen die Regeln für optionale Typen einhalten.
Verifikation
internal/tunnel/golden_test.go prüft
docs/protocol/testdata/tunnel-v1.json
byteweise. Frame-Reader und Policy-Eingaben besitzen zusätzlich Fuzz-Targets.