### Implement MCP Clients in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/quick-start.mdx Shows how to connect to MCP servers using either Stdio or StreamableHTTP transports, initialize the connection, list available tools, and execute tool calls. ```go // Stdio Client Example package main import ( "context" "fmt" "log" "github.com/mathiasXie/mcp-go/client" "github.com/mathiasXie/mcp-go/mcp" ) func main() { c, err := client.NewStdioMCPClient("go", "run", "path/to/server/main.go") if err != nil { log.Fatal(err) } defer c.Close() ctx := context.Background() if err := c.Initialize(ctx); err != nil { log.Fatal(err) } tools, _ := c.ListTools(ctx) result, _ := c.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolParams{Name: "hello_world", Arguments: map[string]interface{}{"name": "World"}}, }) } ``` ```go // StreamableHTTP Client Example package main import ( "context" "fmt" "log" "github.com/mathiasXie/mcp-go/client" "github.com/mathiasXie/mcp-go/mcp" ) func main() { c := client.NewStreamableHttpClient("http://localhost:8080/mcp") defer c.Close() ctx := context.Background() c.Initialize(ctx) result, _ := c.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolRequestParams{Name: "hello_world", Arguments: map[string]interface{}{"name": "StreamableHTTP World"}}, }) } ``` -------------------------------- ### Implement an MCP Hello World Server in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/quick-start.mdx Demonstrates how to initialize an MCP server, define a tool with required arguments, and register a handler function to process tool calls via stdio. ```go package main import ( "context" "errors" "fmt" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { s := server.NewMCPServer( "Hello World Server", "1.0.0", server.WithToolCapabilities(false), ) tool := mcp.NewTool("hello_world", mcp.WithDescription("Say hello to someone"), mcp.WithString("name", mcp.Required(), mcp.Description("Name of the person to greet"), ), ) s.AddTool(tool, helloHandler) if err := server.ServeStdio(s); err != nil { fmt.Printf("Server error: %v\n", err) } } func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { name, err := request.RequireString("name") if err != nil { return mcp.NewToolResultError(err.Error()), nil } return mcp.NewToolResultText(fmt.Sprintf("Hello, %s! 👋", name)), nil } ``` -------------------------------- ### Install MCP-Go Package Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This command adds the MCP-Go library to your Go project, making its functionalities available for use. Ensure you have Go installed and configured in your environment. ```bash go get github.com/mathiasXie/mcp-go ``` -------------------------------- ### Create a Basic MCP Server with a 'hello_world' Tool in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code demonstrates the creation of a simple MCP server. It defines a 'hello_world' tool that takes a 'name' argument and returns a greeting. The server is then started using the stdio transport. ```go package main import ( "context" "fmt" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { // Create a new MCP server s := server.NewMCPServer( "Demo 🚀", "1.0.0", server.WithToolCapabilities(false), ) // Add tool tool := mcp.NewTool("hello_world", mcp.WithDescription("Say hello to someone"), mcp.WithString("name", mcp.Required(), mcp.Description("Name of the person to greet"), ), ) // Add tool handler s.AddTool(tool, helloHandler) // Start the stdio server if err := server.ServeStdio(s); err != nil { fmt.Printf("Server error: %v\n", err) } } func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { name, err := request.RequireString("name") if err != nil { return mcp.NewToolResultError(err.Error()), nil } return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil } ``` -------------------------------- ### Implement SSE Server with Tools and Resources in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/sse.mdx This example shows how to configure an MCP server with tool and resource capabilities, register handlers for data streaming and system monitoring, and start an SSE transport server. It includes logic for sending real-time progress notifications to clients using the server context. ```go package main import ( "context" "fmt" "log" "time" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { s := server.NewMCPServer("SSE Server", "1.0.0", server.WithToolCapabilities(true), server.WithResourceCapabilities(true, true), ) s.AddTool( mcp.NewTool("stream_data", mcp.WithDescription("Stream data with real-time updates"), mcp.WithString("source", mcp.Required()), mcp.WithNumber("count", mcp.DefaultNumber(10)), ), handleStreamData, ) s.AddResource( mcp.NewResource( "metrics://current", "Current System Metrics", mcp.WithResourceDescription("Real-time system metrics"), mcp.WithMIMEType("application/json"), ), handleCurrentMetrics, ) log.Println("Starting SSE server on :8080") sseServer := server.NewSSEServer(s) if err := sseServer.Start(":8080"); err != nil { log.Fatal(err) } } func handleStreamData(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { source := req.GetString("source", "") count := req.GetInt("count", 10) mcpServer := server.ServerFromContext(ctx) for i := 0; i < count; i++ { select { case <-ctx.Done(): return nil, ctx.Err() default: } if mcpServer != nil { mcpServer.SendNotificationToClient(ctx, "notifications/progress", map[string]interface{}{ "progress": i + 1, "total": count, }) } time.Sleep(100 * time.Millisecond) } return mcp.NewToolResultText("Done"), nil } ``` -------------------------------- ### Run MCP Go OAuth Example Source: https://github.com/mathiasxie/mcp-go/blob/main/examples/oauth_client/README.md Instructions for setting up environment variables and executing the OAuth authentication example using the Go CLI. ```bash export MCP_CLIENT_ID=your_client_id export MCP_CLIENT_SECRET=your_client_secret go run main.go ``` -------------------------------- ### Basic StreamableHTTP Server Setup in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/http.mdx Sets up a StreamableHTTP server using mcp-go. It initializes the server, adds RESTful tools with descriptions and parameters, and registers resources. The server is then started on port 8080. Dependencies include the 'mcp' and 'server' packages from github.com/mathiasXie/mcp-go. ```go package main import ( "context" "fmt" "log" "net/http" "strings" "time" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { s := server.NewMCPServer("StreamableHTTP API Server", "1.0.0", server.WithToolCapabilities(true), server.WithResourceCapabilities(true, true), ) // Add RESTful tools s.AddTool( mcp.NewTool("get_user", mcp.WithDescription("Get user information"), mcp.WithString("user_id", mcp.Required()), ), handleGetUser, ) s.AddTool( mcp.NewTool("create_user", mcp.WithDescription("Create a new user"), mcp.WithString("name", mcp.Required()), mcp.WithString("email", mcp.Required()), mcp.WithNumber("age", mcp.Min(0)), ), handleCreateUser, ) s.AddTool( mcp.NewTool("search_users", mcp.WithDescription("Search users with filters"), mcp.WithString("query", mcp.Description("Search query")), mcp.WithNumber("limit", mcp.DefaultNumber(10), mcp.Max(100)), mcp.WithNumber("offset", mcp.DefaultNumber(0), mcp.Min(0)), ), handleSearchUsers, ) // Add resources s.AddResource( mcp.NewResource( "users://{user_id}", "User Profile", mcp.WithResourceDescription("User profile data"), mcp.WithMIMEType("application/json"), ), handleUserResource, ) // Start StreamableHTTP server log.Println("Starting StreamableHTTP server on :8080") httpServer := server.NewStreamableHTTPServer(s) if err := httpServer.Start(":8080"); err != nil { log.Fatal(err) } } func handleGetUser(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { userID := req.GetString("user_id", "") if userID == "" { return nil, fmt.Errorf("user_id is required") } // Simulate database lookup user, err := getUserFromDB(userID) if err != nil { return nil, fmt.Errorf("user not found: %s", userID) } return mcp.NewToolResultText(fmt.Sprintf(`{"id":"%s","name":"%s","email":"%s","age":%d}`, user.ID, user.Name, user.Email, user.Age)), nil } func handleCreateUser(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { name := req.GetString("name", "") email := req.GetString("email", "") age := req.GetInt("age", 0) if name == "" || email == "" { return nil, fmt.Errorf("name and email are required") } // Validate input if !isValidEmail(email) { return nil, fmt.Errorf("invalid email format: %s", email) } // Create user user := &User{ ID: generateID(), Name: name, Email: email, Age: age, CreatedAt: time.Now(), } if err := saveUserToDB(user); err != nil { return nil, fmt.Errorf("failed to create user: %w", err) } return mcp.NewToolResultText(fmt.Sprintf(`{"id":"%s","message":"User created successfully","user":{"id":"%s","name":"%s","email":"%s","age":%d}}`, user.ID, user.ID, user.Name, user.Email, user.Age)), nil } // Helper functions and types for the examples type User struct { ID string `json:"id"` Name string `json:"name"` Email string `json:"email"` Age int `json:"age"` CreatedAt time.Time `json:"created_at"` } func getUserFromDB(userID string) (*User, error) { // Placeholder implementation return &User{ ID: userID, Name: "John Doe", Email: "john@example.com", Age: 30, }, nil } func isValidEmail(email string) bool { return strings.Contains(email, "@") && strings.Contains(email, ".") } func generateID() string { // Placeholder implementation return fmt.Sprintf("user_%d", time.Now().UnixNano()) } func saveUserToDB(user *User) error { // Placeholder implementation return nil } func handleSearchUsers(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { query := req.GetString("query", "") limit := req.GetInt("limit", 10) offset := req.GetInt("offset", 0) // Search users with pagination users, total, err := searchUsersInDB(query, limit, offset) if err != nil { return nil, fmt.Errorf("search failed: %w", err) } return mcp.NewToolResultText(fmt.Sprintf(`{"users":[{"id":"1","name":"John Doe","email":"john@example.com","age":30},{"id":"2","name":"Jane Smith","email":"jane@example.com","age":25}],"total":%d,"limit":%d,"offset":%d,"query":"%s"}`, total, limit, offset, query)), nil } func handleUserResource(ctx context.Context, req mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { userID := extractUserIDFromURI(req.Params.URI) ``` -------------------------------- ### Initialize and Start an MCP Server Source: https://github.com/mathiasxie/mcp-go/blob/main/README.md Shows the minimal configuration required to instantiate an MCP server and start it using standard input/output streams. ```go s := server.NewMCPServer( "My Server", "1.0.0", ) if err := server.ServeStdio(s); err != nil { log.Fatalf("Server error: %v", err) } ``` -------------------------------- ### Initialize and Run an MCP STDIO Server in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/stdio.mdx Demonstrates the setup of an MCP server using the mcp-go library, including tool registration for directory listing and resource registration for file content access. It includes essential security patterns like path validation to prevent directory traversal attacks. ```go package main import ( "context" "fmt" "os" "path/filepath" "strings" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { s := server.NewMCPServer("File Tools", "1.0.0", server.WithToolCapabilities(true), server.WithResourceCapabilities(true, true), ) s.AddTool( mcp.NewTool("list_files", mcp.WithDescription("List files in a directory"), mcp.WithString("path", mcp.Required(), mcp.Description("Directory path to list")), mcp.WithBoolean("recursive", mcp.DefaultBool(false), mcp.Description("List files recursively")), ), handleListFiles, ) s.AddResource( mcp.NewResource("file://{path}", "File Content", mcp.WithResourceDescription("Read file contents"), mcp.WithMIMEType("text/plain")), handleFileContent, ) if err := server.ServeStdio(s); err != nil { fmt.Fprintf(os.Stderr, "Server error: %v\n", err) os.Exit(1) } } func handleListFiles(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { path, err := req.RequireString("path") if err != nil { return mcp.NewToolResultError(err.Error()), nil } recursive, err := req.RequireBool("recursive") if err != nil { return mcp.NewToolResultError(err.Error()), nil } if !isValidPath(path) { return mcp.NewToolResultError(fmt.Sprintf("invalid path: %s", path)), nil } files, err := listFiles(path, recursive) if err != nil { return mcp.NewToolResultError(fmt.Sprintf("failed to list files: %v", err)), nil } return mcp.NewToolResultText(fmt.Sprintf(`{"path":"%s","files":%v,"count":%d,"recursive":%t}`, path, files, len(files), recursive)), nil } func handleFileContent(ctx context.Context, req mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { path := extractPathFromURI(req.Params.URI) if !isValidPath(path) { return nil, fmt.Errorf("invalid path: %s", path) } content, err := os.ReadFile(path) if err != nil { return nil, fmt.Errorf("failed to read file: %w", err) } return []mcp.ResourceContents{ mcp.TextResourceContents{ URI: req.Params.URI, MIMEType: detectMIMEType(path), Text: string(content), }, }, nil } func isValidPath(path string) bool { clean := filepath.Clean(path) if strings.Contains(clean, "..") { return false } if filepath.IsAbs(clean) { safeBaseDirs := []string{"/tmp", "/var/tmp", "/home", "/Users"} for _, baseDir := range safeBaseDirs { if strings.HasPrefix(clean, baseDir) { return true } } return false } return !strings.HasPrefix(clean, "..") } ``` -------------------------------- ### Configure MCP Server Options in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code illustrates how to customize an MCP server using various options. It shows how to enable tool capabilities, add recovery middleware, and configure hooks. ```go s := server.NewMCPServer( "My Server", "1.0.0", server.WithToolCapabilities(true), server.WithRecovery(), server.WithHooks(myHooks), ) ``` -------------------------------- ### Start Advanced SSE Server with Tools - Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/sse.mdx Initializes and starts an advanced SSE server with various capabilities enabled, including resource, prompt, and tool capabilities. It also demonstrates adding collaborative tools like document editing, real-time chat, and live data subscriptions. This function sets up the core server and its endpoints. ```go func main() { s := server.NewMCPServer("Advanced SSE Server", "1.0.0", server.WithResourceCapabilities(true, true), server.WithPromptCapabilities(true), server.WithToolCapabilities(true), server.WithLogging(), ) // Add collaborative tools addCollaborativeTools(s) addRealTimeResources(s) // Placeholder log.Println("Starting advanced SSE server on :8080") sseServer := server.NewSSEServer(s, server.WithStaticBasePath("/mcp"), server.WithKeepAliveInterval(30*time.Second), server.WithBaseURL("http://localhost:8080"), ) if err := sseServer.Start(":8080"); err != nil { log.Fatal(err) } } // Helper functions for the advanced example func addRealTimeResources(s *server.MCPServer) { // Placeholder implementation - would add real-time resources } func addCollaborativeTools(s *server.MCPServer) { // Shared document editing s.AddTool( mcp.NewTool("edit_document", mcp.WithDescription("Edit a shared document"), mcp.WithString("doc_id", mcp.Required()), mcp.WithString("operation", mcp.Required()), mcp.WithObject("data", mcp.Required()), ), handleDocumentEdit, // Assumed handler function ) // Real-time chat s.AddTool( mcp.NewTool("send_message", mcp.WithDescription("Send a message to all connected clients"), mcp.WithString("message", mcp.Required()), mcp.WithString("channel", mcp.DefaultString("general")), ), handleSendMessage, // Assumed handler function ) // Live data updates s.AddTool( mcp.NewTool("subscribe_updates", mcp.WithDescription("Subscribe to real-time data updates"), mcp.WithString("topic", mcp.Required()), mcp.WithArray("filters", mcp.Description("Optional filters")), ), handleSubscribeUpdates, // Assumed handler function ) } ``` -------------------------------- ### Initialize and Start MCP Server with Stdio Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/servers/basics.mdx Demonstrates the creation of a basic MCP server instance and its execution using the standard input/output transport, which is ideal for local CLI tools. ```go package main import ( "github.com/mathiasXie/mcp-go/server" ) func main() { // Create a basic server s := server.NewMCPServer( "My MCP Server", // Server name "1.0.0", // Server version ) // Start the server (stdio transport) server.ServeStdio(s) } ``` -------------------------------- ### Initialize and Configure an MCP Server in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/servers/index.mdx Demonstrates how to create an MCP server instance, register tools, resources, and prompts, and start the server using standard I/O. It includes handler functions for executing tools, reading resources, and generating prompts. ```go package main import ( "context" "encoding/json" "fmt" "time" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) var start time.Time func main() { start = time.Now() s := server.NewMCPServer( "Demo Server", "1.0.0", server.WithToolCapabilities(true), server.WithResourceCapabilities(false, true), server.WithPromptCapabilities(true), ) s.AddTool( mcp.NewTool("get_time", mcp.WithDescription("Get the current time"), mcp.WithString("format", mcp.Description("Time format (RFC3339, Unix, etc.)"), mcp.DefaultString("RFC3339"), ), ), handleGetTime, ) s.AddResource( mcp.NewResource( "config://server", "Server Configuration", mcp.WithResourceDescription("Current server configuration"), mcp.WithMIMEType("application/json"), ), handleConfig, ) s.AddPrompt( mcp.NewPrompt("analyze_logs", mcp.WithPromptDescription("Analyze server logs for issues"), mcp.WithArgument("log_level", mcp.ArgumentDescription("Minimum log level to analyze"), ), ), handleAnalyzeLogs, ) if err := server.ServeStdio(s); err != nil { fmt.Printf("Server error: %v\n", err) } } func handleGetTime(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { format := req.GetString("format", "RFC3339") var timeStr string switch format { case "Unix": timeStr = fmt.Sprintf("%d", time.Now().Unix()) default: timeStr = time.Now().Format(time.RFC3339) } return mcp.NewToolResultText(timeStr), nil } func handleConfig(ctx context.Context, req mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { config := map[string]interface{}{ "name": "Demo Server", "version": "1.0.0", "uptime": time.Since(start).String(), } configJSON, err := json.Marshal(config) if err != nil { return nil, err } return []mcp.ResourceContents{ mcp.TextResourceContents{ URI: req.Params.URI, MIMEType: "application/json", Text: string(configJSON), }, }, nil } func handleAnalyzeLogs(ctx context.Context, req mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { logLevel := "error" if args := req.Params.Arguments; args != nil { if level, ok := args["log_level"].(string); ok { logLevel = level } } return &mcp.GetPromptResult{ Description: "Analyze server logs for potential issues", Messages: []mcp.PromptMessage{ { Role: mcp.RoleUser, Content: mcp.NewTextContent(fmt.Sprintf( "Please analyze the server logs for entries at %s level or higher. "+ "Look for patterns, errors, and potential issues that need attention.", logLevel, )), }, }, }, nil } ``` -------------------------------- ### Usage Example for SubscriptionManager Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/clients/operations.mdx Demonstrates how to initialize the SubscriptionManager, register handlers for specific notification methods, and manage the start/stop lifecycle. ```go func demonstrateSubscriptionManager(c client.Client) { sm, err := NewSubscriptionManager(c) if err != nil { log.Printf("Failed to create subscription manager: %v", err) return } // Add handlers sm.AddHandler("notifications/progress", func(n mcp.Notification) error { log.Printf("Progress notification: %+v", n) return nil }) sm.AddHandler("notifications/message", func(n mcp.Notification) error { log.Printf("Message notification: %+v", n) return nil }) // Start handling if err := sm.Start(); err != nil { log.Printf("Failed to start subscription manager: %v", err) return } // Let it run for a while time.Sleep(30 * time.Second) // Stop sm.Stop() } ``` -------------------------------- ### Define a 'docs://readme' Resource in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code defines a resource named 'docs://readme' representing the project's README file. It includes a description and specifies the MIME type as 'text/markdown'. ```go resource := mcp.NewResource( "docs://readme", "Project README", mcp.WithResourceDescription("The project's README file"), mcp.WithMIMEType("text/markdown"), ) ``` -------------------------------- ### Serve Application Configuration Resource (Go) Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/servers/resources.mdx Exposes application configuration as a resource. This example shows how to create a configuration resource with a JSON MIME type and a handler that marshals environment variables and hardcoded settings into a JSON string. ```go import ( "context" "encoding/json" "os" "github.com/mathiasxie/mcp" "github.com/mathiasxie/mcp/server" ) // Configuration resource s.AddResource( mcp.NewResource( "config://app", "Application Configuration", mcp.WithResourceDescription("Current application settings"), mcp.WithMIMEType("application/json"), ), handleAppConfig, ) func handleAppConfig(ctx context.Context, req mcp.ReadResourceRequest) (*mcp.ReadResourceResult, error) { config := map[string]interface{}{ "database_url": os.Getenv("DATABASE_URL"), "debug_mode": os.Getenv("DEBUG") == "true", "version": "1.0.0", "features": []string{ "authentication", "caching", "logging", }, } configJSON, err := json.Marshal(config) if err != nil { return nil, err } return &mcp.ReadResourceResult{ Contents: []mcp.ResourceContent{ mcp.TextResourceContent{ URI: req.Params.URI, MIMEType: "application/json", Text: string(configJSON), }, }, }, nil } ``` -------------------------------- ### Create STDIO MCP Client Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/clients/basics.mdx Shows how to instantiate an MCP client that communicates via standard I/O with a subprocess. Includes examples for basic usage and passing custom environment variables to the server process. ```go func createStdioClient() (client.Client, error) { c, err := client.NewStdioMCPClient( "go", []string{}, "run", "/path/to/server/main.go", ) if err != nil { return nil, fmt.Errorf("failed to create STDIO client: %w", err) } return c, nil } func createStdioClientWithEnv() (client.Client, error) { env := []string{"LOG_LEVEL=debug", "DATABASE_URL=sqlite://test.db"} c, err := client.NewStdioMCPClient( "go", env, "run", "/path/to/server/main.go", ) if err != nil { return nil, fmt.Errorf("failed to create STDIO client: %w", err) } return c, nil } ``` -------------------------------- ### Implement Basic In-Process MCP Server and Client in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/inprocess.mdx Demonstrates how to set up an MCP server with a 'calculate' tool and then connect to it using an in-process client. This example showcases adding tools, handling requests, and making tool calls. It requires the 'mcp', 'server', and 'client' packages from the 'mathiasXie/mcp-go' library. ```go package main import ( "context" "fmt" "log" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" "github.com/mathiasXie/mcp-go/client" ) func main() { // Create server s := server.NewMCPServer("Calculator Server", "1.0.0", server.WithToolCapabilities(true), ) // Add calculator tool s.AddTool( mcp.NewTool("calculate", mcp.WithDescription("Perform basic mathematical calculations"), mcp.WithString("operation", mcp.Required(), mcp.Enum("add", "subtract", "multiply", "divide"), mcp.Description("The operation to perform"), ), mcp.WithNumber("x", mcp.Required(), mcp.Description("First number")), mcp.WithNumber("y", mcp.Required(), mcp.Description("Second number")), ), handleCalculate, ) // Create in-process client mcpClient, err := client.NewInProcessClient(s) if err != nil { log.Fatal(err) } defer mcpClient.Close() ctx := context.Background() // Initialize _, err = mcpClient.Initialize(ctx, mcp.InitializeRequest{ Params: mcp.InitializeRequestParams{ ProtocolVersion: "2024-11-05", Capabilities: mcp.ClientCapabilities{ Tools: &mcp.ToolsCapability{}, }, ClientInfo: mcp.Implementation{ Name: "test-client", Version: "1.0.0", }, }, }) if err != nil { log.Fatal(err) } // Use the calculator result, err := mcpClient.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolParams{ Name: "calculate", Arguments: map[string]interface{}{ "operation": "add", "x": 10.0, "y": 5.0, }, }, }) if err != nil { log.Fatal(err) } // Extract text from the first content item if len(result.Content) > 0 { if textContent, ok := mcp.AsTextContent(result.Content[0]); ok { fmt.Printf("Result: %s\n", textContent.Text) } } } func handleCalculate(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) { operation := req.GetString("operation", "") x := req.GetFloat("x", 0) y := req.GetFloat("y", 0) var result float64 switch operation { case "add": result = x + y case "subtract": result = x - y case "multiply": result = x * y case "divide": if y == 0 { return mcp.NewToolResultError("division by zero"), nil } result = x / y default: return nil, fmt.Errorf("unknown operation: %s", operation) } return mcp.NewToolResultText(fmt.Sprintf("%.2f", result)), nil } ``` -------------------------------- ### Create and Use MCP Client (Go) Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/clients/index.mdx Demonstrates the creation and usage of an MCP client using the STDIO transport. It covers client initialization, discovering capabilities like tools and resources, and performing operations such as calling tools and reading resources. This example requires the 'mcp-go' library. ```go package main import ( "context" "fmt" "log" "github.com/mathiasXie/mcp-go/client" "github.com/mathiasXie/mcp-go/mcp" ) func main() { // Create STDIO client c, err := client.NewStdioMCPClient( "go", []string{} , "run", "/path/to/server/main.go", ) if err != nil { log.Fatal(err) } defer c.Close() ctx := context.Background() // Initialize the connection if err := c.Initialize(ctx, initRequest); err != nil { log.Fatal(err) } // Discover available capabilities if err := demonstrateClientOperations(ctx, c); err != nil { log.Fatal(err) } } func demonstrateClientOperations(ctx context.Context, c client.Client) error { // List available tools tools, err := c.ListTools(ctx) if err != nil { return fmt.Errorf("failed to list tools: %w", err) } fmt.Printf("Available tools: %d\n", len(tools.Tools)) for _, tool := range tools.Tools { fmt.Printf("- %s: %s\n", tool.Name, tool.Description) } // List available resources resources, err := c.ListResources(ctx) if err != nil { return fmt.Errorf("failed to list resources: %w", err) } fmt.Printf("\nAvailable resources: %d\n", len(resources.Resources)) for _, resource := range resources.Resources { fmt.Printf("- %s: %s\n", resource.URI, resource.Name) } // Call a tool if available if len(tools.Tools) > 0 { tool := tools.Tools[0] fmt.Printf("\nCalling tool: %s\n", tool.Name) result, err := c.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolRequestParams{ Name: tool.Name, Arguments: map[string]interface{}{ "input": "example input", "format": "text", }, }, }) if err != nil { return fmt.Errorf("tool call failed: %w", err) } fmt.Printf("Tool result: %+v\n", result) } // Read a resource if available if len(resources.Resources) > 0 { resource := resources.Resources[0] fmt.Printf("\nReading resource: %s\n", resource.URI) content, err := c.ReadResource(ctx, mcp.ReadResourceRequest{ Params: mcp.ReadResourceRequestParams{ URI: resource.URI, }, }) if err != nil { return fmt.Errorf("resource read failed: %w", err) } fmt.Printf("Resource content: %+v\n", content) } return nil } ``` -------------------------------- ### Deploy MCP Server via HTTP and SSE Transports Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/servers/basics.mdx Provides examples for initializing servers using HTTP and Server-Sent Events (SSE) transports, including custom endpoint and keep-alive configurations. ```go // HTTP Transport httpServer := server.NewStreamableHTTPServer(s) if err := httpServer.Start(":8080"); err != nil { log.Fatal(err) } // SSE Transport sseServer := server.NewSSEServer(s) if err := sseServer.Start(":8080"); err != nil { log.Fatal(err) } ``` ```go // HTTP with custom options httpServer := server.NewStreamableHTTPServer(s, server.WithEndpointPath("/mcp"), server.WithStateless(true), ) // SSE with custom options sseServer := server.NewSSEServer(s, server.WithSSEEndpoint("/events"), server.WithMessageEndpoint("/message"), server.WithKeepAlive(true), ) ``` -------------------------------- ### Basic Tool Calling in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/clients/operations.mdx Demonstrates how to call tools provided by a client, including listing available tools and invoking a specific tool with arguments. The `callTool` function handles the actual invocation, while `demonstrateToolCalling` provides a complete example of interaction. ```go func callTool(ctx context.Context, c client.Client, name string, args map[string]interface{}) (*mcp.CallToolResult, error) { result, err := c.CallTool(ctx, mcp.CallToolRequest{ Params: mcp.CallToolRequestParams{ Name: name, Arguments: args, }, }) if err != nil { return nil, fmt.Errorf("tool call failed: %w", err) } return result, nil } func demonstrateToolCalling(ctx context.Context, c client.Client) { // List available tools tools, err := c.ListTools(ctx) if err != nil { log.Printf("Failed to list tools: %v", err) return } fmt.Printf("Available tools: %d\n", len(tools.Tools)) for _, tool := range tools.Tools { fmt.Printf("- %s: %s\n", tool.Name, tool.Description) } // Call a specific tool if len(tools.Tools) > 0 { tool := tools.Tools[0] fmt.Printf("\nCalling tool: %s\n", tool.Name) result, err := callTool(ctx, c, tool.Name, map[string]interface{}{ "input": "example input", "format": "text", }) if err != nil { log.Printf("Tool call failed: %v", err) return } fmt.Printf("Tool result:\n") for i, content := range result.Content { fmt.Printf("Content %d (%s): %s\n", i+1, content.Type, content.Text) } } } ``` -------------------------------- ### Start MCP Server with StreamableHTTP Transport in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code snippet demonstrates how to start an MCP server using the StreamableHTTP transport, listening on port 8080. This allows for HTTP-based communication with the server. ```go server.NewStreamableHTTPServer(s).Start(":8080") ``` -------------------------------- ### Start MCP Server with Server-Sent Events (SSE) Transport in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code shows how to initiate an MCP server using the Server-Sent Events (SSE) transport, binding to port 8080. SSE enables real-time, one-way communication from the server to clients. ```go server.ServeSSE(s, ":8080") ``` -------------------------------- ### Configure MCP Server for Claude Desktop Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/quick-start.mdx Provides the JSON configuration structure required to register an MCP server within the Claude Desktop application settings. ```json { "mcpServers": { "hello-world": { "command": "go", "args": ["run", "/path/to/your/hello-server/main.go"] } } } ``` -------------------------------- ### Implement Advanced STDIO Server in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/stdio.mdx Demonstrates how to initialize a robust MCP server with resource, prompt, and tool capabilities. Includes graceful shutdown handling and modular helper functions for system, file, Git, and database tools. ```go package main import ( "context" "fmt" "log" "os" "os/signal" "syscall" "time" "github.com/mathiasXie/mcp-go/mcp" "github.com/mathiasXie/mcp-go/server" ) func main() { s := server.NewMCPServer("Advanced CLI Tool", "1.0.0", server.WithResourceCapabilities(true, true), server.WithPromptCapabilities(true), server.WithToolCapabilities(true), server.WithLogging(), ) addSystemTools(s) addFileTools(s) addGitTools(s) addDatabaseTools(s) setupGracefulShutdown(s) if err := server.ServeStdio(s); err != nil { logError(fmt.Sprintf("Server error: %v", err)) os.Exit(1) } } ``` -------------------------------- ### Register and Serve Resources in MCP-Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/servers/resources.mdx Illustrates the server initialization process and how to register multiple resources with their respective handlers for client discovery. ```go func main() { s := server.NewMCPServer("Resource Server", "1.0.0", server.WithResourceCapabilities(true), ) // Add multiple resources resources := []struct { uri string name string description string mimeType string handler server.ResourceHandler }{ {"docs://readme", "README", "Project documentation", "text/markdown", handleReadme}, {"config://app", "App Config", "Application settings", "application/json", handleConfig}, {"users://{id}", "User Profile", "User information", "application/json", handleUser}, } for _, r := range resources { s.AddResource( mcp.NewResource(r.uri, r.name, mcp.WithResourceDescription(r.description), mcp.WithMIMEType(r.mimeType), ), r.handler, ) } server.ServeStdio(s) } ``` -------------------------------- ### Define a 'calculate' Tool for Arithmetic Operations in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/getting-started.mdx This Go code snippet shows how to define a tool named 'calculate' that can perform basic arithmetic operations. It specifies required string and number arguments for the operation and operands. ```go calculatorTool := mcp.NewTool("calculate", mcp.WithDescription("Perform basic arithmetic operations"), mcp.WithString("operation", mcp.Required(), mcp.Enum("add", "subtract", "multiply", "divide"), ), mcp.WithNumber("x", mcp.Required()), mcp.WithNumber("y", mcp.Required()), ) ``` -------------------------------- ### Install Dependencies Source: https://github.com/mathiasxie/mcp-go/blob/main/CONTRIBUTING.md Command to download and install all the necessary dependencies for the MCP Go SDK project using Go modules. ```bash go mod tidy ``` -------------------------------- ### Manage Server Process and Lifecycle Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/stdio.mdx Techniques for graceful panic recovery, signal handling for clean shutdowns, and retry logic for server startup. ```go defer func() { if r := recover(); r != nil { logError(fmt.Sprintf("Server panic: %v", r)) os.Exit(1) } }() for attempts := 0; attempts < 3; attempts++ { if err := server.ServeStdio(s); err != nil { time.Sleep(time.Second * time.Duration(attempts+1)) } else { break } } ``` -------------------------------- ### Standard MCP Endpoints Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/http.mdx These endpoints are automatically created when a StreamableHTTP MCP server starts. ```APIDOC ## Standard MCP Endpoints These endpoints are automatically created when a StreamableHTTP MCP server starts. ### POST /mcp/initialize #### Description Initialize MCP session. ### Method POST ### Endpoint /mcp/initialize ### POST /mcp/tools/list #### Description List available tools. ### Method POST ### Endpoint /mcp/tools/list ### POST /mcp/tools/call #### Description Call a tool. ### Method POST ### Endpoint /mcp/tools/call ### POST /mcp/resources/list #### Description List available resources. ### Method POST ### Endpoint /mcp/resources/list ### POST /mcp/resources/read #### Description Read a resource. ### Method POST ### Endpoint /mcp/resources/read ### POST /mcp/prompts/list #### Description List available prompts. ### Method POST ### Endpoint /mcp/prompts/list ### POST /mcp/prompts/get #### Description Get a prompt. ### Method POST ### Endpoint /mcp/prompts/get ### GET /mcp/health #### Description Health check. ### Method GET ### Endpoint /mcp/health ### GET /mcp/capabilities #### Description Server capabilities. ### Method GET ### Endpoint /mcp/capabilities ``` -------------------------------- ### Standard MCP Request/Response Patterns Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/http.mdx Examples of request and response formats for standard MCP operations. ```APIDOC ## Standard MCP Request/Response Patterns ### Standard MCP Request Example (POST /mcp/tools/call) ```json { "jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": { "name": "search_users", "arguments": { "query": "john", "limit": 10, "offset": 0 } } } ``` ### Standard MCP Response Example ```json { "jsonrpc": "2.0", "id": 1, "result": { "content": [ { "type": "text", "text": "{\"users\":[...],\"total\":25,\"limit\":10,\"offset\":0}" } ] } } ``` ### Error Response Example ```json { "jsonrpc": "2.0", "id": 1, "error": { "code": -32602, "message": "Invalid params", "data": { "details": "user_id is required" } } } ``` ``` -------------------------------- ### Implement Custom MCP Client in Go Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/stdio.mdx Shows how to create a client that communicates with an MCP server via STDIO. Includes initialization, listing available tools, and executing a specific tool call. ```go package main import ( "context" "log" "github.com/mathiasXie/mcp-go/client" ) func main() { c, err := client.NewStdioClient("go", "run", "/path/to/server/main.go") if err != nil { log.Fatal(err) } defer c.Close() ctx := context.Background() _, err = c.Initialize(ctx, mcp.InitializeRequest{...}) tools, err := c.ListTools(ctx, mcp.ListToolsRequest{}) result, err := c.CallTool(ctx, mcp.CallToolRequest{...}) } ``` -------------------------------- ### Integrate MCP Inspector Source: https://github.com/mathiasxie/mcp-go/blob/main/www/docs/pages/transports/stdio.mdx Commands to install and run the MCP Inspector for visual debugging of your Go MCP server. ```bash npm install -g @modelcontextprotocol/inspector mcp-inspector go run main.go ``` -------------------------------- ### Check Go Version Source: https://github.com/mathiasxie/mcp-go/blob/main/CONTRIBUTING.md Command to check the installed Go version on your machine. This is a prerequisite for contributing to the project. ```bash go version ``` -------------------------------- ### Regenerate Server Code Source: https://github.com/mathiasxie/mcp-go/blob/main/README.md Command to trigger the regeneration of server hooks and request handlers. Requires Go and goimports to be installed. ```bash go generate ./... ```