### Install go-sdk Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/quick_start.md Use `go get` to install the go-sdk. ```bash go get github.com/modelcontextprotocol/go-sdk ``` -------------------------------- ### Setup MCP Server with Auth Middleware Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/auth-middleware/README.md Navigate to the example directory and run the Go server. Ensure dependencies are managed with 'go mod tidy'. ```bash cd examples/server/auth-middleware go mod tidy go run main.go ``` -------------------------------- ### Example: MCP Resource Management Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/server.md Demonstrates client and server setup, resource/template registration, connection, listing resources, and reading resources with error handling. Use this example to understand the full lifecycle of resource management in the MCP Go SDK. ```go func Example_resources() { ctx := context.Background() resources := map[string]string{ "file:///a": "a", "file:///dir/x": "x", "file:///dir/y": "y", } handler := func(_ context.Context, req *mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) { uri := req.Params.URI c, ok := resources[uri] if !ok { return nil, mcp.ResourceNotFoundError(uri) } return &mcp.ReadResourceResult{ Contents: []*mcp.ResourceContents{{URI: uri, Text: c}}, }, } // Create a server with a single resource. ss := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) ss.AddResource(&mcp.Resource{URI: "file:///a"}, handler) ss.AddResourceTemplate(&mcp.ResourceTemplate{URITemplate: "file:///dir/{f}"}, handler) // Create a client. c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) // Connect the server and client. t1, t2 := mcp.NewInMemoryTransports() if _, err := ss.Connect(ctx, t1, nil); err != nil { log.Fatal(err) } cs, err := c.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer cs.Close() // List resources and resource templates. for r, err := range cs.Resources(ctx, nil) { if err != nil { log.Fatal(err) } fmt.Println(r.URI) } for r, err := range cs.ResourceTemplates(ctx, nil) { if err != nil { log.Fatal(err) } fmt.Println(r.URITemplate) } // Read resources. for _, path := range []string{"a", "dir/x", "b"} { res, err := cs.ReadResource(ctx, &mcp.ReadResourceParams{URI: "file:///" + path}) if err != nil { fmt.Println(err) } else { fmt.Println(res.Contents[0].Text) } } // Output: // file:///a // file:///dir/{f} // a // x // calling "resources/read": Resource not found } ``` -------------------------------- ### Run the Proxy Header Propagation Example Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/proxy/README.md Execute the example application to demonstrate header forwarding between a client, proxy, and backend server. ```bash go run main.go ``` -------------------------------- ### Example MCP Client and Server Lifecycle Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/protocol.md Demonstrates creating and connecting an MCP client and server using in-memory transports. The example shows how to handle the session initialization and termination, including waiting for the server session to end after the client closes. ```go func Example_lifecycle() { ctx := context.Background() // Create a client and server. // Wait for the client to initialize the session. client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, &mcp.ServerOptions{ InitializedHandler: func(context.Context, *mcp.InitializedRequest) { fmt.Println("initialized!") }, }) // Connect the server and client using in-memory transports. // // Connect the server first so that it's ready to receive initialization // messages from the client. t1, t2 := mcp.NewInMemoryTransports() serverSession, err := server.Connect(ctx, t1, nil) if err != nil { log.Fatal(err) } clientSession, err := client.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } // Now shut down the session by closing the client, and waiting for the // server session to end. if err := clientSession.Close(); err != nil { log.Fatal(err) } if err := serverSession.Wait(); err != nil { log.Fatal(err) } // Output: initialized! } ``` -------------------------------- ### Server-Side Tool Registration and Execution Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Example of creating an MCP server, registering a tool, and running the server over standard I/O. ```go // Create a server with a single tool. server := mcp.NewServer(&mcp.Implementation{Name:"greeter", Version:"v1.0.0"}, nil) mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, SayHi) // Run the server over stdin/stdout, until the client disconnects. if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil { log.Fatal(err) } ``` -------------------------------- ### Client-Side Connection and Tool Execution Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Example of initializing an MCP client, connecting via a command transport, and invoking a tool. ```go client := mcp.NewClient(&mcp.Implementation{Name:"mcp-client", Version:"v1.0.0"}, nil) // Connect to a server over stdin/stdout transport := &mcp.CommandTransport{ Command: exec.Command("myserver"}, } session, err := client.Connect(ctx, transport) if err != nil { ... } // Call a tool on the server. content, err := session.CallTool(ctx, "greet", map[string]any{"name": "you"}, nil) ... return session.Close() ``` -------------------------------- ### Example Weather Tool Implementation Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/server.md An example implementation of a weather tool handler function. It adheres to the expected signature and would typically perform an API call to fetch weather data. ```go func WeatherTool(ctx context.Context, req *mcp.CallToolRequest, in WeatherInput) (*mcp.CallToolResult, WeatherOutput, error) { ``` -------------------------------- ### Create an MCP Client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/quick_start.md Create an `mcp.Client` and connect it to a server using a `mcp.CommandTransport` to communicate over stdin/stdout. This example connects to a server and calls the 'greet' tool. ```go package main import ( "context" "log" "os/exec" "github.com/modelcontextprotocol/go-sdk/mcp" ) func main() { ctx := context.Background() // Create a new client, with no features. client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil) // Connect to a server over stdin/stdout. transport := &mcp.CommandTransport{Command: exec.Command("myserver")} session, err := client.Connect(ctx, transport, nil) if err != nil { log.Fatal(err) } defer session.Close() // Call a tool on the server. 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) } if res.IsError { log.Fatal("tool failed") } for _, c := range res.Content { log.Print(c.(*mcp.TextContent).Text) } } ``` -------------------------------- ### Implement Server-Side Logging Middleware Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Example of a receiving middleware that logs request and response details. ```go func withLogging(h mcp.MethodHandler) mcp.MethodHandler{ return func(ctx context.Context, method string, req mcp.Request) (res mcp.Result, err error) { log.Printf("request: %s %v", method, params) defer func() { log.Printf("response: %v, %v", res, err) }() return h(ctx, s , method, params) } } server.AddReceivingMiddleware(withLogging) ``` -------------------------------- ### Example of RPC Cancellation in Go Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/protocol.md Demonstrates how cancelling a context used in a session method terminates the RPC and sends a cancellation notification. This example shows a client cancelling a tool call after the server has started processing it. ```go func Example_cancellation() { // For this example, we're going to be collecting observations from the // server and client. var clientResult, serverResult string var wg sync.WaitGroup wg.Add(2) // Create a server with a single slow tool. // When the client cancels its request, the server should observe // cancellation. server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) started := make(chan struct{}, 1) // signals that the server started handling the tool call mcp.AddTool(server, &mcp.Tool{Name: "slow"}, func(ctx context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) { started <- struct{}{} defer wg.Done() select { case <-time.After(5 * time.Second): serverResult = "tool done" case <-ctx.Done(): serverResult = "tool canceled" } return &mcp.CallToolResult{}, nil, nil }) // Connect a client to the server. client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) ctx := context.Background() t1, t2 := mcp.NewInMemoryTransports() if _, err := server.Connect(ctx, t1, nil); err != nil { log.Fatal(err) } session, err := client.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer session.Close() // Make a tool call, asynchronously. ctx, cancel := context.WithCancel(context.Background()) go func() { defer wg.Done() _, err = session.CallTool(ctx, &mcp.CallToolParams{Name: "slow"}) clientResult = fmt.Sprintf("%v", err) }() // As soon as the server has started handling the call, cancel it from the // client side. <-started cancel() wg.Wait() fmt.Println(clientResult) fmt.Println(serverResult) // Output: // context canceled // tool canceled } ``` -------------------------------- ### Create an MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/quick_start.md Create an `mcp.Server` instance, add features (tools), and run it over a transport like `mcp.StdioTransport` for communication over stdin/stdout. This example adds a single 'greet' tool. ```go package main import ( "context" "log" "github.com/modelcontextprotocol/go-sdk/mcp" ) type Input struct { Name string `json:"name" jsonschema:"the name of the person to greet"` } type Output struct { Greeting string `json:"greeting" jsonschema:"the greeting to tell to the user"` } func SayHi(ctx context.Context, req *mcp.CallToolRequest, input Input) ( *mcp.CallToolResult, Output, error, ) { return nil, Output{Greeting: "Hi " + input.Name}, nil } func main() { // Create a server with a single tool. server := mcp.NewServer(&mcp.Implementation{Name: "greeter", Version: "v1.0.0"}, nil) mcp.AddTool(server, &mcp.Tool{Name: "greet", Description: "say hi"}, SayHi) // Run the server over stdin/stdout, until the client disconnects. if err := server.Run(context.Background(), &mcp.StdioTransport{}); err != nil { log.Fatal(err) } } ``` -------------------------------- ### Implement Typed Tool Handler Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Example of a handler implementation using a custom parameter struct and adding it to the server. ```go type AddParams struct { X int `json:"x"` Y int `json:"y"` } func addHandler(ctx context.Context, req *mcp.ServerRequest[*mcp.CallToolParamsFor[AddParams]]) (*mcp.CallToolResultFor[int], error) { return &mcp.CallToolResultFor[int]{StructuredContent: req.Params.Arguments.X + req.Params.Arguments.Y}, nil } ``` ```go mcp.AddTool(server, &mcp.Tool{Name: "add", Description: "add numbers"}, addHandler) ``` -------------------------------- ### Start MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/http/README.md Launches the MCP server. It defaults to http://localhost:8000 and provides a 'cityTime' tool. You can specify a custom host and port. ```bash go run . server ``` ```bash go run . -host 0.0.0.0 -port 9000 server ``` -------------------------------- ### Create a Streamable MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/protocol.md Initializes a StreamableHTTPHandler with an MCP server instance. Note that the provided example uses JSONResponse for deterministic output in tests. ```go // 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": {}}`, 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"}}} } ``` -------------------------------- ### Define Tool Input and Output Schemas Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/server.md Define Go structs for tool input and output, using JSON and jsonschema tags for schema inference and documentation. This example shows a weather tool's input and output structures. ```go type WeatherInput struct { Location Location `json:"location" jsonschema:"user location"` Days int `json:"days" jsonschema:"number of days to forecast"` } type WeatherOutput struct { Summary string `json:"summary" jsonschema:"a summary of the weather forecast"` Confidence Probability `json:"confidence" jsonschema:"confidence, between 0 and 1"` AsOf time.Time `json:"asOf" jsonschema:"the time the weather was computed"` DailyForecast []Forecast `json:"dailyForecast" jsonschema:"the daily forecast"` Source string `json:"source,omitempty" jsonschema:"the organization providing the weather forecast"` } ``` -------------------------------- ### Start Thinking API Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/sequentialthinking/README.md Initiates a new sequential thinking session for a given problem. You can optionally provide a custom session ID and an initial estimate of the steps required. ```APIDOC ## POST /tools/call (start_thinking) ### Description Begins a new sequential thinking session for a complex problem. ### Method POST ### Endpoint /tools/call ### Parameters #### Request Body - **method** (string) - Required - The tool name, should be "tools/call". - **params** (object) - Required - Parameters for the tool call. - **name** (string) - Required - The name of the tool to call, should be "start_thinking". - **arguments** (object) - Required - Arguments for the "start_thinking" tool. - **problem** (string) - Required - The problem or question to think about. - **sessionId** (string) - Optional - Custom session identifier. - **estimatedSteps** (integer) - Optional - Initial estimate of thinking steps needed. ### Request Example ```json { "method": "tools/call", "params": { "name": "start_thinking", "arguments": { "problem": "How should I design a scalable microservices architecture?", "sessionId": "architecture_design", "estimatedSteps": 8 } } } ``` ### Response #### Success Response (200) - **result** (object) - The result of the tool call, typically containing session information. - **sessionId** (string) - The ID of the newly created session. - **message** (string) - A confirmation message. #### Response Example ```json { "result": { "sessionId": "architecture_design", "message": "Thinking session started successfully." } } ``` ``` -------------------------------- ### Create and Run an MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/readme/README.src.md This Go code demonstrates how to create an MCP server, add features, and run it over a transport like stdin/stdout. Ensure the 'mcp' package is imported. ```go package main import ( "context" "log" "os" "github.com/modelcontextprotocol/go-sdk/mcp" ) func main() { // Create a new server instance. server := mcp.NewServer(mcp.WithServerLogger(log.New(os.Stderr, "", log.LstdFlags))) // Add a simple tool to the server. server.AddTool(mcp.NewTool("simple", mcp.ToolOptions{ Name: "Simple Tool", Description: "A basic tool for demonstration.", })) // Create a transport that uses stdin and stdout. transport := mcp.NewStdinStdoutTransport(os.Stdin, os.Stdout) // Run the server with the transport. ctx := context.Background() if err := server.Run(ctx, transport); err != nil { log.Fatalf("server failed: %v", err) } } ``` -------------------------------- ### GET /.well-known/oauth-protected-resource Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/auth-middleware/README.md Endpoint for OAuth 2.0 resource metadata discovery, supporting CORS for cross-origin client discovery. ```APIDOC ## GET /.well-known/oauth-protected-resource ### Description Provides OAuth 2.0 resource metadata for client discovery. This endpoint is public and supports CORS. ### Method GET ### Endpoint /.well-known/oauth-protected-resource ### Response #### Success Response (200) - **Metadata** (object) - OAuth protected resource metadata as defined in RFC 9728. ``` -------------------------------- ### Implement MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/quick_start.src.md Create an mcp.Server instance and run it over an mcp.Transport. ```go package main import ( "context" "fmt" "os" "github.com/modelcontextprotocol/go-sdk/server" "github.com/modelcontextprotocol/go-sdk/server/stdio" "github.com/modelcontextprotocol/go-sdk/shared" ) func main() { // Create a new MCP server s := server.NewServer( "example-server", "1.0.0", server.WithResourceCapabilities(false, false), server.WithLogging(), ) // Add a tool s.AddTool( server.NewTool( "hello", server.WithDescription("Says hello"), server.WithHandler(func(ctx context.Context, req shared.CallToolRequest) (shared.CallToolResult, error) { return shared.NewTextToolResult("Hello, world!"), nil }), ), ) // Run the server over stdio transport := stdio.NewStdioServerTransport() fmt.Fprintf(os.Stderr, "Starting server...\n") if err := s.Connect(context.Background(), transport); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } } ``` -------------------------------- ### Run MCP Server in HTTP Mode Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/sequentialthinking/README.md Start the MCP server with HTTP endpoint enabled, specifying the port. ```bash go run . -http :8080 ``` -------------------------------- ### Create a Streamable MCP Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/protocol.src.md Initialize a StreamableHTTPHandler with an mcp.Server to serve streamable sessions. ```go handler := &mcp.StreamableHTTPHandler{ Server: server, } ``` -------------------------------- ### Implement and consume MCP prompts in Go Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/server.md Demonstrates creating an MCP server with a prompt handler, connecting it to a client via in-memory transports, and retrieving prompt results. ```go func Example_prompts() { ctx := context.Background() promptHandler := func(ctx context.Context, req *mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { return &mcp.GetPromptResult{ Description: "Hi prompt", Messages: []*mcp.PromptMessage{ { Role: "user", Content: &mcp.TextContent{Text: "Say hi to " + req.Params.Arguments["name"]}, }, }, }, nil } // Create a server with a single prompt. s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) prompt := &mcp.Prompt{ Name: "greet", Arguments: []*mcp.PromptArgument{ { Name: "name", Description: "the name of the person to greet", Required: true, }, }, } s.AddPrompt(prompt, promptHandler) // Create a client. c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) // Connect the server and client. t1, t2 := mcp.NewInMemoryTransports() if _, err := s.Connect(ctx, t1, nil); err != nil { log.Fatal(err) } cs, err := c.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer cs.Close() // List the prompts. for p, err := range cs.Prompts(ctx, nil) { if err != nil { log.Fatal(err) } fmt.Println(p.Name) } // Get the prompt. res, err := cs.GetPrompt(ctx, &mcp.GetPromptParams{ Name: "greet", Arguments: map[string]string{"name": "Pat"}, }) if err != nil { log.Fatal(err) } for _, msg := range res.Messages { fmt.Println(msg.Role, msg.Content.(*mcp.TextContent).Text) } // Output: // greet // user Say hi to Pat } ``` -------------------------------- ### Iterator Method for Resources Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Handles pagination for List spec methods automatically. Iteration starts from the provided cursor if present in ListResourceParams. ```go func (*ClientSession) Resources(context.Context, *ListResourceParams) iter.Seq2[Resource, error] ``` -------------------------------- ### Implement MCP Logging Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/server.md Demonstrates setting up a server and client to exchange log messages using a slog.Handler and a custom logging message handler. ```go func Example_logging() { ctx := context.Background() // Create a server. s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) // Create a client that displays log messages. done := make(chan struct{}) // solely for the example var nmsgs atomic.Int32 c := mcp.NewClient( &mcp.Implementation{Name: "client", Version: "v0.0.1"}, &mcp.ClientOptions{ LoggingMessageHandler: func(_ context.Context, r *mcp.LoggingMessageRequest) { m := r.Params.Data.(map[string]any) fmt.Println(m["msg"], m["value"]) if nmsgs.Add(1) == 2 { // number depends on logger calls below close(done) } }, }) // Connect the server and client. t1, t2 := mcp.NewInMemoryTransports() ss, err := s.Connect(ctx, t1, nil) if err != nil { log.Fatal(err) } defer ss.Close() cs, err := c.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer cs.Close() // Set the minimum log level to "info". if err := cs.SetLoggingLevel(ctx, &mcp.SetLoggingLevelParams{Level: "info"}); err != nil { log.Fatal(err) } // Get a slog.Logger for the server session. logger := slog.New(mcp.NewLoggingHandler(ss, nil)) // Log some things. logger.Info("info shows up", "value", 1) logger.Debug("debug doesn't show up", "value", 2) logger.Warn("warn shows up", "value", 3) // Wait for them to arrive on the client. // In a real application, the log messages would appear asynchronously // while other work was happening. <-done // Output: // info shows up 1 // warn shows up 3 } ``` -------------------------------- ### Create and Connect an MCP Client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/readme/README.src.md This Go code shows how to create an MCP client and connect it to a running MCP server using stdin/stdout for communication. The 'mcp' package is required. ```go package main import ( "context" "log" "os" "github.com/modelcontextprotocol/go-sdk/mcp" ) func main() { // Create a new client instance. client := mcp.NewClient(mcp.WithClientLogger(log.New(os.Stderr, "", log.LstdFlags))) // Create a transport that uses stdin and stdout. transport := mcp.NewStdinStdoutTransport(os.Stdin, os.Stdout) // Connect the client to the server using the transport. ctx := context.Background() if err := client.Connect(ctx, transport); err != nil { log.Fatalf("client failed: %v", err) } // The client is now connected and ready to communicate. log.Println("client connected") // Keep the client running (e.g., to process responses or send further requests). <-ctx.Done() } ``` -------------------------------- ### Iterator Method for Prompts Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Handles pagination for List spec methods automatically. Iteration starts from the provided cursor if present in ListPromptsParams. ```go func (*ClientSession) Prompts(context.Context, *ListPromptsParams) iter.Seq2[Prompt, error] ``` -------------------------------- ### Iterator Method for Tools Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Handles pagination for List spec methods automatically. Iteration starts from the provided cursor if present in ListToolsParams. ```go func (*ClientSession) Tools(context.Context, *ListToolsParams) iter.Seq2[Tool, error] ``` -------------------------------- ### Implement MCP Client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/quick_start.src.md Create an mcp.Client and connect it to a server using stdio transport. ```go package main import ( "context" "fmt" "os" "os/exec" "github.com/modelcontextprotocol/go-sdk/client" "github.com/modelcontextprotocol/go-sdk/client/stdio" ) func main() { // Create a command to run the server cmd := exec.Command("go", "run", "../server/server.go") // Create a transport to communicate with the server transport := stdio.NewStdioClientTransport(cmd) // Create a client c := client.NewClient(transport) // Connect to the server if err := c.Connect(context.Background()); err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } // List tools tools, err := c.ListTools(context.Background(), nil) if err != nil { fmt.Fprintf(os.Stderr, "Error: %v\n", err) os.Exit(1) } fmt.Printf("Tools: %+v\n", tools) } ``` -------------------------------- ### Iterator Method for Resource Templates Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Handles pagination for List spec methods automatically. Iteration starts from the provided cursor if present in ListResourceTemplatesParams. ```go func (*ClientSession) ResourceTemplates(context.Context, *ListResourceTemplatesParams) iter.Seq2[ResourceTemplate, error] ``` -------------------------------- ### Manage filesystem roots with MCP client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/client.md Demonstrates adding roots to a client and handling root change notifications on the server side. ```go func Example_roots() { ctx := context.Background() // Create a client with a single root. c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) c.AddRoots(&mcp.Root{URI: "file://a"}) // Now create a server with a handler to receive notifications about roots. rootsChanged := make(chan struct{}) handleRootsChanged := func(ctx context.Context, req *mcp.RootsListChangedRequest) { rootList, err := req.Session.ListRoots(ctx, nil) if err != nil { log.Fatal(err) } var roots []string for _, root := range rootList.Roots { roots = append(roots, root.URI) } fmt.Println(roots) close(rootsChanged) } s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, &mcp.ServerOptions{ RootsListChangedHandler: handleRootsChanged, }) // Connect the server and client... t1, t2 := mcp.NewInMemoryTransports() serverSession, err := s.Connect(ctx, t1, nil) if err != nil { log.Fatal(err) } defer serverSession.Close() clientSession, err := c.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer clientSession.Close() // ...and add a root. The server is notified about the change. c.AddRoots(&mcp.Root{URI: "file://b"}) <-rootsChanged // Output: [file://a file://b] } ``` -------------------------------- ### Implement sampling capability in MCP client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/client.md Shows how to configure a client to handle sampling requests and trigger them from the server session. ```go func Example_sampling() { ctx := context.Background() // Create a client with a sampling handler. c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, &mcp.ClientOptions{ CreateMessageHandler: func(_ context.Context, req *mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { return &mcp.CreateMessageResult{ Content: &mcp.TextContent{ Text: "would have created a message", }, }, nil }, }) // Connect the server and client... ct, st := mcp.NewInMemoryTransports() s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) session, err := s.Connect(ctx, st, nil) if err != nil { log.Fatal(err) } defer session.Close() if _, err := c.Connect(ctx, ct, nil); err != nil { log.Fatal(err) } msg, err := session.CreateMessage(ctx, &mcp.CreateMessageParams{}) if err != nil { log.Fatal(err) } fmt.Println(msg.Content.(*mcp.TextContent).Text) // Output: would have created a message } ``` -------------------------------- ### Initialize a Go workspace Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/CONTRIBUTING.md Use a go.work file to manage dependencies between your project and the SDK during development. ```sh go work init ./project ./go-sdk ``` -------------------------------- ### Implement Progress Reporting Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/protocol.src.md Demonstrates how to handle progress notifications and send updates using the MCP Go SDK. ```go func Example_progress() { // Server-side progress reporting server := mcp.NewServer( mcp.WithServerOptions(mcp.ServerOptions{ ProgressNotificationHandler: func(ctx context.Context, notification mcp.ProgressNotification) error { fmt.Printf("Progress: %v/%v\n", notification.Progress, notification.Total) return nil }, }), ) // Client-side progress reporting client := mcp.NewClient( mcp.WithClientOptions(mcp.ClientOptions{ ProgressNotificationHandler: func(ctx context.Context, notification mcp.ProgressNotification) error { fmt.Printf("Progress: %v/%v\n", notification.Progress, notification.Total) return nil }, }), ) // Sending a progress notification // Assuming we have a progress token from request metadata token := mcp.ProgressToken{Value: "task-1"} _ = server.NotifyProgress(context.Background(), mcp.ProgressNotification{ Progress: 50, Total: 100, Token: token, }) _ = client.NotifyProgress(context.Background(), mcp.ProgressNotification{ Progress: 50, Total: 100, Token: token, }) } ``` -------------------------------- ### Calling Ping with Nil Params Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Example of calling a spec method with optional parameters. Passing nil for unnecessary parameters is safe and maintains backward compatibility. ```go err := session.Ping(ctx, nil) ``` -------------------------------- ### Interact with cityTime Tool in Claude Code Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/http/README.md Example interaction within Claude Code, demonstrating how to query the timezone for a specific city using the 'cityTime' tool. ```text > what's the timezone ⏺ I'll get the current time in a major US city for you. ⏺ timezone - cityTime (MCP)(city: "nyc") ⎿ The current time in New York City is 7:30:16 PM EDT on Wedn esday, July 23, 2025 ⏺ The current timezone is EDT (Eastern Daylight Time), and it's 7:30 PM on Wednesday, July 23, 2025. > what timezones do you support? ⏺ The timezone tool supports three US cities: - NYC (Eastern Time) - SF (Pacific Time) - Boston (Eastern Time) ``` -------------------------------- ### Implement Elicitation in MCP Go SDK Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/client.md Demonstrates setting up a client-side elicitation handler and triggering an elicitation request from the server. ```go func Example_elicitation() { ctx := context.Background() ct, st := mcp.NewInMemoryTransports() s := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) ss, err := s.Connect(ctx, st, nil) if err != nil { log.Fatal(err) } defer ss.Close() c := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, &mcp.ClientOptions{ ElicitationHandler: func(context.Context, *mcp.ElicitRequest) (*mcp.ElicitResult, error) { return &mcp.ElicitResult{Action: "accept", Content: map[string]any{"test": "value"}}, nil }, }) if _, err := c.Connect(ctx, ct, nil); err != nil { log.Fatal(err) } res, err := ss.Elicit(ctx, &mcp.ElicitParams{ Message: "This should fail", RequestedSchema: &jsonschema.Schema{ Type: "object", Properties: map[string]*jsonschema.Schema{ "test": {Type: "string"}, }, }, }) if err != nil { log.Fatal(err) } fmt.Println(res.Content["test"]) // Output: value } ``` -------------------------------- ### Inspect HTTP Traffic with Middleware Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/troubleshooting.md Implement an HTTP middleware to inspect request bodies before they are processed by the MCP server. This example logs the request method and body. ```go 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": {}} } ``` -------------------------------- ### Log MCP Traffic with LoggingTransport Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/troubleshooting.md Use LoggingTransport to capture and inspect MCP traffic for stdio connections. This example logs to a bytes.Buffer, but can be adapted for files or os.Stderr. ```go func ExampleLoggingTransport() { ctx := context.Background() t1, t2 := mcp.NewInMemoryTransports() server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) serverSession, err := server.Connect(ctx, t1, nil) if err != nil { log.Fatal(err) } defer serverSession.Close() client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, nil) var b bytes.Buffer logTransport := &mcp.LoggingTransport{Transport: t2, Writer: &b} clientSession, err := client.Connect(ctx, logTransport, nil) if err != nil { log.Fatal(err) } defer clientSession.Close() // Sort for stability: reads are concurrent to writes. for _, line := range slices.Sorted(strings.SplitSeq(b.String(), "\n")) { fmt.Println(line) } // Output: // read: {"jsonrpc":"2.0","id":1,"result":{"capabilities":{"logging":{}},"protocolVersion":"2025-11-25","serverInfo":{"name":"server","version":"v0.0.1"}}} // write: {"jsonrpc":"2.0","id":1,"method":"initialize","params":{"clientInfo":{"name":"client","version":"v0.0.1"},"protocolVersion":"2025-11-25","capabilities":{"roots":{"listChanged":true}}}} // write: {"jsonrpc":"2.0","method":"notifications/initialized","params":{}} } ``` -------------------------------- ### SSE Server Transport Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Represents a logical SSE session created via a hanging GET request. Use this for custom session management and endpoint handling. ```go // A SSEServerTransport is a logical SSE session created through a hanging GET // request. type SSEServerTransport struct { Endpoint string Response http.ResponseWriter } // ServeHTTP handles POST requests to the transport endpoint. func (*SSEServerTransport) ServeHTTP(w http.ResponseWriter, req *http.Request) // Connect sends the 'endpoint' event to the client. // See [SSEServerTransport] for more details on the [Connection] implementation. func (*SSEServerTransport) Connect(context.Context) (Connection, error) ``` -------------------------------- ### Run MCP Server in Standard I/O Mode Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/sequentialthinking/README.md Execute the MCP server using the Go SDK in standard input/output mode. ```bash go run . ``` -------------------------------- ### Add Tools to Server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Methods for registering tools on an MCP server, supporting both explicit and generic type-inferred registration. ```go func (s *Server) AddTool(t *Tool, h ToolHandler) func AddTool[In, Out any](s *Server, t *Tool, h ToolHandlerFor[In, Out]) ``` ```go mcp.AddTool(server, &mcp.Tool{Name: "add", Description: "add numbers"}, addHandler) mcp.AddTool(server, &mcp.Tool{Name: "subtract", Description: "subtract numbers"}, subHandler) ``` ```go t := &Tool{Name: ..., Description: ..., InputSchema: &jsonschema.Schema{...}} server.AddTool(t, myHandler) ``` -------------------------------- ### Start a New Thinking Session Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/sequentialthinking/README.md Initiate a sequential thinking session for a given problem. Optional parameters include a custom session ID and an initial estimate of steps. ```json { "method": "tools/call", "params": { "name": "start_thinking", "arguments": { "problem": "How should I design a scalable microservices architecture?", "sessionId": "architecture_design", "estimatedSteps": 8 } } } ``` -------------------------------- ### Configure Client Sampling Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Handler configuration for processing server-initiated sampling requests. ```go type ClientOptions struct { ... CreateMessageHandler func(context.Context, *ClientSession, *CreateMessageParams) (*CreateMessageResult, error) } ``` -------------------------------- ### Get a specific prompt from an MCP server Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/server.src.md Call `ClientSession.GetPrompt` to retrieve a specific prompt by its name and provide any necessary arguments for expansion. This allows clients to fetch and use prompt templates defined on the server. ```go func (s *ClientSession) GetPrompt(ctx context.Context, name string, args map[string]string) (*Prompt, error) ``` -------------------------------- ### Define and Apply MCP Middleware Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Defines the MethodHandler and Middleware types and shows how to register them on Client or Server instances. ```go // A MethodHandler handles MCP messages. // For methods, exactly one of the return values must be nil. // For notifications, both must be nil. type MethodHandler func(ctx context.Context, method string, req Request) (result Result, err error) // Middleware is a function from MethodHandlers to MethodHandlers. type Middleware func(MethodHandler) MethodHandler // AddMiddleware wraps the client/server's current method handler using the provided // middleware. Middleware is applied from right to left, so that the first one // is executed first. // // For example, AddMiddleware(m1, m2, m3) augments the server method handler as // m1(m2(m3(handler))). func (c *Client) AddSendingMiddleware(middleware ...Middleware) func (c *Client) AddReceivingMiddleware(middleware ...Middleware) func (s *Server) AddSendingMiddleware(middleware ...Middleware) func (s *Server) AddReceivingMiddleware(middleware ...Middleware) ``` -------------------------------- ### Implement CompletionHandler Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/design/design.md Register a CompletionHandler in ServerOptions to process completion requests from clients. ```go type ServerOptions struct { ... // If non-nil, called when a client sends a completion request. CompletionHandler func(context.Context, *ServerRequest[*CompleteParams]) (*CompleteResult, error) } ``` -------------------------------- ### Implement Progress Reporting in MCP Go SDK Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/docs/protocol.md Demonstrates how to send progress notifications from a server and handle them on the client side using the MCP Go SDK. ```go func Example_progress() { server := mcp.NewServer(&mcp.Implementation{Name: "server", Version: "v0.0.1"}, nil) mcp.AddTool(server, &mcp.Tool{Name: "makeProgress"}, func(ctx context.Context, req *mcp.CallToolRequest, _ any) (*mcp.CallToolResult, any, error) { if token := req.Params.GetProgressToken(); token != nil { for i := range 3 { params := &mcp.ProgressNotificationParams{ Message: "frobbing widgets", ProgressToken: token, Progress: float64(i), Total: 2, } req.Session.NotifyProgress(ctx, params) // ignore error } } return &mcp.CallToolResult{}, nil, nil }) client := mcp.NewClient(&mcp.Implementation{Name: "client", Version: "v0.0.1"}, &mcp.ClientOptions{ ProgressNotificationHandler: func(_ context.Context, req *mcp.ProgressNotificationClientRequest) { fmt.Printf("%s %.0f/%.0f\n", req.Params.Message, req.Params.Progress, req.Params.Total) }, }) ctx := context.Background() t1, t2 := mcp.NewInMemoryTransports() if _, err := server.Connect(ctx, t1, nil); err != nil { log.Fatal(err) } session, err := client.Connect(ctx, t2, nil) if err != nil { log.Fatal(err) } defer session.Close() if _, err := session.CallTool(ctx, &mcp.CallToolParams{ Name: "makeProgress", Meta: mcp.Meta{"progressToken": "abc123"}, }); err != nil { log.Fatal(err) } // Output: // frobbing widgets 0/2 // frobbing widgets 1/2 // frobbing widgets 2/2 } ``` -------------------------------- ### Implement sampling in MCP client Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/internal/docs/client.src.md Configure CreateMessageHandler in ClientOptions to handle sampling requests from the server. ```go client, err := mcp.NewClient(transport, mcp.ClientOptions{ CreateMessageHandler: func(ctx context.Context, req mcp.CreateMessageRequest) (*mcp.CreateMessageResult, error) { // Handle sampling request return &mcp.CreateMessageResult{Content: mcp.TextContent{Text: "hello"}}, nil }, }) ``` -------------------------------- ### Testing MCP Server with Go Source: https://github.com/modelcontextprotocol/go-sdk/blob/main/examples/server/auth-middleware/README.md Execute Go tests to verify functionality, including benchmarks and coverage reports. ```bash # Run all tests go test -v # Run benchmark tests go test -bench=. # Generate coverage report go test -cover ```