首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >golang实现mcp client(2)

golang实现mcp client(2)

作者头像
golangLeetcode
发布2026-03-18 17:02:01
发布2026-03-18 17:02:01
1370
举报

本文继续上一篇介绍mcp client。首先还是实现一个mcp server,作为实验用。

代码语言:javascript
复制
package main
import (
    "context"
    "errors"
    "fmt"
    "os"
    "github.com/mark3labs/mcp-go/mcp"
    "github.com/mark3labs/mcp-go/server"
)
func main() {
    s := server.NewMCPServer(
        "Server Demo",
        "1.0.0",
    )
    // 添加工具
    {
        calculatorTool := mcp.NewTool("calculate",
            mcp.WithDescription("执行基本的算术运算"),
            mcp.WithString("operation",
                mcp.Required(),
                mcp.Description("要执行的算术运算类型"),
                mcp.Enum("add", "subtract", "multiply", "divide"), // 保持英文
            ),
            mcp.WithNumber("x",
                mcp.Required(),
                mcp.Description("第一个数字"),
            ),
            mcp.WithNumber("y",
                mcp.Required(),
                mcp.Description("第二个数字"),
            ),
        )
        s.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":
                result = x + y
            case "subtract":
                result = x - y
            case "multiply":
                result = x * y
            case "divide":
                if y == 0 {
                    return nil, errors.New("不允许除以零")
                }
                result = x / y
            }
            return mcp.FormatNumberResult(result), nil
        })
    }
    // 添加资源
    {
        // 静态资源示例 - 暴露一个 README 文件
        resource := mcp.NewResource(
            "docs://readme",
            "项目说明文档",
            mcp.WithResourceDescription("项目的 README 文件"),
            mcp.WithMIMEType("text/markdown"),
        )
        // 添加资源及其处理函数
        s.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
        })
    }
    // 添加提示词
    {
        // 简单问候提示
        s.AddPrompt(mcp.NewPrompt("greeting",
            mcp.WithPromptDescription("一个友好的问候提示"),
            mcp.WithArgument("name",
                mcp.ArgumentDescription("要问候的人的名字"),
            ),
        ), func(ctx context.Context, request mcp.GetPromptRequest) (*mcp.GetPromptResult, error) {
            name := request.Params.Arguments["name"]
            if name == "" {
                name = "朋友"
            }
            return mcp.NewGetPromptResult(
                "友好的问候",
                []mcp.PromptMessage{
                    mcp.NewPromptMessage(
                        mcp.RoleAssistant,
                        mcp.NewTextContent(fmt.Sprintf("你好,%s!今天有什么可以帮您的吗?", name)),
                    ),
                },
            ), nil
        })
    }
    // 启动基于 stdio 传输类型的服务
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("Server error: %v\n", err)
    }
}
代码语言:javascript
复制
go build -o server ./main.go

然后,用golang实现一个mcp client

代码语言:javascript
复制
package main
import (
    "context"
    "fmt"
    "time"
    "github.com/mark3labs/mcp-go/client"
    "github.com/mark3labs/mcp-go/mcp"
)
func main() {
    // 创建一个基于 stdio 的MCP客户端
    mcpClient, err := client.NewStdioMCPClient(
        "./server",
        []string{},
    )
    if err != nil {
        panic(err)
    }
    defer mcpClient.Close()
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    fmt.Println("初始化 mcp 客户端...")
    initRequest := mcp.InitializeRequest{}
    initRequest.Params.ProtocolVersion = mcp.LATEST_PROTOCOL_VERSION
    initRequest.Params.ClientInfo = mcp.Implementation{
        Name:    "Client Demo",
        Version: "1.0.0",
    }
    // 初始化MCP客户端并连接到服务器
    initResult, err := mcpClient.Initialize(ctx, initRequest)
    if err != nil {
        panic(err)
    }
    fmt.Printf(
        "\n初始化成功,服务器信息: %s %s\n\n",
        initResult.ServerInfo.Name,
        initResult.ServerInfo.Version,
    )
    // 从服务器获取提示词列表
    fmt.Println("提示词列表:")
    promptsRequest := mcp.ListPromptsRequest{}
    prompts, err := mcpClient.ListPrompts(ctx, promptsRequest)
    if err != nil {
        panic(err)
    }
    for _, prompt := range prompts.Prompts {
        fmt.Printf("- %s: %s\n", prompt.Name, prompt.Description)
        fmt.Println("参数:", prompt.Arguments)
    }
    // 从服务器获取资源列表
    fmt.Println()
    fmt.Println("资源列表:")
    resourcesRequest := mcp.ListResourcesRequest{}
    resources, err := mcpClient.ListResources(ctx, resourcesRequest)
    if err != nil {
        panic(err)
    }
    for _, resource := range resources.Resources {
        fmt.Printf("- uri: %s, name: %s, description: %s, MIME类型: %s\n", resource.URI, resource.Name, resource.Description, resource.MIMEType)
    }
    // 从服务器获取工具列表
    fmt.Println()
    fmt.Println("可用工具列表:")
    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)
    }
    fmt.Println()
    // 调用工具
    fmt.Println("调用工具: calculate")
    toolRequest := mcp.CallToolRequest{
        Request: mcp.Request{
            Method: "tools/call",
        },
    }
    toolRequest.Params.Name = "calculate"
    toolRequest.Params.Arguments = map[string]any{
        "operation": "add",
        "x":         1,
        "y":         1,
    }
    // Call the tool
    result, err := mcpClient.CallTool(ctx, toolRequest)
    if err != nil {
        panic(err)
    }
    fmt.Println("调用工具结果:", result.Content[0].(mcp.TextContent).Text)
}

首先NewStdioMCPClient,它的参数传入刚刚我们实现的server的路径,拼接好client的参数,也就是组装我们上一篇介绍的grpcjson后,初始化客户端,initResult, err := mcpClient.Initialize(ctx, initRequest),然后我们就可以通过函数来获取资源、提示词和工具列表

代码语言:javascript
复制
 mcpClient.ListPrompts(ctx, promptsRequest)
代码语言:javascript
复制
mcpClient.ListResources(ctx, resourcesRequest)
代码语言:javascript
复制
 mcpClient.ListTools(ctx, toolsRequest)

最后组装参数调用我们的工具

代码语言:javascript
复制
toolRequest := mcp.CallToolRequest{
        Request: mcp.Request{
            Method: "tools/call",
        },
    }
    toolRequest.Params.Name = "calculate"
    toolRequest.Params.Arguments = map[string]any{
        "operation": "add",
        "x":         1,
        "y":         1,
    }
    // Call the tool
    result, err := mcpClient.CallTool(ctx, toolRequest)
    if err != nil {
        panic(err)
    }

测试下效果

代码语言:javascript
复制
go run ./main.go
[{human [What is 1 + 1?]} {ai [<think>
I need to determine the sum of 1 and 1.
First, I'll identify the two numbers involved in the addition: 1 and 1.
Next, I'll perform the addition by combining these two numbers.
Finally, I'll state that the result of adding 1 and 1 is 2.
</think>
**Solution:**
To find the sum of \(1 + 1\), follow these simple steps:
1. **Identify the numbers to add:**  
   The numbers are \(1\) and \(1\).
2. **Perform the addition:**  
   \[
   1 + 1 = 2
   \]
3. **State the final answer:**  
   \[
   \boxed{2}
   \]]}]

至此一个完整的client使用例子介绍完毕。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-04-12,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 golang算法架构leetcode技术php 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档