Skip to main content
Glama
folder_documentation_mcp.py13.7 kB
# folder_documentation_mcp.py """ MCP服务:文件夹中文说明文件生成器 功能:为项目中的每个主要文件夹添加中文说明文件和思维导图 """ from mcp.server.fastmcp import FastMCP from pydantic import BaseModel, Field from typing import Optional, List, Dict, Any import os import datetime import json # 初始化MCP服务器 mcp = FastMCP("folder_documentation_mcp") # 定义工具输入模型 class GenerateReadmeInput(BaseModel): """生成README.md文件输入模型""" root_dir: str = Field(..., description="项目根目录路径") exclude_dirs: List[str] = Field(default_factory=list, description="排除的目录列表") force_update: bool = Field(default=False, description="是否强制更新现有README.md文件") class GenerateMindmapInput(BaseModel): """生成思维导图输入模型""" root_dir: str = Field(..., description="项目根目录路径") output_file: str = Field(default="folder_structure_mindmap.md", description="思维导图输出文件路径") exclude_dirs: List[str] = Field(default_factory=list, description="排除的目录列表") class UpdateDocumentationInput(BaseModel): """更新文档输入模型""" root_dir: str = Field(..., description="项目根目录路径") exclude_dirs: List[str] = Field(default_factory=list, description="排除的目录列表") update_mindmap: bool = Field(default=True, description="是否更新思维导图") # 辅助函数:获取文件夹描述 def get_folder_description(folder_path: str) -> str: """根据文件夹名称获取中文描述""" # 预设常见文件夹的中文描述 folder_descriptions = { "skills": "技能文件夹", "skills-translated": "翻译后的技能文件夹", "技能": "中文技能文件夹", "算法艺术": "算法艺术相关技能", "品牌指南": "品牌指南相关技能", "画布设计": "画布设计相关技能", "文档协作": "文档协作相关技能", "Word文档": "Word文档处理技能", "PDF文档": "PDF文档处理技能", "PPT演示文稿": "PPT演示文稿处理技能", "Excel表格": "Excel表格处理技能", "Web应用测试": "Web应用测试技能", "Web构件构建器": "Web构件构建器技能", "前端设计": "前端设计技能", "内部通信": "内部通信技能", "主题工厂": "主题工厂技能", "MCP构建器": "MCP构建器技能", "技能创建器": "技能创建器技能", "参考": "参考文档", "脚本": "脚本文件", "示例": "示例文件", "模板": "模板文件", "规范": "规范文件", "Office开放XML": "Office开放XML相关文件", "画布字体": "画布设计使用的字体文件", "ArsenalSC": "ArsenalSC字体", "BigShoulders": "BigShoulders字体", "Boldonse": "Boldonse字体", "BricolageGrotesque": "BricolageGrotesque字体", "CrimsonPro": "CrimsonPro字体", "DMMono": "DMMono字体", "EricaOne": "EricaOne字体", "GeistMono": "GeistMono字体", "Gloock": "Gloock字体", "IBMPlexMono": "IBMPlexMono字体", "IBMPlexSerif": "IBMPlexSerif字体", "InstrumentSans": "InstrumentSans字体", "InstrumentSerif": "InstrumentSerif字体", "Italiana": "Italiana字体", "JetBrainsMono": "JetBrainsMono字体", "Jura": "Jura字体", "LibreBaskerville": "LibreBaskerville字体", "Lora": "Lora字体", "NationalPark": "NationalPark字体", "NothingYouCouldDo": "NothingYouCouldDo字体", "Outfit": "Outfit字体", "PixelifySans": "PixelifySans字体", "PoiretOne": "PoiretOne字体", "RedHatMono": "RedHatMono字体", "Silkscreen": "Silkscreen字体", "SmoochSans": "SmoochSans字体", "Tektur": "Tektur字体", "WorkSans": "WorkSans字体", "YoungSerif": "YoungSerif字体", "Slack动图创建器": "Slack动图创建器技能", "核心": "核心功能模块" } folder_name = os.path.basename(folder_path) return folder_descriptions.get(folder_name, folder_name) # 辅助函数:生成README.md内容 def generate_readme_content(folder_path: str) -> str: """生成文件夹的README.md内容""" folder_name = os.path.basename(folder_path) description = get_folder_description(folder_path) # 获取文件夹中的文件列表 files = [] subfolders = [] for item in os.listdir(folder_path): item_path = os.path.join(folder_path, item) if os.path.isfile(item_path): files.append(item) elif os.path.isdir(item_path): subfolders.append(item) # 生成README.md内容 content = f"# {description}\n\n" content += f"## 文件夹用途\n\n" content += f"该文件夹包含{description.lower()}相关的文件和子文件夹。\n\n" if subfolders: content += "## 子文件夹\n\n" for subfolder in subfolders: subfolder_desc = get_folder_description(os.path.join(folder_path, subfolder)) content += f"- **{subfolder}**: {subfolder_desc}\n" content += "\n" if files: content += "## 文件说明\n\n" for file in files: # 根据文件扩展名获取文件类型描述 file_ext = os.path.splitext(file)[1].lower() if file_ext in ['.py']: file_type = "Python脚本文件" elif file_ext in ['.md']: file_type = "Markdown文档" elif file_ext in ['.txt']: file_type = "文本文件" elif file_ext in ['.json']: file_type = "JSON配置文件" elif file_ext in ['.xsd']: file_type = "XML Schema文件" elif file_ext in ['.ttf', '.otf']: file_type = "字体文件" elif file_ext in ['.html']: file_type = "HTML文件" elif file_ext in ['.js']: file_type = "JavaScript文件" elif file_ext in ['.pdf']: file_type = "PDF文档" else: file_type = "其他文件" content += f"- **{file}**: {file_type}\n" content += f"\n## 更新时间\n\n" content += f"该文件生成于:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" return content # 辅助函数:生成文件夹结构树 def generate_folder_tree(root_dir: str, exclude_dirs: List[str], prefix: str = "", is_last: bool = True) -> str: """生成文件夹结构树""" tree = "" items = os.listdir(root_dir) items.sort() # 过滤排除的目录 items = [item for item in items if item not in exclude_dirs] for i, item in enumerate(items): is_last_item = i == len(items) - 1 item_path = os.path.join(root_dir, item) if os.path.isdir(item_path): # 添加目录到树中 connector = "└── " if is_last_item else "├── " tree += f"{prefix}{connector}{item}/\n" # 递归处理子目录 new_prefix = prefix + (" " if is_last_item else "│ ") tree += generate_folder_tree(item_path, exclude_dirs, new_prefix, is_last_item) else: # 添加文件到树中 connector = "└── " if is_last_item else "├── " tree += f"{prefix}{connector}{item}\n" return tree # 辅助函数:生成思维导图 def generate_mindmap(root_dir: str, exclude_dirs: List[str]) -> str: """生成文件夹结构思维导图""" mindmap = f"# 项目文件夹结构思维导图\n\n" mindmap += f"生成时间:{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n" # 生成Markdown格式的思维导图 mindmap += "```mermaid\n" mindmap += "flowchart TD\n" mindmap += " subgraph 项目结构\n" # 生成节点和连接 def add_nodes(path: str, parent_node: str, level: int): """递归添加节点和连接""" if level > 4: # 限制最大深度,避免思维导图过于复杂 return "" result = "" items = os.listdir(path) items.sort() items = [item for item in items if item not in exclude_dirs] for item in items: item_path = os.path.join(path, item) node_id = item_path.replace("\\", "_").replace(":", "_").replace(".", "_") node_label = item if os.path.isdir(item_path): node_label += "/" # 添加节点 result += f" {node_id}[\"{node_label}\"]\n" # 添加连接 if parent_node: result += f" {parent_node} --> {node_id}\n" # 递归处理子目录 if os.path.isdir(item_path): result += add_nodes(item_path, node_id, level + 1) return result mindmap += add_nodes(root_dir, "", 0) mindmap += " end\n" mindmap += "```\n" # 添加更新日志 mindmap += "\n## 更新日志\n\n" mindmap += f"- **{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}**: 生成初始文件夹结构思维导图\n" return mindmap # 注册工具:生成README.md文件 @mcp.tool() async def generate_readme_files(params: GenerateReadmeInput) -> str: """为项目中的每个主要文件夹生成中文README.md文件""" root_dir = params.root_dir exclude_dirs = params.exclude_dirs + [".git", ".trae", ".claude-plugin", ".claude插件"] force_update = params.force_update generated_count = 0 skipped_count = 0 # 遍历根目录下的所有文件夹 for root, dirs, files in os.walk(root_dir): # 过滤排除的目录 dirs[:] = [d for d in dirs if d not in exclude_dirs] # 为当前文件夹生成README.md文件 readme_path = os.path.join(root, "README.md") # 检查是否已存在README.md文件 if os.path.exists(readme_path) and not force_update: skipped_count += 1 continue # 生成README.md内容 readme_content = generate_readme_content(root) # 写入README.md文件 with open(readme_path, "w", encoding="utf-8") as f: f.write(readme_content) generated_count += 1 return f"已生成 {generated_count} 个README.md文件,跳过 {skipped_count} 个已存在的文件。" # 注册工具:生成思维导图 @mcp.tool() async def generate_mindmap(params: GenerateMindmapInput) -> str: """生成项目文件夹结构的思维导图""" root_dir = params.root_dir output_file = params.output_file exclude_dirs = params.exclude_dirs + [".git", ".trae", ".claude-plugin", ".claude插件"] # 生成思维导图内容 mindmap_content = generate_mindmap(root_dir, exclude_dirs) # 写入输出文件 with open(output_file, "w", encoding="utf-8") as f: f.write(mindmap_content) return f"已生成思维导图文件:{output_file}" # 注册工具:更新文档 @mcp.tool() async def update_documentation(params: UpdateDocumentationInput) -> str: """更新项目中的README.md文件和思维导图""" root_dir = params.root_dir exclude_dirs = params.exclude_dirs + [".git", ".trae", ".claude-plugin", ".claude插件"] update_mindmap_flag = params.update_mindmap # 更新README.md文件 generated_count = 0 updated_count = 0 for root, dirs, files in os.walk(root_dir): # 过滤排除的目录 dirs[:] = [d for d in dirs if d not in exclude_dirs] # 更新当前文件夹的README.md文件 readme_path = os.path.join(root, "README.md") # 生成README.md内容 readme_content = generate_readme_content(root) if os.path.exists(readme_path): # 更新现有文件 with open(readme_path, "w", encoding="utf-8") as f: f.write(readme_content) updated_count += 1 else: # 生成新文件 with open(readme_path, "w", encoding="utf-8") as f: f.write(readme_content) generated_count += 1 result = f"已更新 {updated_count} 个README.md文件,生成 {generated_count} 个新的README.md文件。\n" # 更新思维导图 if update_mindmap_flag: mindmap_path = os.path.join(root_dir, "folder_structure_mindmap.md") mindmap_content = generate_mindmap(root_dir, exclude_dirs) with open(mindmap_path, "w", encoding="utf-8") as f: f.write(mindmap_content) result += f"已更新思维导图文件:{mindmap_path}" return result # 注册工具:获取文件夹结构 @mcp.tool() async def get_folder_structure(params: GenerateReadmeInput) -> str: """获取项目的文件夹结构""" root_dir = params.root_dir exclude_dirs = params.exclude_dirs + [".git", ".trae", ".claude-plugin", ".claude插件"] # 生成文件夹结构树 folder_tree = generate_folder_tree(root_dir, exclude_dirs) return f"# 项目文件夹结构\n\n```\n{folder_tree}```" # 启动服务器 if __name__ == "__main__": mcp.run()

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/kscz0000/Zhiwen-Assistant-MCP'

If you have feedback or need assistance with the MCP directory API, please join our Discord server