The Model Context Protocol (MCP) is quickly becoming the connective tissue between AI agents, developer tools, and internal automation.

But if you're building MCP servers in Go today, you'll notice something familiar: you're handed a protocol SDK — and then you're on your own.

That's fine for experimentation. It breaks down quickly in production.

This post explains why MCP needs a real Go framework, how SDKs and frameworks differ, and why we built mcp-go.


MCP SDKs are necessary — but insufficient

SDKs do an important job:

  • enforce protocol correctness
  • track spec changes
  • expose low-level primitives

That's exactly what they should do.

But SDKs intentionally do not:

  • define application structure
  • enforce input validation
  • provide middleware
  • offer production defaults
  • optimize for developer experience

If you've used Go long enough, this pattern is familiar.


The HTTP analogy everyone understands

Go already solved this once.

  • net/http gives you correctness and control
  • frameworks like Gin give you structure, ergonomics, and safety

Nobody argues that Gin "competes" with net/http. They live at different layers.

MCP is no different.


The real problem: production MCP servers

Once you move beyond demos, every MCP server needs the same things:

  • typed inputs
  • validation before business logic
  • consistent error handling
  • middleware (auth, timeouts, logging, rate limits)
  • multiple transports (stdio for agents, HTTP for services)
  • predictable defaults

Without a framework, every team rebuilds this themselves.

That's wasted effort — and inconsistent outcomes.


Enter mcp-go

mcp-go is a Go framework for building MCP servers, designed the same way Gin was designed for HTTP.

What it focuses on:

  • typed handlers
  • automatic JSON Schema generation
  • first-class middleware
  • multiple transports from the same server
  • boring, production-safe defaults

What it intentionally avoids:

  • agent logic
  • LLM abstractions
  • "magic"
  • protocol reinvention

If the MCP SDK is the kernel, mcp-go is the runtime.


A concrete example

Instead of manually decoding maps and validating input, you write:

srv.Tool("search").
    Input(SearchInput{}).
    Handler(func(ctx context.Context, in SearchInput) (any, error) {
        return svc.Search(ctx, in.Query, in.Limit)
    })

Schema generation, validation, and error mapping happen automatically.

This is not about saving keystrokes. It's about making the correct thing the easy thing.


SDKs, community libraries, and frameworks can coexist

The MCP ecosystem doesn't need "one library to rule them all".

It needs:

  • a protocol SDK for correctness
  • community SDKs for flexibility
  • a framework for building real systems

That's where mcp-go fits.


Who mcp-go is for

  • Go platform and infra teams
  • AI tooling and automation services
  • OSS authors building on MCP
  • anyone deploying MCP servers in production

If you just want raw protocol access, an SDK is perfect. If you want structure and safety, you want a framework.


Closing

Frameworks don't replace SDKs. They unlock adoption.

That's why we built mcp-go — and why we think MCP in Go needs one.

View mcp-go on GitHub →