This PR adds the protocol version `2026-07-28` to the list of supported protocol versions and fixes legacy tests hardcoding the legacy protocol version for those use cases.
87 lines
2.9 KiB
Go
87 lines
2.9 KiB
Go
// Copyright 2025 The Go MCP SDK Authors. All rights reserved.
|
|
// Use of this source code is governed by an MIT-style
|
|
// license that can be found in the LICENSE file.
|
|
|
|
package mcp_test
|
|
|
|
import (
|
|
"bytes"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"strings"
|
|
|
|
"github.com/modelcontextprotocol/go-sdk/mcp"
|
|
)
|
|
|
|
// !+streamablehandler
|
|
|
|
// TODO: Until we have a way to clean up abandoned sessions, this test will leak goroutines (see #499)
|
|
func ExampleStreamableHTTPHandler() {
|
|
// Create a new streamable handler, using the same MCP server for every request.
|
|
//
|
|
// Here, we configure it to serves application/json responses rather than
|
|
// text/event-stream, just so the output below doesn't use random event ids.
|
|
server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil)
|
|
handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
|
|
return server
|
|
}, &mcp.StreamableHTTPOptions{JSONResponse: true})
|
|
httpServer := httptest.NewServer(handler)
|
|
defer httpServer.Close()
|
|
|
|
// The SDK is currently permissive of some missing keys in "params".
|
|
resp := mustPostMessage(`{"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {"protocolVersion":"2025-11-25"}}`, httpServer.URL)
|
|
fmt.Println(resp)
|
|
// Output:
|
|
// {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{}},"protocolVersion":"2025-11-25","serverInfo":{"name":"server","version":"v0.1.0"}}}
|
|
}
|
|
|
|
// !-streamablehandler
|
|
|
|
// !+httpmiddleware
|
|
|
|
func ExampleStreamableHTTPHandler_middleware() {
|
|
server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.1.0"}, nil)
|
|
handler := mcp.NewStreamableHTTPHandler(func(r *http.Request) *mcp.Server {
|
|
return server
|
|
}, &mcp.StreamableHTTPOptions{Stateless: true})
|
|
loggingHandler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
// Example debugging; you could also capture the response.
|
|
body, err := io.ReadAll(req.Body)
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
req.Body.Close() // ignore error
|
|
req.Body = io.NopCloser(bytes.NewBuffer(body))
|
|
fmt.Println(req.Method, string(body))
|
|
handler.ServeHTTP(w, req)
|
|
})
|
|
httpServer := httptest.NewServer(loggingHandler)
|
|
defer httpServer.Close()
|
|
|
|
// The SDK is currently permissive of some missing keys in "params".
|
|
mustPostMessage(`{"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}`, httpServer.URL)
|
|
// Output:
|
|
// POST {"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}
|
|
}
|
|
|
|
// !-httpmiddleware
|
|
|
|
func mustPostMessage(msg, url string) string {
|
|
req := orFatal(http.NewRequest("POST", url, strings.NewReader(msg)))
|
|
req.Header["Content-Type"] = []string{"application/json"}
|
|
req.Header["Accept"] = []string{"application/json", "text/event-stream"}
|
|
resp := orFatal(http.DefaultClient.Do(req))
|
|
defer resp.Body.Close()
|
|
body := orFatal(io.ReadAll(resp.Body))
|
|
return string(body)
|
|
}
|
|
|
|
func orFatal[T any](t T, err error) T {
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
return t
|
|
}
|