Go 语言如何开发一个 MCP Client ? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
Markxu0
V2EX    Go 编程语言

Go 语言如何开发一个 MCP Client ?

  •  
  •   Markxu0 252 天前 3161 次点击
    这是一个创建于 252 天前的主题,其中的信息可能已经有所发展或是发生改变。

    目标

    首先感谢:探索 MCP-我的学习与实践笔记

    我想写个能够支持 MCP 协议的对话终端,类似 cheery-ai 这种,通过 config.json 配置 MCP Server ,在终端中实现对话。

    困扰

    MCP Server 的实现搜索到了不少资料,也比较好理解。但是关于 Go 语言实现 MCP Client 的资料看到比较少。

    关于 MCP Client 的实现参考了: cp_simple_chatbot

    初步是想着把 Python 代码翻译为 Go 代码,使用 Go 三方库metoro-io/mcp-golang, 翻译如下代码

     async def start(self) -> None: """Main chat session handler.""" try: for server in self.servers: try: await server.initialize() except Exception as e: logging.error(f"Failed to initialize server: {e}") await self.cleanup_servers() return all_tools = [] for server in self.servers: tools = await server.list_tools() all_tools.extend(tools) tools_description = "\n".join([tool.format_for_llm() for tool in all_tools]) system_message = ( "You are a helpful assistant with access to these tools:\n\n" f"{tools_description}\n" "Choose the appropriate tool based on the user's question. " "If no tool is needed, reply directly.\n\n" "IMPORTANT: When you need to use a tool, you must ONLY respond with " "the exact JSON object format below, nothing else:\n" "{\n" ' "tool": "tool-name",\n' ' "arguments": {\n' ' "argument-name": "value"\n' " }\n" "}\n\n" "After receiving a tool's response:\n" "1. Transform the raw data into a natural, conversational response\n" "2. Keep responses concise but informative\n" "3. Focus on the most relevant information\n" "4. Use appropriate context from the user's question\n" "5. Avoid simply repeating the raw data\n\n" "Please use only the tools that are explicitly defined above." ) messages = [{"role": "system", "content": system_message}] while True: try: user_input = input("You: ").strip().lower() if user_input in ["quit", "exit"]: logging.info("\nExiting...") break messages.append({"role": "user", "content": user_input}) llm_respOnse= self.llm_client.get_response(messages) logging.info("\nAssistant: %s", llm_response) result = await self.process_llm_response(llm_response) if result != llm_response: messages.append({"role": "assistant", "content": llm_response}) messages.append({"role": "system", "content": result}) final_respOnse= self.llm_client.get_response(messages) logging.info("\nFinal response: %s", final_response) messages.append( {"role": "assistant", "content": final_response} ) else: messages.append({"role": "assistant", "content": llm_response}) except KeyboardInterrupt: logging.info("\nExiting...") break finally: await self.cleanup_servers() 

    主要思路是将 “告诉 AI 工具清单”,以及 “AI 分析你的需求,决定用哪个工具” 这段逻辑翻译一下,然后使用 mcp-golang 来处理和 MCP Server 的连接。

    目前问题就来了,这样实现感觉不够优雅。MCP Client 的 SDK 其实可以把 LLM+'MCP Server'封装到一起,向大模型提问就可以调用 MCP Server, 引用 SDK 的人就不需要再手动实现“把工具清单告诉 AI”,以及“AI 分析你的需求,决定用哪个工具”逻辑了。

    问题

    问题 1: 如果我翻译“告诉 AI 工具清单”,以及 “AI 分析你的需求,决定用哪个工具”这段代码,感觉实现不够优雅,其他类似的 MCP Client (如 Cline 、CherryAi 等)是如何实现的呢?

    问题 2:Go 语言有类似 mcp_simple_chatbot 的示例代码吗?

    问题 3:如果是你,你会如何实现这个需求呢?

    5 条回复    2025-03-26 13:57:39 +08:00
    harlen
        1
    harlen  
       252 天前
    GitHub topic MCP 然后找评分最高的实现,借鉴一下
    kaneg
        2
    kaneg  
       251 天前
    一般这类需求,如果是 OpenAI , 用 function call 比用自然语言约束要方便和精准。
    sz1211
        3
    sz1211  
       251 天前
    @kaneg open ai 不是支持 response format 吗
    rkonfj
        4
    rkonfj  
       249 天前 via iPhone
    iamzcr
        5
    iamzcr  
       249 天前
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2816 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 32ms UTC 13:04 PVG 21:04 LAX 05:04 JFK 08:04
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86