go-mcp 是一个用于轻松自信地构建MCP(模型上下文协议)服务器的Go SDK。它提供了一个类型安全且直观的接口,使得服务器开发变得简单。
使用go-mcp创建一个MCP服务器非常简单!
下面是一个温度转换MCP服务器的目录结构示例:
.
├── cmd
│ ├── mcpgen
│ │ └── main.go
│ └── temperature
│ └── main.go
├── mcp.gen.go
└── temperature.go
首先,在cmd/mcpgen/main.go中创建代码生成器。运行此文件会自动生成所需的代码。
package main
import (
"log"
"os"
"path/filepath"
"github.com/ktr0731/go-mcp/codegen"
)
func main() {
// 创建输出目录
outDir := "."
if err := os.MkdirAll(outDir, 0o755); err != nil {
log.Fatalf("创建输出目录失败: %v", err)
}
// 创建输出文件
f, err := os.Create(filepath.Join(outDir, "mcp.gen.go"))
if err != nil {
log.Fatalf("创建文件失败: %v", err)
}
defer f.Close()
// 服务器定义
def := &codegen.ServerDefinition{
Capabilities: codegen.ServerCapabilities{
Tools: &codegen.ToolCapability{},
Logging: &codegen.LoggingCapability{},
},
Implementation: codegen.Implementation{
Name: "温度转换MCP服务器",
Version: "1.0.0",
},
// 工具定义(使用Go结构体声明)
Tools: []codegen.Tool{
{
Name: "convert_temperature",
Description: "在摄氏度和华氏度之间转换温度",
InputSchema: struct {
Temperature float64 `json:"temperature" jsonschema:"description=要转换的温度值"`
FromUnit string `json:"from_unit" jsonschema:"description=源温度单位,enum=celsius,enum=fahrenheit"`
ToUnit string `json:"to_unit" jsonschema:"description=目标温度单位,enum=celsius,enum=fahrenheit"`
}{},
},
},
}
// 生成代码
if err := codegen.Generate(f, def, "temperature"); err != nil {
log.Fatalf("生成代码失败: %v", err)
}
}
生成代码:
go run ./cmd/mcpgen
接下来,在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("不支持的转换: %s 到 %s", fromUnit, toUnit)
}
// 四舍五入到两位小数
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("服务失败: %v", err)
}
srv.Wait()
}
运行服务器:
go run ./cmd/temperature
🚧 正在开发
🚫 未计划
动态提示和工具更改
Go并不适合动态添加工具。动态添加工具需要在运行时构造工具定义、JSON Schema和处理器。虽然生成的代码保持类型安全,但动态添加的组件不会,这迫使大量使用any和类型断言,并损害接口的一致性。我们把这些用例委托给更适合动态变化的语言的SDK,如TypeScript。
目前大多数已实现的MCP服务器仅使用静态定义,动态变化似乎还不是主要用例。
欢迎贡献!请随意提交拉取请求。
本项目采用MIT许可证 – 详情见LICENSE文件。