package mcp import ( "context" "yunyan/lego/core" "yunyan/lego/core/cbase" "yunyan/lego/sys/log" "yunyan/sys/hefengweather" "yunyan/utils" "fmt" "time" "github.com/mark3labs/mcp-go/mcp" ) // 和风天气查询 type tool_hefeng_weather struct { cbase.ModuleCompBase module *Mcp } // 组件初始化接口 func (this *tool_hefeng_weather) Init(service core.IService, module core.IModule, comp core.IModuleComp, opt core.IModuleOptions) (err error) { this.ModuleCompBase.Init(service, module, comp, opt) this.module = module.(*Mcp) return } func (this *tool_hefeng_weather) Start() (err error) { err = this.ModuleCompBase.Start() if this.module.AddTool(ToolGroup_GLOBAL, this.Tool(), this.Handl) { if err := hefengweather.OnInit(this.module.service.GetSettings().Sys["hefengweather"]); err != nil { panic(fmt.Sprintf("init sys.hefengweather err: %s", err.Error())) } else { log.Infof("init sys.hefengweather success!") } } return } func (this *tool_hefeng_weather) Tool() (tool mcp.Tool) { return mcp.NewTool("hefeng_weather", mcp.WithDescription("根据城市名称查询对应城市的实时和未来天气信息"), mcp.WithString("city", mcp.Description("城市名称 例如:'北京'"), mcp.Required(), ), mcp.WithString("time", mcp.Description("查询时间 ,格式:'yyyy-MM-dd',例如:'2025-03-12'"), ), ) } // Handl 工具处理接口 // 参数: // - ctx: 上下文 // - request: MCP 工具调用请求 // // 返回值: // - result: MCP 工具调用结果 // - err: 处理过程中的错误 // // 异常: // - 无(不主动 panic) func (this *tool_hefeng_weather) Handl(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) { var ( city string day string cityresult *hefengweather.CityLookupResponse weatherresult *hefengweather.WeatherResponse context string ) this.module.Debug("tool_hefeng_weather", log.Field{Key: "request.Params.Arguments", Value: request.GetRawArguments()}, ) day = request.GetString("time", "") if day == "" { day = time.Now().Format("2006-01-02") } else { if !isValidDate(day) { switch day { case "今天": day = time.Now().Format("2006-01-02") case "明天": day = time.Now().AddDate(0, 0, 1).Format("2006-01-02") case "后天": day = time.Now().AddDate(0, 0, 2).Format("2006-01-02") default: day = time.Now().Format("2006-01-02") } } } if city, err = request.RequireString("city"); err != nil || city == "" { err = nil result = mcp.NewToolResultError("缺少必要参数 city,请补充需要查询的城市名称后重试") return } //城市查询失败(网络错误、返回码非200、没有匹配到城市)统一按工具错误返回,交给模型自行纠正参数 if cityresult, err = hefengweather.CityLookup(city); err != nil || cityresult == nil || cityresult.Code != "200" || len(cityresult.Location) == 0 { log.Error("获取天气信息失败", log.Field{Key: "city", Value: city}, log.Field{Key: "day", Value: day}, log.Field{Key: "err", Value: err}, ) err = nil result = mcp.NewToolResultError(fmt.Sprintf("查询目标城市信息失败 city:%s,请重新确认城市名是否正确", city)) return } if weatherresult, err = hefengweather.QueryWeather(cityresult.Location[0].ID); err != nil || weatherresult == nil || weatherresult.Code != "200" { this.module.Debug("tool_hefeng_weather fail", log.Field{Key: "city", Value: city}, log.Field{Key: "day", Value: day}, log.Field{Key: "err", Value: err}, ) err = nil result = mcp.NewToolResultError(fmt.Sprintf("查询目标城市天气信息失败 city:%s,请重新确认城市名是否正确", city)) return } else { context = utils.ToString(map[string]interface{}{ "city": city, "day": day, "data": weatherresult.Daily, "iscard": true, "broadcast": true, }) this.module.Debug("tool_hefeng_weather success", log.Field{Key: "city", Value: city}, log.Field{Key: "result", Value: weatherresult}, ) } result = &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: context, }, }, } return }