A feature-complete Model Context Protocol (MCP) server template in Go using the official go-sdk. This starter demonstrates all major MCP features with clean, idiomatic Go code.
| Category | Feature | Description |
|---|---|---|
| Tools | hello |
Basic tool with annotations |
get_weather |
Tool returning structured data | |
ask_llm |
Tool that invokes LLM sampling | |
long_task |
Tool with 5-second progress updates | |
load_bonus_tool |
Dynamically loads a new tool | |
| Resources | info://about |
Static informational resource |
file://example.md |
File-based markdown resource | |
| Templates | greeting://{name} |
Personalized greeting |
data://items/{id} |
Data lookup by ID | |
| Prompts | greet |
Greeting in various styles |
code_review |
Code review with focus areas |
- Go 1.22+
- (Optional) air for live reload
- (Optional) golangci-lint for linting
# Clone the repository
git clone https://github.com/SamMorrowDrums/mcp-go-starter.git
cd mcp-go-starter
# Download dependencies
go mod downloadstdio transport (for local development):
go run ./cmd/stdio
# Or: make run-stdioHTTP transport (for remote/web deployment):
go run ./cmd/http
# Or: make run-http
# Server runs on http://localhost:3000make build
# Creates bin/stdio and bin/httpThis project includes VS Code configuration for seamless development:
- Open the project in VS Code
- The MCP configuration is in
.vscode/mcp.json - Build with
Ctrl+Shift+B(orCmd+Shift+Bon Mac) - Test the server using VS Code's MCP tools
- Install the Dev Containers extension
- Open command palette: "Dev Containers: Reopen in Container"
- Everything is pre-configured and ready to use!
.
βββ cmd/
β βββ stdio/
β β βββ main.go # stdio transport entrypoint
β βββ http/
β βββ main.go # HTTP transport entrypoint
βββ internal/
β βββ server/
β βββ server.go # Server orchestration
β βββ tools.go # Tool definitions (hello, get_weather, etc.)
β βββ resources.go # Resource and template definitions
β βββ prompts.go # Prompt definitions
βββ .vscode/
β βββ mcp.json # MCP server configuration
β βββ tasks.json # Build/run tasks
β βββ extensions.json
βββ .devcontainer/
β βββ devcontainer.json
βββ .air.toml # Live reload configuration
βββ .golangci.yml # Linter configuration
βββ go.mod
βββ Makefile
βββ README.md
# Development with live reload (recommended)
make dev
# Requires air: go install github.com/air-verse/air@latest
# Run without live reload
make run-stdio
# Run tests
make test
# Format code
make fmt
# Lint code
make lint
# Install all dev tools
make install-tools
# Clean build artifacts
make cleanInstall air for automatic rebuilds:
go install github.com/air-verse/air@latest
make devChanges to any .go file will automatically rebuild and restart the server.
The MCP Inspector is an essential development tool for testing and debugging MCP servers.
npx @modelcontextprotocol/inspector -- go run ./cmd/stdio/main.go- Tools Tab: List and invoke all registered tools with parameters
- Resources Tab: Browse and read resources and templates
- Prompts Tab: View and test prompt templates
- Logs Tab: See JSON-RPC messages between client and server
- Schema Validation: Verify tool input/output schemas
- Start Inspector before connecting your IDE/client
- Use the "Logs" tab to see exact request/response payloads
- Test tool annotations (ToolAnnotations) are exposed correctly
- Verify progress notifications appear for
long_task - Check that sampling works with
ask_llm
mcp.AddTool(server, &mcp.Tool{
Name: "hello",
Title: "Say Hello",
Description: "A friendly greeting tool",
Annotations: &mcp.ToolAnnotations{
ReadOnlyHint: ptr(true),
},
}, helloHandler)
func helloHandler(ctx context.Context, req *mcp.CallToolRequest, input helloInput) (*mcp.CallToolResult, any, error) {
return &mcp.CallToolResult{
Content: []mcp.Content{
&mcp.TextContent{Text: fmt.Sprintf("Hello, %s!", input.Name)},
},
}, nil, nil
}server.AddResourceTemplate(&mcp.ResourceTemplate{
Name: "Personalized Greeting",
URITemplate: "greeting://{name}",
MIMEType: "text/plain",
}, greetingHandler)func longTaskHandler(ctx context.Context, req *mcp.CallToolRequest, input longTaskInput) (*mcp.CallToolResult, any, error) {
progressToken := req.Params.GetProgressToken()
for i := 0; i < 5; i++ {
req.Session.NotifyProgress(ctx, &mcp.ProgressNotificationParams{
ProgressToken: progressToken,
Progress: float64(i) / 5.0,
Total: 1.0,
})
time.Sleep(time.Second)
}
return &mcp.CallToolResult{
Content: []mcp.Content{&mcp.TextContent{Text: "Done!"}},
}, nil, nil
}result, err := req.Session.CreateMessage(ctx, &mcp.CreateMessageParams{
Messages: []*mcp.SamplingMessage{
{Role: "user", Content: &mcp.TextContent{Text: prompt}},
},
MaxTokens: 100,
})Copy .env.example to .env and configure:
cp .env.example .env| Variable | Description | Default |
|---|---|---|
PORT |
HTTP server port | 3000 |
Contributions welcome! Please ensure your changes maintain feature parity with other language starters.
MIT License - see LICENSE for details.