Files
moss-ai/mcp/didatodolist-mcp/tools/project_tools.py

280 lines
8.1 KiB
Python
Raw Normal View History

2025-12-15 22:05:56 +08:00
"""
项目相关MCP工具
"""
from typing import Dict, List, Optional, Any
from fastmcp import FastMCP
from .adapter import adapter, APIError
# --- 模块级核心逻辑函数 ---
def get_projects_logic() -> List[Dict[str, Any]]:
"""
获取所有项目列表 (逻辑部分)
Returns:
项目列表 (包含 id, name, color, sortOrder, sortType, modifiedTime)
"""
projects = adapter.list_projects()
# 直接返回官方结构的精简版
result: List[Dict[str, Any]] = []
for p in projects:
result.append({k: v for k, v in p.items() if v is not None})
return result
def create_project_logic(
name: str,
color: Optional[str] = None,
view_mode: Optional[str] = None,
kind: Optional[str] = None,
sort_order: Optional[int] = None
) -> Dict[str, Any]:
"""
创建新项目 (逻辑部分)
Args:
name: 项目名称
color: 项目颜色 "#FF0000" 表示红色
Returns:
创建的项目信息 (API 原始响应)
"""
payload = {"name": name, "color": color}
if view_mode is not None:
payload["viewMode"] = view_mode
if kind is not None:
payload["kind"] = kind
if sort_order is not None:
payload["sortOrder"] = sort_order
payload = {k: v for k, v in payload.items() if v is not None}
return adapter.create_project(**payload)
def update_project_logic(
project_id_or_name: str,
name: Optional[str] = None,
color: Optional[str] = None,
view_mode: Optional[str] = None,
kind: Optional[str] = None,
sort_order: Optional[int] = None
) -> Dict[str, Any]:
"""
更新项目信息 (逻辑部分)
Args:
project_id_or_name: 项目ID或项目名称
name: 新项目名称
color: 新项目颜色
Returns:
更新操作的结果字典 (包含 success, info, data)
"""
# 获取项目信息
projects = get_projects_logic()
# 查找项目
project = None
project_id = None
# 先尝试按ID查找
for p in projects:
if p.get('id') == project_id_or_name:
project = p
project_id = p.get('id')
break
# 如果没找到,按名称查找
if not project:
for p in projects:
if p.get('name') == project_id_or_name:
project = p
project_id = p.get('id')
break
if not project or not project_id:
return {
"success": False,
"info": f"未找到ID或名称为 '{project_id_or_name}' 的项目",
"data": None
}
try:
# 准备更新数据
update_data = {
"id": project_id,
"name": name if name is not None else project.get('name'),
"color": color if color is not None else project.get('color')
}
if view_mode is not None:
update_data["viewMode"] = view_mode
if kind is not None:
update_data["kind"] = kind
if sort_order is not None:
update_data["sortOrder"] = sort_order
# 移除 name 和 color 为 None 的情况,避免 API 报错
update_data = {k:v for k,v in update_data.items() if v is not None}
# 发送更新请求
response = adapter.update_project(project_id, name=name, color=color)
updated_project_data = response if isinstance(response, dict) else {**update_data, "id": project_id}
updated_project_data['id'] = project_id # 确保 ID 在返回数据中
return {
"success": True,
"info": "项目更新成功",
"data": updated_project_data
}
except Exception as e:
# 更新项目失败禁用print避免干扰JSONRPC
pass
return {
"success": False,
"info": f"更新项目失败: {str(e)}",
"data": None
}
def delete_project_logic(project_id_or_name: str) -> Dict[str, Any]:
"""
删除项目 (逻辑部分)
Args:
project_id_or_name: 项目ID或项目名称
Returns:
删除操作的响应字典 (包含 success, info, data)
"""
# 获取项目信息
projects = get_projects_logic()
# 查找项目
project = None
project_id = None
# 先尝试按ID查找
for p in projects:
if p.get('id') == project_id_or_name:
project = p
project_id = p.get('id')
break
# 如果没找到,按名称查找
if not project:
for p in projects:
if p.get('name') == project_id_or_name:
project = p
project_id = p.get('id')
break
if not project or not project_id:
return {
"success": False,
"info": f"未找到ID或名称为 '{project_id_or_name}' 的项目",
"data": None
}
try:
# 发送删除请求
# 滴答清单删除项目通常不需要请求体直接调用DELETE方法
adapter.delete_project(project_id)
return {
"success": True,
"info": f"成功删除项目 '{project.get('name')}'",
"data": project # 返回被删除项目的信息
}
except Exception as e:
# 删除项目失败禁用print避免干扰JSONRPC
pass
return {
"success": False,
"info": f"删除项目失败: {str(e)}",
"data": None
}
# --- MCP工具注册 ---
def register_project_tools(server: FastMCP, auth_info: Dict[str, Any]):
"""
注册项目相关工具到MCP服务器
Args:
server: MCP服务器实例
auth_info: 认证信息字典包含token或email/password
"""
# 适配层按需初始化,无需在此显式初始化
@server.tool()
def get_projects() -> List[Dict[str, Any]]:
"""
获取所有项目列表
(调用模块级逻辑函数)
Returns:
项目列表
"""
return get_projects_logic()
@server.tool()
def create_project(
name: str,
color: Optional[str] = None,
view_mode: Optional[str] = None,
kind: Optional[str] = None,
sort_order: Optional[int] = None
) -> Dict[str, Any]:
"""
创建新项目
(调用模块级逻辑函数)
Args:
name: 项目名称
color: 项目颜色 "#FF0000" 表示红色
Returns:
创建的项目信息 (API 原始响应)
"""
return create_project_logic(name=name, color=color, view_mode=view_mode, kind=kind, sort_order=sort_order)
@server.tool()
def update_project(
project_id_or_name: str,
name: Optional[str] = None,
color: Optional[str] = None,
view_mode: Optional[str] = None,
kind: Optional[str] = None,
sort_order: Optional[int] = None
) -> Dict[str, Any]:
"""
更新项目信息
(调用模块级逻辑函数)
Args:
project_id_or_name: 项目ID或项目名称
name: 新项目名称
color: 新项目颜色
Returns:
更新操作的结果字典 (包含 success, info, data)
"""
return update_project_logic(project_id_or_name=project_id_or_name, name=name, color=color, view_mode=view_mode, kind=kind, sort_order=sort_order)
@server.tool()
def delete_project(project_id_or_name: str) -> Dict[str, Any]:
"""
删除项目
(调用模块级逻辑函数)
Args:
project_id_or_name: 项目ID或项目名称
Returns:
删除操作的响应字典 (包含 success, info, data)
"""
return delete_project_logic(project_id_or_name=project_id_or_name)
# 导出可供外部引用的函数
__all__ = [
'get_projects_logic',
'create_project_logic',
'update_project_logic',
'delete_project_logic',
'register_project_tools'
]