Skip to content

voocel/mcp-sdk-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

20 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
  • 服务器 SDK - 快速构建 MCP 服务器,支持工具、资源、提示模板
  • 客户端 SDK - 连接任何 MCP 兼容服务器的客户端实现
  • 多种传输协议 - STDIO、SSE、Streamable HTTP (官方标准)
  • 类型安全 - 完整的类型定义和参数验证
  • 高性能 - 并发安全,优化的消息处理
  • 安全防护 - 内置输入验证、路径遍历保护、资源限制

安装

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

快速开始

服务器端 (主要功能)

package main

import (
    "context"
    "fmt"
    "log"
    "os"
    "os/signal"
    "syscall"

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

func main() {
    ctx, cancel := context.WithCancel(context.Background())
    defer cancel()

    // 处理优雅关闭
    signalCh := make(chan os.Signal, 1)
    signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
    go func() {
        <-signalCh
        cancel()
    }()

    // 创建 FastMCP 服务器
    mcp := server.NewFastMCP("快速入门服务器", "1.0.0")

    // 注册一个简单的问候工具
    mcp.Tool("greet", "问候用户").
        WithStringParam("name", "用户名称", true).
        Handle(func(ctx context.Context, args map[string]interface{}) (*protocol.CallToolResult, error) {
            name, ok := args["name"].(string)
            if !ok {
                return protocol.NewToolResultError("参数 'name' 必须是字符串"), nil
            }
            
            greeting := fmt.Sprintf("你好,%s!欢迎使用 MCP Go SDK!", name)
            return protocol.NewToolResultText(greeting), nil
        })

    // 注册一个资源
    mcp.Resource("info://server", "服务器信息", "获取服务器基本信息").
        Handle(func(ctx context.Context) (*protocol.ReadResourceResult, error) {
            info := "MCP Go SDK 服务器正在运行..."
            contents := protocol.NewTextResourceContents("info://server", info)
            return protocol.NewReadResourceResult(contents), nil
        })

    // 创建 SSE 传输服务器 (也可以使用 Streamable HTTP)
    sseServer := sse.NewServer(":8080", mcp)
    
    log.Println("服务器启动在 http://localhost:8080")
    if err := sseServer.Serve(ctx); err != nil && err != context.Canceled {
        log.Fatalf("服务器错误: %v", err)
    }
}

客户端 (连接 MCP 服务器)

package main

import (
    "context"
    "fmt"
    "log"
    "time"

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

func main() {
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()

    // 创建 SSE 客户端
    mcpClient, err := client.New(
        client.WithSSETransport("http://localhost:8080"),
        client.WithClientInfo("demo-client", "1.0.0"),
    )
    if err != nil {
        log.Fatalf("创建客户端失败: %v", err)
    }
    defer mcpClient.Close()

    // 初始化连接
    initResult, err := mcpClient.Initialize(ctx, protocol.ClientInfo{
        Name:    "演示客户端",
        Version: "1.0.0",
    })
    if err != nil {
        log.Fatalf("初始化失败: %v", err)
    }

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

    // 发送初始化完成通知
    if err := mcpClient.SendInitialized(ctx); err != nil {
        log.Printf("发送初始化完成通知失败: %v", err)
    }

    // 调用工具
    result, err := mcpClient.CallTool(ctx, "greet", 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 := mcpClient.ReadResource(ctx, "info://server")
    if err != nil {
        log.Fatalf("读取资源失败: %v", err)
    }
    
    if len(resource.Contents) > 0 {
        fmt.Printf("服务器信息: %s\n", resource.Contents[0].Text)
    }
}

示例项目

示例 描述 传输协议 运行方式
Calculator 数学计算器服务 STDIO cd examples/calculator/server && go run main.go
SSE Demo SSE 传输演示 SSE cd examples/sse-demo/server && go run main.go
Chatbot 聊天机器人服务 SSE cd examples/chatbot/server && go run main.go
File Server 文件操作服务 SSE cd examples/file-server/server && go run main.go
Streamable Demo Streamable HTTP 演示 (MCP 2025-06-18) Streamable HTTP cd examples/streamable-demo/server && go run main.go

运行示例: 每个示例都包含服务器和客户端,需要在不同终端中分别运行。

核心架构

服务器端 (主要功能)

// 创建FastMCP服务器
mcp := server.NewFastMCP("服务名称", "1.0.0")

// 注册工具 - 链式 API
mcp.Tool("tool_name", "工具描述").
    WithStringParam("param1", "参数1描述", true).
    WithIntParam("param2", "参数2描述", false).
    Handle(func(ctx context.Context, args map[string]interface{}) (*protocol.CallToolResult, error) {
        // 工具逻辑实现
        return protocol.NewToolResultText("结果"), nil
    })

// 注册资源
mcp.Resource("resource://uri", "资源名称", "资源描述").
    Handle(func(ctx context.Context) (*protocol.ReadResourceResult, error) {
        contents := protocol.NewTextResourceContents("resource://uri", "内容")
        return protocol.NewReadResourceResult(contents), nil
    })

// 注册提示模板
mcp.Prompt("prompt_name", "提示描述").
    WithArgument("arg1", "参数描述", true).
    Handle(func(ctx context.Context, args map[string]string) (*protocol.GetPromptResult, error) {
        messages := []protocol.PromptMessage{
            protocol.NewPromptMessage(protocol.RoleUser, protocol.NewTextContent("内容")),
        }
        return protocol.NewGetPromptResult("描述", messages...), nil
    })

// 启动服务器 (SSE 传输)
sseTransport := sse.NewServer(":8080", mcp)
sseTransport.Serve(ctx)

// 或者使用 Streamable HTTP 传输 (推荐用于新项目)
// streamableTransport := streamable.NewServer(":8080", mcp)
// streamableTransport.Serve(ctx)

客户端 (连接 MCP 服务器)

// 创建客户端
client, err := client.New(
    client.WithSSETransport("http://localhost:8080"),
    client.WithClientInfo("client-name", "1.0.0"),
)

// 初始化并调用工具
initResult, err := client.Initialize(ctx, protocol.ClientInfo{...})
client.SendInitialized(ctx)
result, err := client.CallTool(ctx, "tool_name", map[string]interface{}{"param": "value"})

协议支持

MCP 标准合规性

完全符合 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 微服务 ❌ 非官方标准 -

支持的协议版本: 2025-06-18, 2025-03-26, 2024-11-05

开发指南

错误处理

// 服务器端
return protocol.NewToolResultError("参数错误"), nil  // 业务错误
return nil, fmt.Errorf("系统错误")                    // 系统错误

// 客户端
if result.IsError {
    // 处理业务错误
}

学习路径

  1. 快速开始示例 → 基本概念
  2. Calculator → 工具注册和调用
  3. SSE Demo → SSE 传输
  4. Streamable Demo → 最新传输协议

贡献

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

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

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

许可证

MIT License - 详见 LICENSE 文件

相关项目


About

Model Context Protocol(MCP) SDK for Go

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages