Skip to content

voocel/mcp-sdk-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

54 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MCP Go SDK

An elegant and efficient Go implementation of the Model Context Protocol (MCP)

English 中文

License Go Reference Go Report Card Build Status

Build Smarter Applications, Connect Powerful Models Easily integrate large language model capabilities with MCP Go SDK

Introduction

MCP Go SDK is a Go implementation of the Model Context Protocol, fully supporting the latest MCP 2025-06-18 specification, while maintaining backward compatibility with MCP 2025-03-26 and MCP 2024-11-05.

Core Features

  • Fully MCP Compliant - Supports latest MCP 2025-06-18 spec, backward compatible with 2025-03-26, 2024-11-05
  • Elegant Architecture - Client/Server + Session pattern, high cohesion and low coupling
  • Server SDK - Quickly build MCP servers with tools, resources, and prompt templates
  • Client SDK - Complete client implementation for connecting to any MCP-compatible server
  • Multiple Transport Protocols - STDIO (recommended), Streamable HTTP (latest), SSE (backward compatible)
  • Multi-Session Support - Both Server and Client can manage multiple concurrent connections
  • High Performance - Concurrency-safe with optimized message processing
  • Security Protection - Built-in input validation, path traversal protection, resource limits

MCP Protocol Version Support

This SDK tracks and supports the latest developments in the MCP protocol, ensuring compatibility with the ecosystem:

Supported Versions

Version Release Date Key Features Support Status
2025-06-18 June 2025 Structured tool output, tool annotations, Elicitation user interaction, Sampling LLM inference Fully Supported
2025-03-26 March 2025 OAuth 2.1 authorization, Streamable HTTP, JSON-RPC batching Fully Supported
2024-11-05 November 2024 HTTP+SSE transport, basic tools and resources Fully Supported

Latest Features (2025-06-18)

  • Structured Tool Output: Tools can return typed JSON data for programmatic processing
  • Tool Annotations: Describe tool behavior characteristics (read-only, destructive, caching strategy, etc.)
  • User Interaction Requests: Tools can proactively request user input or confirmation
  • Resource Links: Support for associations and references between resources
  • Protocol Version Header: HTTP transport requires MCP-Protocol-Version header
  • Extended Metadata (_meta): Add custom metadata to tools, resources, and prompts

Major Change History

2025-03-26 → 2025-06-18:

  • Added structured tool output support
  • Enhanced tool annotation system
  • Added user interaction request mechanism
  • Support for resource linking functionality
  • Added _meta field for extended metadata

2024-11-05 → 2025-03-26:

  • Introduced OAuth 2.1 authorization framework
  • Replaced HTTP+SSE with Streamable HTTP
  • Added JSON-RPC batching support
  • Added audio content type support

Installation

go get github.com/voocel/mcp-sdk-go

Quick Start

Server Side - STDIO Transport (Recommended)

The simplest way is to use STDIO transport, suitable for command-line tools and Claude Desktop integration:

package main

import (
    "context"
    "fmt"
    "log"

    "github.com/voocel/mcp-sdk-go/protocol"
    "github.com/voocel/mcp-sdk-go/server"
    "github.com/voocel/mcp-sdk-go/transport/stdio"
)

func main() {
    ctx := context.Background()

    // Create MCP server
    mcpServer := server.NewServer(&protocol.ServerInfo{
        Name:    "Quick Start Server",
        Version: "1.0.0",
    }, nil)

    // Register a simple greeting tool
    mcpServer.AddTool(
        &protocol.Tool{
            Name:        "greet",
            Description: "Greet the user",
            InputSchema: map[string]interface{}{
                "type": "object",
                "properties": map[string]interface{}{
                    "name": map[string]interface{}{
                        "type":        "string",
                        "description": "User name",
                    },
                },
                "required": []string{"name"},
            },
        },
        func(ctx context.Context, req *server.CallToolRequest) (*protocol.CallToolResult, error) {
            name := req.Params.Arguments["name"].(string)
            greeting := fmt.Sprintf("Hello, %s! Welcome to MCP Go SDK!", name)
            return protocol.NewToolResultText(greeting), nil
        },
    )

    // Run server with STDIO transport
    if err := mcpServer.Run(ctx, &stdio.StdioTransport{}); err != nil {
        log.Fatal(err)
    }
}

Server Side - HTTP Transport

Build web services using Streamable HTTP transport:

package main

import (
    "context"
    "log"
    "net/http"

    "github.com/voocel/mcp-sdk-go/protocol"
    "github.com/voocel/mcp-sdk-go/server"
    "github.com/voocel/mcp-sdk-go/transport/streamable"
)

func main() {
    // Create MCP server
    mcpServer := server.NewServer(&protocol.ServerInfo{
        Name:    "HTTP Server",
        Version: "1.0.0",
    }, nil)

    // Register tools...
    mcpServer.AddTool(...)

    // Create HTTP handler
    handler := streamable.NewHTTPHandler(func(*http.Request) *server.Server {
        return mcpServer
    })

    // Start HTTP server
    log.Println("Server started at http://localhost:8081")
    if err := http.ListenAndServe(":8081", handler); err != nil {
        log.Fatal(err)
    }
}

Client Side - Connect to MCP Server

package main

import (
    "context"
    "fmt"
    "log"
    "os/exec"

    "github.com/voocel/mcp-sdk-go/client"
    "github.com/voocel/mcp-sdk-go/protocol"
)

func main() {
    ctx := context.Background()

    // Create client
    mcpClient := client.NewClient(&client.ClientInfo{
        Name:    "Demo Client",
        Version: "1.0.0",
    }, nil)

    // Connect to server via STDIO (launch subprocess)
    transport := client.NewCommandTransport(exec.Command("./server"))
    session, err := mcpClient.Connect(ctx, transport, nil)
    if err != nil {
        log.Fatalf("Connection failed: %v", err)
    }
    defer session.Close()

    fmt.Printf("Connected successfully! Server: %s v%s\n",
        session.ServerInfo().Name, session.ServerInfo().Version)

    // List available tools
    tools, err := session.ListTools(ctx, nil)
    if err != nil {
        log.Fatalf("Failed to list tools: %v", err)
    }

    for _, tool := range tools.Tools {
        fmt.Printf("Tool: %s - %s\n", tool.Name, tool.Description)
    }

    // Call tool
    result, err := session.CallTool(ctx, &protocol.CallToolParams{
        Name: "greet",
        Arguments: map[string]interface{}{
            "name": "Go Developer",
        },
    })
    if err != nil {
        log.Fatalf("Failed to call tool: %v", err)
    }

    if len(result.Content) > 0 {
        if textContent, ok := result.Content[0].(protocol.TextContent); ok {
            fmt.Printf("Result: %s\n", textContent.Text)
        }
    }

    // Read resource
    resource, err := session.ReadResource(ctx, &protocol.ReadResourceParams{
        URI: "info://server",
    })
    if err != nil {
        log.Fatalf("Failed to read resource: %v", err)
    }

    if len(resource.Contents) > 0 {
        fmt.Printf("Server info: %s\n", resource.Contents[0].Text)
    }
}

Example Projects

Example Description Transport Features
Basic Complete comprehensive example STDIO All core features + client
Calculator Math calculator service STDIO Tools, resources
SSE Demo SSE transport demo SSE SSE transport
Chatbot Chatbot service SSE Conversational interaction
File Server File operation service SSE File operations
Streamable Demo Streamable HTTP demo Streamable HTTP Streaming transport

Recommended to start with Basic example: Complete demonstration of all core features, including server and client implementations.

How to run:

# Server
cd examples/basic && go run main.go

# Client
cd examples/basic/client && go run main.go

Core Architecture

Server Side API

// Create MCP server
mcpServer := server.NewServer(&protocol.ServerInfo{
    Name:    "My Server",
    Version: "1.0.0",
}, nil)

// Register tool
mcpServer.AddTool(
    &protocol.Tool{
        Name:        "greet",
        Description: "Greet the user",
        InputSchema: map[string]interface{}{
            "type": "object",
            "properties": map[string]interface{}{
                "name": map[string]interface{}{
                    "type":        "string",
                    "description": "User name",
                },
            },
            "required": []string{"name"},
        },
    },
    func(ctx context.Context, req *server.CallToolRequest) (*protocol.CallToolResult, error) {
        name := req.Params.Arguments["name"].(string)
        return protocol.NewToolResultText(fmt.Sprintf("Hello, %s!", name)), nil
    },
)

// Register resource
mcpServer.AddResource(
    &protocol.Resource{
        URI:         "info://server",
        Name:        "Server Info",
        Description: "Get basic server information",
        MimeType:    "text/plain",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        contents := protocol.NewTextResourceContents("info://server", "Server information content")
        return protocol.NewReadResourceResult(contents), nil
    },
)

// Register resource template
mcpServer.AddResourceTemplate(
    &protocol.ResourceTemplate{
        URITemplate: "log://app/{date}",
        Name:        "Application Logs",
        Description: "Get application logs for a specific date",
        MimeType:    "text/plain",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        // Extract parameters from URI
        date := extractDateFromURI(req.Params.URI)
        contents := protocol.NewTextResourceContents(req.Params.URI, fmt.Sprintf("Log content: %s", date))
        return protocol.NewReadResourceResult(contents), nil
    },
)

// Register prompt template
mcpServer.AddPrompt(
    &protocol.Prompt{
        Name:        "code_review",
        Description: "Code review prompt",
        Arguments: []protocol.PromptArgument{
            {Name: "language", Description: "Programming language", Required: true},
            {Name: "code", Description: "Code content", Required: true},
        },
    },
    func(ctx context.Context, req *server.GetPromptRequest) (*protocol.GetPromptResult, error) {
        language := req.Params.Arguments["language"]
        code := req.Params.Arguments["code"]

        messages := []protocol.PromptMessage{
            protocol.NewPromptMessage(protocol.RoleUser,
                protocol.NewTextContent(fmt.Sprintf("Please review this %s code:\n%s", language, code))),
        }
        return protocol.NewGetPromptResult("Code Review", messages...), nil
    },
)

// Run server (STDIO)
if err := mcpServer.Run(ctx, &stdio.StdioTransport{}); err != nil {
    log.Fatal(err)
}

// Or use HTTP transport
handler := streamable.NewHTTPHandler(func(r *http.Request) *server.Server {
    return mcpServer
})
http.ListenAndServe(":8081", handler)

Client Side API

// Create client
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "My Client",
    Version: "1.0.0",
}, nil)

// Connect via STDIO (launch subprocess)
transport := client.NewCommandTransport(exec.Command("./server"))
session, err := mcpClient.Connect(ctx, transport, nil)
if err != nil {
    log.Fatal(err)
}
defer session.Close()

// List tools
tools, err := session.ListTools(ctx, nil)
for _, tool := range tools.Tools {
    fmt.Printf("Tool: %s\n", tool.Name)
}

// Call tool
result, err := session.CallTool(ctx, &protocol.CallToolParams{
    Name:      "greet",
    Arguments: map[string]interface{}{"name": "World"},
})

// List resources
resources, err := session.ListResources(ctx, nil)
for _, res := range resources.Resources {
    fmt.Printf("Resource: %s\n", res.URI)
}

// Read resource
resource, err := session.ReadResource(ctx, &protocol.ReadResourceParams{
    URI: "info://server",
})

// Get prompt
prompt, err := session.GetPrompt(ctx, &protocol.GetPromptParams{
    Name: "code_review",
    Arguments: map[string]string{
        "language": "Go",
        "code":     "func main() { ... }",
    },
})

Advanced Features

Resource Templates

// Server side: register resource template
mcpServer.AddResourceTemplate(
    &protocol.ResourceTemplate{
        URITemplate: "log://app/{date}",
        Name:        "Application Logs",
        Description: "Get application logs for a specific date",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        // Handle dynamic resource request
        return protocol.NewReadResourceResult(contents), nil
    },
)

// Client side: list resource templates
templates, err := session.ListResourceTemplates(ctx, nil)
for _, tpl := range templates.ResourceTemplates {
    fmt.Printf("Template: %s\n", tpl.URITemplate)
}

// Read specific resource
resource, err := session.ReadResource(ctx, &protocol.ReadResourceParams{
    URI: "log://app/2025-01-15",
})

Roots Management

// Client side: set roots
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "Client",
    Version: "1.0.0",
}, &client.ClientOptions{
    Roots: []*protocol.Root{
        protocol.NewRoot("file:///home/user/projects", "Projects Directory"),
        protocol.NewRoot("file:///home/user/documents", "Documents Directory"),
    },
})

// Server side: request client roots list
// Note: Must be called within ServerSession
rootsList, err := session.ListRoots(ctx)
for _, root := range rootsList.Roots {
    fmt.Printf("Root: %s - %s\n", root.URI, root.Name)
}

Sampling (LLM Inference)

// Client side: set Sampling handler
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "Client",
    Version: "1.0.0",
}, &client.ClientOptions{
    SamplingHandler: func(ctx context.Context, req *protocol.CreateMessageRequest) (*protocol.CreateMessageResult, error) {
        // Call actual LLM API
        response := callLLMAPI(req.Messages)
        return protocol.NewCreateMessageResult(
            protocol.RoleAssistant,
            protocol.NewTextContent(response),
            "gpt-4",
            protocol.StopReasonEndTurn,
        ), nil
    },
})

// Server side: initiate Sampling request
// Note: Must be called within ServerSession
result, err := session.CreateMessage(ctx, &protocol.CreateMessageRequest{
    Messages: []protocol.SamplingMessage{
        {Role: protocol.RoleUser, Content: protocol.NewTextContent("Calculate 2+2")},
    },
    MaxTokens: 100,
})

Transport Protocols

Fully compliant with MCP 2025-06-18 specification, backward compatible with MCP 2025-03-26, 2024-11-05

Supported Transports

Protocol Use Case Official Support Protocol Version
STDIO Subprocess communication Official standard 2024-11-05+
SSE Web applications Official standard 2024-11-05+
Streamable HTTP Modern web applications Official standard 2025-06-18
WebSocket Real-time applications Unofficial -
gRPC Microservices Unofficial -

STDIO Transport (Recommended)

// Server side
mcpServer.Run(ctx, &stdio.StdioTransport{})

// Client side (launch subprocess)
transport := client.NewCommandTransport(exec.Command("./server"))
session, err := mcpClient.Connect(ctx, transport, nil)

Streamable HTTP Transport (Web Applications)

// Server side
handler := streamable.NewHTTPHandler(func(r *http.Request) *server.Server {
    return mcpServer
})
http.ListenAndServe(":8081", handler)

// Client side
transport, err := streamable.NewStreamableTransport("http://localhost:8081/mcp")
session, err := mcpClient.Connect(ctx, transport, nil)

SSE Transport (Backward Compatible)

// Server side
handler := sse.NewHTTPHandler(func(r *http.Request) *server.Server {
    return mcpServer
})
http.ListenAndServe(":8080", handler)

// Client side
transport, err := sse.NewSSETransport("http://localhost:8080")
session, err := mcpClient.Connect(ctx, transport, nil)

Development Guide

Learning Path

  1. Quick Start → Understand basic concepts
  2. Basic Example → Complete feature demonstration
  3. Streamable Demo → HTTP transport
  4. Client Example → Client development

Contributing

We welcome all forms of contributions!

  1. Report Bugs - Submit issues describing problems
  2. Feature Suggestions - Propose new feature ideas
  3. Improve Documentation - Enhance documentation and examples
  4. Code Contributions - Submit Pull Requests

Please see Contributing Guide for details.

License

MIT License - See LICENSE file for details

Roadmap

Completed (MCP 2025-06-18 Fully Supported)

Core Architecture:

  • Client/Server + Session Pattern
  • Transport Abstraction Layer - Unified Transport/Connection interface
  • Multi-Session Support - Both Server and Client support multiple concurrent connections

Transport Protocols:

  • STDIO Transport - Standard input/output, suitable for CLI and Claude Desktop
  • Streamable HTTP Transport - Latest HTTP transport protocol (MCP 2025-06-18)
  • SSE Transport - Backward compatible with legacy HTTP+SSE (MCP 2024-11-05)

MCP 2025-06-18 Features:

  • Tools - Complete tool registration and invocation
  • Resources - Resource management and subscription
  • Resource Templates - Dynamic resource URI templates
  • Prompts - Prompt template management
  • Roots - Client roots management
  • Sampling - LLM inference request support
  • Progress Tracking - Progress feedback for long-running operations
  • Logging - Structured log messages
  • Request Cancellation - Cancel long-running operations

Planned

  • CLI Tool - Command-line tool for developing, testing, and debugging MCP servers
  • OAuth 2.1 Authorization - Enterprise-grade security authentication (MCP 2025-03-26)
  • Middleware System - Request/response interception and processing
  • More Examples - More example code for real-world scenarios

Related Projects


About

Model Context Protocol(MCP) SDK for Go

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages