ktr0731 / go-mcp Public

⚡ 一款类型安全、直观的 Go SDK,让你轻松自信地构建 MCP 服务。

License

MIT license

ktr0731/go-mcp

main BranchesTags

⚡ go-mcp

一款类型安全、直观的 Go SDK,用于 MCP 服务开发

🤔 什么是 go-mcp?✨ 功能特性🏁 快速开始🔍 示例✅ 支持的功能🤝 贡献

🤔 什么是 go-mcp?

go-mcp 是一个 Go SDK,旨在让你能够轻松自信地构建 MCP (Model Context Protocol) 服务。 它提供了一个类型安全、直观的接口,让服务器开发变得轻而易举。

✨ 功能特性

🏁 快速开始

使用 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

🔍 示例

请参阅 examples 目录API 文档 中的完整示例。

✅ 支持的功能

🚧 开发中

🚫 未计划

Go 不太适合动态添加工具。 动态添加工具需要在运行时构造工具定义、JSON Schema 和 handlers。 虽然生成的代码保持类型安全,但动态添加的组件并非如此,从而强制大量使用 any 和类型断言,并损害接口一致性。 我们将这些用例委派给更适合动态更改的语言的 SDK,例如 TypeScript。

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

🤝 贡献

欢迎贡献! 随时提交 pull request。

📄 License

本项目根据 MIT License 授权 – 有关详细信息,请参阅 LICENSE 文件。