Skip to main content
Glama

Documentation Generator MCP Server

by srwlli
server.py9.19 kB
#!/usr/bin/env python3 """ Documentation Generation MCP Server Provides tools for generating project documentation using POWER framework templates. """ import asyncio from pathlib import Path from mcp.server import Server from mcp.types import Tool, TextContent from mcp.server.stdio import stdio_server # Import generators from generators import FoundationGenerator, BaseGenerator # Get server directory SERVER_DIR = Path(__file__).parent TEMPLATES_DIR = SERVER_DIR / "templates" / "power" FRAMEWORKS_DIR = SERVER_DIR / "frameworks" # Create MCP server app = Server("docs-mcp") @app.list_tools() async def list_tools() -> list[Tool]: """List available documentation tools.""" return [ Tool( name="list_templates", description="Lists all available documentation templates (README, ARCHITECTURE, API, COMPONENTS, SCHEMA)", inputSchema={ "type": "object", "properties": {}, "required": [] } ), Tool( name="get_template", description="Retrieves the content of a specific documentation template", inputSchema={ "type": "object", "properties": { "template_name": { "type": "string", "description": "Name of template: readme, architecture, api, components, schema, or user-guide", "enum": ["readme", "architecture", "api", "components", "schema", "user-guide"] } }, "required": ["template_name"] } ), Tool( name="list_frameworks", description="Lists available prompt framework documentation (POWER, COSTAR, Five S, CRISPE)", inputSchema={ "type": "object", "properties": {}, "required": [] } ), Tool( name="generate_foundation_docs", description="Generate foundation documentation (README, ARCHITECTURE, API, COMPONENTS, SCHEMA) for a project. Returns templates and generation plan - Claude will generate and save the actual documents.", inputSchema={ "type": "object", "properties": { "project_path": { "type": "string", "description": "Absolute path to the project directory" } }, "required": ["project_path"] } ), Tool( name="generate_individual_doc", description="Generate a single individual documentation file for a project. Returns the template - Claude will generate and save the document.", inputSchema={ "type": "object", "properties": { "project_path": { "type": "string", "description": "Absolute path to the project directory" }, "template_name": { "type": "string", "description": "Name of template to generate", "enum": ["readme", "architecture", "api", "components", "schema", "user-guide"] } }, "required": ["project_path", "template_name"] } ) ] @app.call_tool() async def call_tool(name: str, arguments: dict) -> list[TextContent]: """Handle tool calls.""" if name == "list_templates": try: templates = [] if TEMPLATES_DIR.exists(): for file in TEMPLATES_DIR.glob("*.txt"): templates.append(file.stem) if templates: result = "Available POWER Framework Templates:\n\n" for i, template in enumerate(sorted(templates), 1): result += f"{i}. {template}\n" result += f"\nTotal: {len(templates)} templates" else: result = "No templates found in templates/power/" return [TextContent(type="text", text=result)] except Exception as e: return [TextContent(type="text", text=f"Error listing templates: {str(e)}")] elif name == "get_template": template_name = arguments.get("template_name", "") template_file = TEMPLATES_DIR / f"{template_name}.txt" try: if not template_file.exists(): return [TextContent( type="text", text=f"Template '{template_name}' not found. Available: readme, architecture, api, components, schema, user-guide" )] with open(template_file, 'r', encoding='utf-8') as f: content = f.read() result = f"=== {template_name.upper()} Template ===\n\n{content}" return [TextContent(type="text", text=result)] except Exception as e: return [TextContent(type="text", text=f"Error reading template: {str(e)}")] elif name == "list_frameworks": try: frameworks = [] if FRAMEWORKS_DIR.exists(): for file in FRAMEWORKS_DIR.glob("*.md"): frameworks.append(file.name) if frameworks: result = "Available Framework Documentation:\n\n" for i, framework in enumerate(sorted(frameworks), 1): file_path = FRAMEWORKS_DIR / framework size = file_path.stat().st_size result += f"{i}. {framework} ({size:,} bytes)\n" result += f"\nTotal: {len(frameworks)} framework docs" else: result = "No framework documentation found" return [TextContent(type="text", text=result)] except Exception as e: return [TextContent(type="text", text=f"Error listing frameworks: {str(e)}")] elif name == "generate_foundation_docs": project_path = arguments.get("project_path", "") try: # Initialize foundation generator generator = FoundationGenerator(TEMPLATES_DIR) # Get generation plan plan = generator.get_generation_plan(project_path) # Get all templates templates = generator.get_templates_for_generation() # Build response result = plan + "\n\n" + "=" * 50 + "\n\n" result += "TEMPLATES FOR GENERATION:\n\n" for template in templates: if 'error' in template: result += f"ERROR - {template['template_name']}: {template['error']}\n\n" else: result += f"=== {template['template_name'].upper()} ===\n\n" result += f"{template['template_content']}\n\n" result += "-" * 50 + "\n\n" result += "\nINSTRUCTIONS:\n" result += "Generate each document in order using the templates above.\n" result += f"Save all documents to: {project_path}/docs/\n" result += "Each document should reference previous documents as indicated in the templates.\n" return [TextContent(type="text", text=result)] except Exception as e: return [TextContent(type="text", text=f"Error generating foundation docs: {str(e)}")] elif name == "generate_individual_doc": project_path = arguments.get("project_path", "") template_name = arguments.get("template_name", "") try: generator = BaseGenerator(TEMPLATES_DIR) paths = generator.prepare_generation(project_path) template_content = generator.read_template(template_name) template_info = generator.get_template_info(template_name) result = f"=== Generating {template_name.upper()} ===\n\n" result += f"Project: {paths['project_path']}\n" result += f"Output: {paths['output_dir']}/{template_info.get('save_as', f'{template_name.upper()}.md')}\n\n" result += "=" * 50 + "\n\n" result += f"TEMPLATE:\n\n{template_content}\n\n" result += "=" * 50 + "\n\n" result += "INSTRUCTIONS:\n" result += f"Generate {template_info.get('save_as', f'{template_name.upper()}.md')} using the template above.\n" result += f"Save the document to: {paths['output_dir']}/{template_info.get('save_as', f'{template_name.upper()}.md')}\n" return [TextContent(type="text", text=result)] except Exception as e: return [TextContent(type="text", text=f"Error generating individual doc: {str(e)}")] else: raise ValueError(f"Unknown tool: {name}") async def main(): """Run the server using stdio transport.""" async with stdio_server() as (read_stream, write_stream): await app.run( read_stream, write_stream, app.create_initialization_options() ) if __name__ == "__main__": asyncio.run(main())

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/srwlli/docs-mcp'

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