返回市场
-go麦普服务器示例-

-go麦普服务器示例-

作者:BearHuddleston10 星标更新:2025-06-04

项目介绍

MCP咖啡店服务器示例 (MCP Coffee Shop)

这是一个用Go语言实现的MCP(模型上下文协议)服务器,它通过工具、资源和提示提供咖啡店信息,并遵循Go项目的最佳实践布局。

特性

  • 符合MCP 2025-03-26规范
  • 多种传输支持stdio(默认,兼容MCP Inspector),http(带SSE)
  • 咖啡店领域:用于咖啡店运营的工具、资源和提示
  • 优雅关闭与可配置超时
  • 生产就绪:结构化日志记录、错误处理和验证

项目结构

simple-mcp-server-refactored/
├── cmd/mcpserver/           # 应用程序入口点
├── pkg/                     # 公共库代码
│   ├── mcp/                 # 核心MCP协议类型
│   ├── config/              # 配置管理
│   ├── transport/           # 传输实现
│   └── handlers/            # 领域特定处理器
├── internal/server/         # 服务器实现
└── go.mod

使用方法

# 构建应用程序
go build -o mcpserver ./cmd/mcpserver

# 使用stdio传输运行(默认)
./mcpserver

# 使用HTTP传输运行
./mcpserver -transport http -port 8080
  • stdio:标准输入/输出(默认,兼容MCP Inspector)
  • http:带有服务端发送事件(SSE)支持的HTTP
  • 咖啡店领域:用于咖啡店运营的工具、资源和提示
  • 优雅关闭:适当的信号处理和资源清理
  • 可配置超时:请求、关闭和HTTP超时
  • 生产就绪:结构化日志记录、错误处理和验证

快速开始

Docker

您可以使用Docker运行MCP服务器:

  1. 构建Docker镜像

    docker build -t mcp-server .
    
  2. 运行容器

    # 对于HTTP传输(暴露8080端口)
    docker run -p 8080:8080 mcp-server --transport http --port 8080
    
    # 对于stdio传输(与MCP Inspector配合使用)
    docker run -it mcp-server --transport stdio
    
  3. 使用环境变量

    docker run -p 8080:8080 -e TRANSPORT=http -e PORT=8080 mcp-server
    

前提条件

安装

git clone <repository-url>
cd simple-mcp-server
go build

基本用法

# 使用stdio传输启动(默认)
go run ./...

# 使用HTTP传输启动
go run ./... --transport http --port 8080

# 自定义配置
go run ./... --transport http --port 9000 --request-timeout 45s

配置

命令行标志

标志描述默认值示例
--transport传输类型(stdiohttpstdio--transport http
--portHTTP端口(对于stdio无效)8080--port 9000
--request-timeout请求超时时间30s--request-timeout 45s

环境变量

服务器使用Go内置的标志解析。配置主要通过命令行标志进行。

传输方式

Stdio传输

适用于命令行工具和MCP Inspector集成:

go run ./... --transport stdio

应用场景:

  • MCP Inspector调试
  • CLI集成
  • 开发和测试

HTTP传输

带有可选服务端发送事件(SSE)的RESTful HTTP API:

go run ./... --transport http --port 8080

端点:

  • POST /mcp - 发送JSON-RPC请求
  • GET /mcp - 打开SSE流
  • GET /health - 健康检查

示例:

# 普通JSON响应
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1}'

# SSE流响应
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -H "Accept: text/event-stream" \
  -d '{"jsonrpc":"2.0","method":"tools/list","id":"test"}'

实现新的处理器

要向MCP服务器添加一个新的处理器,请按照以下步骤操作,以getWeather处理器为例:

  1. pkg/handlers/中创建一个新的处理器文件(例如,weather.go):
package handlers

import (
	"context"
	"encoding/json"

	"github.com/your-org/simple-mcp-server-refactored/pkg/mcp"
)

type WeatherHandler struct {
	// 在这里添加任何依赖项(如API客户端、配置)
}

// WeatherRequest 表示预期的请求参数
type WeatherRequest struct {
	Location string `json:"location"`
}

// WeatherResponse 表示响应结构
type WeatherResponse struct {
	Location    string  `json:"location"`
	Temperature float64 `json:"temperature"`
	Condition   string  `json:"condition"`
	Humidity    int     `json:"humidity"`
	WindSpeed   float64 `json:"wind_speed"`
	Unit        string  `json:"unit"`
}

// Handle 处理天气请求
func (h *WeatherHandler) Handle(ctx context.Context, request json.RawMessage) (interface{}, error) {
	var req WeatherRequest
	if err := json.Unmarshal(request, &req); err != nil {
		return nil, mcp.NewInvalidParamsError("无效的请求参数")
	}

	// TODO: 实现实际的天气数据检索
	// 这是一个模拟实现
	return WeatherResponse{
		Location:    req.Location,
		Temperature: 72.5,
		Condition:   "晴朗",
		Humidity:    45,
		WindSpeed:   8.2,
		Unit:        "华氏度",
	}, nil
}

// Register 将处理器注册到MCP服务器
func (h *WeatherHandler) Register(router *mcp.Router) {
	router.RegisterHandler("getWeather", h.Handle)
}
  1. internal/server/server.go中注册处理器
// 在NewServer函数中
weatherHandler := &handlers.WeatherHandler{}
weatherHandler.Register(router)
  1. pkg/handlers/weather_test.go中添加测试
package handlers_test

import (
	"context"
	"encoding/json"
	"testing"

	"github.com/your-org/simple-mcp-server-refactored/pkg/handlers"
	"github.com/stretchr/testify/assert"
)

func TestWeatherHandler(t *testing.T) {
	h := &handlers.WeatherHandler{}
	
	t.Run("成功的请求", func(t *testing.T) {
		req := map[string]interface{}{
			"location": "纽约, 纽约州",
		}
		reqBytes, _ := json.Marshal(req)

		result, err := h.Handle(context.Background(), reqBytes)
		assert.NoError(t, err)
		assert.NotNil(t, result)
		
		resp, ok := result.(handlers.WeatherResponse)
		assert.True(t, ok)
		assert.Equal(t, "纽约, 纽约州", resp.Location)
	})

	t.Run("无效的请求", func(t *testing.T) {
		req := map[string]interface{}{
			"invalid": "数据",
		}
		reqBytes, _ := json.Marshal(req)

		_, err := h.Handle(context.Background(), reqBytes)
		assert.Error(t, err)
	})
}
  1. 更新README.md中的文档,以记录新的处理器。

MCP能力

工具

可以由LLM调用的交互式功能:

工具描述参数
getDrinkNames获取可用饮品列表
getDrinkInfo获取详细饮品信息name: 字符串(必需)

示例:

{
  "jsonrpc": "2.0",
  "method": "tools/call",
  "id": "1",
  "params": {
    "name": "getDrinkInfo",
    "arguments": {"name": "拿铁"}
  }
}

资源

由应用程序管理的上下文数据:

资源URI描述
menumenu://app完整的咖啡店菜单

示例:

{
  "jsonrpc": "2.0",
  "method": "resources/read",
  "id": "1",
  "params": {"uri": "menu://app"}
}

提示

驱动LLM交互的模板:

提示描述参数
drinkRecommendation获取个性化的饮品推荐budget: 数字(可选)<br>preference: 字符串(可选)
drinkDescription获取详细的饮品描述drink_name: 字符串(必需)

示例:

{
  "jsonrpc": "2.0",
  "method": "prompts/get",
  "id": "1",
  "params": {
    "name": "drinkRecommendation",
    "arguments": {"budget": 6, "preference": "甜"}
  }
}

使用MCP Inspector进行测试

  1. 安装MCP Inspector:

    npm install -g @modelcontextprotocol/inspector
    
  2. 启动Inspector:

    npx @modelcontextprotocol/inspector
    
  3. 连接到服务器:

    • 传输stdio
    • 命令go
    • 参数run ./...

手动测试

# 测试stdio传输
echo '{"jsonrpc":"2.0","method":"initialize","id":1}' | go run ./... --transport stdio

# 测试HTTP传输
go run ./... --transport http &
curl -X POST http://localhost:8080/mcp \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","method":"initialize","id":1}'

API参考

JSON-RPC方法

方法描述参数
initialize初始化MCP会话客户端信息(可选)
tools/list列出可用工具
tools/call执行一个工具name, arguments
resources/list列出可用资源
resources/read读取资源内容uri
prompts/list列出可用提示
prompts/get获取提示模板name, arguments(可选)
ping健康检查

错误码

代码含义描述
-32700解析错误接收到无效的JSON
-32600无效请求无效的JSON-RPC请求
-32601方法未找到方法不存在
-32602无效参数无效的方法参数
-32603内部错误内部JSON-RPC错误

systemd服务

[Unit]
Description=MCP Coffee Server
After=network.target

[Service]
Type=simple
User=mcp
ExecStart=/usr/local/bin/mcp-server --transport http --port 8080
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

故障排除

常见问题

连接被拒绝(HTTP)

# 检查服务器是否正在运行
curl http://localhost:8080/health

# 验证端口未被占用
lsof -i :8080

Stdio传输不响应

# 检查JSON格式
echo '{"jsonrpc":"2.0","method":"ping","id":1}' | go run ./...

请求超时

# 增加超时时间
go run ./... --request-timeout 60s

解析错误

  • 确保JSON有效且格式正确
  • 检查所有必需字段是否存在
  • 验证JSON-RPC 2.0合规性

资源

支持

对于问题和疑问:

许可证

MIT