Skip to main content
Glama

analyze_backlinks

Analyze backlinks and graph structure for a specific note to understand connections and relationships within your Obsidian vault.

Instructions

バックリンク分析とグラフ構造の把握を行います

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
targetNoteYes分析対象のノートパス(vault相対パス)

Implementation Reference

  • Core implementation of the analyze_backlinks tool. Scans all Markdown files in the Obsidian vault for links (wiki and markdown style) pointing to the target note, extracts surrounding context, computes related notes and basic graph metrics (popularity and centrality).
    async analyzeBacklinks(targetNote: string): Promise<{ targetNote: string; backlinks: Array<{ sourceFile: string; context: string; linkType: 'wiki' | 'markdown'; }>; relatedNotes: string[]; metrics: { popularity: number; centrality: number; }; }> { if (!FileUtils.validatePath(this.config.vaultPath, targetNote)) { throw new Error('無効なターゲットノートパスです'); } const targetFullPath = path.join(this.config.vaultPath, targetNote); if (!(await FileUtils.fileExists(targetFullPath))) { throw new Error(`ターゲットノート '${targetNote}' が見つかりません`); } const vaultPath = this.config.vaultPath; const backlinks: Array<{ sourceFile: string; context: string; linkType: 'wiki' | 'markdown'; }> = []; // ターゲットノートのベース名(拡張子なし) const targetBaseName = path.basename(targetNote, '.md'); // すべてのMarkdownファイルを取得 const allMdFiles = await this.getAllMdFiles(vaultPath); 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); // ターゲットノート自体はスキップ if (path.resolve(filePath) === path.resolve(targetFullPath)) { return; } for (let lineIndex = 0; lineIndex < lines.length; lineIndex++) { const line = lines[lineIndex]; // ウィキリンク [[]] の検出 const wikiLinkMatches = line.matchAll(/\[\[([^\]|]+)(\|[^\]]+)?\]\]/g); for (const match of wikiLinkMatches) { const linkTarget = match[1]; if (linkTarget === targetBaseName || linkTarget === targetNote || linkTarget === targetNote.replace(/\.md$/, '')) { const context = this.extractContext(lines, lineIndex); backlinks.push({ sourceFile: relativeFilePath, context, linkType: 'wiki', }); } } // Markdownリンク []() の検出 const mdLinkMatches = line.matchAll(/\[([^\]]+)\]\(([^)]+)\)/g); for (const match of mdLinkMatches) { const linkTarget = match[2]; if (linkTarget.includes(targetBaseName) || linkTarget.includes(targetNote)) { const context = this.extractContext(lines, lineIndex); backlinks.push({ sourceFile: relativeFilePath, context, linkType: 'markdown', }); } } } } catch (error) { // ファイル読み込みエラーは無視 } }; // すべてのMarkdownファイルを処理 for (const filePath of allMdFiles) { await processFile(filePath); } // 関連ノートを計算(バックリンクを持つファイル) const relatedNotes = [...new Set(backlinks.map(bl => bl.sourceFile))]; // メトリクスを計算 const popularity = backlinks.length; const centrality = this.calculateCentrality(backlinks, allMdFiles.length); return { targetNote, backlinks, relatedNotes, metrics: { popularity, centrality, }, }; }
  • src/server.ts:200-213 (registration)
    MCP tool registration in the listTools response, defining the tool name, description, and input schema.
    { name: 'analyze_backlinks', description: 'バックリンク分析とグラフ構造の把握を行います', inputSchema: { type: 'object', properties: { targetNote: { type: 'string', description: '分析対象のノートパス(vault相対パス)', }, }, required: ['targetNote'], }, },
  • Input schema for the analyze_backlinks tool, specifying the required targetNote parameter.
    inputSchema: { type: 'object', properties: { targetNote: { type: 'string', description: '分析対象のノートパス(vault相対パス)', }, }, required: ['targetNote'], },
  • Dispatch handler in CallToolRequest that invokes the ObsidianHandler's analyzeBacklinks method and formats the response as MCP content.
    case 'analyze_backlinks': const backlinksResult = await this.obsidianHandler.analyzeBacklinks( args.targetNote as string ); return { content: [ { type: 'text', text: JSON.stringify(backlinksResult, null, 2), }, ], };
  • Helper function used by analyzeBacklinks to recursively collect all .md files in the vault for scanning.
    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