You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

141 lines
4.1 KiB

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
}