generate_documentation_navigation
Create a JSON-based navigation structure from markdown documents in a specified directory for use in navigation menus. Supports path and recursive options for flexible document organization.
Instructions
Generate a navigation structure from the markdown documents in the docs directory. Returns a JSON structure that can be used for navigation menus.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| basePath | No | ||
| path | No | ||
| recursive | No |
Implementation Reference
- src/handlers/navigation.ts:24-122 (handler)Core handler implementation: NavigationHandler.generateNavigation method that scans markdown files, parses frontmatter for titles and order, builds hierarchical navigation structure, sorts by order, and returns JSON.async generateNavigation(basePath = ""): Promise<ToolResponse> { try { const baseDir = path.join(this.docsDir, basePath); const pattern = path.join(baseDir, "**/*.md"); const files = await glob(pattern); // Sort files to ensure consistent order and process index.md files first files.sort((a, b) => { const aIsIndex = path.basename(a) === "index.md"; const bIsIndex = path.basename(b) === "index.md"; if (aIsIndex && !bIsIndex) return -1; if (!aIsIndex && bIsIndex) return 1; return a.localeCompare(b); }); const navigation: any[] = []; const directoryMap: Record<string, any> = {}; for (const file of files) { const relativePath = path.relative(this.docsDir, file); const content = await fs.readFile(file, "utf-8"); const { frontmatter } = parseFrontmatter(content); const title = frontmatter.title || path.basename(file, ".md"); const order = frontmatter.order !== undefined ? Number(frontmatter.order) : 999; const item = { title, path: relativePath, order, children: [], }; const dirPath = path.dirname(relativePath); if (dirPath === "." || dirPath === basePath) { navigation.push(item); } else { // Create parent directories if they don't exist in the navigation const pathParts = dirPath.split(path.sep); let currentPath = ""; let currentNavigation = navigation; for (const part of pathParts) { currentPath = currentPath ? path.join(currentPath, part) : part; if (!directoryMap[currentPath]) { const dirItem = { title: part, path: currentPath, order: 0, children: [], }; directoryMap[currentPath] = dirItem; currentNavigation.push(dirItem); } currentNavigation = directoryMap[currentPath].children; } currentNavigation.push(item); } } // Sort navigation items by order function sortNavigation(items: any[]) { items.sort((a, b) => a.order - b.order); for (const item of items) { if (item.children && item.children.length > 0) { sortNavigation(item.children); } } } sortNavigation(navigation); return { content: [{ type: "text", text: JSON.stringify(navigation, null, 2) }], }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error generating navigation: ${errorMessage}`, }, ], isError: true, }; } }
- src/schemas/tools.ts:13-16 (schema)Input schema for the tool, Zod schema defining optional basePath and recursive flag.export const ListDocumentsSchema = ToolInputSchema.extend({ basePath: z.string().optional(), recursive: z.boolean().default(false), });
- src/index.ts:236-241 (registration)Tool registration in ListToolsRequestSchema handler: defines name, description, and input schema.name: "generate_documentation_navigation", description: "Generate a navigation structure from the markdown documents in the docs directory. " + "Returns a JSON structure that can be used for navigation menus.", inputSchema: zodToJsonSchema(ListDocumentsSchema) as any, },
- src/index.ts:375-385 (registration)Dispatch logic in CallToolRequestSchema switch: validates input with ListDocumentsSchema and calls NavigationHandler.generateNavigation.case "generate_documentation_navigation": { const parsed = ListDocumentsSchema.safeParse(args); if (!parsed.success) { throw new Error( `Invalid arguments for generate_navigation: ${parsed.error}` ); } return await navigationHandler.generateNavigation( parsed.data.basePath ); }