diff --git a/README.md b/README.md index 299245c..bffd48a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# MCP Go SDK v0.2.0 +# MCP Go SDK v0.3.0 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/modelcontextprotocol/go-sdk) @@ -7,7 +7,7 @@ This version contains breaking changes. See the [release notes]( -https://github.com/modelcontextprotocol/go-sdk/releases/tag/v0.2.0) for details. +https://github.com/modelcontextprotocol/go-sdk/releases/tag/v0.3.0) for details. [![PkgGoDev](https://pkg.go.dev/badge/github.com/modelcontextprotocol/go-sdk)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) diff --git a/internal/readme/README.src.md b/internal/readme/README.src.md index de5dd48..bafcbc7 100644 --- a/internal/readme/README.src.md +++ b/internal/readme/README.src.md @@ -1,4 +1,4 @@ -# MCP Go SDK v0.2.0 +# MCP Go SDK v0.3.0 [![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://codespaces.new/modelcontextprotocol/go-sdk) @@ -6,7 +6,7 @@ This version contains breaking changes. See the [release notes]( -https://github.com/modelcontextprotocol/go-sdk/releases/tag/v0.2.0) for details. +https://github.com/modelcontextprotocol/go-sdk/releases/tag/v0.3.0) for details. [![PkgGoDev](https://pkg.go.dev/badge/github.com/modelcontextprotocol/go-sdk)](https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk) diff --git a/mcp/mcp.go b/mcp/mcp.go index a22748c..839f919 100644 --- a/mcp/mcp.go +++ b/mcp/mcp.go @@ -7,32 +7,84 @@ // The mcp package provides an SDK for writing model context protocol clients // and servers. // -// 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: +// To get started, create either a [Client] or [Server], add features to it +// using `AddXXX` functions, and connect it to a peer using a [Transport]. +// +// For example, to run a simple server on the [StdioTransport]: +// +// server := mcp.NewServer(&mcp.Implementation{Name: "greeter"}, nil) +// +// // Using the generic AddTool automatically populates the the input and output +// // schema of the tool. +// type args struct { +// Name string `json:"name" jsonschema:"the person to greet"` +// } +// mcp.AddTool(server, &mcp.Tool{ +// Name: "greet", +// Description: "say hi", +// }, func(ctx context.Context, req *mcp.CallToolRequest, args args) (*mcp.CallToolResult, any, error) { +// return &mcp.CallToolResult{ +// Content: []mcp.Content{ +// &mcp.TextContent{Text: "Hi " + args.Name}, +// }, +// }, nil, nil +// }) +// +// // Run the server on the stdio transport. +// if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil { +// log.Printf("Server failed: %v", err) +// } +// +// To connect to this server, use the [CommandTransport]: +// +// client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil) +// transport := &mcp.CommandTransport{Command: exec.Command("myserver")} +// session, err := client.Connect(ctx, transport, nil) +// if err != nil { +// log.Fatal(err) +// } +// defer session.Close() +// +// params := &mcp.CallToolParams{ +// Name: "greet", +// Arguments: map[string]any{"name": "you"}, +// } +// res, err := session.CallTool(ctx, params) +// if err != nil { +// log.Fatalf("CallTool failed: %v", err) +// } +// +// # Clients, servers, and sessions +// +// In this SDK, both a [Client] and [Server] may handle many concurrent +// connections. Each time a client or server is connected to a peer using a +// [Transport], it creates a new session (either a [ClientSession] or +// [ServerSession]): // // Client Server // ⇅ (jsonrpc2) ⇅ // ClientSession ⇄ 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 -// using the [Client.Connect] method. -// -// 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 -// [ServerSession]. -// -// A [Transport] connects a bidirectional [Connection] of jsonrpc2 messages. In -// practice, transports in the MCP spec are are either client transports or -// server transports. For example, the [StdioTransport] is a server transport -// that communicates over stdin/stdout, and its counterpart is a -// [CommandTransport] that communicates with a subprocess over its -// stdin/stdout. -// -// Some transports may hide more complicated details, such as an -// [SSEClientTransport], which reads messages via server-sent events on a -// hanging GET request, and writes them to a POST endpoint. Users of this SDK -// may define their own custom Transports by implementing the [Transport] -// interface. +// The session types expose an API to interact with its peer. For example, +// [ClientSession.CallTool] or [ServerSession.ListRoots]. +// +// # Adding features +// +// Add MCP servers to your Client or Server using AddXXX methods (for example +// [Client.AddRoot] or [Server.AddPrompt]). If any peers are connected when +// AddXXX is called, they will receive a corresponding change notification +// (for example notifications/roots/list_changed). +// +// Adding tools is special: tools may be bound to ordinary Go functions by +// using the top-level generic [AddTool] function, which allows specifying an +// input and output type. When AddTool is used, the tool's input schema and +// output schema are automatically populated, and inputs are automatically +// validated. As a special case, if the output type is 'any', no output schema +// is generated. +// +// func double(_ context.Context, _ *mcp.CallToolRequest, in In) (*mcp.CallToolResponse, Out, error) { +// return nil, Out{Answer: 2*in.Number}, nil +// } +// ... +// mcp.AddTool(&mcp.Tool{Name: "double", Description: "double a number"}, double) package mcp diff --git a/mcp/server.go b/mcp/server.go index 75632f7..5020823 100644 --- a/mcp/server.go +++ b/mcp/server.go @@ -182,16 +182,17 @@ func (s *Server) AddTool(t *Tool, h ToolHandler) { } // ToolFor returns a shallow copy of t and a [ToolHandler] that wraps h. +// // If the tool's input schema is nil, it is set to the schema inferred from the In // type parameter, using [jsonschema.For]. The In type parameter must be a map // or a struct, so that its inferred JSON Schema has type "object". // -// If the tool's output schema is nil and the Out type parameter is not the empty -// interface, then the output schema is set to the schema inferred from Out, which -// must be a map or a struct. +// For tools that don't return structured output, Out should be 'any'. +// Otherwise, if the tool's output schema is nil the output schema is set to +// the schema inferred from Out, which must be a map or a struct. // -// Most users will call [AddTool]. Use [ToolFor] if you wish to modify the tool's -// schemas or wrap the ToolHandler before calling [Server.AddTool]. +// Most users will call [AddTool]. Use [ToolFor] if you wish to modify the +// tool's schemas or wrap the ToolHandler before calling [Server.AddTool]. func ToolFor[In, Out any](t *Tool, h ToolHandlerFor[In, Out]) (*Tool, ToolHandler) { tt, hh, err := toolForErr(t, h) if err != nil { @@ -317,7 +318,16 @@ func setSchema[T any](sfield **jsonschema.Schema, rfield **jsonschema.Resolved) return zero, err } -// AddTool adds a tool and handler to the server. +// AddTool adds a tool and typed tool handler to the server. +// +// If the tool's input schema is nil, it is set to the schema inferred from the +// In type parameter, using [jsonschema.For]. The In type parameter must be a +// map or a struct, so that its inferred JSON Schema has type "object". +// +// For tools that don't return structured output, Out should be 'any'. +// Otherwise, if the tool's output schema is nil the output schema is set to +// the schema inferred from Out, which must be a map or a struct. +// // It is a convenience for s.AddTool(ToolFor(t, h)). func AddTool[In, Out any](s *Server, t *Tool, h ToolHandlerFor[In, Out]) { s.AddTool(ToolFor(t, h))