Skip to main content
Glama
generate-docs.ts6.94 kB
import type { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js'; import { z } from 'zod'; import fs from 'fs-extra'; import path from 'path'; interface DocumentationStructure { title: string; sections: { title: string; content: string; subsections?: DocumentationStructure[]; }[]; } export default function registerGenerateDocsTool(server: McpServer) { server.registerTool( 'generate-docs', { title: 'Generate Documentation', description: 'Generates documentation for a project including README, API docs, and code documentation.', inputSchema: { project_path: z.string().describe('Path to the project directory'), output_dir: z.string().optional().default('./docs').describe('Output directory for generated documentation'), include_api_docs: z.boolean().optional().default(true).describe('Include API documentation'), include_code_docs: z.boolean().optional().default(true).describe('Include code documentation'), template: z.enum(['simple', 'detailed', 'api-focused']).optional().default('simple').describe('Documentation template style'), }, }, async (params: { project_path: string; output_dir?: string; include_api_docs?: boolean; include_code_docs?: boolean; template?: 'simple' | 'detailed' | 'api-focused'; }) => { try { const { project_path, output_dir = './docs', include_api_docs = true, include_code_docs = true, template = 'simple' } = params; if (!(await fs.pathExists(project_path))) { return { content: [{ type: 'text', text: `Error: Project directory does not exist: ${project_path}` }], isError: true, }; } // Ensure output directory exists const fullOutputDir = path.isAbsolute(output_dir) ? output_dir : path.join(project_path, output_dir); await fs.ensureDir(fullOutputDir); // Read package.json if it exists let packageInfo = null; const packageJsonPath = path.join(project_path, 'package.json'); if (await fs.pathExists(packageJsonPath)) { try { packageInfo = JSON.parse(await fs.readFile(packageJsonPath, 'utf-8')); } catch (error) { // Ignore package.json parsing errors } } // Generate different documentation based on template const docs: { [key: string]: string } = {}; // Main README docs['README.md'] = generateReadme(packageInfo, template); if (include_api_docs) { docs['API.md'] = generateApiDocs(project_path, template); } if (include_code_docs) { docs['CODE.md'] = await generateCodeDocs(project_path, template); } // Write all documentation files const createdFiles: string[] = []; for (const [filename, content] of Object.entries(docs)) { const filePath = path.join(fullOutputDir, filename); await fs.writeFile(filePath, content); createdFiles.push(filePath); } return { content: [ { type: 'text', text: `Successfully generated documentation in ${createdFiles.length} files:\n${createdFiles.join('\n')}`, }, ], }; } catch (error: any) { return { content: [{ type: 'text', text: `Error generating documentation: ${error.message}` }], isError: true, }; } } ); } function generateReadme(packageInfo: any, template: string): string { const name = packageInfo?.name || 'Project'; const description = packageInfo?.description || 'A software project'; const version = packageInfo?.version || '1.0.0'; let readme = `# ${name} ${description} ## Version ${version} `; if (template === 'detailed') { readme += `## Installation \`\`\`bash npm install ${name} \`\`\` ## Usage \`\`\`javascript import { ${name} } from '${name}'; // Example usage const result = ${name}.example(); console.log(result); \`\`\` ## API Reference See [API.md](./API.md) for detailed API documentation. ## Development See [CODE.md](./CODE.md) for code documentation. `; } readme += `## License This project is licensed under the MIT License. `; return readme; } function generateApiDocs(projectPath: string, template: string): string { let apiDocs = `# API Documentation This document contains the API reference for the project. `; if (template === 'api-focused') { apiDocs += `## Core Modules ### Main Module - **Location**: \`src/index.ts\` - **Purpose**: Main entry point - **Exports**: Public API functions and classes ### Utility Modules - **Location**: \`src/utils/\` - **Purpose**: Helper functions and utilities - **Exports**: Utility functions ## API Reference ### Functions #### \`main()\` Main entry point function. **Returns**: \`Promise<void>\` ### Classes #### \`ExampleClass\` Example class for demonstration. **Constructor**: \`new ExampleClass(options)\` **Methods**: - \`method1(param: string): boolean\` - \`method2(param: number): void\` `; } return apiDocs; } async function generateCodeDocs(projectPath: string, template: string): Promise<string> { let codeDocs = `# Code Documentation This document contains documentation for the codebase structure and implementation details. `; try { // Try to analyze source files const srcDir = path.join(projectPath, 'src'); if (await fs.pathExists(srcDir)) { const files = await fs.readdir(srcDir, { recursive: true }); const tsFiles = files.filter(file => typeof file === 'string' && file.endsWith('.ts')); codeDocs += `## Source Files (${tsFiles.length} files) ### Core Files `; for (const file of tsFiles.slice(0, 10)) { // Show first 10 files const filePath = path.join(srcDir, file as string); try { const content = await fs.readFile(filePath, 'utf-8'); const lines = content.split('\n'); // Extract function/class names const functions = content.match(/function\s+(\w+)|const\s+(\w+)\s*=\s*\([^)]*\)\s*=>/g) || []; const classes = content.match(/class\s+(\w+)/g) || []; codeDocs += `- **${file}**`; if (functions.length > 0) { codeDocs += ` - Functions: ${functions.slice(0, 3).join(', ')}`; } if (classes.length > 0) { codeDocs += ` - Classes: ${classes.slice(0, 3).join(', ')}`; } codeDocs += '\n'; } catch (error) { // Ignore file reading errors } } if (tsFiles.length > 10) { codeDocs += `\n*... and ${tsFiles.length - 10} more files*\n`; } } } catch (error) { codeDocs += `\n*Could not analyze source files: ${error}*\n`; } return codeDocs; }

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/Yussefgafer/MyMCP'

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