feat: Phase 9 - Linking & Backlinks

Implement three new tools for wikilink validation, resolution, and backlink queries:

New Tools:
- validate_wikilinks: Validate all wikilinks in a note with suggestions for broken links
- resolve_wikilink: Resolve a single wikilink to its target path
- backlinks: Get all backlinks to a note with optional unlinked mentions

New Files:
- src/utils/link-utils.ts: Complete wikilink parsing, resolution, and backlink utilities

Modified Files:
- src/tools/vault-tools.ts: Added 3 new methods for link operations
- src/tools/index.ts: Added 3 tool definitions and handlers
- src/types/mcp-types.ts: Added Phase 9 type definitions
- ROADMAP.md: Marked Phase 9 as complete
- CHANGELOG.md: Added v8.0.0 release notes

Key Features:
- Regex-based wikilink parsing with position tracking
- Uses MetadataCache.getFirstLinkpathDest() for accurate resolution
- Fuzzy matching suggestion engine for broken links
- Efficient backlink detection using MetadataCache.resolvedLinks
- Optional unlinked mentions with word-boundary matching
- Context snippet extraction for each occurrence
This commit is contained in:
2025-10-17 00:52:51 -04:00
parent 99e2ade3ca
commit 6017f879f4
6 changed files with 877 additions and 26 deletions

View File

@@ -2,6 +2,131 @@
All notable changes to the Obsidian MCP Server plugin will be documented in this file.
## [8.0.0] - 2025-10-17
### 🚀 Phase 9: Linking & Backlinks
This release adds powerful tools for working with wikilinks, resolving links, and querying backlinks. Enables programmatic link validation, resolution, and knowledge graph exploration.
#### Added
**New Tool: `validate_wikilinks`**
- Validate all wikilinks in a note and report unresolved links
- Parses all `[[wikilinks]]` in the file using regex
- Resolves links using Obsidian's MetadataCache for accuracy
- Provides suggestions for broken links using fuzzy matching
- Returns structured JSON with:
- `path` - File path
- `totalLinks` - Total number of links found
- `resolvedLinks` - Array of resolved links with:
- `text` - Full link text including brackets
- `target` - Resolved target file path
- `alias` - Display alias (if present)
- `unresolvedLinks` - Array of unresolved links with:
- `text` - Full link text including brackets
- `line` - Line number where link appears
- `suggestions` - Array of suggested target paths
- Supports both `[[link]]` and `[[link|alias]]` formats
- Handles links with headings `[[note#heading]]`
- Use to identify and fix broken links in notes
**New Tool: `resolve_wikilink`**
- Resolve a single wikilink from a source note to its target path
- Uses Obsidian's MetadataCache.getFirstLinkpathDest() for accurate resolution
- Follows Obsidian's link resolution rules:
- Shortest path matching
- Relative paths
- Aliases
- Headings and blocks
- Returns structured JSON with:
- `sourcePath` - Source note path
- `linkText` - Link text to resolve (without brackets)
- `resolved` - Boolean indicating if link was resolved
- `targetPath` - Resolved target file path (if found)
- `suggestions` - Array of suggested paths (if not found)
- Parameters:
- `sourcePath` - Path of note containing the link
- `linkText` - Link text without brackets (e.g., "target note", "folder/note", "note#heading")
- Supports complex link formats (headings, aliases, relative paths)
- Use to programmatically resolve links before following them
**New Tool: `backlinks`**
- Get all backlinks to a note with optional unlinked mentions
- Uses Obsidian's MetadataCache.getBacklinksForFile() for linked backlinks
- Optional text-based search for unlinked mentions
- Returns structured JSON with:
- `path` - Target note path
- `backlinks` - Array of backlinks with:
- `sourcePath` - Source file path containing the link
- `type` - Either "linked" (wikilink) or "unlinked" (text mention)
- `occurrences` - Array of occurrences with:
- `line` - Line number (1-indexed)
- `snippet` - Context snippet around the link
- `totalBacklinks` - Total number of backlinks
- Parameters:
- `path` - Target note path
- `includeUnlinked` - Include unlinked mentions (default: false)
- `includeSnippets` - Include context snippets (default: true)
- Efficient use of Obsidian's built-in caching and indexing
- Use to explore note connections and build knowledge graphs
- Warning: `includeUnlinked` can be slow for large vaults
**New Utility: `link-utils.ts`**
- `LinkUtils` class for wikilink operations
- `parseWikilinks()` - Parse all wikilinks from content with positions
- `resolveLink()` - Resolve a wikilink to its target file
- `findSuggestions()` - Find potential matches for unresolved links
- `getBacklinks()` - Get all backlinks to a file
- `validateWikilinks()` - Validate all wikilinks in a file
- Regex-based wikilink parsing: `/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g`
- Fuzzy matching algorithm for link suggestions
- Handles edge cases (circular links, missing files)
#### Modified
**Updated: `vault-tools.ts`**
- Added `validateWikilinks()` method
- Added `resolveWikilink()` method
- Added `getBacklinks()` method
- Imports LinkUtils for wikilink operations
**Updated: `index.ts` (Tool Registry)**
- Added `validate_wikilinks` tool definition
- Added `resolve_wikilink` tool definition
- Added `backlinks` tool definition
- Added case handlers for three new tools
**Updated: `mcp-types.ts`**
- Added Phase 9 types:
- `ResolvedLink` - Resolved wikilink information
- `UnresolvedLink` - Unresolved wikilink information
- `ValidateWikilinksResult` - Result from validate_wikilinks
- `ResolveWikilinkResult` - Result from resolve_wikilink
- `BacklinkOccurrence` - Backlink occurrence in a file
- `BacklinkInfo` - Backlink from a source file
- `BacklinksResult` - Result from backlinks operation
#### Benefits
- **Link Validation**: Identify and fix broken links in notes
- **Link Resolution**: Programmatically resolve links before following them
- **Knowledge Graphs**: Explore note connections and build knowledge graphs
- **Complex Links**: Support for headings, aliases, and relative paths
- **Accurate Resolution**: Uses Obsidian's native link resolution rules
- **Performance**: Efficient use of MetadataCache and built-in indexing
- **Suggestions**: Fuzzy matching helps find intended targets for broken links
#### Technical Details
- Wikilink parsing uses regex: `/\[\[([^\]|]+)(?:\|([^\]]+))?\]\]/g`
- Link resolution uses `MetadataCache.getFirstLinkpathDest()`
- Backlink detection uses `MetadataCache.getBacklinksForFile()`
- Suggestion engine uses multi-factor scoring (basename, path, character matching)
- Unlinked mentions use word boundary regex for whole-word matching
- Context snippets extracted with configurable length (default: 100 chars)
---
## [7.0.0] - 2025-10-17
### 🚀 Phase 8: Write Operations & Concurrency