Skip to content

voocel/mcp-sdk-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

43 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MCP Go SDK

一个优雅、高效的模型上下文协议 (Model Context Protocol, MCP) Go 实现

English 中文

License Go Reference Go Report Card Build Status

构建更智能的应用,连接更强大的模型 使用 MCP Go SDK,轻松集成大语言模型能力

介绍

MCP Go SDK 是模型上下文协议(Model Context Protocol)的 Go 语言实现,完全支持最新的 MCP 2025-06-18 规范,同时向后兼容 MCP 2025-03-26MCP 2024-11-05

核心特性

  • 完全符合 MCP 标准 - 支持最新 MCP 2025-06-18 规范,向后兼容 2025-03-26, 2024-11-05
  • 优雅的架构设计 - Client/Server + Session 模式,高内聚低耦合
  • 服务器 SDK - 快速构建 MCP 服务器,支持工具、资源、提示模板
  • 客户端 SDK - 连接任何 MCP 兼容服务器的完整客户端实现
  • 多种传输协议 - STDIO (推荐)、Streamable HTTP (最新)、SSE (向后兼容)
  • 多会话支持 - Server 和 Client 都可以同时管理多个连接
  • 高性能 - 并发安全,优化的消息处理
  • 安全防护 - 内置输入验证、路径遍历保护、资源限制

MCP协议版本支持

本SDK跟踪并支持MCP协议的最新发展,确保与生态系统的兼容性:

支持的版本

版本 发布时间 主要特性 支持状态
2025-06-18 2025年6月 结构化工具输出、工具注解、Elicitation 用户交互Sampling LLM推理 完全支持
2025-03-26 2025年3月 OAuth 2.1授权、Streamable HTTP、JSON-RPC批处理 完全支持
2024-11-05 2024年11月 HTTP+SSE传输、基础工具和资源 完全支持

最新特性 (2025-06-18)

  • 结构化工具输出:工具可返回类型化JSON数据,便于程序化处理
  • 工具注解:描述工具行为特征(只读、破坏性、缓存策略等)
  • 用户交互请求:工具可主动请求用户输入或确认
  • 资源链接:支持资源间的关联和引用
  • 协议版本头:HTTP传输需要MCP-Protocol-Version
  • 扩展元数据 (_meta):为工具、资源、提示添加自定义元数据

主要变更历史

2025-03-26 → 2025-06-18

  • 新增结构化工具输出支持
  • 增强工具注解系统
  • 添加用户交互请求机制
  • 支持资源链接功能
  • 新增 _meta 字段用于扩展元数据

2024-11-05 → 2025-03-26

  • 引入OAuth 2.1授权框架
  • 用Streamable HTTP替代HTTP+SSE
  • 添加JSON-RPC批处理支持
  • 增加音频内容类型支持

安装

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

快速开始

服务器端 - STDIO Transport (推荐)

最简单的方式是使用 STDIO transport,适用于命令行工具和 Claude Desktop 集成:

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()

    // 创建 MCP 服务器
    mcpServer := server.NewServer(&protocol.ServerInfo{
        Name:    "快速入门服务器",
        Version: "1.0.0",
    }, nil)

    // 注册一个简单的问候工具
    mcpServer.AddTool(
        &protocol.Tool{
            Name:        "greet",
            Description: "问候用户",
            InputSchema: map[string]interface{}{
                "type": "object",
                "properties": map[string]interface{}{
                    "name": map[string]interface{}{
                        "type":        "string",
                        "description": "用户名称",
                    },
                },
                "required": []string{"name"},
            },
        },
        func(ctx context.Context, req *server.CallToolRequest) (*protocol.CallToolResult, error) {
            name := req.Params.Arguments["name"].(string)
            greeting := fmt.Sprintf("你好,%s!欢迎使用 MCP Go SDK!", name)
            return protocol.NewToolResultText(greeting), nil
        },
    )

    // 使用 STDIO transport 运行服务器
    if err := mcpServer.Run(ctx, &stdio.StdioTransport{}); err != nil {
        log.Fatal(err)
    }
}

服务器端 - HTTP Transport

使用 Streamable HTTP transport 构建 Web 服务:

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() {
    // 创建 MCP 服务器
    mcpServer := server.NewServer(&protocol.ServerInfo{
        Name:    "HTTP 服务器",
        Version: "1.0.0",
    }, nil)

    // 注册工具...
    mcpServer.AddTool(...)

    // 创建 HTTP 处理器
    handler := streamable.NewHTTPHandler(func(*http.Request) *server.Server {
        return mcpServer
    })

    // 启动 HTTP 服务器
    log.Println("服务器启动在 http://localhost:8081")
    if err := http.ListenAndServe(":8081", handler); err != nil {
        log.Fatal(err)
    }
}

客户端 - 连接 MCP 服务器

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()

    // 创建客户端
    mcpClient := client.NewClient(&client.ClientInfo{
        Name:    "演示客户端",
        Version: "1.0.0",
    }, nil)

    // 通过 STDIO 连接到服务器(启动子进程)
    transport := client.NewCommandTransport(exec.Command("./server"))
    session, err := mcpClient.Connect(ctx, transport, nil)
    if err != nil {
        log.Fatalf("连接失败: %v", err)
    }
    defer session.Close()

    fmt.Printf("连接成功!服务器: %s v%s\n",
        session.ServerInfo().Name, session.ServerInfo().Version)

    // 列出可用工具
    tools, err := session.ListTools(ctx, nil)
    if err != nil {
        log.Fatalf("列出工具失败: %v", err)
    }

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

    // 调用工具
    result, err := session.CallTool(ctx, &protocol.CallToolParams{
        Name: "greet",
        Arguments: map[string]interface{}{
            "name": "Go 开发者",
        },
    })
    if err != nil {
        log.Fatalf("调用工具失败: %v", err)
    }

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

    // 读取资源
    resource, err := session.ReadResource(ctx, &protocol.ReadResourceParams{
        URI: "info://server",
    })
    if err != nil {
        log.Fatalf("读取资源失败: %v", err)
    }

    if len(resource.Contents) > 0 {
        fmt.Printf("服务器信息: %s\n", resource.Contents[0].Text)
    }
}

示例项目

示例 描述 传输协议 特性
Basic 完整综合示例 STDIO 所有核心功能 + 客户端
Calculator 数学计算器服务 STDIO 工具、资源
SSE Demo SSE 传输演示 SSE SSE 传输
Chatbot 聊天机器人服务 SSE 对话式交互
File Server 文件操作服务 SSE 文件操作
Streamable Demo Streamable HTTP 演示 Streamable HTTP 流式传输

推荐从 Basic 示例开始: 包含所有核心功能的完整演示,含服务器和客户端实现。

运行方式:

# 服务器
cd examples/basic && go run main.go

# 客户端
cd examples/basic/client && go run main.go

核心架构

服务器端 API

// 创建 MCP 服务器
mcpServer := server.NewServer(&protocol.ServerInfo{
    Name:    "我的服务器",
    Version: "1.0.0",
}, nil)

// 注册工具
mcpServer.AddTool(
    &protocol.Tool{
        Name:        "greet",
        Description: "问候用户",
        InputSchema: map[string]interface{}{
            "type": "object",
            "properties": map[string]interface{}{
                "name": map[string]interface{}{
                    "type":        "string",
                    "description": "用户名称",
                },
            },
            "required": []string{"name"},
        },
    },
    func(ctx context.Context, req *server.CallToolRequest) (*protocol.CallToolResult, error) {
        name := req.Params.Arguments["name"].(string)
        return protocol.NewToolResultText(fmt.Sprintf("你好,%s!", name)), nil
    },
)

// 注册资源
mcpServer.AddResource(
    &protocol.Resource{
        URI:         "info://server",
        Name:        "服务器信息",
        Description: "获取服务器基本信息",
        MimeType:    "text/plain",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        contents := protocol.NewTextResourceContents("info://server", "服务器信息内容")
        return protocol.NewReadResourceResult(contents), nil
    },
)

// 注册资源模板
mcpServer.AddResourceTemplate(
    &protocol.ResourceTemplate{
        URITemplate: "log://app/{date}",
        Name:        "应用日志",
        Description: "获取指定日期的应用日志",
        MimeType:    "text/plain",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        // 从 URI 中提取参数
        date := extractDateFromURI(req.Params.URI)
        contents := protocol.NewTextResourceContents(req.Params.URI, fmt.Sprintf("日志内容: %s", date))
        return protocol.NewReadResourceResult(contents), nil
    },
)

// 注册提示模板
mcpServer.AddPrompt(
    &protocol.Prompt{
        Name:        "code_review",
        Description: "代码审查提示",
        Arguments: []protocol.PromptArgument{
            {Name: "language", Description: "编程语言", Required: true},
            {Name: "code", Description: "代码内容", 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("请审查这段 %s 代码:\n%s", language, code))),
        }
        return protocol.NewGetPromptResult("代码审查", messages...), nil
    },
)

// 运行服务器 (STDIO)
if err := mcpServer.Run(ctx, &stdio.StdioTransport{}); err != nil {
    log.Fatal(err)
}

// 或者使用 HTTP 传输
handler := streamable.NewHTTPHandler(func(r *http.Request) *server.Server {
    return mcpServer
})
http.ListenAndServe(":8081", handler)

客户端 API

// 创建客户端
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "我的客户端",
    Version: "1.0.0",
}, nil)

// 通过 STDIO 连接(启动子进程)
transport := client.NewCommandTransport(exec.Command("./server"))
session, err := mcpClient.Connect(ctx, transport, nil)
if err != nil {
    log.Fatal(err)
}
defer session.Close()

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

// 调用工具
result, err := session.CallTool(ctx, &protocol.CallToolParams{
    Name:      "greet",
    Arguments: map[string]interface{}{"name": "世界"},
})

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

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

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

高级特性

资源模板

// 服务器端注册资源模板
mcpServer.AddResourceTemplate(
    &protocol.ResourceTemplate{
        URITemplate: "log://app/{date}",
        Name:        "应用日志",
        Description: "获取指定日期的应用日志",
    },
    func(ctx context.Context, req *server.ReadResourceRequest) (*protocol.ReadResourceResult, error) {
        // 处理动态资源请求
        return protocol.NewReadResourceResult(contents), nil
    },
)

// 客户端列出资源模板
templates, err := session.ListResourceTemplates(ctx, nil)
for _, tpl := range templates.ResourceTemplates {
    fmt.Printf("模板: %s\n", tpl.URITemplate)
}

// 读取具体资源
resource, err := session.ReadResource(ctx, &protocol.ReadResourceParams{
    URI: "log://app/2025-01-15",
})

根目录管理 (Roots)

// 客户端设置根目录
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "客户端",
    Version: "1.0.0",
}, &client.ClientOptions{
    Roots: []*protocol.Root{
        protocol.NewRoot("file:///home/user/projects", "项目目录"),
        protocol.NewRoot("file:///home/user/documents", "文档目录"),
    },
})

// 服务器端请求客户端根目录列表
// 注意: 需要在 ServerSession 中调用
rootsList, err := session.ListRoots(ctx)
for _, root := range rootsList.Roots {
    fmt.Printf("根目录: %s - %s\n", root.URI, root.Name)
}

Sampling (LLM 推理)

// 客户端设置 Sampling 处理器
mcpClient := client.NewClient(&client.ClientInfo{
    Name:    "客户端",
    Version: "1.0.0",
}, &client.ClientOptions{
    SamplingHandler: func(ctx context.Context, req *protocol.CreateMessageRequest) (*protocol.CreateMessageResult, error) {
        // 调用实际的 LLM API
        response := callLLMAPI(req.Messages)
        return protocol.NewCreateMessageResult(
            protocol.RoleAssistant,
            protocol.NewTextContent(response),
            "gpt-4",
            protocol.StopReasonEndTurn,
        ), nil
    },
})

// 服务器端发起 Sampling 请求
// 注意: 需要在 ServerSession 中调用
result, err := session.CreateMessage(ctx, &protocol.CreateMessageRequest{
    Messages: []protocol.SamplingMessage{
        {Role: protocol.RoleUser, Content: protocol.NewTextContent("计算 2+2")},
    },
    MaxTokens: 100,
})

传输协议

完全符合 MCP 2025-06-18 规范,向后兼容 MCP 2025-03-26, 2024-11-05

支持的传输方式

协议 使用场景 官方支持 协议版本
STDIO 子进程通信 官方标准 2024-11-05+
SSE Web 应用 官方标准 2024-11-05+
Streamable HTTP 现代 Web 应用 官方标准 2025-06-18
WebSocket 实时应用 非官方标准 -
gRPC 微服务 非官方标准 -

STDIO Transport (推荐)

// 服务器端
mcpServer.Run(ctx, &stdio.StdioTransport{})

// 客户端(启动子进程)
transport := client.NewCommandTransport(exec.Command("./server"))
session, err := mcpClient.Connect(ctx, transport, nil)

Streamable HTTP Transport (Web 应用)

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

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

SSE Transport (向后兼容)

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

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

开发指南

学习路径

  1. 快速开始 → 理解基本概念
  2. Basic 示例 → 完整功能演示
  3. Streamable Demo → HTTP 传输
  4. Client Example → 客户端开发

贡献

我们欢迎各种形式的贡献!

  1. 报告 Bug - 提交 Issue 描述问题
  2. 功能建议 - 提出新功能想法
  3. 改进文档 - 完善文档和示例
  4. 代码贡献 - 提交 Pull Request

请查看 贡献指南 了解详细信息。

许可证

MIT License - 详见 LICENSE 文件

Roadmap

已完成 (MCP 2025-06-18 完全支持)

核心架构:

  • Client/Server + Session 模式
  • Transport 抽象层 - 统一的 Transport/Connection 接口
  • 多会话支持 - Server 和 Client 都支持多个并发连接

传输协议:

  • STDIO Transport - 标准输入/输出,适用于 CLI 和 Claude Desktop
  • Streamable HTTP Transport - 最新 HTTP 传输协议 (MCP 2025-06-18)
  • SSE Transport - 向后兼容旧版 HTTP+SSE (MCP 2024-11-05)

MCP 2025-06-18 特性:

  • 工具 (Tools) - 完整的工具注册和调用
  • 资源 (Resources) - 资源管理和订阅
  • 资源模板 (Resource Templates) - 动态资源 URI 模板
  • 提示模板 (Prompts) - 提示模板管理
  • 根目录 (Roots) - 客户端根目录管理
  • Sampling - LLM 推理请求支持
  • 进度跟踪 (Progress) - 长时间操作进度反馈
  • 日志 (Logging) - 结构化日志消息
  • 请求取消 (Cancellation) - 取消长时间运行的操作

计划中

  • CLI 工具 - 开发、测试和调试 MCP 服务器的命令行工具
  • OAuth 2.1 授权 - 企业级安全认证机制 (MCP 2025-03-26)
  • 中间件系统 - 请求/响应拦截和处理
  • 更多示例 - 更多实际应用场景的示例代码

相关项目


About

Model Context Protocol(MCP) SDK for Go

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages