mcp-go Go搭建MCP服务的实现示例
目录
- 介绍
- 安装
- API介绍
- 1. server.NewMCPServer:新建一个mcp server
- 2. mcp.NewResource:对外提供资源
- 3. mcp.NewTool:对外提供工具
- 4. s.AddPrompt:添加提示词
- 实战使用
- 1. 编写mcp server
- 2. 桌面版调用mcp server插件
介绍
目前Go 生态圈有两个知名的开发 MCP 的库,一个是mark3labs/mcp-go,另一个是metoro-io/mcp-golang。
在介绍常用库之前,先来简单介绍一下mcp协议:
MCP全称Model Context Protocol 模型上下文协议,MCP 是一个开放协议,它为应用程序向 LLM 提供上下文的方式进行了标准化。你可以将 MCP 想象成 AI 应用程序的 USB-C 接口。就像 USB-C 为设备连接各种外设和配件提供了标准化的方式一样,MCP 为 AI 模型连接各种数据源和工具提供了标准化的接口。
相比之前各大AI厂商各自为战,接口以及协议之间不通用,导致开发者针对同一个功能为了适配多个AI模型,需要开发多套。现在有了MCP,各大模型厂商和开发者只需遵循MCP协议,即可实现一次编写,多模型适用。
MCP与大模型调用之间原理图:
MCP架构主要包含一下几个模块:
- MCP Hosts: 如 Claude Desktop、IDE 、DeepChat或 AI 工具,希望通过 MCP 访问数据的程序
- MCP Clients: 维护与服务器一对一连接的协议客户端
- MCP Servers: 轻量级程序,通过标准的 Model Context Protocol 提供特定能力
- 本地数据源: MCP 服务器可安全访问的计算机文件、数据库和服务
- 远程服务: MCP 服务器可连接的互联网上的外部系统(如通过 APIs)
安装
go get "github.com/mark3labs/mcp-go"
API介绍
1. server.NewMCPServer:新建一个mcp server
目前MCP 支持 SSE 和Stdio两种类型。
stdio:standard input output,标准输入输出,适用于mcp client和mcp server部署在同一个机器上,不涉及跨机器。
sse:Server-Sent Events,服务器发送事件,是一个基于HTTP的协议。适用于mcp client与mcp server不在同一个机器中的场景,涉及网络传输。
这里我们以新建一个基于Stdio协议的mcp server为例:
//新建mcp 服务 mcpServer := server.NewMCPServer("ziyi Mcp Server", "1.0.0") //对外提供 stdio mcp server服务 if err := server.ServeStdio(mcpServer); err != nil { panic(err) }
2. mcp.NewResource:对外提供资源
资源是你向 LLMs 暴露数据的方式。它们可以是任何东西:文件、API 响应、数据库查询、系统信息等。资源可以是:
- 静态资源(固定 URI)
- 动态资源(使用 URI 模板)
//新增一个mcp server对外暴露的静态资源(固定URI),比如:对外暴露项目的操作手册以及部署方式等,就可以通过静态资源README文件的方式来告诉大模型 resource := mcp.NewResource( "docs://readme", "项目的README文件", mcp.WithResourceDescription("这是一个项目的README文件"), mcp.WithMIMEType("text/markdown"), ) // 添加对静态资源的处理器 mcpServer.AddResource(resource, func(ctx context.Context, request mcp.ReadResourceRequest) ([]mcp.ResourceContents, error) { content, err := os.ReadFile("README.md") if err != nil { return nil, err } return []mcp.ResourceContents{ mcp.TextResourceContents{ URI: "docs://readme", MIMEType: "text/markdown", Text: string(content), }, }, nil })
3. mcp.NewTool:对外提供工具
工具让 LLM 通过你的服务器执行操作。与资源不同,工具预期会进行计算并产生副作用。它们类似于 REST API 中的 POST 端点。 下面是一个算术运算的工具示例:
工具可以用于任何种类的计算:
Database queries 数据库查询
File operations 文件操作
External API calls 外部 API 调用
Calculations 计算
System operations 系统操作
每个工具应该:
有清晰的描述
验证输入
优雅处理错误
返回结构化的响应
使用适当的结果类型
//给该mcp server添加计算能力(Tools) // 1. 描述该工具,以及调用该工具调用的参数机器含义 calculatorTool := mcp.NewTool("calculate", mcp.WithDescription("进行基础的数学运算"), mcp.WithString("operation", mcp.Required(), mcp.Description("Thpythone arithmetic operation to perform"), mcp.Enum("add", "subtract", "multiply", "d编程ivide"), ), mcp.WithNumber("x", mcp.Required(), mcp.Description("First number"), ), mcp.WithNumber("y", mcp.Required(), mcp.Description("Second number"), ), ) // 2. 实现工具的具体处理逻辑,类比大模型function_calling中的func部分 mcpServer.AddTool(calculatorTool, func(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { op := request.Params.Arguments["operation"].(string) x := request.Params.Arguments["x"].(float64) y := request.Params.Arguments["y"].(float64) var result float64 switch op { case "add": resultjavascript = x + y case "subtract": result = x - y case "multiply": result = x * y case "divide": if y == 0 { return nil, errors.New("Division by zero is not allowed") } result = x / y } return mcp.FormatNumberResult(result), nil })
4. s.AddPrompt:添加提示词
下面是一个简单的提示词示例,它需要一个名称参数,然后返回一个问候提示词:
// 给mcpServer添加提示词模版 mcpServer.AddPrompt(mcp.Newprompt("打招呼", mcp.WithPromptDescription("A friendly greeting prompt"), mcp.WithArgument("name", mcp.ArgumentDescription("Name of the person to greet"), ), ), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) { name := request.Params.Arguments["name"] if name == "" { name = "friend" } return mcp.NewGetPromptResult( "A friendly greeting", []mcp.PromptMessage{ mcp.NewPromptMessage( mcp.RoleAssistant, mcp.NewTextContent(fmt.Sprintf("Hello, %s! How can I help you today?", name)), ), }, ), nil })
实战使用
1. 编写mcp server
这里我们演示一个查询IP的mcp server。大模型传入ip,mcp server返回地址信息。
ip mcp server全部代码:
package main import ( "context" "errors" "fmt" "github.com/mark3labs/mcp-go/mcp" "github.com/mark3labs/mcp-go/server" "io" "net" "net/http" ) func main() { // Create MCP server s := server.NewMCPServer( "ip-mcp", "1.0.0", ) // Add tool tool := mcp.NewTool("ip_query", mcp.WithDescription("query geo location of an IP address"), mcp.WithString("ip", mcp.Required(), mcp.Description("IP address to query"), ), ) // Add tool handler s.AddTool(tool, ipQueryHandler) // Start the stdio server if err := server.ServeStdio(s); err != nil { fmt.Printf("Server error: %v\n", err) } } func ipQueryHandler(ctx context.Context, request mcp.CallToolRequest) (*mcp.CallToolResult, error) { ip, ok := request.Params.Arguments["ip"].(string) if !ok { return nil, errors.New("ip must be a string") } parsedIP := net.ParseIP(ip) if parsedIP == nil { return nil, errors.New("invalid IP address") } resp, err := http.Get("https://ip.rpcx.io/api/ip?ip=" + ip) if err != nil { return nil, fmt.Errorf("Error fetching IP information: %v", err) } defer resp.Body.Close() data, err := io.Read编程客栈All(resp.Body) if err != nil { return nil, fmt.Errorf("Error reading response body: %v", err) } fmt.Printf("编程客栈call ip: %s Response body: %s\n", ip, string(data)) return mcp.NewToolResultText(string(data)), nil }
然后我们编译代码:
# 执行命令编译mcp server go build -o mcp-ip main.go
2. 桌面版调用mcp server插件
这里使用桌面版的deepchat来演示大模型调用mcp server。
deepchat下载地址:https://deepchat.thinkinai.xyz/#/download
- 下载后配置本地大模型(通过ollama方式搭建等)或者直接配置远程模型地址
远程模型这里我使用openrouter的免费deepseek-r1版本:https://openrouter.ai/deepseek/deepseek-r1:free
选择模型,配置URL以及Token后,点击校验
点击下一步,然后就可以与大模型对话了
tips:
可修改页面文字为中文
可修改对话模型
下面我们配置mcp server
跳过json方式配置,转为手动配置
填写mcp server配置参数,然后点击提交
启用mcp server
- 输入问题,查看效果
如:帮我查询39.156.66.10 IP信息
参考文章:
https://mcp-docs.cn/introductionhttps://mp.weixin.qq.com/s/UgdXztu3SKYMs56DqiX3Sghttps://www.junki.cn/archives/Zqgi7fzK到此这篇关于mcp-go Go搭建MCP服务的实现示例的文章就介绍到这了,更多相关mcp-go Go搭建MCP服务内容请搜索编程客栈(www.devze.com)以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程客栈(www.devze.com)!
精彩评论