mirror of
https://github.com/zap-proto/zip.git
synced 2026-10-30 14:57:51 +00:00
MCP 2026-07-28 made the protocol stateless, and zip already was — there is no Mcp-Session-Id anywhere in mcp.go, nothing is remembered between requests, and tools/list answers without a preceding initialize. So the door met the new revision's central requirement before the revision existed and went on announcing the old one, which is the version a client negotiates against. What was actually missing is one method. The new spec drops the mandatory handshake, so `initialize` stops being a lifecycle step and becomes one more way to ask "what are you"; `server/discover` is the name the spec gives that question. It is optional, which is exactly why it has to be answered — a client that uses it to inspect a server before committing got `method not found` from a door that is otherwise fully stateless, and reads the whole thing as pre-2026. Both names now return the same payload, and `initialize` stays for every client still speaking the older revision. Nothing needs a migration window: roots, sampling, logging and the HTTP+SSE transport are what this revision deprecates, and zip never had any of them.
45 lines
1.3 KiB
Go
45 lines
1.3 KiB
Go
package zip
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"testing"
|
|
|
|
zapmcp "github.com/zap-proto/mcp"
|
|
)
|
|
|
|
// 2026-07-28 removed the mandatory handshake, so a client may inspect a server
|
|
// with server/discover instead of initialize. Answering one and not the other
|
|
// reads as a pre-2026 door however stateless the transport already is.
|
|
func TestDiscoverAnswersLikeInitialize(t *testing.T) {
|
|
a := New(Config{})
|
|
get := func(method string) map[string]any {
|
|
f := a.MCP(context.Background(), &zapmcp.Frame{Method: method, Kind: zapmcp.Request, ID: "1"})
|
|
if f == nil {
|
|
t.Fatalf("%s: nil frame", method)
|
|
}
|
|
b, err := json.Marshal(f)
|
|
if err != nil {
|
|
t.Fatalf("%s: marshal: %v", method, err)
|
|
}
|
|
var env struct {
|
|
Result map[string]any `json:"result"`
|
|
Error any `json:"error"`
|
|
}
|
|
if err := json.Unmarshal(b, &env); err != nil {
|
|
t.Fatalf("%s: unmarshal %s: %v", method, b, err)
|
|
}
|
|
if env.Error != nil {
|
|
t.Fatalf("%s: error %v", method, env.Error)
|
|
}
|
|
return env.Result
|
|
}
|
|
in, disc := get("initialize"), get("server/discover")
|
|
if in["protocolVersion"] != "2026-07-28" {
|
|
t.Fatalf("protocolVersion = %v, want 2026-07-28", in["protocolVersion"])
|
|
}
|
|
if disc["protocolVersion"] != in["protocolVersion"] {
|
|
t.Fatalf("server/discover %v != initialize %v", disc["protocolVersion"], in["protocolVersion"])
|
|
}
|
|
}
|