99
1010## Lifecycle
1111
12-
13-
1412## Transports
1513
14+ Transports should not be reused for multiple connections: if you need to create
15+ multiple connections, use different transports.
16+
1617### Streamable Transport
1718
18- ### Stateless Mode
19+ ### Streamable Transport API
20+
21+ The streamable transport API is implemented across three types:
22+
23+ - ` StreamableHTTPHandler ` : an` http.Handler ` that serves streamable MCP
24+ sessions.
25+ - ` StreamableServerTransport ` : a ` Transport ` that implements the server side of
26+ the streamable transport.
27+ - ` StreamableClientTransport ` : a ` Transport ` that implements the client side of
28+ the streamable transport.
29+
30+ To create a streamable MCP server, you create a ` StreamableHTTPHandler ` and
31+ pass it an ` mcp.Server ` :
32+
33+ ``` go
34+ func ExampleStreamableHTTPHandler () {
35+ // Create a new stramable handler, using the same MCP server for every request.
36+ //
37+ // Here, we configure it to serves application/json responses rather than
38+ // text/event-stream, just so the output below doesn't use random event ids.
39+ server := mcp.NewServer (&mcp.Implementation {Name: " server" , Version: " v0.1.0" }, nil )
40+ handler := mcp.NewStreamableHTTPHandler (func (r *http.Request ) *mcp.Server {
41+ return server
42+ }, &mcp.StreamableHTTPOptions {JSONResponse: true })
43+ httpServer := httptest.NewServer (handler)
44+ defer httpServer.Close ()
45+
46+ // The SDK is currently permissive of some missing keys in "params".
47+ resp := mustPostMessage (` {"jsonrpc": "2.0", "id": 1, "method":"initialize", "params": {}}` , httpServer.URL )
48+ fmt.Println (resp)
49+ // Output: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{}},"protocolVersion":"2025-06-18","serverInfo":{"name":"server","version":"v0.1.0"}}}
50+ }
51+ ```
52+
53+ The ` StreamableHTTPHandler ` handles the HTTP requests and creates a new
54+ ` StreamableServerTransport ` for each new session. The transport is then used to
55+ communicate with the client.
56+
57+ On the client side, you create a ` StreamableClientTransport ` and use it to
58+ connect to the server:
59+
60+ ``` go
61+ transport := &mcp.StreamableClientTransport {
62+ Endpoint : " http://localhost:8080/mcp" ,
63+ }
64+ client , err := mcp.Connect (context.Background (), transport, &mcp.ClientOptions {...})
65+ ```
66+
67+ The ` StreamableClientTransport ` handles the HTTP requests and communicates with
68+ the server using the streamable transport protocol.
69+
70+ #### Stateless Mode
71+
72+ #### Sessionless mode
73+
74+ ### Custom transports
75+
76+ ### Concurrency
77+
78+ In general, MCP offers no guarantees about concurrency semantics: if a client
79+ or server sends a notification, the spec says nothing about when the peer
80+ observes that notification relative to other request. However, the Go SDK
81+ implements the following heuristics:
82+
83+ - If a notifying method (such as progress notification or
84+ ` notifications/initialized ` ) returns, then it is guaranteed that the peer
85+ observes that notification before other notifications or calls.
86+ - Calls (such as ` tools/call ` ) are handled asynchronously with respect to
87+ eachother.
88+
89+ See
90+ [ modelcontextprotocol/go-sdk #26 ] ( https://github.com/modelcontextprotocol/go-sdk/issues/26 )
91+ for more background.
1992
2093## Authorization
2194
@@ -29,28 +102,15 @@ Cancellation is implemented with context cancellation. Cancelling a context
29102used in a method on ` ClientSession ` or ` ServerSession ` will terminate the RPC
30103and send a "notifications/cancelled" message to the peer.
31104
32- For example, consider the following slow tool
33-
34- // go get golang.org/x/example/docs/../../mcp
35-
36105``` go
37- var (
38- start = make (chan struct {})
39- cancelled = make (chan struct {}, 1 ) // don't block the request
40- )
41- slowTool := func (ctx context.Context , req *CallToolRequest, args any) (*CallToolResult, any, error ) {
42- start <- struct {}{}
43- select {
44- case <- ctx.Done ():
45- cancelled <- struct {}{}
46- case <- time.After (5 * time.Second ):
47- return nil , nil , nil
48- }
49- return nil , nil , nil
50- }
106+ ctx , cancel := context.WithCancel (context.Background ())
107+ go cs.CallTool (ctx, &CallToolParams{Name: " slow" })
108+ cancel () // cancel the tool call
51109```
52110
53- When an RPC exits due to a cancellation error, there's a guarantee
111+ When an RPC exits due to a cancellation error, there's a guarantee that the
112+ cancellation notification has been sent, but there's no guarantee that the
113+ server has observed it (see [ concurrency] ( #concurrency ) ).
54114
55115### Ping
56116
0 commit comments