package controllers import ( "encoding/json" "fmt" "io" "strconv" "strings" "time" "server/models" "server/pkg/jwtutil" beego "github.com/beego/beego/v2/server/web" ) // BackendMcpToolController MCP工具控制器 type BackendMcpToolController struct { beego.Controller } func (c *BackendMcpToolController) mcpClaims() (*jwtutil.Claims, error) { auth := c.Ctx.Request.Header.Get("Authorization") if auth == "" { return nil, fmt.Errorf("未登录") } parts := strings.SplitN(auth, " ", 2) if len(parts) != 2 || parts[0] != "Bearer" { return nil, fmt.Errorf("认证信息格式错误") } claims, err := jwtutil.ParseToken(parts[1]) if err != nil { return nil, fmt.Errorf("无效的token") } if claims.UserType != "backend" { return nil, fmt.Errorf("无权访问") } return claims, nil } func (c *BackendMcpToolController) mcpJsonErr(httpStatus, bizCode int, msg string) { c.Ctx.Output.SetStatus(httpStatus) c.Data["json"] = map[string]interface{}{"code": bizCode, "msg": msg} _ = c.ServeJSON() } func (c *BackendMcpToolController) mcpOk(data interface{}) { c.Data["json"] = map[string]interface{}{"code": 200, "msg": "success", "data": data} _ = c.ServeJSON() } type mcpToolPayload struct { Name string `json:"name"` Type string `json:"type"` URL string `json:"url"` Method string `json:"method"` Headers string `json:"headers"` Params string `json:"params"` Body string `json:"body"` Enabled int8 `json:"enabled"` Remark string `json:"remark"` } // List GET /backend/mcp/tool/list func (c *BackendMcpToolController) List() { claims, err := c.mcpClaims() if err != nil { c.mcpJsonErr(401, 401, err.Error()) return } var list []models.BackendMcpTool _, err = models.Orm.QueryTable(new(models.BackendMcpTool)). Filter("tenant_id", fmt.Sprintf("%d", claims.TenantId)). Filter("user_id", uint64(claims.UserID)). Filter("delete_time__isnull", true). OrderBy("-id"). All(&list) if err != nil { c.mcpJsonErr(500, 500, "查询失败: "+err.Error()) return } c.mcpOk(map[string]interface{}{"list": list}) } // Create POST /backend/mcp/tool func (c *BackendMcpToolController) Create() { claims, err := c.mcpClaims() if err != nil { c.mcpJsonErr(401, 401, err.Error()) return } body, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.mcpJsonErr(400, 400, "读取请求体失败") return } var p mcpToolPayload if err := json.Unmarshal(body, &p); err != nil { c.mcpJsonErr(400, 400, "参数格式错误") return } if strings.TrimSpace(p.Name) == "" { c.mcpJsonErr(400, 400, "工具名称不能为空") return } if strings.TrimSpace(p.URL) == "" { c.mcpJsonErr(400, 400, "API地址不能为空") return } tool := models.BackendMcpTool{ TenantID: fmt.Sprintf("%d", claims.TenantId), UserID: uint64(claims.UserID), Name: strings.TrimSpace(p.Name), Type: strings.TrimSpace(p.Type), URL: strings.TrimSpace(p.URL), Method: strings.TrimSpace(p.Method), Headers: strings.TrimSpace(p.Headers), Params: strings.TrimSpace(p.Params), Body: strings.TrimSpace(p.Body), Enabled: p.Enabled, Remark: strings.TrimSpace(p.Remark), CreateTime: time.Now(), UpdateTime: time.Now(), } id, err := models.Orm.Insert(&tool) if err != nil { c.mcpJsonErr(500, 500, "创建失败: "+err.Error()) return } c.mcpOk(map[string]interface{}{"id": id}) } // Update PUT /backend/mcp/tool/:id func (c *BackendMcpToolController) Update() { claims, err := c.mcpClaims() if err != nil { c.mcpJsonErr(401, 401, err.Error()) return } idStr := c.Ctx.Input.Param(":id") id, err := strconv.ParseUint(idStr, 10, 64) if err != nil { c.mcpJsonErr(400, 400, "ID格式错误") return } tool := models.BackendMcpTool{ID: id} if err := models.Orm.Read(&tool); err != nil { c.mcpJsonErr(404, 404, "工具不存在") return } if tool.TenantID != fmt.Sprintf("%d", claims.TenantId) { c.mcpJsonErr(403, 403, "无权操作") return } body, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.mcpJsonErr(400, 400, "读取请求体失败") return } var p mcpToolPayload if err := json.Unmarshal(body, &p); err != nil { c.mcpJsonErr(400, 400, "参数格式错误") return } tool.Name = strings.TrimSpace(p.Name) tool.Type = strings.TrimSpace(p.Type) tool.URL = strings.TrimSpace(p.URL) tool.Method = strings.TrimSpace(p.Method) tool.Headers = strings.TrimSpace(p.Headers) tool.Params = strings.TrimSpace(p.Params) tool.Body = strings.TrimSpace(p.Body) tool.Enabled = p.Enabled tool.Remark = strings.TrimSpace(p.Remark) tool.UpdateTime = time.Now() _, err = models.Orm.Update(&tool) if err != nil { c.mcpJsonErr(500, 500, "更新失败: "+err.Error()) return } c.mcpOk(nil) } // Delete DELETE /backend/mcp/tool/:id func (c *BackendMcpToolController) Delete() { claims, err := c.mcpClaims() if err != nil { c.mcpJsonErr(401, 401, err.Error()) return } idStr := c.Ctx.Input.Param(":id") id, err := strconv.ParseUint(idStr, 10, 64) if err != nil { c.mcpJsonErr(400, 400, "ID格式错误") return } tool := models.BackendMcpTool{ID: id} if err := models.Orm.Read(&tool); err != nil { c.mcpJsonErr(404, 404, "工具不存在") return } if tool.TenantID != fmt.Sprintf("%d", claims.TenantId) { c.mcpJsonErr(403, 403, "无权操作") return } now := time.Now() tool.DeleteTime = &now _, err = models.Orm.Update(&tool, "delete_time") if err != nil { c.mcpJsonErr(500, 500, "删除失败: "+err.Error()) return } c.mcpOk(nil) } // Test POST /backend/mcp/tool/test func (c *BackendMcpToolController) Test() { // 验证用户登录状态 if _, err := c.mcpClaims(); err != nil { c.mcpJsonErr(401, 401, err.Error()) return } body, err := io.ReadAll(c.Ctx.Request.Body) if err != nil { c.mcpJsonErr(400, 400, "读取请求体失败") return } var p mcpToolPayload if err := json.Unmarshal(body, &p); err != nil { c.mcpJsonErr(400, 400, "参数格式错误") return } if strings.TrimSpace(p.URL) == "" { c.mcpJsonErr(400, 400, "API地址不能为空") return } // TODO: 实现MCP工具测试逻辑 // 这里只是一个示例实现,实际测试逻辑需要根据工具类型和配置来实现 c.mcpOk(map[string]interface{}{ "success": true, "message": "测试连接成功", "method": p.Method, "url": p.URL, }) }