Go MCP Template
Template repository for creating MCP servers in Go
Installation
npx go-mcp-templateAsk AI about Go MCP Template
Powered by Claude Β· Grounded in docs
I know everything about Go MCP Template. Ask me about installation, configuration, usage, or troubleshooting.
0/500
Reviews
Documentation
MCP Server Template (Go)
A production-ready template for building Model Context Protocol (MCP) servers in Go, following official best practices and guidelines.
Features
- Complete MCP Implementation - Tools, Resources, and Prompts
- Production-Ready - Graceful shutdown, signal handling, and error handling
- Well-Tested - Unit and integration tests with examples
- Configurable - YAML-based configuration with validation
- Secure - Input validation, sanitization, and best practices
- Docker Support - Ready for containerized deployments
- Best Practices - Follows the official MCP implementation guide
Quick Start
Prerequisites
- Go 1.23 or higher
- Make (optional, for using Makefile commands)
Installation
-
Clone or use this template:
git clone <your-repo-url> cd mcp-server-template -
Install dependencies:
go mod download -
π¨ IMPORTANT: Clean up template examples
This template includes example tools, resources, and prompts. You should remove these before starting your project.
See
CLAUDE.mdfor detailed instructions on:- What files to remove
- How to clean up register functions
- How to update configuration
- How to customize CLAUDE.md for your project
Quick cleanup:
# Remove example implementations rm internal/tools/{search,calculate,analyze}.go rm internal/tools/{search,calculate,analyze}_test.go rm internal/resources/files.go internal/resources/files_test.go rm internal/prompts/greet.go internal/prompts/greet_test.go rm tests/integration/server_test.go tests/testdata/fixtures.json -
Configure the server:
# Edit configs/config.yaml to customize nano configs/config.yaml -
Build and run:
make build make serveOr directly:
go run ./cmd/server serve
Usage
This server provides two interfaces: MCP server mode for integration with MCP clients, and CLI tool mode for direct command-line execution.
As MCP Server
Run as an MCP server using stdio transport for integration with MCP clients (like Claude Desktop):
# Using make
make serve
# Or directly
./bin/server serve
The server will run in the foreground and communicate via stdin/stdout. Press Ctrl+C for graceful shutdown.
As CLI Tool
Execute tools directly from the command line:
# Get help
./bin/server --help
./bin/server --version
# Get help for a specific command
./bin/server search --help
# Execute tools (examples - replace with your actual tools)
./bin/server search --query "golang testing" --limit 5
./bin/server calculate --operation add --a 10 --b 20
# Different output formats
./bin/server search --query "golang" --output json
./bin/server search --query "golang" --output yaml
./bin/server search --query "golang" --output text # default
# Quiet mode (exit code only, no output)
./bin/server search --query "golang" --quiet
echo $? # Check exit code
Note: The example commands above assume you have implemented tools like search and calculate. Adjust the commands based on your actual tool implementations.
Configuration
Both MCP server mode and CLI tool mode use the same configuration file:
# Use default config (configs/config.yaml)
./bin/server serve
# Use custom config
./bin/server --config /path/to/config.yaml serve
./bin/server --config /path/to/config.yaml search --query "test"
Project Structure
mcp-server-template/
βββ cmd/
β βββ server/
β βββ main.go # Entry point with graceful shutdown
βββ internal/
β βββ tools/ # MCP tools (one per file)
β β βββ register.go # Tool registration
β β βββ search.go # Search tool
β β βββ search_test.go # Search tests (same package)
β β βββ calculate.go # Calculate tool
β β βββ calculate_test.go # Calculate tests
β β βββ analyze.go # Analyze tool
β β βββ analyze_test.go # Analyze tests
β βββ resources/ # MCP resources
β β βββ register.go # Resource registration
β β βββ files.go # File system resources
β β βββ files_test.go # File tests
β βββ prompts/ # MCP prompts
β β βββ register.go # Prompt registration
β β βββ greet.go # Greeting prompt
β β βββ greet_test.go # Greeting tests
β βββ config/ # Configuration management
β β βββ config.go # Config loading and validation
β β βββ config_test.go # Config tests
β βββ services/ # Business logic (add your services here)
βββ tests/
β βββ integration/ # Integration tests
β β βββ server_test.go # Full server tests
β βββ testdata/ # Test fixtures
β βββ fixtures.json
βββ configs/
β βββ config.yaml # Server configuration
βββ docs/
β βββ MCP_SERVER_IMPLEMENTATION_GUIDE.md # Complete implementation guide
βββ go.mod # Go module definition
βββ go.sum # Dependency checksums
βββ Makefile # Build automation
βββ Dockerfile # Container image
βββ README.md # This file
βββ CLAUDE.md # Instructions for Claude Code
Included Examples
Tools
- search - Search for information with configurable limits
- calculate - Perform arithmetic operations (add, subtract, multiply, divide)
- analyze - Analyze text using various methods (sentiment, keywords, summary)
Resources
- File System - Access local files via
file:///URIs
Prompts
- greet - Generate personalized greetings with different styles
Configuration
Edit configs/config.yaml:
server:
name: "your-server-name"
version: "1.0.0"
port: 8080
features:
enable_tools: true
enable_resources: true
enable_prompts: true
environment: "dev" # dev, staging, production
tools:
search_enabled: true
analyze_enabled: true
calculate_enabled: true
Using Environment Variables
For secrets and sensitive data, use environment variables:
# configs/config.yaml
database:
password: ${DB_PASSWORD}
api:
api_key: ${API_KEY}
Then set them before running:
export DB_PASSWORD="your-password"
export API_KEY="your-api-key"
./bin/server
Development
Running Tests
# All tests with coverage
make test
# Unit tests only
make test-unit
# Integration tests only
make test-integration
# Generate coverage report
make coverage
Building
# Build binary
make build
# Run locally
make run
# Clean build artifacts
make clean
Code Quality
# Format code
make fmt
# Run linters (requires golangci-lint)
make lint
Docker
# Build image
make docker-build
# Run container
make docker-run
Adding New Features
Adding a New Tool
- Create
internal/tools/mytool.go:
package tools
import (
"context"
"fmt"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type MyToolInput struct {
Query string `json:"query" jsonschema:"required,description=Your query"`
}
type MyToolOutput struct {
Result string `json:"result" jsonschema:"description=The result"`
}
func registerMyTool(server *mcp.Server) {
mcp.AddTool(server, &mcp.Tool{
Name: "mytool",
Description: "Description of what your tool does",
}, myToolHandler)
}
func myToolHandler(ctx context.Context, req *mcp.CallToolRequest, input MyToolInput) (
*mcp.CallToolResult, MyToolOutput, error,
) {
// Validate inputs
if input.Query == "" {
return nil, MyToolOutput{}, fmt.Errorf("query is required")
}
// Check context cancellation
select {
case <-ctx.Done():
return nil, MyToolOutput{}, ctx.Err()
default:
}
// Your implementation here
result := processQuery(input.Query)
return nil, MyToolOutput{Result: result}, nil
}
-
Create
internal/tools/mytool_test.go(in same package) -
Update
internal/tools/register.go:
func Register(server *mcp.Server, cfg *config.Config) {
// ...
registerMyTool(server)
}
- Add config option in
configs/config.yaml:
tools:
mytool_enabled: true
- Run tests:
make test
Adding Resources or Prompts
Follow the same pattern in internal/resources/ or internal/prompts/.
Testing
This template includes comprehensive tests:
- Unit Tests - Test individual functions and handlers
- Integration Tests - Test the full server with all features
- Table-Driven Tests - Easy to add new test cases
- Error Testing - Verify error handling
- Context Testing - Verify context cancellation
Run tests before committing:
make test
Deployment
Stdio Transport (Default)
The template uses stdio transport by default, suitable for:
- CLI tools
- Local integrations
- Subprocess communication
HTTP Transport
To use HTTP transport, modify cmd/server/main.go:
// Change from stdio to HTTP
handler := mcp.NewStreamableHTTPHandler(
func(r *http.Request) *mcp.Server { return server },
nil,
)
log.Fatal(http.ListenAndServe(":8080", handler))
Docker Deployment
# Build image
docker build -t your-server:latest .
# Run container (stdio)
docker run -i your-server:latest
# Run container (HTTP)
docker run -p 8080:8080 your-server:latest
Security Best Practices
This template follows security best practices:
- β Input validation on all tools
- β File path sanitization
- β Parameterized queries (when using databases)
- β Context cancellation support
- β Error wrapping with context
- β No hardcoded secrets
- β Non-root user in Docker
Always:
- Validate and sanitize all inputs
- Use parameterized queries for SQL
- Never commit secrets to version control
- Use environment variables for sensitive data
Customization
Renaming the Module
-
Update
go.mod:module your-module-name -
Update imports in all files:
import "your-module-name/internal/config" -
Run:
go mod tidy
Removing Example Features
To remove example tools/resources/prompts:
- Delete the corresponding files from
internal/ - Update
register.gofiles - Update
configs/config.yaml - Run tests to verify
Documentation
- Implementation Guide: See
docs/MCP_SERVER_IMPLEMENTATION_GUIDE.mdfor comprehensive guidelines - MCP Specification: https://modelcontextprotocol.io/specification
- Go SDK Documentation: https://pkg.go.dev/github.com/modelcontextprotocol/go-sdk
Contributing
Contributions are welcome! Please:
- Follow the existing code structure
- Add tests for new features
- Update documentation
- Run
make testandmake lintbefore submitting
Architecture Principles
This template follows strict architectural principles:
- ONE tool per file - Maintainability and clarity
- Register pattern - Centralized feature registration
- Unexported handlers - Clean public API
- Same-package unit tests - Access to internals
- Separate integration tests - End-to-end testing
- Configuration-driven - No hardcoded values
- Context-aware - Proper cancellation support
- Error wrapping - Complete error context
See CLAUDE.md for detailed architectural guidelines.
License
[Your License Here]
Support
For questions or issues:
- Check the implementation guide in
docs/ - Review example code in
internal/ - Open an issue on GitHub
Acknowledgments
Built following the official MCP Go SDK and implementation guidelines.
