暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

golang实现mcp client(2)

        本文继续上一篇介绍mcp client。首先还是实现一个mcp server,作为实验用。
    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)
        }
    }
      go build -o server ./main.go
      然后,用golang实现一个mcp client
        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),然后我们就可以通过函数来获取资源、提示词和工具列表
           mcpClient.ListPrompts(ctx, promptsRequest)
            mcpClient.ListResources(ctx, resourcesRequest)
               mcpClient.ListTools(ctx, toolsRequest)
              最后组装参数调用我们的工具
                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)
                    }
                测试下效果
                  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使用例子介绍完毕。

                  文章转载自golang算法架构leetcode技术php,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                  评论