MM

mark3labs/mcp-go

Developer tools
8.9천 stars 0 forks 품질 99 트렌드 99

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:

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 Total to indicate the total number of available matches
  • Use HasMore to signal if additional results exist beyond the returned values
View this README on GitHub

설치

This server does not publish a one-line install command.

Open the repository installation guide