Python and TypeScript get most of the MCP tutorials, but Go quietly became the language you reach for when a server has to ship as one binary and take real traffic. The official modelcontextprotocol/go-sdk — maintained in collaboration with Google, and one of the four Tier 1 SDKs with a beta for the 2026-07-28 spec — makes that path short. Here's the minimal, production-shaped version.
Why Go for an MCP server
A Go server compiles to a single static binary with no runtime to install, starts in milliseconds, and handles concurrent tool calls natively through goroutines. That matters the moment your server moves off a laptop: there's no node_modules, no virtualenv, no cold-start penalty, and the container image is tiny. For a tool that a fleet of agents hammers in parallel, those properties stop being nice-to-haves.
Install
The SDK lives at github.com/modelcontextprotocol/go-sdk. Add it to a fresh module:
go mod init weather-mcp
go get github.com/modelcontextprotocol/go-sdk/mcp
The server
The shape mirrors the other SDKs: create a server, register a tool with a typed handler, and run it over a transport. The win is that Go structs generate the JSON schema for you — no hand-written parameter definitions to drift out of sync.
package main
import (
"context"
"github.com/modelcontextprotocol/go-sdk/mcp"
)
type Args struct {
City string `json:"city" jsonschema:"the city to look up"`
}
func GetWeather(ctx context.Context, req *mcp.CallToolRequest, args Args) (*mcp.CallToolResult, any, error) {
text := args.City + ": 18°C, partly cloudy"
return &mcp.CallToolResult{Content: []mcp.Content{&mcp.TextContent{Text: text}}}, nil, nil
}
func main() {
server := mcp.NewServer(&mcp.Implementation{Name: "weather-mcp", Version: "0.1.0"}, nil)
mcp.AddTool(server, &mcp.Tool{Name: "get_weather", Description: "Current weather for a city"}, GetWeather)
server.Run(context.Background(), &mcp.StdioTransport{})
}
Build and test
go build -o weather-mcp .
npx @modelcontextprotocol/inspector ./weather-mcp
The inspector opens a browser UI; list tools, call get_weather with {"city":"Berlin"}, and confirm the response before you wire it into a host. Then point Claude Desktop at the compiled binary — "command": "/absolute/path/to/weather-mcp" with no args — restart, and the tool appears under the hammer icon.
stdio now, HTTP when you need it
The official SDK ships stdio and command transports out of the box, which is all a local server needs. When you outgrow that and want a remote endpoint, upgrading the SDK does not by itself change what the server speaks over the wire — serving the stateless 2026-07-28 revision is an explicit choice you make when you wire up the HTTP transport. If you need HTTP and SSE today, the community mark3labs/mcp-go is the well-trodden alternative; we compare the two in official Go SDK vs mark3labs/mcp-go.
Where to go next
The concepts are identical across languages, so the Python tutorial and Node.js version transfer cleanly if you switch stacks. Decide stdio versus HTTP with transports compared, understand the stateless shift in the 2026-07-28 spec changes, then publish your server to the registry. For live examples of well-built servers, browse the GitHub and filesystem entries — curated, categorised and vetted so you can copy patterns that already work.