"""
README工具模块
提供README文档生成相关工具。
"""
from typing import Optional, List
from pathlib import Path
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from middleware.logging import log_performance
from middleware import logging_middleware, error_handler_middleware
from services.document_service import DocumentService
from data_access.file_system import FileSystemInterface
class GenerateReadmeInput(BaseModel):
"""生成README输入模型"""
folder_path: str = Field(..., description="要生成README的文件夹路径")
template_name: str = Field(default="simple", description="使用的模板名称")
force_update: bool = Field(default=False, description="是否强制更新已存在的README")
include_hidden: bool = Field(default=False, description="是否包含隐藏文件")
def register_readme_tools(
mcp_server: FastMCP,
document_service: DocumentService,
file_system: FileSystemInterface
):
"""
注册README相关工具
Args:
mcp_server: FastMCP服务器实例
document_service: 文档服务实例
file_system: 文件系统接口实例
"""
@mcp_server.tool(
name="folder_docs_generate_readme",
description="为指定文件夹生成README.md文档",
input_schema=GenerateReadmeInput.model_json_schema()
)
@log_performance("generate_readme")
@error_handler_middleware.handle_errors("generate_readme")
async def generate_readme(input_data: dict) -> dict:
"""
生成README文档
Args:
input_data: 输入参数
Returns:
生成结果
"""
# 解析输入参数
try:
params = GenerateReadmeInput(**input_data)
except (RuntimeError, ValueError) as e:
return {
"success": False,
"error": f"参数解析失败: {str(e)}"
}
try:
# 验证路径
is_valid, error_msg = await file_system.validate_path(params.folder_path)
if not is_valid:
return {
"success": False,
"error": f"路径验证失败: {error_msg}"
}
# 生成README
result = await document_service.generate_readme(
folder_path=params.folder_path,
template_name=params.template_name,
force_update=params.force_update,
include_hidden=params.include_hidden
)
return result
except (RuntimeError, ValueError) as e:
return {
"success": False,
"error": f"生成README失败: {str(e)}"
}
@mcp_server.tool(
name="folder_docs_preview_readme",
description="预览将要生成的README内容(不实际写入文件)",
input_schema=GenerateReadmeInput.model_json_schema()
)
@log_performance("preview_readme")
@error_handler_middleware.handle_errors("preview_readme")
async def preview_readme(input_data: dict) -> dict:
"""
预览README内容
Args:
input_data: 输入参数
Returns:
预览结果
"""
# 解析输入参数
try:
params = GenerateReadmeInput(**input_data)
except (RuntimeError, ValueError) as e:
return {
"success": False,
"error": f"参数解析失败: {str(e)}"
}
try:
# 验证路径
is_valid, error_msg = await file_system.validate_path(params.folder_path)
if not is_valid:
return {
"success": False,
"error": f"路径验证失败: {error_msg}"
}
# 预览README
result = await document_service.preview_readme(
folder_path=params.folder_path,
template_name=params.template_name,
include_hidden=params.include_hidden
)
return result
except (RuntimeError, ValueError) as e:
return {
"success": False,
"error": f"预览README失败: {str(e)}"
}
@mcp_server.tool(
name="folder_docs_check_readme_exists",
description="检查指定文件夹是否存在README文件",
input_schema={
"type": "object",
"properties": {
"folder_path": {
"type": "string",
"description": "要检查的文件夹路径"
}
},
"required": ["folder_path"]
}
)
@log_performance("check_readme_exists")
@error_handler_middleware.handle_errors("check_readme_exists")
async def check_readme_exists(input_data: dict) -> dict:
"""
检查README是否存在
Args:
input_data: 输入参数
Returns:
检查结果
"""
folder_path = input_data.get("folder_path")
if not folder_path:
return {
"success": False,
"error": "缺少必需参数: folder_path"
}
try:
# 验证路径
is_valid, error_msg = await file_system.validate_path(folder_path)
if not is_valid:
return {
"success": False,
"error": f"路径验证失败: {error_msg}"
}
# 检查README文件
readme_paths = [
Path(folder_path) / "README.md",
Path(folder_path) / "readme.md",
Path(folder_path) / "README.txt"
]
existing_readmes = []
for readme_path in readme_paths:
if readme_path.exists():
existing_readmes.append({
"path": str(readme_path),
"size": readme_path.stat().st_size,
"modified": readme_path.stat().st_mtime
})
return {
"success": True,
"exists": len(existing_readmes) > 0,
"readme_files": existing_readmes,
"folder_path": folder_path
}
except (RuntimeError, ValueError) as e:
return {
"success": False,
"error": f"检查README失败: {str(e)}"
}