golang-mcp-server-sdk
A Golang SDK that implements the Model Context Protocol (MCP) for building servers that provide context for LLMs in a standardized way.
Golang MCP Server SDK
Table of Contents
- Overview
- Installation
- Quickstart
- What is MCP?
- Core Concepts
- Running Your Server
- Examples
- Advanced Usage
- Documentation
- Contributing
- License
Overview
The Model Context Protocol allows applications to provide context for LLMs in a standardized way, separating the concerns of providing context from the actual LLM interaction. This Golang SDK implements the full MCP specification, making it easy to:
- Build MCP servers that expose resources, prompts and tools
- Use standard transports like stdio, SSE, and WebSockets
- Handle all MCP protocol messages and lifecycle events
- Follow Go best practices and clean architecture principles
Note: This SDK is always updated to align with the latest MCP specification from spec.modelcontextprotocol.io/latest
Installation
go get github.com/FreePeak/golang-mcp-server-sdk
Quickstart
Let's create a simple MCP server that exposes an echo tool:
package main
import (
"context"
"log"
"os"
"github.com/FreePeak/golang-mcp-server-sdk/internal/domain"
"github.com/FreePeak/golang-mcp-server-sdk/internal/infrastructure/server"
"github.com/FreePeak/golang-mcp-server-sdk/internal/interfaces/stdio"
"github.com/FreePeak/golang-mcp-server-sdk/internal/usecases"
)
func main() {
// Configure logger
logger := log.New(os.Stderr, "[ECHO-SERVER] ", log.LstdFlags)
// Create the echo tool
echoTool := &domain.Tool{
Name: "echo",
Description: "Echoes back the input message",
Parameters: []domain.ToolParameter{
{
Name: "message",
Description: "The message to echo back",
Type: "string",
Required: true,
},
},
}
// Create tool repository
toolRepo := server.NewInMemoryToolRepository()
ctx := context.Background()
toolRepo.AddTool(ctx, echoTool)
// Create server service
serviceConfig := usecases.ServerConfig{
Name: "Echo Server",
Version: "1.0.0",
ToolRepo: toolRepo,
}
service := usecases.NewServerService(serviceConfig)
// Create MCP server
mcpServer := stdio.NewStdioServer(service, logger)
// Start the stdio server
if err := mcpServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
}
What is MCP?
The Model Context Protocol (MCP) is a standardized protocol that allows applications to provide context for LLMs in a secure and efficient manner. It separates the concerns of providing context and tools from the actual LLM interaction. MCP servers can:
- Expose data through Resources (read-only data endpoints)
- Provide functionality through Tools (executable functions)
- Define interaction patterns through Prompts (reusable templates)
- Support various transport methods (stdio, HTTP/SSE, WebSockets)
Core Concepts
Server
The MCP Server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
serviceConfig := usecases.ServerConfig{
Name: "My App",
Version: "1.0.0",
ToolRepo: toolRepo,
}
service := usecases.NewServerService(serviceConfig)
Resources
Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects:
// Create resource repository
resourceRepo := server.NewInMemoryResourceRepository()
// Add a static resource
resource := &domain.Resource{
Name: "config",
Description: "Application configuration",
Uri: "config://app",
Content: "App configuration data goes here",
}
resourceRepo.AddResource(ctx, resource)
// Add resource repository to server config
serviceConfig.ResourceRepo = resourceRepo
Tools
Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects:
// Define a simple calculator tool
calculatorTool := &domain.Tool{
Name: "calculate",
Description: "Performs basic arithmetic",
Parameters: []domain.ToolParameter{
{
Name: "operation",
Description: "The operation to perform (add, subtract, multiply, divide)",
Type: "string",
Required: true,
},
{
Name: "a",
Description: "First number",
Type: "number",
Required: true,
},
{
Name: "b",
Description: "Second number",
Type: "number",
Required: true,
},
},
}
// Add tool implementation
service.RegisterToolHandler("calculate", func(ctx context.Context, params map[string]interface{}) (interface{}, error) {
operation := params["operation"].(string)
a := params["a"].(float64)
b := params["b"].(float64)
var result float64
switch operation {
case "add":
result = a + b
case "subtract":
result = a - b
case "multiply":
result = a * b
case "divide":
result = a / b
default:
return nil, fmt.Errorf("unknown operation: %s", operation)
}
return result, nil
})
Prompts
Prompts are reusable templates that help LLMs interact with your server effectively:
// Create prompt repository
promptRepo := server.NewInMemoryPromptRepository()
// Add a code review prompt
codeReviewPrompt := &domain.Prompt{
Name: "review-code",
Description: "A prompt for code review",
Template: "Please review this code:\n\n{{.code}}",
Parameters: []domain.PromptParameter{
{
Name: "code",
Description: "The code to review",
Type: "string",
Required: true,
},
},
}
promptRepo.AddPrompt(ctx, codeReviewPrompt)
// Add prompt repository to server config
serviceConfig.PromptRepo = promptRepo
Running Your Server
MCP servers in Go can be connected to different transports depending on your use case:
stdio
For command-line tools and direct integrations:
import (
"github.com/FreePeak/golang-mcp-server-sdk/internal/interfaces/stdio"
)
// Create stdio server
stdioServer := stdio.NewStdioServer(service, logger)
// Start the stdio server
if err := stdioServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
HTTP with SSE
For remote servers, start a web server with a Server-Sent Events (SSE) endpoint:
import (
"github.com/FreePeak/golang-mcp-server-sdk/internal/interfaces/rest"
)
// Create HTTP server with SSE support
httpServer := rest.NewMCPServer(service, ":8080")
// Start the HTTP server
if err := httpServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
WebSockets
For bidirectional communication:
import (
"github.com/FreePeak/golang-mcp-server-sdk/internal/interfaces/ws"
)
// Create WebSocket server
wsServer := ws.NewWebSocketServer(service, ":8081")
// Start the WebSocket server
if err := wsServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
Multi-Protocol
You can also run multiple protocol servers simultaneously:
import (
"github.com/FreePeak/golang-mcp-server-sdk/internal/builder"
)
// Create a multi-protocol server builder
serverBuilder := builder.NewServerBuilder(service)
// Add protocols
serverBuilder.WithStdio(logger)
serverBuilder.WithSSE(":8080")
serverBuilder.WithWebSocket(":8081")
// Build and run the server
multiServer, err := serverBuilder.Build()
if err != nil {
logger.Fatalf("Error building server: %v", err)
}
// Start all servers
if err := multiServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
Testing and Debugging
For testing your MCP server, you can use the MCP Inspector.
Examples
Check out the cmd directory for complete example servers:
Echo Server
A simple server demonstrating tools functionality:
package main
import (
"context"
"log"
"os"
"github.com/FreePeak/golang-mcp-server-sdk/internal/domain"
"github.com/FreePeak/golang-mcp-server-sdk/internal/infrastructure/server"
"github.com/FreePeak/golang-mcp-server-sdk/internal/interfaces/stdio"
"github.com/FreePeak/golang-mcp-server-sdk/internal/usecases"
)
func main() {
logger := log.New(os.Stderr, "[ECHO] ", log.LstdFlags)
// Create the echo tool
echoTool := &domain.Tool{
Name: "echo",
Description: "Echoes back the input message",
Parameters: []domain.ToolParameter{
{
Name: "message",
Description: "The message to echo back",
Type: "string",
Required: true,
},
},
}
// Create tool repository
toolRepo := server.NewInMemoryToolRepository()
ctx := context.Background()
toolRepo.AddTool(ctx, echoTool)
// Create server service
serviceConfig := usecases.ServerConfig{
Name: "Echo Server",
Version: "1.0.0",
ToolRepo: toolRepo,
}
service := usecases.NewServerService(serviceConfig)
// Register tool handler
service.RegisterToolHandler("echo", func(ctx context.Context, params map[string]interface{}) (interface{}, error) {
message := params["message"].(string)
return message, nil
})
// Create stdio server
stdioServer := stdio.NewStdioServer(service, logger)
// Start the stdio server
if err := stdioServer.Serve(); err != nil {
logger.Fatalf("Error serving: %v", err)
}
}
Advanced Usage
Low-Level Server
For more control, you can use the low-level server interfaces directly:
import (
"context"
"encoding/json"
"log"
"github.com/FreePeak/golang-mcp-server-sdk/internal/domain"
"github.com/FreePeak/golang-mcp-server-sdk/internal/infrastructure/protocol"
)
func handleRequest(ctx context.Context, request []byte) ([]byte, error) {
var mcpRequest protocol.Request
if err := json.Unmarshal(request, &mcpRequest); err != nil {
return nil, err
}
// Process the request based on method
switch mcpRequest.Method {
case "capabilities":
response := protocol.CapabilitiesResponse{
JSONRPC: "2.0",
ID: mcpRequest.ID,
Result: protocol.Capabilities{
Resources: &protocol.ResourceCapabilities{},
Tools: &protocol.ToolCapabilities{},
},
}
return json.Marshal(response)
// Handle other methods similarly
default:
return nil, fmt.Errorf("unknown method: %s", mcpRequest.Method)
}
}
Clean Architecture
The SDK follows Clean Architecture principles, separating concerns into layers:
- Domain: Core business entities and interfaces
- Use Cases: Application business logic
- Infrastructure: Implementation details
- Interfaces: Adapters for different transport protocols
This design makes it easy to:
- Test components in isolation
- Replace implementations without affecting business logic
- Add new transport protocols without changing core functionality
Documentation
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.
License
This project is licensed under the MIT License - see the LICENSE file for details.
📧 Support & Contact
- For questions or issues, email mnhatlinh.doan@gmail.com
- Open an issue directly: Issue Tracker
- If Golang MCP Server SDK helps your work, please consider supporting: