使用说明
MCP演示Go服务器
用Go编写的演示模型上下文协议(MCP)服务器,提供数学运算作为工具。
概述
此MCP服务器实现了一个可以添加两个整数的简单计算器工具。它演示了使用以下工具构建MCP服务器的核心概念 mcp走 图书馆。
服务器信息:
- 名字:演示开始
- 版本: 0.0.1
- 协议版本: 2024-11-05
特性
可用工具
add
将两个整数相加。
参数:
a(数字,必填):第一个整数b(数字,必填):第二个整数
退货: 总和为文本
例子:
{
"name": "add",
"arguments": {
"a": 5,
"b": 3
}
}
结果: 8
先决条件
- 达到1.21或更高
- Node.js和npm(用于MCP检查器)
安装
1.克隆或导航到存储库
cd /Users/alessandro/repos/labs/mcp/mcp-demo-go
2.安装依赖项
go mod download
3.构建服务器
go build -o mcp-demo-go main.go
可执行文件 mcp-demo-go 将在当前目录中创建。
用法
方法1:MCP检查员(建议用于测试)
MCP检查器提供了一个可视化的web界面,用于与您的MCP服务器进行交互。
npx @modelcontextprotocol/inspector ./mcp-demo-go
这将:
- 启动本地web服务器(通常在http://localhost:5173)
- 启动您的MCP服务器
- 打开一个带有交互式UI的浏览器,您可以在其中:
- 查看所有可用工具
- 请参阅工具说明和参数
- 具有自定义输入的测试工具
- 实时查看响应
方法2:与Claude Desktop集成
要将此MCP服务器与Claude Desktop一起使用,请将其添加到配置文件中。
地点: ~/Library/Application Support/Claude/claude_desktop_config.json (macOS)
配置:
{
"mcpServers": {
"demo-go": {
"command": "/Users/alessandro/repos/labs/mcp/mcp-demo-go/mcp-demo-go"
}
}
}
添加配置后:
- 重新启动克劳德桌面
- 服务器将自动连接
- 克劳德将有权访问
add工具
方法3:使用JSON-RPC进行手动测试
您可以通过stdio使用JSON-RPC消息手动与服务器交互。
创建测试脚本(test_mcp.py):
#!/usr/bin/env python3
import json
import subprocess
def send_request(proc, request):
request_str = json.dumps(request) + "\n"
proc.stdin.write(request_str.encode())
proc.stdin.flush()
response_line = proc.stdout.readline().decode()
if response_line:
return json.loads(response_line)
return None
# Start the MCP server
proc = subprocess.Popen(
['./mcp-demo-go'],
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
try:
# Initialize
init_request = {
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": {"name": "test-client", "version": "1.0.0"}
}
}
response = send_request(proc, init_request)
print("Initialize:", json.dumps(response, indent=2))
# Send initialized notification
initialized = {"jsonrpc": "2.0", "method": "notifications/initialized"}
proc.stdin.write((json.dumps(initialized) + "\n").encode())
proc.stdin.flush()
# List tools
list_request = {
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}
response = send_request(proc, list_request)
print("\nTools:", json.dumps(response, indent=2))
# Call add tool
call_request = {
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "add",
"arguments": {"a": 10, "b": 20}
}
}
response = send_request(proc, call_request)
print("\nResult:", json.dumps(response, indent=2))
finally:
proc.terminate()
proc.wait()
运行测试:
python3 test_mcp.py
方法4:使用curl(用于单个消息)
# Start the server
./mcp-demo-go &
SERVER_PID=$!
# Initialize
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}' | ./mcp-demo-go
# List tools
echo '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' | ./mcp-demo-go
# Clean up
kill $SERVER_PID
发展
项目结构
mcp-demo-go/
├── main.go # Main server implementation
├── go.mod # Go module dependencies
├── go.sum # Dependency checksums
├── mcp-demo-go # Compiled binary
└── README.md # This file
添加新工具
要添加新工具,请按照以下模式操作 main.go:
mcpServer.AddTool(
mcp.NewTool("tool_name",
mcp.WithDescription("Description of what the tool does"),
mcp.WithString("param1",
mcp.Description("Description of parameter"),
mcp.Required(),
),
),
func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := req.GetArguments()
param1 := args["param1"].(string)
// Your tool logic here
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: "result",
},
},
}, nil
},
)
参数类型
mcp-go库支持各种参数类型:
mcp.WithString()-字符串参数mcp.WithNumber()-数字参数mcp.WithBoolean()-布尔参数mcp.WithArray()-数组参数mcp.WithObject()-对象参数
建筑
# Build for current platform
go build -o mcp-demo-go main.go
# Build for specific platform
GOOS=linux GOARCH=amd64 go build -o mcp-demo-go-linux main.go
GOOS=darwin GOARCH=arm64 go build -o mcp-demo-go-macos main.go
GOOS=windows GOARCH=amd64 go build -o mcp-demo-go.exe main.go
构建Docker镜像(多平台)
# Set your registry and image details
REGISTRY=ghcr.io/ams0
IMAGE=mcp-demo-go
TAG=latest
# Build and push multi-platform image (macOS with Docker Desktop)
docker buildx build \
--platform linux/amd64,linux/arm64 \
-t $REGISTRY/$IMAGE:$TAG \
--push .
注: 多平台构建需要Docker Buildx。在带有Docker Desktop的macOS上,这是默认启用的。
在发展中奔跑
# Run without building
go run main.go
# Run with race detector
go run -race main.go
MCP协议
该服务器实现了模型上下文协议,该协议允许AI助手和外部工具通过stdio上的JSON-RPC进行通信。
关键概念
- 初始化:客户端和服务器交换功能
- 工具:AI可以调用的函数
- JSON-RPC:用于所有消息的通信协议
- 标准运输:通过标准输入/输出交换消息
消息流
Client Server
| |
|---initialize----------------->|
|<--capabilities----------------|
| |
|---notifications/initialized-->|
| |
|---tools/list----------------->|
|<--tool definitions-----------|
| |
|---tools/call----------------->|
|<--result---------------------|
故障排除
服务器未启动
- 确保二进制文件具有执行权限:
chmod +x mcp-demo-go - 检查端口5173是否未使用(用于MCP检查器)
- 验证Go版本:
go version
工具未出现在Claude Desktop中
- 检查配置文件路径是否正确
- 确保使用二进制文件的绝对路径
- 配置更改后重新启动Claude Desktop
- 检查Claude Desktop日志是否有错误
JSON-RPC错误
- 确保消息的JSON格式正确
- 每条消息必须以换行符结尾
- 验证协议版本是否匹配(2024-11-05)
资源
APIM故障排除(容器应用程序后端)
如果APIM调用超时,但直接调用容器应用程序FQDN有效,请按如下方式配置APIM:
- 后端
serviceUrl:https://mcp-demo-go.graywave-b3e914df.swedencentral.azurecontainerapps.io(公共FQDN,没有尾随斜线,没有/mcp). - API
path:空("")所以/api/joke地图干净利落。 - 操作:
GET /api/joke(后端路径/api/joke);对于MCP JSON-RPC,添加POST /mcp(后端路径/mcp). - 产品:确保API位于与您的订阅密钥匹配的产品中,并且订阅处于活动状态。
通过APIM进行测试(用您的密钥替换):
curl -i --max-time 15 \
-H "Ocp-Apim-Subscription-Key: <your key>" \
https://aigwcloud.azure-api.net/api/joke
APIM+入口ID(JWT)身份验证
通过Entra ID和APIM保护此API的示例工作设置:
- APIM
serviceUrl:https://mcp-demo-go.graywave-b3e914df.swedencentral.azurecontainerapps.io(没有尾随斜线,没有/mcp). - API URL后缀:
entraid⇒ 公有https://aigwcloud.azure-api.net/entraid. - 操作:
GET /api/joke(后端路径/api/joke);添加POST /mcp如果需要,可以使用JSON-RPC。 - 订阅:可选;如果禁用,则只需要JWT。如果启用,则发送JWT和订阅密钥。
- Entra应用程序(API资源):
api://5e52ac77-93a5-49aa-923d-a1cdeb3e7cbf作为观众。
用于验证的入站策略(APIM):
<inbound>
<base />
<validate-jwt header-name="Authorization"
failed-validation-httpcode="401"
failed-validation-error-message="Unauthorized">
<openid-config url="https://login.microsoftonline.com/2f88d75e-5ed4-41c4-9556-e627fd1ee262/v2.0/.well-known/openid-configuration" />
<audiences>
<audience>api://5e52ac77-93a5-49aa-923d-a1cdeb3e7cbf</audience>
</audiences>
<issuers>
<issuer>https://sts.windows.net/2f88d75e-5ed4-41c4-9556-e627fd1ee262/</issuer>
</issuers>
</validate-jwt>
</inbound>
获取令牌(基于范围):
API_APP_ID=5e52ac77-93a5-49aa-923d-a1cdeb3e7cbf
TOKEN=$(az account get-access-token --scope api://$API_APP_ID/.default --query accessToken -o tsv)
通过APIM致电(仅限JWT):
curl -i --max-time 15 \
-H "Authorization: Bearer $TOKEN" \
https://aigwcloud.azure-api.net/entraid/api/joke
如果需要订阅,请添加: -H "Ocp-Apim-Subscription-Key: <key>".
许可证
这是一个用于学习目的的示范项目。
贡献
欢迎通过以下方式扩展此演示:
- 添加更多的数学运算(减法、乘法、除法)
- 对边缘情况实施错误处理
- 添加输入验证
- 创建更复杂的工具
示例扩展:添加乘法工具
mcpServer.AddTool(
mcp.NewTool("multiply",
mcp.WithDescription("Multiply two numbers"),
mcp.WithNumber("a",
mcp.Description("First number"),
mcp.Required(),
),
mcp.WithNumber("b",
mcp.Description("Second number"),
mcp.Required(),
),
),
func(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
args := req.GetArguments()
a, ok1 := args["a"].(float64)
b, ok2 := args["b"].(float64)
if !ok1 || !ok2 {
return mcp.NewToolResultError("Invalid arguments"), nil
}
product := a * b
return &mcp.CallToolResult{
Content: []mcp.Content{
mcp.TextContent{
Type: "text",
Text: strconv.FormatFloat(product, 'f', -1, 64),
},
},
}, nil
},
)
问题?
关于以下问题:
- MCP协议:参见 MCP文件
- Go SDK:参见 mcp转到GitHub
- 此演示:打开一个问题或修改代码,边做边学!
