package mcp import ( "context" "yunyan/comm" "yunyan/lego/core" "yunyan/lego/core/cbase" "yunyan/lego/sys/log" "yunyan/lego/sys/mysql" "yunyan/pb" "yunyan/utils" "fmt" "time" "github.com/mark3labs/mcp-go/mcp" ) // 取消用户任务工具 type tool_cancel_user_task struct { cbase.ModuleCompBase module *Mcp } func (this *tool_cancel_user_task) 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_cancel_user_task) Start() (err error) { err = this.ModuleCompBase.Start() this.module.AddTool(ToolGroup_GLOBAL, this.Tool(), this.Handl) return } func (this *tool_cancel_user_task) Tool() mcp.Tool { return mcp.NewTool("cancel_user_task", mcp.WithDescription("取消用户的提醒任务"), // uid 不再是必填:身份由请求头里的 JWT 决定。保留这个参数只为兼容 // 百炼后台已配好的工具定义,传上来也只会被拿去和会话 uid 比对。 mcp.WithString("uid", mcp.Description("用户ID(可省略,服务端以登录身份为准)"), ), mcp.WithNumber("task_id", mcp.Description("要取消的任务ID"), mcp.Required(), ), ) } func (this *tool_cancel_user_task) Handl(ctx context.Context, request mcp.CallToolRequest) (result *mcp.CallToolResult, err error) { this.module.Debug("tool_cancel_user_task", log.Field{Key: "request.Params.Arguments", Value: request.GetRawArguments()}, ) // ⚠️ 参数里的 uid 只用于比对,**绝不作为身份来源**。真正的身份从 // Authorization 里的 JWT 解出来(见 auth.go)。此前这里直接信任模型填的 uid, // 而 MCP 是公网可达且无鉴权的独立服务,等于谁都能读改任意人的数据。 argUID := request.GetString("uid", "") uid, err := this.module.ResolveUID(ctx, argUID) if err != nil { return mcp.NewToolResultError(err.Error()), nil } taskId := request.GetInt("task_id", 0) if taskId <= 0 { return mcp.NewToolResultError("task_id is required"), nil } // 查找任务并验证归属 task := &pb.DBTask{} if findErr := mysql.FindOne(comm.TableAllhelpTask, task, "id = ?", taskId); findErr != nil { return mcp.NewToolResultError("任务不存在"), nil } if task.Uid != uid { return mcp.NewToolResultError("无权操作该任务"), nil } if task.Status != pb.TaskStatus_TaskStatus_Pending { return mcp.NewToolResultError(fmt.Sprintf("任务当前状态(%d)无法取消", task.Status)), nil } now := time.Now().Unix() updateErr := mysql.Table(comm.TableAllhelpTask).Where("id = ?", taskId).Updates(map[string]interface{}{ "status": int32(pb.TaskStatus_TaskStatus_Cancelled), "update_time": now, "finish_time": now, }).Error if updateErr != nil { this.module.Errorln("cancel_user_task error:", updateErr) return mcp.NewToolResultError("取消任务失败"), nil } text := utils.ToString(map[string]interface{}{ "result": "success", "task_id": task.Id, "message": fmt.Sprintf("已成功取消任务「%s」", task.TaskName), }) result = &mcp.CallToolResult{ Content: []mcp.Content{ mcp.TextContent{ Type: "text", Text: text, }, }, } return }