GoMCP is a complete Go implementation of the Model Context Protocol (MCP), designed to facilitate seamless interaction between applications and Large Language Models (LLMs). The library supports all specification versions with automatic negotiation and provides a clean, idiomatic API for both clients and servers.
- Overview
- Key Features
- Installation
- Quickstart
- Core Concepts
- Examples
- Documentation
- Contributing
- License
The Model Context Protocol (MCP) standardizes communication between applications and LLMs, enabling:
- Tool Calling: Execute actions and functions through LLMs
- Resource Access: Provide structured data to LLMs
- Prompt Rendering: Create reusable templates for LLM interactions
- Sampling: Generate text from LLMs with control over parameters
GoMCP provides an idiomatic Go implementation that handles all the protocol details while offering a clean, developer-friendly API.
- Complete Protocol Implementation: Full support for all MCP specification versions
- Automatic Version Negotiation: Seamless compatibility between clients and servers
- Multiple Transport Options: Support for stdio, HTTP, WebSocket, and Server-Sent Events
- Type-Safe API: Leverages Go's type system for safety and expressiveness
- Server Process Management: Automatically start, manage, and stop external MCP servers
- Server Configuration: Load server definitions from configuration files
- Flexible Architecture: Modular design for easy extension and customization
go get github.com/localrivet/gomcppackage main
import (
"log"
"github.com/localrivet/gomcp/client"
)
func main() {
// Create a new client
c, err := client.NewClient("my-client",
client.WithProtocolVersion("2025-03-26"),
client.WithProtocolNegotiation(true),
)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close()
// Call a tool on the MCP server
result, err := c.CallTool("say_hello", map[string]interface{}{
"name": "World",
})
if err != nil {
log.Fatalf("Tool call failed: %v", err)
}
log.Printf("Result: %v", result)
}package main
import (
"fmt"
"log/slog"
"os"
"github.com/localrivet/gomcp/server"
)
func main() {
// Create a logger
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{
Level: slog.LevelInfo,
}))
// Create a new server
s := server.NewServer("example-server",
server.WithLogger(logger),
).AsStdio()
// Register a tool
s.Tool("say_hello", "Greet someone", func(ctx *server.Context, args struct {
Name string `json:"name"`
}) (string, error) {
return fmt.Sprintf("Hello, %s!", args.Name), nil
})
// Start the server
s.Run()
}package main
import (
"log"
"github.com/localrivet/gomcp/client"
)
func main() {
// Define server configuration
config := client.ServerConfig{
MCPServers: map[string]client.ServerDefinition{
"task-master-ai": {
Command: "npx",
Args: []string{"-y", "--package=task-master-ai", "task-master-ai"},
Env: map[string]string{
"ANTHROPIC_API_KEY": "${ANTHROPIC_API_KEY}",
},
},
},
}
// Create a client with automatic server management
c, err := client.NewClient("my-client",
client.WithServers(config, "task-master-ai"),
)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
defer c.Close() // Automatically stops the server process
// Call a tool on the managed server
result, err := c.CallTool("add_task", map[string]interface{}{
"prompt": "Create a login page with authentication",
})
if err != nil {
log.Fatalf("Tool call failed: %v", err)
}
log.Printf("Task created: %v", result)
}client.Client: Interface for communicating with MCP serversserver.Server: Core component for implementing MCP servers
Tools allow you to expose functionality to LLMs:
// Register a tool with a struct for type-safe parameters
s.Tool("calculate", "Perform calculations", func(ctx *server.Context, args struct {
Operation string `enum:"add,subtract,multiply,divide"` // Tag-based validation
X float64
Y float64
}) (string, error) {
// Implementation...
})Resources provide data to LLMs:
// Register a static resource
s.Resource("app/version", "Get application version",
func(ctx *server.Context) (string, error) {
return "1.0.0", nil
})
// Register a resource with parameters
s.Resource("users/{id}", "Get user information",
func(ctx *server.Context, args struct {
ID string `path:"id"`
}) (map[string]interface{}, error) {
return map[string]interface{}{
"id": args.ID,
"name": "Example User",
}, nil
})Prompts define reusable templates for LLM interactions:
// Register a prompt template
s.Prompt("greeting", "Greet a user",
func(ctx *server.Context, args struct {
Name string
Service string
}) (string, error) {
return fmt.Sprintf("Hello %s, welcome to %s!", args.Name, args.Service), nil
})GoMCP supports multiple transport layers:
- stdio: For CLI tools and direct LLM integration
- WebSocket: For web applications with bidirectional communication
- Server-Sent Events (SSE): For web applications with a hybrid communication pattern:
- Server-to-client messages use SSE for real-time streaming
- Client-to-server messages use HTTP POST requests
- The server provides a message endpoint URL via the SSE connection
- Ideal for applications needing real-time updates with standard HTTP infrastructure
- HTTP: For simple RESTful interfaces
- Unix Socket: For high-performance interprocess communication
- UDP: For low-overhead, high-throughput communication
- MQTT: For publish/subscribe messaging in IoT applications
- NATS: For cloud-native, high-performance messaging
- gRPC: For service-to-service communication with strong typing
GoMCP provides robust functionality for managing external MCP server processes:
// Load configuration from file
client, err := client.NewClient("my-client",
client.WithServerConfig("mcpservers.json", "task-master-ai"),
)
// Or define configuration programmatically
config := client.ServerConfig{
MCPServers: map[string]client.ServerDefinition{
"memory-server": {
Command: "npx",
Args: []string{"-y", "@modelcontextprotocol/server-memory"},
Env: map[string]string{"DEBUG": "true"},
},
},
}
client, err := client.NewClient("my-client",
client.WithServers(config, "memory-server"),
)The server management system:
- Automatically starts the specified server process
- Connects the client to the server
- Manages environment variables and arguments
- Properly terminates the server when the client is closed
For advanced use cases, you can use the ServerRegistry directly:
registry := client.NewServerRegistry()
if err := registry.LoadConfig("mcpservers.json"); err != nil {
log.Fatalf("Failed to load configuration: %v", err)
}
// Get all available servers
serverNames, _ := registry.GetServerNames()
// Get a client for a specific server
memoryClient, _ := registry.GetClient("memory")
// Stop all servers when done
registry.StopAll()The examples/ directory contains complete examples demonstrating various features:
examples/minimal/: Basic client and server examplesexamples/sampling/: Examples of text generation via the sampling APIexamples/server_config/: Server management and configuration examplesexamples/server/: Various server implementation patterns
- GoDoc: API reference documentation
docs/: Additional documentation and guidesdocs/examples/: Detailed feature guidesdocs/getting-started/: Getting started guidesdocs/api-reference/: Detailed API documentation
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.