shower_code 2025-07-28 17:59 采纳率: 100%
浏览 21
已结题

MCP客户端初始化失败


            for _, toolCall := range resp.Choices[0].Message.ToolCalls {
                if toolCall.Function.Name == "weather" {
                    log.Println("调用了天气工具")
                    log.Printf("参数是:%s", toolCall.Function.Arguments)

                    var args map[string]interface{}
                    if err := json.Unmarshal([]byte(toolCall.Function.Arguments), &args); err != nil {
                        log.Printf("解析 Arguments 失败: %v", err)
                        continue
                    }

                    location, ok := args["location"].(string)
                    if !ok {
                        log.Println("location 字段不存在或不是字符串类型")
                        continue
                    }
                    log.Printf("0")
                    transport := transport.NewStdio("./mcp_server", nil, "")
                    mcpClient := client.NewClient(transport)
                    log.Printf("1")
                    ctx,cancel := context.WithTimeout(context.Background(),100*time.Second)
                    defer cancel()
                    if err := mcpClient.Start(ctx); err != nil {
                        log.Fatalf("MCP 客户端启动失败: %v", err)
                    }
                    defer mcpClient.Close()
                    log.Printf("2")
                    initReq := mcp.InitializeRequest{
                        Params: mcp.InitializeParams{
                            // Capabilities: mcp.ClientCapabilities{},
                            ProtocolVersion: mcp.LATEST_PROTOCOL_VERSION,
                            ClientInfo: mcp.Implementation{
                                Name:    "weather",
                                Version: "1.0.0",
                            },
                        },
                    }
                    log.Printf("3.5")
                    initResult, err := mcpClient.Initialize(ctx, initReq);
                    if  err != nil {
                        log.Fatalf("MCP 初始化失败: %v", err)
                    }
                    fmt.Printf("初始化成功,服务器信息: %s %s\n", initResult.ServerInfo.Name, initResult.ServerInfo.Version)

                    log.Printf("3")

                    weatherReq := mcp.CallToolRequest{
                        Request: mcp.Request{Method: "tools/call"},
                        Params: mcp.CallToolParams{
                            Name: "weather",
                            Arguments: map[string]interface{}{
                                "location": location,
                            },
                        },
                    }

                    log.Printf("4")
                    result, err := mcpClient.CallTool(ctx, weatherReq)
                    if err != nil {
                        log.Fatalf("调用天气工具失败: %v", err)
                    }

                    log.Printf("天气查询结果: %+v", result)

                }
            }

img


如上,我在为我的LLM添加MCP Server 中Tool的调用,因此初始化为一个客户端。但是在执行 initResult, err := mcpClient.Initialize(ctx, initReq); 这行代码的时候,会卡住,通过终端打印也可以看出来,我设置的上下文过期时间为100秒,感觉已经可以排除网络问题了,所以原因到底在哪。transport的mcp_server是我自己写的,在终端可以正常运行,并返回信息,如图(已经统一了服务端与客户端的版本号)

img

补充服务端实现

服务端

看见回答说要对客户端初始化请求做响应,但是我用的是mark3labs/mcp-go的库,是这个库没有封装初始化响应吗,有没有知道的,还是说我需要创建一个会话管理?

    s := server.NewMCPServer(
        "weather",
        "1.0.0",
        server.WithToolCapabilities(true),
        server.WithRecovery(),
    )

    weather.RegisterWeatherTool(s)

    fmt.Printf("0")
    if err := server.ServeStdio(s); err != nil {
        fmt.Printf("server start error: %v\n", err)
    }

    fmt.Printf("1")

  • 写回答

4条回答 默认 最新

  • 一杯年华@编程空间 2025-07-28 18:29
    关注

    一杯年华@编程空间帮您解答,本答案结合 ChatGPT4.0和DeepSeek整理
    我曾经遇到过类似的问题,客户端初始化时卡在连接环节并超时,大概率是客户端与服务端的交互链路或协议处理出了问题。结合你的情况,我分析可能是服务端对初始化请求的处理不完整,或者客户端与服务端的通信链路存在隐性阻塞。

    这里有两种解决方案供你参考:

    第一种是检查服务端对初始化请求的响应逻辑。MCP客户端初始化时,会向服务端发送Initialize请求,只有服务端正确接收并返回响应后,初始化才能完成。你提到服务端能正常返回天气信息,但可能忽略了对初始化请求的处理——比如服务端代码里是否有专门接收并处理Initialize请求的逻辑,是否能按照MCP协议规范组装并返回初始化响应。如果服务端漏了这一步,客户端会一直等待响应,最终触发超时。

    第二种是排查客户端与服务端的通信通道是否通畅。你用了stdio作为传输方式,需要确认客户端通过该通道发送的初始化请求是否能被服务端正确接收,以及服务端的响应是否能顺利传回客户端。比如,服务端的stdio输入输出是否被其他逻辑占用(比如打印日志时阻塞了通信流),或者客户端的传输配置(如路径、权限)是否存在隐性问题,导致数据传输单向不通。

    其中最优的方案是优先检查服务端对初始化请求的处理逻辑。因为你的服务端能返回天气信息,说明工具调用的链路基本可行,但初始化是更前置的环节——服务端必须先处理并响应初始化请求,才能建立后续的交互基础。你可以先确认服务端是否能“感知”到客户端发送的Initialize请求(比如在服务端加日志,记录是否收到初始化请求),再检查服务端是否按照MCP协议要求的格式返回了初始化结果。如果服务端能正确接收并返回初始化响应,客户端的超时问题通常会迎刃而解。

    希望这些思路能帮到你,楼主可以试试看,如有问题请继续留言,也请采纳我的建议~

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 8月8日
  • 已采纳回答 7月31日
  • 修改了问题 7月29日
  • 创建了问题 7月28日