| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237 |
- package data
- import (
- "context"
- "github.com/mark3labs/mcp-go/mcp"
- "fwh-toolbox-server/cmd/mcp/tools/helper"
- "fwh-toolbox-server/repositories"
- )
- // planeRawResult 将 Plane API 返回的原始 JSON bytes 转为 MCP 结果。
- // 原始字节先经流式 PII 脱敏(优化 B),脱敏失败(含非法 JSON)则返回错误、拒绝输出。
- func planeRawResult(data []byte, err error, action string) (*mcp.CallToolResult, error) {
- if err != nil {
- return helper.ServiceError(action, err), nil
- }
- return helper.BytesResultOrFileMasked(data, "plane_"+action), nil
- }
- // === Project Handlers ===
- func handlePlaneListProjects(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListProjects()
- return planeRawResult(data, err, "列出项目")
- }
- func handlePlaneGetProject(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- projectID, err := req.RequireString("project_id")
- if err != nil {
- return helper.ParamError("project_id"), nil
- }
- data, apiErr := repositories.PlaneGetProject(projectID)
- return planeRawResult(data, apiErr, "获取项目详情")
- }
- func handlePlaneGetProjectSummary(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- projectID, err := req.RequireString("project_id")
- if err != nil {
- return helper.ParamError("project_id"), nil
- }
- fields := req.GetString("fields", "")
- data, apiErr := repositories.PlaneGetProjectSummary(projectID, fields)
- return planeRawResult(data, apiErr, "获取项目摘要")
- }
- // === Work Item Handlers ===
- func handlePlaneListWorkItems(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- params := make(map[string]string)
- if v := req.GetString("state", ""); v != "" {
- params["state"] = v
- }
- if v := req.GetString("priority", ""); v != "" {
- params["priority"] = v
- }
- if v := req.GetString("assignee", ""); v != "" {
- params["assignee"] = v
- }
- if v := req.GetString("label", ""); v != "" {
- params["label"] = v
- }
- data, err := repositories.PlaneListWorkItems(params)
- return planeRawResult(data, err, "列出工作项")
- }
- func handlePlaneGetWorkItem(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneGetWorkItem(id)
- return planeRawResult(data, apiErr, "获取工作项详情")
- }
- func handlePlaneGetWorkItemByIdentifier(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- identifier, err := req.RequireString("identifier")
- if err != nil {
- return helper.ParamError("identifier"), nil
- }
- seqID := int(req.GetFloat("sequence_id", 0))
- if seqID <= 0 {
- return helper.ParamError("sequence_id"), nil
- }
- data, apiErr := repositories.PlaneGetWorkItemByIdentifier(identifier, seqID)
- return planeRawResult(data, apiErr, "通过标识符获取工作项")
- }
- func handlePlaneSearchWorkItems(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- query, err := req.RequireString("query")
- if err != nil {
- return helper.ParamError("query"), nil
- }
- limit := int(req.GetFloat("limit", 20))
- data, apiErr := repositories.PlaneSearchWorkItems(query, limit, "")
- return planeRawResult(data, apiErr, "搜索工作项")
- }
- // === Cycle Handlers ===
- func handlePlaneListCycles(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListCycles()
- return planeRawResult(data, err, "列出迭代")
- }
- func handlePlaneGetCycle(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("cycle_id")
- if err != nil {
- return helper.ParamError("cycle_id"), nil
- }
- data, apiErr := repositories.PlaneGetCycle(id)
- return planeRawResult(data, apiErr, "获取迭代详情")
- }
- func handlePlaneListCycleIssues(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("cycle_id")
- if err != nil {
- return helper.ParamError("cycle_id"), nil
- }
- data, apiErr := repositories.PlaneListCycleIssues(id)
- return planeRawResult(data, apiErr, "列出迭代工作项")
- }
- // === Module Handlers ===
- func handlePlaneListModules(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListModules()
- return planeRawResult(data, err, "列出模块")
- }
- func handlePlaneGetModule(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("module_id")
- if err != nil {
- return helper.ParamError("module_id"), nil
- }
- data, apiErr := repositories.PlaneGetModule(id)
- return planeRawResult(data, apiErr, "获取模块详情")
- }
- func handlePlaneListModuleIssues(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("module_id")
- if err != nil {
- return helper.ParamError("module_id"), nil
- }
- data, apiErr := repositories.PlaneListModuleIssues(id)
- return planeRawResult(data, apiErr, "列出模块工作项")
- }
- // === State / Label / Member Handlers ===
- func handlePlaneListStates(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListStates()
- return planeRawResult(data, err, "列出状态")
- }
- func handlePlaneListLabels(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListLabels()
- return planeRawResult(data, err, "列出标签")
- }
- func handlePlaneListWorkspaceMembers(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListWorkspaceMembers()
- return planeRawResult(data, err, "列出工作空间成员")
- }
- func handlePlaneListProjectMembers(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneListProjectMembers()
- return planeRawResult(data, err, "列出项目成员")
- }
- // === Comment / Activity / Link / Attachment / Relation Handlers ===
- func handlePlaneListWorkItemComments(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneListWorkItemComments(id)
- return planeRawResult(data, apiErr, "列出评论")
- }
- func handlePlaneListWorkItemActivities(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneListWorkItemActivities(id)
- return planeRawResult(data, apiErr, "列出活动历史")
- }
- func handlePlaneListWorkItemLinks(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneListWorkItemLinks(id)
- return planeRawResult(data, apiErr, "列出链接")
- }
- func handlePlaneListWorkItemAttachments(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneListWorkItemAttachments(id)
- return planeRawResult(data, apiErr, "列出附件")
- }
- func handlePlaneListWorkItemRelations(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("work_item_id")
- if err != nil {
- return helper.ParamError("work_item_id"), nil
- }
- data, apiErr := repositories.PlaneListWorkItemRelations(id)
- return planeRawResult(data, apiErr, "列出关系")
- }
- // === Intake Handlers ===
- func handlePlaneGetIntakeIssueList(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- data, err := repositories.PlaneGetIntakeIssueList()
- if err != nil {
- return helper.ServiceError("查询Intake列表", err), nil
- }
- return helper.JSONResultOrFileAuto(data), nil
- }
- func handlePlaneGetIntakeIssueDetail(ctx context.Context, req mcp.CallToolRequest) (*mcp.CallToolResult, error) {
- id, err := req.RequireString("intake_id")
- if err != nil {
- return helper.ParamError("intake_id"), nil
- }
- data, apiErr := repositories.PlaneGetIntakeIssueDetail(id)
- return planeRawResult(data, apiErr, "获取Intake详情")
- }
- // === V2 Web API: Page Handlers (已迁移到 plane_v2_api_handlers.go) ===
|