Build an MCP Server in Go: Tools, Connections, and Tests

Go is a practical choice for an MCP server when you need a small binary, high concurrency, or integration with an existing Go codebase. This guide walks through building a focused Go MCP server, testing it, and recording the tool contracts your team depends on.

Updated 5 min read

Go is a reasonable choice for an MCP server when you want a small, self-contained binary, when you need to handle many concurrent connections efficiently, or when the server integrates with an existing Go codebase. The MCP specification does not require a specific language; a Go server that implements the protocol correctly connects to any compliant client.

Building in Go means using community libraries rather than an official SDK — the Model Context Protocol team publishes official SDKs for TypeScript and Python, but not yet for Go. Before starting, check the Go libraries available at modelcontextprotocol.io/sdks (opens in a new tab) and in the wider community for the current maintenance state. Tools like fenbs store the decision about which library to use and why, so the next person working on the server starts from the agreed choice.

Why Go for an MCP server

Go produces small, statically linked binaries with no runtime dependency. An MCP server that compiles to a single executable is easy to distribute, deploy into containers, and run on machines without a Node.js or Python installation.

Go's concurrency model handles many simultaneous tool calls efficiently. For a remote Streamable HTTP server that multiple team members connect to, Go's goroutines and standard library HTTP server are a natural fit.

The trade-off is maturity. The TypeScript and Python SDKs are maintained by the same team that writes the specification and track protocol changes closely. A Go community library may lag behind on protocol versions or optional capabilities. Verify the library's spec coverage before building production features on it. See mcp server frameworks for a broader comparison.

Choose a Go MCP library

Search for Go MCP libraries on GitHub and compare them by: the MCP protocol version they target, the transports they support (stdio and/or Streamable HTTP), how recently the repository was updated, and whether the maintainers respond to issues.

A library that supports both stdio and HTTP transports is more flexible. One that generates JSON Schema from Go types automatically saves you from writing schemas by hand. Check the README for examples of both tool registration and transport setup before committing to a library.

Once you have chosen a library, record the choice as a Decision in fenbs: the library name and version, the protocol version it targets, the date you evaluated it, and the alternatives you considered. That record saves the next person from repeating the evaluation.

Project setup and structure

Start with a standard Go module. Keep the MCP server in its own package or in main for a simple server. Separate the transport setup, the tool registration, and the business logic (the actual lookup or action the tool performs) into distinct parts, so each is testable independently.

Minimal Go MCP server structure
package main

import (
    "context"
    "fmt"
    // import your chosen MCP library here
)

func main() {
    // 1. Create a server instance
    // 2. Register tools
    // 3. Start the transport (stdio or HTTP)
}

// Tool handler: separate from transport setup
func lookupItem(ctx context.Context, id string) (string, error) {
    // replace with real lookup logic
    return fmt.Sprintf("Item %s: example data", id), nil
}

The exact API depends on the library you choose. Follow its documentation for creating the server instance and registering tools. The pattern above — separate handler functions, minimal main — applies to any library.

Define input schemas clearly

MCP tools describe their inputs as JSON Schema. Some Go libraries generate the schema from struct tags or function signatures automatically. Others expect you to provide the schema as a Go map or a raw JSON string.

Whichever approach the library uses, make sure each input parameter has a clear description. The AI client reads those descriptions when it decides what values to pass. A parameter labeled id with no description is much less useful than one labeled id: the unique identifier from the item lookup, e.g. "ORD-12345".

Also provide a description on the tool itself: what it does, when to call it, and what the output looks like. An AI that understands when to call your tool will call it correctly; one that is guessing may call it with wrong inputs or when a different tool would be more appropriate.

How fenbs helps

Record tool contracts where your team shares them

Add each tool's name, input parameters, expected output, and known error cases as a Decisions and rules entry in fenbs. When the tool contract changes — a new parameter, a renamed field, a changed error format — update the decision. Every AI assistant working on the server reads those decisions first and builds on the agreed contract.

Create a free account

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

Set up the transport

For a local server, use stdio transport. The client starts your compiled binary when it needs the server and communicates through the process's stdin and stdout. In your client's configuration, set command to the absolute path to the compiled binary.

For a remote server, use Streamable HTTP. The Go standard library's net/http package handles the HTTP side. Your MCP library wraps it. Start the HTTP listener on a specific port and configure the client to connect by URL.

For a stdio server, read environment variables from os.Getenv — do not hardcode credentials. For an HTTP server, credentials and configuration belong in environment variables or a config file that is not committed to version control.

Test with the MCP Inspector

The MCP Inspector, available from the modelcontextprotocol.io repository, is the fastest way to test a server without setting up a full AI client. It connects over stdio, lists the tools your server declares, lets you call them with specific inputs, and shows the raw JSON responses.

Run the Inspector before connecting to Claude or another client. Confirm that: your tool appears in the tool list with the correct name and description, calling it with valid inputs returns the expected result, and calling it with invalid inputs returns a clear isError: true response.

After the Inspector, test in the actual client. Ask the AI to use the tool by name with a specific known input. If it calls the tool with wrong parameters or not at all, revise the tool and parameter descriptions until it behaves correctly.

How to do this with fenbs

  1. Create a free account and set up a project for the Go MCP server work.
  2. Record the Go library choice and version as a Decisions and rules entry before writing any code. Include the alternatives you evaluated.
  3. Add each planned tool as a task with a plan: its name, inputs, expected output, and refusal cases.
  4. After the first working tool, add a lesson with what the library got right and what was harder than expected. Link it to the task.
  5. Connect your AI to fenbs over MCP from Integrations so it reads the current tool contracts and library decisions before working on the server code.

fenbs connects to AI clients over Streamable HTTP at https://fenbs.ai/api/mcp and is a working example of a remote MCP server. If the context you need to share is project tasks, decisions, and lessons rather than a custom internal tool, fenbs may be the right service to connect rather than one to build.

Questions people ask.

Is there an official Go SDK for MCP?

As of October 2026, the Model Context Protocol team publishes official SDKs for TypeScript and Python. Go is supported through community-maintained libraries. Check modelcontextprotocol.io/sdks and GitHub for current options, and verify the library's spec coverage and maintenance activity before choosing one.

What transport should a Go MCP server use?

Use stdio for a local server that individual developers run on their own machines. Use Streamable HTTP for a server that multiple clients connect to over a network. Go's standard library handles both well; check your chosen MCP library's documentation for the exact setup for each transport.

How do I pass credentials to a Go MCP server?

Use environment variables read with os.Getenv. For a stdio server, the client configuration's env block sets those variables when it starts the process. For an HTTP server, set them in the deployment environment. Never hardcode credentials in the source code or commit them to version control.

How do I test a Go MCP server without an AI client?

Use the MCP Inspector from the modelcontextprotocol.io repository. It connects over stdio, lists your tools, and lets you call them directly. Confirm that tools appear with correct descriptions, valid inputs return the expected result, and invalid inputs return a clear error before connecting to a real AI client.

Can a Go MCP server handle multiple clients simultaneously?

Yes, when using Streamable HTTP transport. Go's HTTP server and goroutine model handle concurrent connections efficiently. A stdio server runs once per client session as a child process, so each client gets its own instance rather than sharing one.

More in Connect your AI tools

All Connect your AI tools articles

Start with one thing.

Free for one person · No credit card · Works with Claude, ChatGPT, Cursor and more

There is nothing to set up first. Write one line and you’ve started.