Skip to content

Commit 1c2993a

Browse files
committed
Merge branch 'main' into stateless-http
# Conflicts: # mcp/streamable.go
2 parents 43ba8d0 + a5aa370 commit 1c2993a

File tree

8 files changed

+164
-205
lines changed

8 files changed

+164
-205
lines changed

examples/sse/main.go

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ package main
77
import (
88
"context"
99
"flag"
10+
"fmt"
1011
"log"
1112
"net/http"
13+
"os"
1214

1315
"github.com/modelcontextprotocol/go-sdk/mcp"
1416
)
1517

16-
var httpAddr = flag.String("http", "", "use SSE HTTP at this address")
18+
var (
19+
host = flag.String("host", "localhost", "host to listen on")
20+
port = flag.String("port", "8080", "port to listen on")
21+
)
1722

1823
type SayHiParams struct {
1924
Name string `json:"name"`
@@ -28,19 +33,27 @@ func SayHi(ctx context.Context, cc *mcp.ServerSession, params *mcp.CallToolParam
2833
}
2934

3035
func main() {
36+
flag.Usage = func() {
37+
fmt.Fprintf(os.Stderr, "Usage: %s [options]\n\n", os.Args[0])
38+
fmt.Fprintf(os.Stderr, "This program runs MCP servers over SSE HTTP.\n\n")
39+
fmt.Fprintf(os.Stderr, "Options:\n")
40+
flag.PrintDefaults()
41+
fmt.Fprintf(os.Stderr, "\nEndpoints:\n")
42+
fmt.Fprintf(os.Stderr, " /greeter1 - Greeter 1 service\n")
43+
fmt.Fprintf(os.Stderr, " /greeter2 - Greeter 2 service\n")
44+
os.Exit(1)
45+
}
3146
flag.Parse()
3247

33-
if httpAddr == nil || *httpAddr == "" {
34-
log.Fatal("http address not set")
35-
}
48+
addr := fmt.Sprintf("%s:%s", *host, *port)
3649

3750
server1 := mcp.NewServer(&mcp.Implementation{Name: "greeter1"}, nil)
3851
mcp.AddTool(server1, &mcp.Tool{Name: "greet1", Description: "say hi"}, SayHi)
3952

4053
server2 := mcp.NewServer(&mcp.Implementation{Name: "greeter2"}, nil)
4154
mcp.AddTool(server2, &mcp.Tool{Name: "greet2", Description: "say hello"}, SayHi)
4255

43-
log.Printf("MCP servers serving at %s", *httpAddr)
56+
log.Printf("MCP servers serving at %s", addr)
4457
handler := mcp.NewSSEHandler(func(request *http.Request) *mcp.Server {
4558
url := request.URL.Path
4659
log.Printf("Handling request for URL %s\n", url)
@@ -53,5 +66,5 @@ func main() {
5366
return nil
5467
}
5568
})
56-
http.ListenAndServe(*httpAddr, handler)
69+
log.Fatal(http.ListenAndServe(addr, handler))
5770
}

internal/jsonrpc2/conn.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ func (c *Connection) updateInFlight(f func(*inFlightState)) {
125125
// that and avoided making any updates that would cause the state to be
126126
// non-idle.)
127127
if !s.idle() {
128-
panic("jsonrpc2_v2: updateInFlight transitioned to non-idle when already done")
128+
panic("jsonrpc2: updateInFlight transitioned to non-idle when already done")
129129
}
130130
return
131131
default:
@@ -718,7 +718,7 @@ func (c *Connection) processResult(from any, req *incomingRequest, result any, e
718718
req.cancel()
719719
c.updateInFlight(func(s *inFlightState) {
720720
if s.incoming == 0 {
721-
panic("jsonrpc2_v2: processResult called when incoming count is already zero")
721+
panic("jsonrpc2: processResult called when incoming count is already zero")
722722
}
723723
s.incoming--
724724
})

mcp/create-repo.sh

Lines changed: 0 additions & 80 deletions
This file was deleted.

mcp/server.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const DefaultPageSize = 1000
2929
// A Server is an instance of an MCP server.
3030
//
3131
// Servers expose server-side MCP features, which can serve one or more MCP
32-
// sessions by using [Server.Start] or [Server.Run].
32+
// sessions by using [Server.Run].
3333
type Server struct {
3434
// fixed at creation
3535
impl *Implementation
@@ -77,8 +77,7 @@ type ServerOptions struct {
7777
// NewServer creates a new MCP server. The resulting server has no features:
7878
// add features using the various Server.AddXXX methods, and the [AddTool] function.
7979
//
80-
// The server can be connected to one or more MCP clients using [Server.Start]
81-
// or [Server.Run].
80+
// The server can be connected to one or more MCP clients using [Server.Run].
8281
//
8382
// The first argument must not be nil.
8483
//
@@ -745,7 +744,7 @@ func (ss *ServerSession) handle(ctx context.Context, req *jsonrpc.Request) (any,
745744
}
746745
// For the streamable transport, we need the request ID to correlate
747746
// server->client calls and notifications to the incoming request from which
748-
// they originated. See [idContext] for details.
747+
// they originated. See [idContextKey] for details.
749748
ctx = context.WithValue(ctx, idContextKey{}, req.ID)
750749
return handleReceive(ctx, ss, req)
751750
}

mcp/shared.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ type MethodHandler[S Session] func(ctx context.Context, _ S, method string, para
4444
// the compiler would complain.
4545
type methodHandler any // MethodHandler[*ClientSession] | MethodHandler[*ServerSession]
4646

47-
// A Session is either a ClientSession or a ServerSession.
47+
// A Session is either a [ClientSession] or a [ServerSession].
4848
type Session interface {
4949
*ClientSession | *ServerSession
5050
// ID returns the session ID, or the empty string if there is none.
@@ -57,7 +57,7 @@ type Session interface {
5757
getConn() *jsonrpc2.Connection
5858
}
5959

60-
// Middleware is a function from MethodHandlers to MethodHandlers.
60+
// Middleware is a function from [MethodHandler] to [MethodHandler].
6161
type Middleware[S Session] func(MethodHandler[S]) MethodHandler[S]
6262

6363
// addMiddleware wraps the handler in the middleware functions.
@@ -203,7 +203,7 @@ func serverMethod[P Params, R Result](
203203
}
204204
}
205205

206-
// clientMethod is glue for creating a typedMethodHandler from a method on Server.
206+
// clientMethod is glue for creating a typedMethodHandler from a method on Client.
207207
func clientMethod[P Params, R Result](
208208
f func(*Client, context.Context, *ClientSession, P) (R, error),
209209
) typedMethodHandler[*ClientSession, P, R] {

mcp/sse.go

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,14 @@ type SSEHandler struct {
5555
// Sessions are created when the client issues a GET request to the server,
5656
// which must accept text/event-stream responses (server-sent events).
5757
// For each such request, a new [SSEServerTransport] is created with a distinct
58-
// messages endpoint, and connected to the server returned by getServer. It is
59-
// up to the user whether getServer returns a distinct [Server] for each new
60-
// request, or reuses an existing server.
61-
//
58+
// messages endpoint, and connected to the server returned by getServer.
6259
// The SSEHandler also handles requests to the message endpoints, by
6360
// delegating them to the relevant server transport.
6461
//
62+
// The getServer function may return a distinct [Server] for each new
63+
// request, or reuse an existing server. If it returns nil, the handler
64+
// will return a 400 Bad Request.
65+
//
6566
// TODO(rfindley): add options.
6667
func NewSSEHandler(getServer func(request *http.Request) *Server) *SSEHandler {
6768
return &SSEHandler{
@@ -208,8 +209,12 @@ func (h *SSEHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
208209
h.mu.Unlock()
209210
}()
210211

211-
// TODO(hxjiang): getServer returns nil will panic.
212212
server := h.getServer(req)
213+
if server == nil {
214+
// The getServer argument to NewSSEHandler returned nil.
215+
http.Error(w, "no server available", http.StatusBadRequest)
216+
return
217+
}
213218
ss, err := server.Connect(req.Context(), transport)
214219
if err != nil {
215220
http.Error(w, "connection failed", http.StatusInternalServerError)

0 commit comments

Comments
 (0)