Day 6:MCP改造——让工具变成标准接口
昨天的问题
Day 4 的工具是硬编码在 Agent 代码里的:GetOrderTool、GetDeliveryTimeTool 直接 import。如果另一个服务也想用这些工具,得复制代码。
今天做什么
用 MCP(Model Context Protocol) 把工具标准化。工具变成独立的 MCP Server,Agent 通过标准协议调用。
代码
MCP Server(工具提供方)
mcp_server/main.go:
go
package main
import (
"context"
"fmt"
"log"
"net/http"
)
// ===== MCP Server 暴露的工具 =====
type MCPServer struct {
tools map[string]ToolHandler
}
type ToolHandler func(ctx context.Context, params map[string]any) (string, error)
func NewMCPServer() *MCPServer {
s := &MCPServer{tools: make(map[string]ToolHandler)}
s.tools["get_order_status"] = handleOrderStatus
s.tools["get_delivery_time"] = handleDeliveryTime
return s
}
func handleOrderStatus(ctx context.Context, params map[string]any) (string, error) {
orderID, _ := params["order_id"].(string)
order, ok := orderDB[orderID]
if !ok {
return fmt.Sprintf("未找到订单 %s", orderID), nil
}
return fmt.Sprintf("订单 %s:%s,预计 %s", order.ID, order.Status, order.ETA), nil
}
func handleDeliveryTime(ctx context.Context, params map[string]any) (string, error) {
city, _ := params["city"].(string)
return fmt.Sprintf("%s地区预计2-3天送达", city), nil
}
// MCP 工具发现接口
func (s *MCPServer) handleListTools(w http.ResponseWriter, r *http.Request) {
tools := []map[string]any{
{"name": "get_order_status", "description": "查询订单状态",
"parameters": map[string]any{"order_id": "string"}},
{"name": "get_delivery_time", "description": "查询配送时间",
"parameters": map[string]any{"city": "string"}},
}
json.NewEncoder(w).Encode(tools)
}
// MCP 工具调用接口
func (s *MCPServer) handleCallTool(w http.ResponseWriter, r *http.Request) {
var req struct {
ToolName string `json:"tool_name"`
Params map[string]any `json:"params"`
}
json.NewDecoder(r.Body).Decode(&req)
handler, ok := s.tools[req.ToolName]
if !ok {
http.Error(w, "tool not found", 404)
return
}
result, err := handler(r.Context(), req.Params)
if err != nil {
http.Error(w, err.Error(), 500)
return
}
json.NewEncoder(w).Encode(map[string]string{"result": result})
}
func main() {
server := NewMCPServer()
http.HandleFunc("/tools", server.handleListTools)
http.HandleFunc("/tools/call", server.handleCallTool)
log.Fatal(http.ListenAndServe(":9090", nil))
}Agent 端(MCP Client)
go
// MCP Client:调用远程工具
type MCPClient struct {
baseURL string
httpClient *http.Client
}
func (c *MCPClient) ListTools(ctx context.Context) ([]ToolInfo, error) {
resp, err := c.httpClient.Get(c.baseURL + "/tools")
// 解析返回的工具列表
var tools []ToolInfo
json.NewDecoder(resp.Body).Decode(&tools)
return tools, nil
}
func (c *MCPClient) CallTool(ctx context.Context,
name string, params map[string]any) (string, error) {
// 调远程 MCP Server 的工具
body, _ := json.Marshal(map[string]any{
"tool_name": name,
"params": params,
})
resp, _ := c.httpClient.Post(c.baseURL+"/tools/call",
"application/json", bytes.NewReader(body))
var result struct{ Result string }
json.NewDecoder(resp.Body).Decode(&result)
return result.Result, nil
}运行
bash
# 终端1:启动 MCP Server
go run mcp_server/main.go
# 终端2:运行 Agent
go run main.go你学到了什么
- MCP 架构:工具从 Agent 代码中解耦,变成独立服务。
- 标准接口:
/tools发现工具,/tools/call调用工具。任何语言都能调。 - Go 编译成二进制:MCP Server 可以
go build成一个文件,分发给团队。
明天的预告
最后一天——把 Agent 部署上线。编译成二进制文件,通过 HTTP 接口对外服务。
Day 6 完成。你的工具现在是标准接口了。

