Skip to main content
Glama
libra850
by libra850

find_broken_links

Detect and fix broken links in Obsidian vaults to maintain note connectivity and improve content organization.

Instructions

壊れたリンクの検出と修復支援を行います

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Primary tool handler that implements the logic to find broken links in Obsidian vault by scanning all MD files for wiki and markdown links, verifying targets, and providing similarity-based suggestions.
    async findBrokenLinks(): Promise<{
      brokenLinks: Array<{
        sourceFile: string;
        linkText: string;
        targetPath: string;
        lineNumber: number;
        suggestions: string[];
      }>;
      totalCount: number;
    }> {
      const vaultPath = this.config.vaultPath;
      const brokenLinks: Array<{
        sourceFile: string;
        linkText: string;
        targetPath: string;
        lineNumber: number;
        suggestions: string[];
      }> = [];
    
      // すべてのMarkdownファイルを取得
      const allMdFiles = await this.getAllMdFiles(vaultPath);
      const allFileBasenames = allMdFiles.map(file => path.basename(file, '.md'));
    
      const processFile = async (filePath: string) => {
        try {
          const content = await fs.readFile(filePath, 'utf-8');
          const lines = content.split('\n');
          const relativeFilePath = path.relative(vaultPath, filePath);
    
          for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) {
            const line = lines[lineIndex];
            
            // ウィキリンク [[]] の検出
            const wikiLinkMatches = line.matchAll(/\[\[([^\]|]+)(\|[^\]]+)?\]\]/g);
            for (const match of wikiLinkMatches) {
              const targetPath = match[1];
              const linkText = match[2] ? match[2].substring(1) : targetPath;
              
              // ターゲットファイルの存在確認
              const possiblePaths = [
                path.join(vaultPath, `${targetPath}.md`),
                path.join(vaultPath, targetPath),
              ];
    
              let exists = false;
              for (const possiblePath of possiblePaths) {
                if (await FileUtils.fileExists(possiblePath)) {
                  exists = true;
                  break;
                }
              }
    
              if (!exists) {
                // 修復候補を検索
                const suggestions = this.findSimilarFiles(targetPath, allFileBasenames);
                brokenLinks.push({
                  sourceFile: relativeFilePath,
                  linkText,
                  targetPath,
                  lineNumber: lineIndex + 1,
                  suggestions,
                });
              }
            }
    
            // Markdownリンク []() の検出
            const mdLinkMatches = line.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g);
            for (const match of mdLinkMatches) {
              const linkText = match[1];
              const targetPath = match[2];
    
              // 内部リンク(.mdファイル)のみチェック
              if (targetPath.endsWith('.md') || !targetPath.includes('://')) {
                const fullTargetPath = path.resolve(path.dirname(filePath), targetPath);
                
                if (!(await FileUtils.fileExists(fullTargetPath))) {
                  const suggestions = this.findSimilarFiles(path.basename(targetPath, '.md'), allFileBasenames);
                  brokenLinks.push({
                    sourceFile: relativeFilePath,
                    linkText,
                    targetPath,
                    lineNumber: lineIndex + 1,
                    suggestions,
                  });
                }
              }
            }
          }
        } catch (error) {
          // ファイル読み込みエラーは無視
        }
      };
    
      // すべてのMarkdownファイルを処理
      for (const filePath of allMdFiles) {
        await processFile(filePath);
      }
    
      return {
        brokenLinks,
        totalCount: brokenLinks.length,
      };
    }
  • src/server.ts:192-199 (registration)
    MCP tool registration defining the name, description, and input schema for find_broken_links.
    {
      name: 'find_broken_links',
      description: '壊れたリンクの検出と修復支援を行います',
      inputSchema: {
        type: 'object',
        properties: {},
      },
    },
  • Server-side dispatch handler that invokes the ObsidianHandler's findBrokenLinks method and formats the response as MCP content.
    case 'find_broken_links':
      const brokenLinksResult = await this.obsidianHandler.findBrokenLinks();
      return {
        content: [
          {
            type: 'text',
            text: JSON.stringify(brokenLinksResult, null, 2),
          },
        ],
      };
  • Helper utility to generate file name suggestions for broken links using similarity scoring.
    private findSimilarFiles(targetName: string, allFileBasenames: string[]): string[] {
      const target = targetName.toLowerCase();
      const suggestions: { name: string; score: number }[] = [];
    
      for (const filename of allFileBasenames) {
        const score = this.calculateSimilarity(target, filename.toLowerCase());
        if (score > 0.3) { // 30%以上の類似度
          suggestions.push({ name: filename, score });
        }
      }
    
      return suggestions
        .sort((a, b) => b.score - a.score)
        .slice(0, 5)
        .map(s => s.name);
    }
  • Helper to recursively collect all Markdown files in the vault.
    private async getAllMdFiles(dirPath: string): Promise<string[]> {
      const files: string[] = [];
      
      const processDirectory = async (currentPath: string) => {
        try {
          const entries = await fs.readdir(currentPath, { withFileTypes: true });
          
          for (const entry of entries) {
            const fullPath = path.join(currentPath, entry.name);
            
            if (entry.isDirectory()) {
              await processDirectory(fullPath);
            } else if (entry.isFile() && entry.name.endsWith('.md')) {
              files.push(fullPath);
            }
          }
        } catch (error) {
          // ディレクトリ読み込みエラーは無視
        }
      };
      
      await processDirectory(dirPath);
      return files;
    }

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/libra850/obsidian-mcp-server'

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