From ac828d5a82af1d9ac67d8afe56183f63ca0680c3 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Wed, 14 May 2025 14:00:02 +0000 Subject: [PATCH] internal/mcp: rename ServerConnection->ServerSession Bring the Server implementation up to date with the spec by renaming ServerConnection to ServerSession. Also update variable names, which were in various states of disarray from the multiple renamings of this type. Change-Id: I4aec883db6d0500fb91e6daa51b702614877cf8a Reviewed-on: https://go-review.googlesource.com/c/tools/+/672655 Auto-Submit: Robert Findley TryBot-Bypass: Robert Findley Commit-Queue: Robert Findley Reviewed-by: Jonathan Amsterdam --- README.md | 2 +- examples/hello/main.go | 4 +-- examples/sse/main.go | 2 +- mcp/mcp.go | 8 ++--- mcp/mcp_test.go | 32 +++++++++---------- mcp/prompt.go | 6 ++-- mcp/prompt_test.go | 2 +- mcp/server.go | 65 +++++++++++++++++++------------------- mcp/server_example_test.go | 6 ++-- mcp/sse.go | 8 ++--- mcp/sse_example_test.go | 2 +- mcp/sse_test.go | 4 +-- mcp/tool.go | 6 ++-- mcp/tool_test.go | 2 +- 14 files changed, 74 insertions(+), 75 deletions(-) diff --git a/README.md b/README.md index da0fec0..9df0f2b 100644 --- a/README.md +++ b/README.md @@ -59,7 +59,7 @@ type HiParams struct { Name string `json:"name"` } -func SayHi(ctx context.Context, cc *mcp.ServerConnection, params *HiParams) ([]mcp.Content, error) { +func SayHi(ctx context.Context, cc *mcp.ServerSession, params *HiParams) ([]mcp.Content, error) { return []mcp.Content{ mcp.TextContent{Text: "Hi " + params.Name}, }, nil diff --git a/examples/hello/main.go b/examples/hello/main.go index f733263..52a8132 100644 --- a/examples/hello/main.go +++ b/examples/hello/main.go @@ -20,13 +20,13 @@ type HiParams struct { Name string `json:"name"` } -func SayHi(ctx context.Context, cc *mcp.ServerConnection, params *HiParams) ([]*mcp.Content, error) { +func SayHi(ctx context.Context, cc *mcp.ServerSession, params *HiParams) ([]*mcp.Content, error) { return []*mcp.Content{ mcp.NewTextContent("Hi " + params.Name), }, nil } -func PromptHi(ctx context.Context, cc *mcp.ServerConnection, params *HiParams) (*mcp.GetPromptResult, error) { +func PromptHi(ctx context.Context, cc *mcp.ServerSession, params *HiParams) (*mcp.GetPromptResult, error) { return &mcp.GetPromptResult{ Description: "Code review prompt", Messages: []*mcp.PromptMessage{ diff --git a/examples/sse/main.go b/examples/sse/main.go index e5b3b71..f72de6e 100644 --- a/examples/sse/main.go +++ b/examples/sse/main.go @@ -19,7 +19,7 @@ type SayHiParams struct { Name string `json:"name" mcp:"the name to say hi to"` } -func SayHi(ctx context.Context, cc *mcp.ServerConnection, params *SayHiParams) ([]*mcp.Content, error) { +func SayHi(ctx context.Context, cc *mcp.ServerSession, params *SayHiParams) ([]*mcp.Content, error) { return []*mcp.Content{ mcp.NewTextContent("Hi " + params.Name), }, nil diff --git a/mcp/mcp.go b/mcp/mcp.go index eaf3e56..c85fe67 100644 --- a/mcp/mcp.go +++ b/mcp/mcp.go @@ -10,9 +10,9 @@ // To get started, create either a [Client] or [Server], and connect it to a // peer using a [Transport]. The diagram below illustrates how this works: // -// Client Server -// ⇅ (jsonrpc2) ⇅ -// Client Transport ⇄ Server Transport ⇄ ServerConnection +// Client Server +// ⇅ (jsonrpc2) ⇅ +// Client Transport ⇄ Server Transport ⇄ ServerSession // // A [Client] is an MCP client, which can be configured with various client // capabilities. Clients may be connected to a [Server] instance @@ -21,7 +21,7 @@ // Similarly, a [Server] is an MCP server, which can be configured with various // server capabilities. Servers may be connected to one or more [Client] // instances using the [Server.Connect] method, which creates a -// [ServerConnection]. +// [ServerSession]. // // A [Transport] connects a bidirectional [Stream] of jsonrpc2 messages. In // practice, transports in the MCP spec are are either client transports or diff --git a/mcp/mcp_test.go b/mcp/mcp_test.go index c15d2f1..1165633 100644 --- a/mcp/mcp_test.go +++ b/mcp/mcp_test.go @@ -24,7 +24,7 @@ type hiParams struct { Name string } -func sayHi(ctx context.Context, cc *ServerConnection, v hiParams) ([]*Content, error) { +func sayHi(ctx context.Context, cc *ServerSession, v hiParams) ([]*Content, error) { if err := cc.Ping(ctx, nil); err != nil { return nil, fmt.Errorf("ping failed: %v", err) } @@ -43,13 +43,13 @@ func TestEndToEnd(t *testing.T) { // The 'fail' tool returns this error. failure := errors.New("mcp failure") s.AddTools( - NewTool("fail", "just fail", func(context.Context, *ServerConnection, struct{}) ([]*Content, error) { + NewTool("fail", "just fail", func(context.Context, *ServerSession, struct{}) ([]*Content, error) { return nil, failure }), ) s.AddPrompts( - NewPrompt("code_review", "do a code review", func(_ context.Context, _ *ServerConnection, params struct{ Code string }) (*GetPromptResult, error) { + NewPrompt("code_review", "do a code review", func(_ context.Context, _ *ServerSession, params struct{ Code string }) (*GetPromptResult, error) { return &GetPromptResult{ Description: "Code review prompt", Messages: []*PromptMessage{ @@ -57,17 +57,17 @@ func TestEndToEnd(t *testing.T) { }, }, nil }), - NewPrompt("fail", "", func(_ context.Context, _ *ServerConnection, params struct{}) (*GetPromptResult, error) { + NewPrompt("fail", "", func(_ context.Context, _ *ServerSession, params struct{}) (*GetPromptResult, error) { return nil, failure }), ) // Connect the server. - sc, err := s.Connect(ctx, st, nil) + ss, err := s.Connect(ctx, st, nil) if err != nil { t.Fatal(err) } - if got := slices.Collect(s.Clients()); len(got) != 1 { + if got := slices.Collect(s.Sessions()); len(got) != 1 { t.Errorf("after connection, Clients() has length %d, want 1", len(got)) } @@ -75,7 +75,7 @@ func TestEndToEnd(t *testing.T) { var clientWG sync.WaitGroup clientWG.Add(1) go func() { - if err := sc.Wait(); err != nil { + if err := ss.Wait(); err != nil { t.Errorf("server failed: %v", err) } clientWG.Done() @@ -198,7 +198,7 @@ func TestEndToEnd(t *testing.T) { URI: "file:///nonexistent.txt", } - readHandler := func(_ context.Context, _ *ServerConnection, p *ReadResourceParams) (*ReadResourceResult, error) { + readHandler := func(_ context.Context, _ *ServerSession, p *ReadResourceParams) (*ReadResourceResult, error) { if p.URI == "file:///file1.txt" { return &ReadResourceResult{ Contents: &ResourceContents{ @@ -249,9 +249,9 @@ func TestEndToEnd(t *testing.T) { } }) t.Run("roots", func(t *testing.T) { - // Take the server's first ServerConnection. - var sc *ServerConnection - for sc = range s.Clients() { + // Take the server's first ServerSession. + var sc *ServerSession + for sc = range s.Sessions() { break } @@ -272,7 +272,7 @@ func TestEndToEnd(t *testing.T) { // After disconnecting, neither client nor server should have any // connections. - for range s.Clients() { + for range s.Sessions() { t.Errorf("unexpected client after disconnection") } } @@ -282,7 +282,7 @@ func TestEndToEnd(t *testing.T) { // // The caller should cancel either the client connection or server connection // when the connections are no longer needed. -func basicConnection(t *testing.T, tools ...*ServerTool) (*ServerConnection, *Client) { +func basicConnection(t *testing.T, tools ...*ServerTool) (*ServerSession, *Client) { t.Helper() ctx := context.Background() @@ -292,7 +292,7 @@ func basicConnection(t *testing.T, tools ...*ServerTool) (*ServerConnection, *Cl // The 'greet' tool says hi. s.AddTools(tools...) - cc, err := s.Connect(ctx, st, nil) + ss, err := s.Connect(ctx, st, nil) if err != nil { t.Fatal(err) } @@ -301,7 +301,7 @@ func basicConnection(t *testing.T, tools ...*ServerTool) (*ServerConnection, *Cl if err := c.Start(ctx); err != nil { t.Fatal(err) } - return cc, c + return ss, c } func TestServerClosing(t *testing.T) { @@ -370,7 +370,7 @@ func TestCancellation(t *testing.T) { cancelled = make(chan struct{}, 1) // don't block the request ) - slowRequest := func(ctx context.Context, cc *ServerConnection, v struct{}) ([]*Content, error) { + slowRequest := func(ctx context.Context, cc *ServerSession, v struct{}) ([]*Content, error) { start <- struct{}{} select { case <-ctx.Done(): diff --git a/mcp/prompt.go b/mcp/prompt.go index 08cc026..6cb008d 100644 --- a/mcp/prompt.go +++ b/mcp/prompt.go @@ -16,7 +16,7 @@ import ( ) // A PromptHandler handles a call to prompts/get. -type PromptHandler func(context.Context, *ServerConnection, map[string]string) (*GetPromptResult, error) +type PromptHandler func(context.Context, *ServerSession, map[string]string) (*GetPromptResult, error) // A Prompt is a prompt definition bound to a prompt handler. type ServerPrompt struct { @@ -32,7 +32,7 @@ type ServerPrompt struct { // of type string or *string. The argument names for the resulting prompt // definition correspond to the JSON names of the request fields, and any // fields that are not marked "omitempty" are considered required. -func NewPrompt[TReq any](name, description string, handler func(context.Context, *ServerConnection, TReq) (*GetPromptResult, error), opts ...PromptOption) *ServerPrompt { +func NewPrompt[TReq any](name, description string, handler func(context.Context, *ServerSession, TReq) (*GetPromptResult, error), opts ...PromptOption) *ServerPrompt { schema, err := jsonschema.For[TReq]() if err != nil { panic(err) @@ -60,7 +60,7 @@ func NewPrompt[TReq any](name, description string, handler func(context.Context, Required: required[name], }) } - prompt.Handler = func(ctx context.Context, cc *ServerConnection, args map[string]string) (*GetPromptResult, error) { + prompt.Handler = func(ctx context.Context, cc *ServerSession, args map[string]string) (*GetPromptResult, error) { // For simplicity, just marshal and unmarshal the arguments. // This could be avoided in the future. rawArgs, err := json.Marshal(args) diff --git a/mcp/prompt_test.go b/mcp/prompt_test.go index c5f25a6..ae2d20a 100644 --- a/mcp/prompt_test.go +++ b/mcp/prompt_test.go @@ -13,7 +13,7 @@ import ( ) // testPromptHandler is used for type inference in TestNewPrompt. -func testPromptHandler[T any](context.Context, *mcp.ServerConnection, T) (*mcp.GetPromptResult, error) { +func testPromptHandler[T any](context.Context, *mcp.ServerSession, T) (*mcp.GetPromptResult, error) { panic("not implemented") } diff --git a/mcp/server.go b/mcp/server.go index dd29495..9c27100 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -30,7 +30,7 @@ type Server struct { prompts *featureSet[*ServerPrompt] tools *featureSet[*ServerTool] resources *featureSet[*ServerResource] - conns []*ServerConnection + conns []*ServerSession } // ServerOptions is used to configure behavior of the server. @@ -121,7 +121,7 @@ const codeResourceNotFound = -31002 // A ResourceHandler is a function that reads a resource. // If it cannot find the resource, it should return the result of calling [ResourceNotFoundError]. -type ResourceHandler func(context.Context, *ServerConnection, *ReadResourceParams) (*ReadResourceResult, error) +type ResourceHandler func(context.Context, *ServerSession, *ReadResourceParams) (*ReadResourceResult, error) // A ServerResource associates a Resource with its handler. type ServerResource struct { @@ -157,16 +157,15 @@ func (s *Server) RemoveResources(uris ...string) { s.resources.remove(uris...) } -// Clients returns an iterator that yields the current set of client -// connections. -func (s *Server) Clients() iter.Seq[*ServerConnection] { +// Sessions returns an iterator that yields the current set of server sessions. +func (s *Server) Sessions() iter.Seq[*ServerSession] { s.mu.Lock() clients := slices.Clone(s.conns) s.mu.Unlock() return slices.Values(clients) } -func (s *Server) listPrompts(_ context.Context, _ *ServerConnection, params *ListPromptsParams) (*ListPromptsResult, error) { +func (s *Server) listPrompts(_ context.Context, _ *ServerSession, params *ListPromptsParams) (*ListPromptsResult, error) { s.mu.Lock() defer s.mu.Unlock() res := new(ListPromptsResult) @@ -176,7 +175,7 @@ func (s *Server) listPrompts(_ context.Context, _ *ServerConnection, params *Lis return res, nil } -func (s *Server) getPrompt(ctx context.Context, cc *ServerConnection, params *GetPromptParams) (*GetPromptResult, error) { +func (s *Server) getPrompt(ctx context.Context, cc *ServerSession, params *GetPromptParams) (*GetPromptResult, error) { s.mu.Lock() prompt, ok := s.prompts.get(params.Name) s.mu.Unlock() @@ -187,7 +186,7 @@ func (s *Server) getPrompt(ctx context.Context, cc *ServerConnection, params *Ge return prompt.Handler(ctx, cc, params.Arguments) } -func (s *Server) listTools(_ context.Context, _ *ServerConnection, params *ListToolsParams) (*ListToolsResult, error) { +func (s *Server) listTools(_ context.Context, _ *ServerSession, params *ListToolsParams) (*ListToolsResult, error) { s.mu.Lock() defer s.mu.Unlock() res := new(ListToolsResult) @@ -197,7 +196,7 @@ func (s *Server) listTools(_ context.Context, _ *ServerConnection, params *ListT return res, nil } -func (s *Server) callTool(ctx context.Context, cc *ServerConnection, params *CallToolParams) (*CallToolResult, error) { +func (s *Server) callTool(ctx context.Context, cc *ServerSession, params *CallToolParams) (*CallToolResult, error) { s.mu.Lock() tool, ok := s.tools.get(params.Name) s.mu.Unlock() @@ -207,7 +206,7 @@ func (s *Server) callTool(ctx context.Context, cc *ServerConnection, params *Cal return tool.Handler(ctx, cc, params) } -func (s *Server) listResources(_ context.Context, _ *ServerConnection, params *ListResourcesParams) (*ListResourcesResult, error) { +func (s *Server) listResources(_ context.Context, _ *ServerSession, params *ListResourcesParams) (*ListResourcesResult, error) { s.mu.Lock() defer s.mu.Unlock() res := new(ListResourcesResult) @@ -217,7 +216,7 @@ func (s *Server) listResources(_ context.Context, _ *ServerConnection, params *L return res, nil } -func (s *Server) readResource(ctx context.Context, ss *ServerConnection, params *ReadResourceParams) (*ReadResourceResult, error) { +func (s *Server) readResource(ctx context.Context, ss *ServerSession, params *ReadResourceParams) (*ReadResourceResult, error) { uri := params.URI // Look up the resource URI in the list we have. // This is a security check as well as an information lookup. @@ -250,29 +249,29 @@ func (s *Server) readResource(ctx context.Context, ss *ServerConnection, params // // Run blocks until the client terminates the connection. func (s *Server) Run(ctx context.Context, t Transport, opts *ConnectionOptions) error { - cc, err := s.Connect(ctx, t, opts) + ss, err := s.Connect(ctx, t, opts) if err != nil { return err } - return cc.Wait() + return ss.Wait() } -// bind implements the binder[*ServerConnection] interface, so that Servers can +// bind implements the binder[*ServerSession] interface, so that Servers can // be connected using [connect]. -func (s *Server) bind(conn *jsonrpc2.Connection) *ServerConnection { - cc := &ServerConnection{conn: conn, server: s} +func (s *Server) bind(conn *jsonrpc2.Connection) *ServerSession { + cc := &ServerSession{conn: conn, server: s} s.mu.Lock() s.conns = append(s.conns, cc) s.mu.Unlock() return cc } -// disconnect implements the binder[*ServerConnection] interface, so that +// disconnect implements the binder[*ServerSession] interface, so that // Servers can be connected using [connect]. -func (s *Server) disconnect(cc *ServerConnection) { +func (s *Server) disconnect(cc *ServerSession) { s.mu.Lock() defer s.mu.Unlock() - s.conns = slices.DeleteFunc(s.conns, func(cc2 *ServerConnection) bool { + s.conns = slices.DeleteFunc(s.conns, func(cc2 *ServerSession) bool { return cc2 == cc }) } @@ -283,17 +282,17 @@ func (s *Server) disconnect(cc *ServerConnection) { // It returns a connection object that may be used to terminate the connection // (with [Connection.Close]), or await client termination (with // [Connection.Wait]). -func (s *Server) Connect(ctx context.Context, t Transport, opts *ConnectionOptions) (*ServerConnection, error) { +func (s *Server) Connect(ctx context.Context, t Transport, opts *ConnectionOptions) (*ServerSession, error) { return connect(ctx, t, opts, s) } -// A ServerConnection is a connection from a single MCP client. Its methods can -// be used to send requests or notifications to the client. Create a connection -// by calling [Server.Connect]. +// A ServerSession is a logical connection from a single MCP client. Its +// methods can be used to send requests or notifications to the client. Create +// a session by calling [Server.Connect]. // -// Call [ServerConnection.Close] to close the connection, or await client -// termination with [ServerConnection.Wait]. -type ServerConnection struct { +// Call [ServerSession.Close] to close the connection, or await client +// termination with [ServerSession.Wait]. +type ServerSession struct { server *Server conn *jsonrpc2.Connection @@ -303,15 +302,15 @@ type ServerConnection struct { } // Ping makes an MCP "ping" request to the client. -func (cc *ServerConnection) Ping(ctx context.Context, _ *PingParams) error { +func (cc *ServerSession) Ping(ctx context.Context, _ *PingParams) error { return call(ctx, cc.conn, "ping", nil, nil) } -func (cc *ServerConnection) ListRoots(ctx context.Context, params *ListRootsParams) (*ListRootsResult, error) { +func (cc *ServerSession) ListRoots(ctx context.Context, params *ListRootsParams) (*ListRootsResult, error) { return standardCall[ListRootsResult](ctx, cc.conn, "roots/list", params) } -func (cc *ServerConnection) handle(ctx context.Context, req *jsonrpc2.Request) (any, error) { +func (cc *ServerSession) handle(ctx context.Context, req *jsonrpc2.Request) (any, error) { cc.mu.Lock() initialized := cc.initialized cc.mu.Unlock() @@ -362,7 +361,7 @@ func (cc *ServerConnection) handle(ctx context.Context, req *jsonrpc2.Request) ( return nil, jsonrpc2.ErrNotHandled } -func (cc *ServerConnection) initialize(ctx context.Context, _ *ServerConnection, params *initializeParams) (*initializeResult, error) { +func (cc *ServerSession) initialize(ctx context.Context, _ *ServerSession, params *initializeParams) (*initializeResult, error) { cc.mu.Lock() cc.initializeParams = params cc.mu.Unlock() @@ -400,12 +399,12 @@ func (cc *ServerConnection) initialize(ctx context.Context, _ *ServerConnection, // Close performs a graceful shutdown of the connection, preventing new // requests from being handled, and waiting for ongoing requests to return. // Close then terminates the connection. -func (cc *ServerConnection) Close() error { +func (cc *ServerSession) Close() error { return cc.conn.Close() } // Wait waits for the connection to be closed by the client. -func (cc *ServerConnection) Wait() error { +func (cc *ServerSession) Wait() error { return cc.conn.Wait() } @@ -413,7 +412,7 @@ func (cc *ServerConnection) Wait() error { // // Importantly, it returns nil if the handler returned an error, which is a // requirement of the jsonrpc2 package. -func dispatch[TParams, TResult any](ctx context.Context, conn *ServerConnection, req *jsonrpc2.Request, f func(context.Context, *ServerConnection, TParams) (TResult, error)) (any, error) { +func dispatch[TParams, TResult any](ctx context.Context, conn *ServerSession, req *jsonrpc2.Request, f func(context.Context, *ServerSession, TParams) (TResult, error)) (any, error) { var params TParams if err := json.Unmarshal(req.Params, ¶ms); err != nil { return nil, err diff --git a/mcp/server_example_test.go b/mcp/server_example_test.go index b7ec788..14a3248 100644 --- a/mcp/server_example_test.go +++ b/mcp/server_example_test.go @@ -16,7 +16,7 @@ type SayHiParams struct { Name string `json:"name" mcp:"the name to say hi to"` } -func SayHi(ctx context.Context, cc *mcp.ServerConnection, params *SayHiParams) ([]*mcp.Content, error) { +func SayHi(ctx context.Context, cc *mcp.ServerSession, params *SayHiParams) ([]*mcp.Content, error) { return []*mcp.Content{ mcp.NewTextContent("Hi " + params.Name), }, nil @@ -29,7 +29,7 @@ func ExampleServer() { server := mcp.NewServer("greeter", "v0.0.1", nil) server.AddTools(mcp.NewTool("greet", "say hi", SayHi)) - clientConnection, err := server.Connect(ctx, serverTransport, nil) + serverSession, err := server.Connect(ctx, serverTransport, nil) if err != nil { log.Fatal(err) } @@ -46,7 +46,7 @@ func ExampleServer() { fmt.Println(res.Content[0].Text) client.Close() - clientConnection.Wait() + serverSession.Wait() // Output: Hi user } diff --git a/mcp/sse.go b/mcp/sse.go index ef8330d..c1f923c 100644 --- a/mcp/sse.go +++ b/mcp/sse.go @@ -64,7 +64,7 @@ func writeEvent(w io.Writer, evt event) (int, error) { // https://modelcontextprotocol.io/specification/2024-11-05/basic/transports type SSEHandler struct { getServer func(request *http.Request) *Server - onConnection func(*ServerConnection) // for testing; must not block + onConnection func(*ServerSession) // for testing; must not block mu sync.Mutex sessions map[string]*SSEServerTransport @@ -229,15 +229,15 @@ func (h *SSEHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) { // TODO(hxjiang): getServer returns nil will panic. server := h.getServer(req) - cc, err := server.Connect(req.Context(), transport, nil) + ss, err := server.Connect(req.Context(), transport, nil) if err != nil { http.Error(w, "connection failed", http.StatusInternalServerError) return } if h.onConnection != nil { - h.onConnection(cc) + h.onConnection(ss) } - defer cc.Close() // close the transport when the GET exits + defer ss.Close() // close the transport when the GET exits select { case <-req.Context().Done(): diff --git a/mcp/sse_example_test.go b/mcp/sse_example_test.go index 60bf3f4..ca66cd8 100644 --- a/mcp/sse_example_test.go +++ b/mcp/sse_example_test.go @@ -18,7 +18,7 @@ type AddParams struct { X, Y int } -func Add(ctx context.Context, cc *mcp.ServerConnection, params *AddParams) ([]*mcp.Content, error) { +func Add(ctx context.Context, cc *mcp.ServerSession, params *AddParams) ([]*mcp.Content, error) { return []*mcp.Content{ mcp.NewTextContent(fmt.Sprintf("%d", params.X+params.Y)), }, nil diff --git a/mcp/sse_test.go b/mcp/sse_test.go index fc844a4..8cd71a1 100644 --- a/mcp/sse_test.go +++ b/mcp/sse_test.go @@ -23,8 +23,8 @@ func TestSSEServer(t *testing.T) { sseHandler := NewSSEHandler(func(*http.Request) *Server { return server }) - conns := make(chan *ServerConnection, 1) - sseHandler.onConnection = func(cc *ServerConnection) { + conns := make(chan *ServerSession, 1) + sseHandler.onConnection = func(cc *ServerSession) { select { case conns <- cc: default: diff --git a/mcp/tool.go b/mcp/tool.go index 8dc5c5c..79a45d1 100644 --- a/mcp/tool.go +++ b/mcp/tool.go @@ -13,7 +13,7 @@ import ( ) // A ToolHandler handles a call to tools/call. -type ToolHandler func(context.Context, *ServerConnection, *CallToolParams) (*CallToolResult, error) +type ToolHandler func(context.Context, *ServerSession, *CallToolParams) (*CallToolResult, error) // A Tool is a tool definition that is bound to a tool handler. type ServerTool struct { @@ -34,12 +34,12 @@ type ServerTool struct { // // TODO: just have the handler return a CallToolResult: returning []Content is // going to be inconsistent with other server features. -func NewTool[TReq any](name, description string, handler func(context.Context, *ServerConnection, TReq) ([]*Content, error), opts ...ToolOption) *ServerTool { +func NewTool[TReq any](name, description string, handler func(context.Context, *ServerSession, TReq) ([]*Content, error), opts ...ToolOption) *ServerTool { schema, err := jsonschema.For[TReq]() if err != nil { panic(err) } - wrapped := func(ctx context.Context, cc *ServerConnection, params *CallToolParams) (*CallToolResult, error) { + wrapped := func(ctx context.Context, cc *ServerSession, params *CallToolParams) (*CallToolResult, error) { var v TReq if err := unmarshalSchema(params.Arguments, schema, &v); err != nil { return nil, err diff --git a/mcp/tool_test.go b/mcp/tool_test.go index fd3d05e..f6239a3 100644 --- a/mcp/tool_test.go +++ b/mcp/tool_test.go @@ -15,7 +15,7 @@ import ( ) // testToolHandler is used for type inference in TestNewTool. -func testToolHandler[T any](context.Context, *mcp.ServerConnection, T) ([]*mcp.Content, error) { +func testToolHandler[T any](context.Context, *mcp.ServerSession, T) ([]*mcp.Content, error) { panic("not implemented") }