// Copyright 2025 The Go MCP SDK Authors. All rights reserved. // Use of this source code is governed by an MIT-style // license that can be found in the LICENSE file. package mcp_test import ( "context" "log" "os" "os/exec" "runtime" "testing" "github.com/google/go-cmp/cmp" "github.com/modelcontextprotocol/go-sdk/mcp" ) const runAsServer = "_MCP_RUN_AS_SERVER" func TestMain(m *testing.M) { if os.Getenv(runAsServer) != "" { os.Unsetenv(runAsServer) runServer() return } os.Exit(m.Run()) } func runServer() { ctx := context.Background() server := mcp.NewServer("greeter", "v0.0.1", nil) server.AddTools(mcp.NewServerTool("greet", "say hi", SayHi)) if err := server.Run(ctx, mcp.NewStdioTransport()); err != nil { log.Fatal(err) } } func TestCmdTransport(t *testing.T) { // Conservatively, limit to major OS where we know that os.Exec is // supported. switch runtime.GOOS { case "darwin", "linux", "windows": default: t.Skip("unsupported OS") } ctx, cancel := context.WithCancel(context.Background()) defer cancel() exe, err := os.Executable() if err != nil { t.Fatal(err) } cmd := exec.Command(exe) cmd.Env = append(os.Environ(), runAsServer+"=true") client := mcp.NewClient("client", "v0.0.1", nil) session, err := client.Connect(ctx, mcp.NewCommandTransport(cmd)) if err != nil { log.Fatal(err) } got, err := session.CallTool(ctx, &mcp.CallToolParams{ Name: "greet", Arguments: map[string]any{"name": "user"}, }) if err != nil { log.Fatal(err) } want := &mcp.CallToolResult{ Content: []mcp.Content{ &mcp.TextContent{Text: "Hi user"}, }, } if diff := cmp.Diff(want, got); diff != "" { t.Errorf("greet returned unexpected content (-want +got):\n%s", diff) } if err := session.Close(); err != nil { t.Fatalf("closing server: %v", err) } }