mcp.md

MCP servers

Use the official Go SDK: github.com/modelcontextprotocol/go-sdk. Default to stdio for local agent use; choose Streamable HTTP only when the server needs networked clients or deployment behind an HTTP boundary.

MCP servers are still command-line binaries. Read cli.md alongside this file for Cobra/Fang setup, command ergonomics, and version-policy guidance.

Shape

cmd/<server>/main.go       # CLI entrypoint
cmd/<server>/serve.go      # serve command and transport flag
internal/config/config.go  # env and flag parsing
internal/server/server.go  # MCP implementation, transports, handlers
internal/server/tools.go   # typed tool parameter structs, split into tool-per-file if it gets unwieldy
internal/<client>/...      # API client being wrapped

Tools

  • Use typed parameter structs with JSON and jsonschema tags.
  • Add tool annotations: read-only/destructive/idempotent/open-world hints.
  • Make descriptions operational: what the tool does, when to use it, and any required prerequisite tool.
  • Return structured errors for real failures; use MCP IsError for tool-level domain errors the model should see.
  • Clamp or validate bounds at the boundary and document whether clamping is silent or an error.

If the wrapped API has sharp edges, add a usage/instructions tool documenting them.

Config

  • Required connection info comes from env vars and/or explicit flags.
  • Validate URLs and auth shape before starting the server.
  • Allow separate auth layers when real deployments need them, but document how headers/cookies interact.

Release

MCP servers are usually plain static binaries. Use CGO_ENABLED=0 unless a dependency requires CGO. Add nFPM only when system installation, services, or managed config files are part of the product (seldom).

Prefer the static build shape from mise.md: netgo, osusergo, optional project-specific static_build, -d -s -w -buildid= -extldflags=-static, and explicit version injection when the server exposes --version or embeds version metadata. Do not rely on Fang's CLI fallback alone for MCP implementation metadata; use the same project-owned version value anywhere the server reports it. Remove those static-only pieces when the wrapped API client or storage layer requires CGO.