diff --git a/documentation/MCP.md b/documentation/MCP.md index 5d08297..ea02e4c 100644 --- a/documentation/MCP.md +++ b/documentation/MCP.md @@ -14,6 +14,7 @@ MCP (Model Context Protocol) is an open standard that allows AI assistants to se - 📂 **Organize** notes (move, rename, folders) - 📋 **Use templates** to create structured notes - 🔗 **Explore** the knowledge graph +- 🔙 **Discover backlinks** (notes that link to a specific note) ## Quick Setup @@ -126,6 +127,7 @@ The MCP server provides these tools to AI assistants: | `list_tags` | List all tags with note counts | | `get_notes_by_tag` | Find notes with a specific tag (supports pagination) | | `get_graph` | Get knowledge graph data | +| `get_backlinks` | Get notes that link to a specific note (reverse links) | ### Note Management @@ -172,6 +174,23 @@ Some tools support optional pagination parameters for large vaults: --- +### `get_backlinks` + +Find all notes that link TO a specific note (reverse links / backlinks). Useful for understanding how a note connects to your knowledge base. + +| Parameter | Type | Required | Description | +|-----------|------|----------|-------------| +| `path` | string | Yes | Path to the note to find backlinks for | + +**Returns:** List of notes that contain links to the specified note, with context snippets showing where the link appears. + +**Example prompts:** +- "What notes link to my Project Alpha note?" +- "Show me the backlinks for meeting-notes.md" +- "Find all notes that reference my API documentation" + +--- + ### `append_to_note` Append content to an existing note without overwriting. Perfect for journals, logs, or collecting ideas. @@ -266,6 +285,12 @@ Once configured, you can interact with your notes naturally: > > "Created 'meetings/design-review-2024-03-13.md' from your meeting-notes template." +> **User:** "What notes link to my Project Alpha document?" +> +> **AI:** *Uses `get_backlinks` to find reverse links* +> +> "3 notes reference Project Alpha: your meeting notes from March 12, the quarterly review, and the team standup notes..." + ## Authentication If you have authentication enabled in NoteDiscovery: diff --git a/mcp_server/client.py b/mcp_server/client.py index c4bb7f2..b97cd5c 100644 --- a/mcp_server/client.py +++ b/mcp_server/client.py @@ -354,11 +354,24 @@ class NoteDiscoveryClient: def get_graph(self) -> APIResponse: """ Get note relationship graph data. - + Returns: APIResponse with graph nodes and links """ return self._request("GET", "/api/graph") + + def get_backlinks(self, path: str) -> APIResponse: + """ + Get backlinks (reverse links) for a specific note. + + Args: + path: Note path (e.g., "folder/note.md") + + Returns: + APIResponse with note info and backlinks + """ + encoded_path = urllib.parse.quote(path, safe="") + return self._request("GET", f"/api/notes/{encoded_path}", params={"include_backlinks": "true"}) # ========================================================================= # Templates API diff --git a/mcp_server/server.py b/mcp_server/server.py index a73d906..e5a1e25 100644 --- a/mcp_server/server.py +++ b/mcp_server/server.py @@ -414,6 +414,41 @@ class MCPServer: output.append(f" {note}: {count} connections") return "\n".join(output) + + def _tool_get_backlinks(self, args: dict) -> str: + """Get backlinks (reverse links) for a note.""" + path = args.get("path", "") + is_valid, error = self._validate_path(path) + if not is_valid: + return f"Error: {error}" + + response = self.client.get_backlinks(path) + + if not response.success: + return f"Failed to get backlinks: {response.error}" + + data = response.data or {} + backlinks = data.get("backlinks", []) + note_path = data.get("path", path) + + if not backlinks: + return f"No backlinks found for '{note_path}'. No other notes link to this note." + + output = [f"Backlinks for '{note_path}': {len(backlinks)} note(s) link to this note\n"] + + for bl in backlinks: + bl_path = bl.get("path", "unknown") + bl_name = bl.get("name", bl_path) + references = bl.get("references", []) + + output.append(f"📄 {bl_name} ({bl_path})") + for ref in references: + line_num = ref.get("line_number", "?") + context = ref.get("context", "") + link_type = ref.get("type", "link") + output.append(f" Line {line_num} [{link_type}]: {context}") + + return "\n".join(output) def _tool_create_note(self, args: dict) -> str: """Create or update a note.""" diff --git a/mcp_server/tools.py b/mcp_server/tools.py index 32c8082..360b580 100644 --- a/mcp_server/tools.py +++ b/mcp_server/tools.py @@ -114,6 +114,20 @@ TOOLS: list[dict[str, Any]] = [ "required": [] } }, + { + "name": "get_backlinks", + "description": "Get all notes that link TO a specific note (backlinks/reverse links). Use this to discover what other notes reference the current note, helping understand its importance and connections in the knowledge base.", + "inputSchema": { + "type": "object", + "properties": { + "path": { + "type": "string", + "description": "Path to the note to find backlinks for (e.g., 'folder/note.md' or 'note.md')" + } + }, + "required": ["path"] + } + }, # ========================================================================= # Note Management (Write Operations)