Go 使用 MCP 官方 SDK 轻松构建 MCP 客户端

前言

模型上下文协议(Model Context Protocol,简称 MCP)是一种开放标准,旨在标准化大型语言模型(LLM)与外部数据源和工具之间的交互方式。随着 MCP 越来越受欢迎,Go MCP 官方库应运而生。本文将介绍如何在 Go 语言里面使用官方提供的库构建一个 MCP 客户端。

如果你不熟悉 MCP 协议,可以看我之前写的这篇文章:一文掌握 MCP 上下文协议:从理论到实践

准备好了吗?准备一杯你最喜欢的咖啡或茶,随着本文一探究竟吧。

要构建 MCP 客户端和服务器,我们需要使用 modelcontextprotocol/go-sdk 库。该库的设计灵感来源于多个现有的 Go 语言 MCP SDK

安装 MCP 库

在 Go 项目根目录下,执行以下命令:

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

go get github.com/modelcontextprotocol/go-sdk

构建 MCP 客户端

接下来,我们使用 go-sdk 库来构建一个通过 stdio 方式连接到打包好的 MCP 服务器的客户端。

该客户端将展示以下功能:

  • 创建客户端并连接服务器

  • 获取提示词、资源、工具列表

  • 调用远程工具(tool)

创建 MCP 客户端

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil)

通过 mcp.NewClient 方法可以创建一个基于 stdio 传输的客户端。

设置传输方式(基于命令行)

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

transport := mcp.NewCommandTransport(exec.Command("myserver"))
  • 使用 exec.Command("myserver") 启动一个 MCP 服务器进程。

  • NewCommandTransport 会使用该命令的标准输入/输出作为传输通道。


建立对话连接

代码语言:Go

自动换行

AI代码解释

session, err := client.Connect(ctx, transport)
if err != nil {
log.Fatal(err)
}
defer session.Close()

通过 transport 与 MCP 服务器建立连接,创建一个会话对象 session

获取提示词(Prompts)列表

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

listPromptsParams := &mcp.ListPromptsParams{}
listPrompts, err := session.ListPrompts(ctx, listPromptsParams)
if err != nil {
panic(err)
}
for _, prompt := range listPrompts.Prompts {
fmt.Printf("- %s: %s\n", prompt.Name, prompt.Description)
fmt.Println("Title:", prompt.Title)
fmt.Println("参数:", prompt.Arguments)
fmt.Println("Meta:", prompt.Meta)
}

客户端可以使用 ListPrompts 获取服务器上定义的所有提示词,包括标题、名称和描述等参数。

获取资源(Resources)列表

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

listResourcesParams := &mcp.ListResourcesParams{}
resources, err := session.ListResources(ctx, listResourcesParams)
if err != nil {
panic(err)
}
for _, resource := range resources.Resources {fmt.Printf("- uri: %s, name: %s, description: %s, MIME类型: %s, title: %s, size: %d\n",
resource.URI, resource.Name, resource.Description, resource.MIMEType, resource.Title, resource.Size)
}

通过 ListResources 方法,客户端可以查看服务器上可用的静态或动态资源信息。

获取工具(Tools)列表

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

toolsRequest := mcp.ListToolsRequest{}
tools, err := mcpClient.ListTools(ctx, toolsRequest)
if err != nil {
panic(err)
}
for _, tool := range tools.Tools {
fmt.Printf("- %s: %s\n", tool.Name, tool.Description)
fmt.Println("参数:", tool.InputSchema.Properties)
}

通过 ListTools,客户端可以获取所有注册的工具信息,方便用户交互式选择或自动生成表单调用。

调用工具(Tool)

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

// Call a tool on the server.
params := &mcp.CallToolParams{Name: "greet",
Arguments: map[string]any{"name": "you"},
}
res, err := session.CallTool(ctx, params)
if err != nil {
log.Fatalf("CallTool failed: %v", err)
}
if res.IsError {
log.Fatal("tool failed")
}
for _, c := range res.Content {
log.Print(c.(*mcp.TextContent).Text)
}

通过构造 CallToolParams,客户端可以向 MCP 服务器发起工具调用请求,并获取返回的结构化结果。

完整代码示例

代码语言:JavaScript
代码运行次数:0

自动换行

运行

AI代码解释

package main

import (
"context"
"fmt"
"log"
"os/exec"

"github.com/modelcontextprotocol/go-sdk/mcp"

)

func main() {
ctx := context.Background()

// Create a new client, with no features.
client := mcp.NewClient(&mcp.Implementation{Name: "mcp-client", Version: "v1.0.0"}, nil)

// Connect to a server over stdin/stdout
transport := mcp.NewCommandTransport(exec.Command("myserver"))
session, err := client.Connect(ctx, transport)
if err != nil {
log.Fatal(err)
}
defer session.Close()

listPromptsParams := &mcp.ListPromptsParams{}
listPrompts, err := session.ListPrompts(ctx, listPromptsParams)
if err != nil {
panic(err)
}
for _, prompt := range listPrompts.Prompts {
fmt.Printf("- %s: %s\n", prompt.Name, prompt.Description)

fmt.Println("Title:", prompt.Title)
fmt.Println("参数:", prompt.Arguments)
fmt.Println("Meta:", prompt.Meta)
}

listResourcesParams := &mcp.ListResourcesParams{}
resources, err := session.ListResources(ctx, listResourcesParams)
if err != nil {
panic(err)
}
for _, resource := range resources.Resources {
fmt.Printf("- uri: %s, name: %s, description: %s, MIME类型: %s, title: %s, size: %d\n",
resource.URI, resource.Name, resource.Description, resource.MIMEType, resource.Title, resource.Size)

}

listToolsParams := &mcp.ListToolsParams{}
tools, err := session.ListTools(ctx, listToolsParams)
if err != nil {

panic(err)
}
for _, tool := range tools.Tools {
fmt.Printf("- %s: %s\n", tool.Name, tool.Description)
fmt.Println("参数:", tool.InputSchema.Properties)
}

// Call a tool on the server.
params := &mcp.CallToolParams{

Name: "greet",
Arguments: map[string]any{"name": "you"},
}
res, err := session.CallTool(ctx, params)

if err != nil {
log.Fatalf("CallTool failed: %v", err)
}
if res.IsError {
log.Fatal("tool failed")

}
for _, c := range res.Content {
log.Print(c.(*mcp.TextContent).Text)
}
}

小结

本文介绍了如何通过 MCP 官方的 Go SDK 实现了一个 MCP 客户端,该客户端具备以下功能:

  • 使用 stdio 模式连接到 MCP 服务器;

  • 初始化连接并获取服务器信息;

  • 列出服务器提供的工具、资源和提示词;

  • 调用服务器注册的工具并获取结果。