A Go implementation of the Model Context Protocol (MCP), enabling seamless integration between LLM applications and external data sources and tools.
概览
A Go implementation of the Model Context Protocol (MCP), enabling seamless integration between LLM applications and external data sources and tools. MCP Go handles all the complex protocol details and server management, so you can focus on building great tools. It aims to be high-level and easy to use. * : High-level interface means less code and faster development * : Build MCP servers with minimal boilerplate * ***: MCP Go aims to provide a full implementation of the core MCP specification 🚨 🚧 🏗️ MCP Go is under active development, as is the MCP specification itself. Core features are working but some advanced capabilities are still in progress. Let's create a simple MCP server that exposes a calculator tool and some data: The Model Context Protocol (MCP) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions.
README
package main
import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Create a new MCP server
s := server.NewMCPServer(
"Demo 🚀",
"1.0.0",
server.WithToolCapabilities(false),
)
// Add tool
tool := mcp.NewTool("hello_world",
mcp.WithDescription("Say hello to someone"),
mcp.WithString("name",
mcp.Required(),
mcp.Description("Name of the person to greet"),
),
)
// Add tool handler
s.AddTool(tool, helloHandler)
// Start the stdio server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
func helloHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
name, err := request.RequireString("name")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
return mcp.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
}
That’s it!
MCP Go handles all the complex protocol details and server management, so you can focus on building great tools. It aims to be high-level and easy to use.
Key features:
- Fast: High-level interface means less code and faster development
- Simple: Build MCP servers with minimal boilerplate
- Complete*: MCP Go aims to provide a full implementation of the core MCP specification
(*emphasis on aims)
🚨 🚧 🏗️ MCP Go is under active development, as is the MCP specification itself. Core features are working but some advanced capabilities are still in progress.
Table of Contents
Installation
go get github.com/mark3labs/mcp-go
Quickstart
Let’s create a simple MCP server that exposes a calculator tool and some data:
package main
import (
"context"
"fmt"
"github.com/mark3labs/mcp-go/mcp"
"github.com/mark3labs/mcp-go/server"
)
func main() {
// Create a new MCP server
s := server.NewMCPServer(
"Calculator Demo",
"1.0.0",
server.WithToolCapabilities(false),
server.WithRecovery(),
)
// Add a calculator tool
calculatorTool := mcp.NewTool("calculate",
mcp.WithDescription("Perform basic arithmetic operations"),
mcp.WithString("operation",
mcp.Required(),
mcp.Description("The operation to perform (add, subtract, multiply, divide)"),
mcp.Enum("add", "subtract", "multiply", "divide"),
),
mcp.WithNumber("x",
mcp.Required(),
mcp.Description("First number"),
),
mcp.WithNumber("y",
mcp.Required(),
mcp.Description("Second number"),
),
)
// Add the calculator handler
s.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) {
// Using helper functions for type-safe argument access
op, err := request.RequireString("operation")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
x, err := request.RequireFloat("x")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
y, err := request.RequireFloat("y")
if err != nil {
return mcp.NewToolResultError(err.Error()), nil
}
var result float64
switch op {
case "add":
result = x + y
case "subtract":
result = x - y
case "multiply":
result = x * y
case "divide":
if y == 0 {
return mcp.NewToolResultError("cannot divide by zero"), nil
}
result = x / y
}
return mcp.NewToolResultText(fmt.Sprintf("%.2f", result)), nil
})
// Start the server
if err := server.ServeStdio(s); err != nil {
fmt.Printf("Server error: %v\n", err)
}
}
What is MCP?
The Model Context Protocol (MCP) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions.
MCP servers can:
- Expose data through Resources (think of these sort of like GET endpoints; they are used to load information into the LLM’s context)
- Provide functionality through Tools (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
- Define interaction patterns through Prompts (reusable templates for LLM interactions)
- And more!
mcp-go implements the Model Context Protocol specification version 2025-11-25, with backward compatibility for versions 2025-06-18, 2025-03-26, and 2024-11-05.
Core Concepts
Server
Resources
Tools
Prompts
Examples
For examples, see the examples/ directory.
Key examples include:
examples/task_tool/- Demonstrates task-augmented tools with TaskSupportRequired and TaskSupportOptional modesexamples/structured_input_and_output/- Shows how to use struct-based input/output schemas with type-safe tool handlersexamples/typed_tools/- Demonstrates type-safe tool handlers with strongly-typed argumentsexamples/custom_context/- Shows how to use custom contexts in tool handlers- Additional examples covering resources, prompts, and more in the examples directory
Extras
Transports
MCP-Go supports stdio, SSE and streamable-HTTP transport layers. For SSE transport, you can use SetConnectionLostHandler() to detect and handle disconnections for implementing reconnection logic.
Embedding StreamableHTTP in non-net/http frameworks
StreamableHTTPServer is an http.Handler, so it can be mounted in any
router that speaks net/http. To embed it in a framework that does not
go through net/http (e.g. fasthttp
or fiber) without buffering the response through an
adaptor, use the transport-agnostic Handle entry point:
func (s *StreamableHTTPServer) Handle(w HTTPResponseWriter, r *HTTPRequest)
HTTPRequest is a plain struct (Method, URL, Header, Body,
Context) and HTTPResponseWriter is a small interface (Header,
WriteHeader, Write, Flush, CanStream). Implementations whose
underlying transport cannot stream MUST return false from CanStream;
the server will then reject GET (SSE listening) with 405 Method Not Allowed and keep POST responses as buffered application/json instead of
upgrading to text/event-stream.
See the HTTP transport docs
for a full fasthttp/fiber adapter example. ServeHTTP is unchanged and
remains the conventional net/http entry point.
OAuth Protected Resource Metadata
Servers that require OAuth can advertise their authorization requirements
via the RFC 9728
/.well-known/oauth-protected-resource endpoint referenced by the
MCP authorization spec.
Use server.WithProtectedResourceMetadata (or
server.WithSSEProtectedResourceMetadata) to auto-mount the endpoint, or
server.NewProtectedResourceMetadataHandler to wire it into a custom router.
See the HTTP transport docs for examples.
httpServer := server.NewStreamableHTTPServer(mcpServer,
server.WithProtectedResourceMetadata(server.ProtectedResourceMetadataConfig{
Resource: "https://my-mcp-server.com",
AuthorizationServers: []string{"https://auth.example.com"},
ScopesSupported: []string{"mcp:read", "mcp:write"},
}),
)
CORS for browser-based clients
Servers exposed to browser-based MCP clients can opt into Cross-Origin
Resource Sharing handling on either HTTP transport. CORS is disabled by
default; configure it explicitly via server.WithStreamableHTTPCORS or
server.WithSSECORS:
httpServer := server.NewStreamableHTTPServer(mcpServer,
server.WithEndpointPath("/mcp"),
server.WithStreamableHTTPCORS(
server.WithCORSAllowedOrigins("https://my-ai-app.com", "http://localhost:3000"),
server.WithCORSAllowCredentials(),
server.WithCORSMaxAge(300),
),
)
The transport answers preflight (OPTIONS) requests directly and decorates
simple responses with the appropriate Access-Control-Allow-Origin,
Access-Control-Allow-Credentials, Access-Control-Expose-Headers and
Vary headers. Sensible defaults are used when the corresponding option is
omitted (GET, POST, DELETE, OPTIONS for methods; Content-Type, Mcp-Session-Id, Last-Event-ID, Authorization for request headers;
Mcp-Session-Id for exposed headers). Combining WithCORSAllowedOrigins("*")
with WithCORSAllowCredentials() echoes the request Origin to remain
spec-compliant.
Session Management
MCP-Go provides a robust session management system that allows you to:
- Maintain separate state for each connected client
- Register and track client sessions
- Send notifications to specific clients
- Provide per-session tool customization
Request Hooks
Hook into the request lifecycle by creating a Hooks object with your
selection among the possible callbacks. This enables telemetry across all
functionality, and observability of various facts, for example the ability
to count improperly-formatted requests, or to log the agent identity during
initialization.
Add the Hooks to the server at the time of creation using the
server.WithHooks option.
Tool Handler Middleware
Add middleware to tool call handlers using the server.WithToolHandlerMiddleware option. Middlewares can be registered on server creation and are applied on every tool call.
A recovery middleware option is available to recover from panics in a tool call and can be added to the server with the server.WithRecovery option.
Prompt Handler Middleware
Add middleware to prompt handlers using the server.WithPromptHandlerMiddleware option. Middlewares can be registered on server creation and are applied on every prompts/get call.
Prompt Filtering
Filter prompts based on context using the server.WithPromptFilter option. This works the same way as tool filtering but applies to prompts/list results.
Regenerating Server Code
Server hooks and request handlers are generated. Regenerate them by running:
go generate ./...
You need go installed and the goimports tool available. The generator runs
goimports automatically to format and fix imports.
Auto-completions
When users are filling in argument values for a specific prompt (identified by name) or resource template (identified by URI), servers can provide contextual suggestions.
To enable completion support, use the server.WithCompletions() option when creating your server.
Completion Providers
You can provide completion logic for both prompt arguments and resource template arguments by implementing the respective interfaces and passing them to the server as options.
Completion Context
For prompts or resource templates with multiple arguments, the CompleteContext parameter provides access to previously completed arguments. This allows you to provide contextual suggestions based on earlier choices.
Response Constraints
When returning completion results:
- Maximum 100 items per response
- Use
Totalto indicate the total number of available matches - Use
HasMoreto signal if additional results exist beyond the returned values
安装
This server does not publish a one-line install command.
Open the repository installation guide