MCP服务器开发SDK

go-mcp是一个用于构建MCP(模型上下文协议)服务器的Go SDK,提供类型安全和直观的接口,简化服务器开发。

  • by ktr0731
  • Go
  • 本地部署
  • 143 星标
  • 更新于
在 GitHub 查看 ktr0731/go-mcp

使用说明

⚡ 去mcp

A type‑safe, intuitive Go SDK for MCP server development

🤔 What is go‑mcp? • ✨ Features • 🏁 Quick Start • 🔍 Examples • ✅ Supported Features • 🤝 Contributing


🤔 What is go‑mcp?

go-mcp 是一个Go SDK,用于轻松自信地构建MCP(模型上下文协议)服务器。它提供了一个类型安全、直观的界面,使服务器开发变得轻而易举。


✨ 特性

  • 🔒 类型-安全 代码生成确保您的工具和提示参数是静态类型的,因此错误是在编译时而不是在运行时捕获的。
  • 🧩 简单直观的API –一个自然、地道的Go界面,让您快速构建服务器,而无需陡峭的学习曲线。
  • 🔌 开发者友好 –设计时考虑到API人体工程学,使其易于接近。

🏁 快速开始

使用go-MCP创建MCP服务器很简单!

目录结构

以下是温度转换MCP服务器的目录结构示例:

.
├── cmd
│   ├── mcpgen
│   │   └── main.go
│   └── temperature
│       └── main.go
├── mcp.gen.go
└── temperature.go

1.定义MCP服务器

首先,创建 cmd/mcpgen/main.go 用于代码生成。运行此文件将自动生成必要的代码。

package main

import (
    "log"
    "os"
    "path/filepath"

    "github.com/ktr0731/go-mcp/codegen"
)

func main() {
    // Create output directory
    outDir := "."
    if err := os.MkdirAll(outDir, 0o755); err != nil {
        log.Fatalf("failed to create output directory: %v", err)
    }

    // Create output file
    f, err := os.Create(filepath.Join(outDir, "mcp.gen.go"))
    if err != nil {
        log.Fatalf("failed to create file: %v", err)
    }
    defer f.Close()

    // Server definition
    def := &codegen.ServerDefinition{
        Capabilities: codegen.ServerCapabilities{
            Tools:   &codegen.ToolCapability{},
            Logging: &codegen.LoggingCapability{},
        },
        Implementation: codegen.Implementation{
            Name:    "Temperature MCP Server",
            Version: "1.0.0",
        },
        // Tool definitions (declared with Go structs)
        Tools: []codegen.Tool{
            {
                Name:        "convert_temperature",
                Description: "Convert temperature between Celsius and Fahrenheit",
                InputSchema: struct {
                    Temperature float64 `json:"temperature" jsonschema:"description=Temperature value to convert"`
                    FromUnit    string  `json:"from_unit"  jsonschema:"description=Source temperature unit,enum=celsius,enum=fahrenheit"`
                    ToUnit      string  `json:"to_unit"    jsonschema:"description=Target temperature unit,enum=celsius,enum=fahrenheit"`
                }{},
            },
        },
    }

    // Generate code
    if err := codegen.Generate(f, def, "temperature"); err != nil {
        log.Fatalf("failed to generate code: %v", err)
    }
}

生成代码:

go run ./cmd/mcpgen

2.实现MCP服务器

接下来,在中实现服务器逻辑 cmd/temperature/main.go:

package main

import (
    "context"
    "fmt"
    "log"
    "math"

    mcp "github.com/ktr0731/go-mcp"
    "golang.org/x/exp/jsonrpc2"
)

type toolHandler struct{}

func (h *toolHandler) HandleToolConvertTemperature(ctx context.Context, req *ToolConvertTemperatureRequest) (*mcp.CallToolResult, error) {
    temperature := req.Temperature
    fromUnit := req.FromUnit
    toUnit := req.ToUnit

    var result float64
    switch {
    case fromUnit == ConvertTemperatureFromUnitTypeCelsius && toUnit == ConvertTemperatureToUnitTypeFahrenheit:
        // °C → °F: (C × 9/5) + 32
        result = (temperature*9/5 + 32)
    case fromUnit == ConvertTemperatureFromUnitTypeFahrenheit && toUnit == ConvertTemperatureToUnitTypeCelsius:
        // °F → °C: (F − 32) × 5/9
        result = (temperature - 32) * 5 / 9
    case fromUnit == toUnit:
        result = temperature
    default:
        return nil, fmt.Errorf("unsupported conversion: %s to %s", fromUnit, toUnit)
    }

    // Round to two decimal places
    result = math.Round(result*100) / 100

    resultText := fmt.Sprintf("%.2f %s = %.2f %s", temperature, fromUnit, result, toUnit)

    return &mcp.CallToolResult{
        Content: []mcp.CallToolContent{
            mcp.TextContent{Text: resultText},
        },
    }, nil
}

func main() {
    handler := NewHandler(&toolHandler{})

    ctx, listener, binder := mcp.NewStdioTransport(context.Background(), handler, nil)
    srv, err := jsonrpc2.Serve(ctx, listener, binder)
    if err != nil {
        log.Fatalf("failed to serve: %v", err)
    }

    srv.Wait()
}

运行服务器:

go run ./cmd/temperature

🔍 例子

请参阅 示例目录 和那个 API文档.


✅ 支持的功能

  • 拼
  • 工具
  • 鼓励
  • 提示、工具、资源、资源模板
  • 资源订阅
  • 资源更新通知
  • 日志记录
  • 完成
  • 取消

🚧 正在开发中

  • Batching (JSON‑RPC 2.0)
  • 可流式HTTP传输
  • 进度通知

🚫 未计划的

  • 动态提示和工具更改

    Go不太适合动态添加工具。动态添加工具需要在运行时构造工具定义、JSON模式和处理程序。虽然生成的代码仍然是类型安全的,但动态添加的组件不是,这迫使大量使用 any 以及类型断言和损害接口一致性。我们将这些用例委托给更适合动态变化的语言(如TypeScript)的SDK。

    目前实现的大多数MCP服务器仅使用静态定义,动态更改似乎还不是主要用例。


🤝 贡献

欢迎投稿!请随时提交pull请求。


📄 许可证

该项目根据MIT许可证获得许可——请参阅 许可证 文件以获取详细信息。