package mcp import ( "context" "yunyan/lego/core" "yunyan/lego/core/cbase" "yunyan/lego/sys/log" "yunyan/sys/amap" "yunyan/utils" "fmt" "strings" "time" "github.com/mark3labs/mcp-go/mcp" ) // 天气卡片数据 结构统一化输出 type WeatherCard struct { City string `json:"city"` //城市 Day *WeatherCarditem `json:"day"` //查询的天气 DayWeather []*WeatherCarditem `json:"dayweather"` //天气 } // 天气卡片数据 结构统一化输出 type WeatherCarditem struct { Date string `json:"date"` //时间 Temperature string `json:"temperature"` //实时温度 MinTemperature string `json:"minTemperature"` //最低温度 MaxTemperature string `json:"maxTemperature"` //最高温度 WeatherCondition string `json:"weatherCondition"` //天气现象,如:"阴" WindDirection string `json:"windDirection"` //风向 WindForce string `json:"windForce"` //风力 } // 天气查询 type tool_gaode_map_weather struct { cbase.ModuleCompBase module *Mcp } // 组件初始化接口 func (this *tool_gaode_map_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_gaode_map_weather) Start() (err error) { err = this.ModuleCompBase.Start() if this.module.AddTool(ToolGroup_CHINA, this.Tool(), this.Handl) { if err := amap.OnInit(this.module.service.GetSettings().Sys["amap"]); err != nil { panic(fmt.Sprintf("init sys.amap err: %s", err.Error())) } else { log.Infof("init sys.amap success!") } } return } func (this *tool_gaode_map_weather) Tool() (tool mcp.Tool) { return mcp.NewTool("gaode_map_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_gaode_map_weather) Handl(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) { var ( city string day string georesult *amap.GeocodeResponse weatherresult *amap.WeatherResponse daydata *WeatherCarditem card *WeatherCard context string ) this.module.Debug("tool_gaode_map_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 = fmt.Errorf("必要参数丢失") } if err == nil { if georesult, err = amap.Geo("", city); err == nil { if georesult.Geocodes != nil && len(georesult.Geocodes) > 0 { weatherresult, err = amap.Weather(georesult.Geocodes[0].Adcode, "all") } else { err = fmt.Errorf("查询目标城市信息失败 city:%s", city) } } } if err != nil { context = "获取天气信息失败" this.module.Debug("tool_gaode_map_weather fail", log.Field{Key: "city", Value: city}, log.Field{Key: "day", Value: day}, log.Field{Key: "err", Value: err}, ) } else { if len(weatherresult.Forecasts) > 0 && weatherresult.Forecasts[0].Casts != nil && len(weatherresult.Forecasts[0].Casts) > 0 { card = &WeatherCard{ City: city, DayWeather: make([]*WeatherCarditem, 0), } for _, v := range weatherresult.Forecasts[0].Casts { daydata = &WeatherCarditem{ Date: v.Date, Temperature: v.Daytemp, MinTemperature: v.Nighttemp, MaxTemperature: v.Daytemp, WeatherCondition: v.Dayweather, WindDirection: v.Daywind, WindForce: v.Daypower, } card.DayWeather = append(card.DayWeather, daydata) if strings.Contains(v.Date, day) { card.Day = daydata context = fmt.Sprintf("%s:%s的天气情况:%s,温度:%s,风向:%s,风力:%s", city, day, v.Dayweather, v.Daytemp, v.Daywind, v.Daypower, ) } } if card.Day == nil { card.Day = card.DayWeather[0] } if context == "" { context = utils.ToString(weatherresult) } this.module.Debug("tool_gaode_map_weather success", log.Field{Key: "city", Value: city}, log.Field{Key: "card", Value: card}, log.Field{Key: "context", Value: context}, ) } else { context = "获取天气信息失败,我只能获取未来4天的天气数据" } } result = &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: context, }, }, } // if card != nil { // result.Meta = map[string]interface{}{ // "card_weather": card, // } // } return }