Quickstart
Quickstart
Let’s create a simple MCP server that exposes a calculator tool and a client that uses it, communicating over stdio.
Server (calculator_server/main.go)
package main
import (
	"fmt"
	"log"
	"os"
	"strconv"
	"github.com/localrivet/gomcp/protocol"
	"github.com/localrivet/gomcp/server"
)
// Arguments for the 'add' tool
type AddArgs struct {
	A float64 `json:"a" description:"First number" required:"true"`
	B float64 `json:"b" description:"Second number" required:"true"`
}
func main() {
	log.SetOutput(os.Stderr)
	log.SetFlags(log.Ltime | log.Lmsgprefix)
	log.SetPrefix("[CalcServer] ")
	log.Println("Starting Calculator MCP Server (Stdio)...")
	// Create the MCP server instance
	srv := server.NewServer("calculator-stdio")
	// Add the 'add' tool using the server.AddTool helper
	// The helper infers the schema from the handler's argument type (AddArgs)
	err := server.AddTool(
		srv,
		"add",
		"Add two numbers.",
		// Handler function using the args struct
		func(args AddArgs) (protocol.Content, error) {
			result := args.A + args.B
			log.Printf("[add tool] %f + %f -> %f", args.A, args.B, result)
			// Use server.Text helper for simple text responses
			return server.Text(strconv.FormatFloat(result, 'f', -1, 64)), nil
		},
	)
	if err != nil {
		log.Fatalf("Failed to add 'add' tool: %v", err)
	}
	// Start the server using the built-in stdio handler.
	// This blocks until the server exits (e.g., stdin is closed).
	log.Println("Server setup complete. Listening on stdio...")
	if err := server.ServeStdio(srv); err != nil {
		log.Fatalf("Server exited with error: %v", err)
	}
	log.Println("Server shutdown complete.")
}Client (calculator_client/main.go)
package main
import (
	"context"
	"log"
	"os"
	"time"
	"github.com/localrivet/gomcp/client"
	"github.com/localrivet/gomcp/protocol"
)
func main() {
	log.SetOutput(os.Stderr)
	log.SetFlags(log.Ltime | log.Lmsgprefix)
	log.SetPrefix("[CalcClient] ")
	log.Println("Starting Calculator MCP Client (Stdio)...")
	// Create a client configured for stdio communication
	// Point it to the server executable (adjust path as needed)
	// For simple Go examples, you might run the server first and then the client.
	// If running separately, use the actual command to start the server:
	// cmd := []string{"go", "run", "../calculator_server/main.go"}
	// clt, err := client.NewStdioClientWithCommand("MyCalcClient", client.ClientOptions{}, cmd)
	// For simplicity here, assume server is already running and connected to stdin/stdout
	clt, err := client.NewStdioClient("MyCalcClient", client.ClientOptions{})
	if err != nil {
		log.Fatalf("Failed to create client: %v", err)
	}
	// Set a timeout for the connection and operations
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
	defer cancel()
	// Connect and perform initialization handshake
	log.Println("Connecting to server via stdio...")
	if err = clt.Connect(ctx); err != nil {
		log.Fatalf("Client failed to connect: %v", err)
	}
	defer clt.Close() // Ensure connection resources are cleaned up
	serverInfo := clt.ServerInfo()
	log.Printf("Connected to server: %s (Version: %s)", serverInfo.Name, serverInfo.Version)
	// Call the 'add' tool
	log.Println("--- Calling 'add' Tool ---")
	addArgs := map[string]interface{}{"a": 15.5, "b": 4.5}
	callParams := protocol.CallToolParams{Name: "add", Arguments: addArgs}
	callCtx, callCancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer callCancel()
	callResult, err := clt.CallTool(callCtx, callParams, nil) // No progress token needed
	if err != nil {
		log.Printf("Error calling tool 'add': %v", err)
	} else if callResult.IsError {
		log.Printf("Tool 'add' call returned an error:")
		for _, content := range callResult.Content {
			if textContent, ok := content.(protocol.TextContent); ok {
				log.Printf("  Error Content: %s", textContent.Text)
			}
		}
	} else {
		log.Printf("Tool 'add' call successful:")
		for _, content := range callResult.Content {
			if textContent, ok := content.(protocol.TextContent); ok {
				log.Printf("  Result: %s", textContent.Text) // Expecting "20"
			}
		}
	}
	log.Println("Client finished.")
}Running the Quickstart:
- Save the server code as 
calculator_server/main.go. - Save the client code as 
calculator_client/main.go. - Compile and run the server: 
go run calculator_server/main.go - In another terminal, compile and run the client: 
go run calculator_client/main.go 
The client will connect to the server via stdio, call the add tool, print the result, and exit.