当前位置: 首页 > news >正文

第四章:Go语言大模型调用框架 - Eino (MCP调用示例)

1. mcp简介MCPModel Context Protocol模型上下文协议就是为了解决这个问题而生的。它定义了一套标准化的协议让任何语言、任何平台上的工具都能以统一的方式暴露给大模型使用。你可以把 MCP 理解成 AI 世界的 USB 接口——不管是键盘、鼠标还是U盘只要遵循 USB 标准插上就能用。同样不管工具是用什么语言写的、跑在哪台机器上只要实现了 MCP 协议Agent 就能直接调用。2. mcp server 示例packagemainimport(contextfmtgithub.com/mark3labs/mcp-go/mcpgithub.com/mark3labs/mcp-go/serverlogstringstimeunicode/utf8)// 处理字符串工具funchandleStringTransform(ctx context.Context,req mcp.CallToolRequest)(*mcp.CallToolResult,error){text:req.GetString(text,)operation:req.GetString(operation,)varresultstringswitchoperation{caseto_upper:resultstrings.ToUpper(text)caseto_lower:resultstrings.ToLower(text)caseto_count:count:utf8.RuneCountInString(text)resultfmt.Sprintf(字符串长度为: %d,count)casereverse:runes:[]rune(text)fori,j:0,len(runes)-1;ij;i,ji1,j-1{runes[i],runes[j]runes[j],runes[i]}resultstring(runes)default:returnmcp.NewToolResultError(不支持的操作类型: operation),nil}returnmcp.NewToolResultText(result),nil}// 时间工具的 handlerfunchandleTimeUtil(ctx context.Context,req mcp.CallToolRequest)(*mcp.CallToolResult,error){operation:req.GetString(operation,)format:req.GetString(format,2006-01-02 15:04:05)switchoperation{casenow:returnmcp.NewToolResultText(time.Now().Format(format)),nilcasediff:date1Str:req.GetString(date1,)date2Str:req.GetString(date2,)ifdate1Str||date2Str{returnmcp.NewToolResultError(计算日期差需要提供 date1 和 date2 参数),nil}d1,err:time.Parse(2006-01-02,date1Str)iferr!nil{returnmcp.NewToolResultError(date1 格式错误请使用 2006-01-02 格式),nil}d2,err:time.Parse(2006-01-02,date2Str)iferr!nil{returnmcp.NewToolResultError(date2 格式错误请使用 2006-01-02 格式),nil}diff:d2.Sub(d1)days:int(diff.Hours()/24)returnmcp.NewToolResultText(fmt.Sprintf(%s 到 %s 相差 %d 天,date1Str,date2Str,days)),nildefault:returnmcp.NewToolResultError(不支持的操作类型: operation),nil}}funcmain(){// 创建MCP server,声明名称和版本s:server.NewMCPServer(DevToolbox,1.0.0,server.WithToolCapabilities(true),)// 注册字符串处理工具s.AddTool(mcp.NewTool(string_transform,mcp.WithDescription(字符串处理工具,支持大小写转换和字数统计),mcp.WithString(text,mcp.Required(),mcp.Description(要处理的文本内容),),mcp.WithString(operation,mcp.Required(),mcp.Description(操作类型),mcp.Enum(to_upper,to_lower,count_chars,reverse),),),handleStringTransform,)// 注册时间工具s.AddTool(mcp.NewTool(time_util,mcp.WithDescription(时间工具支持获取当前时间和计算日期差),mcp.WithString(operation,mcp.Required(),mcp.Description(操作类型),mcp.Enum(now,diff),),mcp.WithString(format,mcp.Description(时间格式默认为 2006-01-02 15:04:05),),mcp.WithString(date1,mcp.Description(第一个日期格式 2006-01-02计算日期差时必填),),mcp.WithString(date2,mcp.Description(第二个日期格式 2006-01-02计算日期差时必填),),),handleTimeUtil,)// 以 SSE 方式启动 ServersseServer:server.NewSSEServer(s,server.WithBaseURL(http://localhost:8080),)fmt.Println(MCP Server (DevToolbox) 启动中监听 :8080 ...)iferr:sseServer.Start(:8080);err!nil{log.Fatal(err)}}3. mcp client 连接 server 示例packagemainimport(contextfmtgithub.com/mark3labs/mcp-go/clientgithub.com/mark3labs/mcp-go/mcplogtime)funcmain(){ctx,cancel:context.WithTimeout(context.Background(),30*time.Second)defercancel()// 创建 SSE Client连接到 MCP Servercli,err:client.NewSSEMCPClient(http://localhost:8080/sse)iferr!nil{log.Fatalf(创建 Client 失败: %v,err)}// 启动连接errcli.Start(ctx)iferr!nil{log.Fatal(err)}defercli.Close()// 握手发送 Initialize 请求initReq:mcp.InitializeRequest{}initReq.Params.ProtocolVersionmcp.LATEST_PROTOCOL_VERSION initReq.Params.ClientInfomcp.Implementation{Name:demo-client,Version:1.0.0,}serverInfo,err:cli.Initialize(ctx,initReq)iferr!nil{log.Fatalf(握手失败: %v,err)}fmt.Printf(已连接到 Server: %s (v%s)\n\n,serverInfo.ServerInfo.Name,serverInfo.ServerInfo.Version)// 发现工具获取 Server 上所有可用的工具toolsResult,err:cli.ListTools(ctx,mcp.ListToolsRequest{})iferr!nil{log.Fatalf(获取工具列表失败: %v,err)}fmt.Printf(发现 %d 个工具:\n,len(toolsResult.Tools))for_,t:rangetoolsResult.Tools{fmt.Printf( - %s: %s\n,t.Name,t.Description)}fmt.Println()// 调用工具字符串转大写callReq:mcp.CallToolRequest{}callReq.Params.Namestring_transformcallReq.Params.Argumentsmap[string]interface{}{text:hello, mcp world!,operation:to_upper,}result,err:cli.CallTool(ctx,callReq)iferr!nil{log.Fatalf(调用工具失败: %v,err)}for_,content:rangeresult.Content{iftc,ok:content.(mcp.TextContent);ok{fmt.Printf(字符串转大写结果: %s\n,tc.Text)}}// 调用工具获取当前时间callReq2:mcp.CallToolRequest{}callReq2.Params.Nametime_utilcallReq2.Params.Argumentsmap[string]interface{}{date1:2026-05-26,date2:2026-05-30,operation:diff,}result2,err:cli.CallTool(ctx,callReq2)iferr!nil{log.Fatalf(调用工具失败: %v,err)}for_,content:rangeresult2.Content{iftc,ok:content.(mcp.TextContent);ok{fmt.Printf(当前时间: %s\n,tc.Text)}}}4. 使用eino的桥接工具获取server端的所有工具packagemainimport(contextfmtmcppgithub.com/cloudwego/eino-ext/components/tool/mcpgithub.com/mark3labs/mcp-go/clientgithub.com/mark3labs/mcp-go/mcplogtime)funcmain(){ctx,cancel:context.WithTimeout(context.Background(),30*time.Second)defercancel()// 连接到mcp servercli,err:client.NewSSEMCPClient(http://localhost:8080/sse)iferr!nil{log.Fatalf(创建 Client 失败: %v,err)}// 启动 SSE 传输层 — Initialize 之前必须先启动底层连接iferr:cli.Start(ctx);err!nil{log.Fatalf(启动传输失败: %v,err)}defercli.Close()// 初始化握手initReq:mcp.InitializeRequest{}initReq.Params.ProtocolVersionmcp.LATEST_PROTOCOL_VERSION initReq.Params.ClientInfomcp.Implementation{Name:eino-bridge-demo,Version:1.0.0,}_,errcli.Initialize(ctx,initReq)iferr!nil{log.Fatalf(握手失败: %v,err)}// 关键一步用 Eino 桥接组件把 MCP 工具转换为 Eino Tooltools,err:mcpp.GetTools(ctx,mcpp.Config{Cli:cli})iferr!nil{log.Fatal(err)}fmt.Printf(成功桥接 %d 个 MCP 工具为 Eino Tool:\n\n,len(tools))fori,t:rangetools{info,_:t.Info(ctx)fmt.Printf([%d] 名称: %s\n 描述: %s\n 参数Schema: %v\n\n,i1,info.Name,info.Desc,info.ParamsOneOf)}}5. 在agent中调用 mcp 工具示例packagemainimport(contextfmtgithub.com/cloudwego/eino-ext/components/model/openaimcppgithub.com/cloudwego/eino-ext/components/tool/mcpgithub.com/cloudwego/eino/components/toolgithub.com/cloudwego/eino/composegithub.com/cloudwego/eino/flow/agent/reactgithub.com/cloudwego/eino/schemagithub.com/mark3labs/mcp-go/clientgithub.com/mark3labs/mcp-go/mcplog)// 连接MCP Server获取工具funcconnectMcpServer(ctx context.Context)([]tool.BaseTool,func()){cli,err:client.NewSSEMCPClient(http://localhost:8080/sse)iferr!nil{log.Fatalf(创建 Client 失败: %v,err)}iferr:cli.Start(ctx);err!nil{log.Fatalf(启动传输失败: %v,err)}initReq:mcp.InitializeRequest{}initReq.Params.ProtocolVersionmcp.LATEST_PROTOCOL_VERSION initReq.Params.ClientInfomcp.Implementation{Name:eino-agent,Version:1.0.0,}_,errcli.Initialize(ctx,initReq)iferr!nil{log.Fatalf(握手失败: %v,err)}tools,err:mcpp.GetTools(ctx,mcpp.Config{Cli:cli})iferr!nil{log.Fatal(桥接工具失败)}returntools,func(){cli.Close()}}funcmain(){ctx:context.Background()// 第一步连接 MCP Server获取工具 mcpTools,cleanup:connectMcpServer(ctx)defercleanup()// 第二步创建大模型实例 model,err:openai.NewChatModel(ctx,openai.ChatModelConfig{BaseURL:https://api-inference.modelscope.cn/v1/,APIKey:xxx,// api_keyModel:Qwen/Qwen3.5-35B-A3B,})iferr!nil{log.Fatalf(创建 ChatModel 失败: %v,err)}// 第三步创建 Agent 实例 agent,err:react.NewAgent(ctx,react.AgentConfig{ToolCallingModel:model,ToolsConfig:compose.ToolsNodeConfig{Tools:mcpTools,},})iferr!nil{log.Fatalf(创建 Agent 失败: %v,err)}// 第四步与 Agent 对话 questions:[]string{请帮我把 hello world from mcp 这段文字转成大写,现在时间是几点,}fori,q:rangequestions{fmt.Printf( 问题 %d \n,i1)fmt.Printf(用户: %s\n\n,q)result,err:agent.Generate(ctx,[]*schema.Message{{Role:schema.User,Content:q},})iferr!nil{fmt.Printf(Agent 执行出错: %v\n\n,err)continue}fmt.Printf(Agent: %s\n\n,result.Content)}}注意 在client, 桥接agent 测试时都需要启动 mcp server 才能正常调用。
http://www.zskr.cn/news/1403381.html

相关文章:

  • 2.5D芯粒测试新架构:基于测试总线与中键合旁路的设计实践
  • 基于深度卷积特征匹配的通信辐射源识别:从射频指纹到硬件身份验证
  • 2026年苏州军事夏令营哪家强?这些企业值得你深入了解! - GrowthUME
  • 2026全国帽子工厂推荐榜:靠谱实力厂家盘点,出货快品质稳首选 - 变量人生001
  • SAT求解器与硬件模型检查:CDCL算法、插值与IC3的工程实践
  • 3个关键技术点构建企业级网络资源管理系统
  • 【生成模型】从概率视角理解VAE:变分自编码器的核心思想与实战解析
  • 如何轻松下载微信视频号、抖音和小红书的精彩内容?
  • 基于双深度神经网络的变压器差动保护抗CT饱和与涌流识别技术
  • ChatGPT歌词辅助不是“抄”,而是“重构”:基于NLP韵律学的5维质量评估体系(附开源打分工具)
  • BLMVisor:裸金属云实时迁移技术解析与性能评估
  • 何庭波重磅论文揭秘:告别“几何缩微”,华为芯片开启“τ(韬)定律”时代
  • 无人值守停车场解决方案完全指南(2026版)
  • 工业增强现实(IAR)在造船厂的应用评估与实战指南
  • 济南各区黄金回收哪家合适?2026年5月行情及变现指南 - 润富黄金珠宝行
  • 国产数据库优化差距肉眼可见:KES的DISTINCT智能改写深度拆解
  • agent tool 代码修复
  • 淄博各区黄金回收门店全覆盖实测:张店淄川博山周村临淄桓台,六家正规店一文讲透 - 润富黄金珠宝行
  • 全网小说下载终极指南:novel-downloader 让你轻松保存心爱小说
  • 2026年顶尖8款AI简历工具深度评测:告别盲投,直击HR心坎的秘籍
  • 终极Windows OCR文字识别方案:Text Grab四大模式让屏幕文字无处可逃
  • 邯郸市2026年5月黄金回收避坑指南:高位金价下如何守住自己的钱袋子? - 润富黄金珠宝行
  • 一份 Agent 工程岗 JD,暴露了市场真正想要什么样的人
  • 突破传统农业监控瓶颈:ESP32边缘计算实战指南
  • 2026年5月济南黄金回收市场解析 附正规变现渠道汇总 - 润富黄金珠宝行
  • 如何轻松探索本地大语言模型的无限可能:llama-cpp-python实践指南
  • 从不确定性到确定性:切比雪夫、大数定律与中心极限定理的工程实践指南
  • 【具身智能】校招求职群
  • Python路径操作实战:巧用glob.glob()与os.path.join()实现高效文件定位与组装
  • ChatGPT生日派对创意终极验证:在14个国家实测后,这5种结构化提示词转化率超行业均值3.8倍