validate_documentation_links
Check for broken internal links in documentation files to maintain content integrity and improve user navigation.
Instructions
Check for broken internal links in documentation files.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| path | No | ||
| basePath | No | ||
| recursive | No |
Implementation Reference
- src/handlers/documents.ts:795-879 (handler)The main handler function that implements the logic for the 'validate_documentation_links' tool. It scans all markdown files in the specified base path (recursively or not), finds internal markdown links, resolves them relative to the file, and checks if the target files exist, collecting broken links.async validateLinks(basePath = "", recursive = true): Promise<ToolResponse> { try { const validBasePath = await this.validatePath(basePath || this.docsDir); // Find all markdown files const pattern = recursive ? "**/*.md" : "*.md"; const files = await glob(pattern, { cwd: validBasePath }); const brokenLinks: Array<{ file: string; link: string; lineNumber: number; }> = []; // Check each file for links for (const file of files) { const filePath = path.join(validBasePath, file); const content = await fs.readFile(filePath, "utf-8"); const lines = content.split("\n"); // Find markdown links: [text](path) const linkRegex = /\[([^\]]+)\]\(([^)]+)\)/g; for (let i = 0; i < lines.length; i++) { const line = lines[i]; let match; while ((match = linkRegex.exec(line)) !== null) { const [, , linkPath] = match; // Skip external links and anchors if ( linkPath.startsWith("http://") || linkPath.startsWith("https://") || linkPath.startsWith("#") || linkPath.startsWith("mailto:") ) { continue; } // Resolve the link path relative to the current file const fileDir = path.dirname(filePath); const resolvedPath = path.resolve(fileDir, linkPath); // Check if the link target exists try { await fs.access(resolvedPath); } catch { brokenLinks.push({ file: path.relative(this.docsDir, filePath), link: linkPath, lineNumber: i + 1, }); } } } } return { content: [ { type: "text", text: brokenLinks.length > 0 ? `Found ${brokenLinks.length} broken links in ${files.length} files` : `No broken links found in ${files.length} files`, }, ], metadata: { brokenLinks, filesChecked: files.length, basePath: path.relative(this.docsDir, validBasePath), }, }; } catch (error) { const errorMessage = error instanceof Error ? error.message : String(error); return { content: [ { type: "text", text: `Error validating links: ${errorMessage}` }, ], isError: true, }; } }
- src/schemas/tools.ts:93-96 (schema)Zod schema defining the input parameters for the 'validate_documentation_links' tool: optional basePath and recursive flag.export const ValidateLinksSchema = ToolInputSchema.extend({ basePath: z.string().optional().default(""), recursive: z.boolean().default(true), });
- src/index.ts:284-289 (registration)Tool registration in the ListTools response, defining name, description, and input schema for 'validate_documentation_links'.{ name: "validate_documentation_links", description: "Check for broken internal links in documentation files.", inputSchema: zodToJsonSchema(ValidateLinksSchema) as any, },
- src/index.ts:470-481 (registration)Dispatch/registration in the CallToolRequest handler switch statement, parsing input with ValidateLinksSchema and calling documentHandler.validateLinks.case "validate_documentation_links": { const parsed = ValidateLinksSchema.safeParse(args); if (!parsed.success) { throw new Error( `Invalid arguments for validate_links: ${parsed.error}` ); } return await documentHandler.validateLinks( parsed.data.basePath, parsed.data.recursive ); }