suggest_links
Find relevant notes to link within your Obsidian vault by analyzing content relationships and suggesting connections based on your current note's context.
Instructions
Suggest related notes for linking
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| limit | No | Maximum suggestions (default: 5) | |
| path | Yes | Path to the note | |
| vault | Yes | Vault name |
Implementation Reference
- src/index.ts:624-638 (handler)MCP tool handler for 'suggest_links': retrieves all notes from the vault, updates the knowledge graph service, calls suggestRelatedNotes to get suggestions, and returns them as JSON.case 'suggest_links': { const connector = this.connectors.get(args?.vault as string); if (!connector) { throw new Error(`Vault "${args?.vault}" not found`); } const notesResult = await connector.getAllNotes(); if (notesResult.success && notesResult.data) { this.knowledgeGraph.updateNotes(notesResult.data); const suggestions = this.knowledgeGraph.suggestRelatedNotes(args?.path as string, (args?.limit as number) || 5); return { content: [{ type: 'text', text: JSON.stringify(suggestions, null, 2) }], }; } throw new Error('Failed to suggest links'); }
- src/index.ts:202-213 (schema)Input schema definition for the 'suggest_links' tool, specifying required vault and path, optional limit.name: 'suggest_links', description: 'Suggest related notes for linking', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, limit: { type: 'number', description: 'Maximum suggestions (default: 5)' }, }, required: ['vault', 'path'], }, },
- Core implementation of related note suggestions: computes similarity scores based on shared tags (weight 10), common title words >3 chars (weight 5), same folder (weight 3), sorts and limits results.suggestRelatedNotes(notePath: string, limit: number = 5): Array<{ path: string; score: number }> { const note = this.notes.get(notePath); if (!note) return []; const scores = new Map<string, number>(); // Score based on shared tags if (note.tags) { for (const otherNote of this.notes.values()) { if (otherNote.path === notePath) continue; if (otherNote.tags) { const sharedTags = note.tags.filter(tag => otherNote.tags!.includes(tag)); if (sharedTags.length > 0) { scores.set(otherNote.path, (scores.get(otherNote.path) || 0) + sharedTags.length * 10); } } } } // Score based on common words in title const noteWords = new Set(note.title.toLowerCase().split(/\s+/)); for (const otherNote of this.notes.values()) { if (otherNote.path === notePath) continue; const otherWords = otherNote.title.toLowerCase().split(/\s+/); const commonWords = otherWords.filter(word => noteWords.has(word) && word.length > 3); if (commonWords.length > 0) { scores.set(otherNote.path, (scores.get(otherNote.path) || 0) + commonWords.length * 5); } } // Score based on folder proximity const folder = this.getFolder(notePath); for (const otherNote of this.notes.values()) { if (otherNote.path === notePath) continue; if (this.getFolder(otherNote.path) === folder) { scores.set(otherNote.path, (scores.get(otherNote.path) || 0) + 3); } } return Array.from(scores.entries()) .map(([path, score]) => ({ path, score })) .sort((a, b) => b.score - a.score) .slice(0, limit); }
- src/index.ts:64-474 (registration)Registers all tools including 'suggest_links' by returning the tools list in ListToolsRequestSchema handler.this.server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: [ { name: 'get_note', description: 'Get a note by its path', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, }, required: ['vault', 'path'], }, }, { name: 'search_notes', description: 'Search for notes in a vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, query: { type: 'string', description: 'Search query' }, tags: { type: 'array', items: { type: 'string' }, description: 'Filter by tags' }, folder: { type: 'string', description: 'Filter by folder' }, limit: { type: 'number', description: 'Maximum number of results' }, }, required: ['vault', 'query'], }, }, { name: 'create_note', description: 'Create a new note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path for the new note' }, content: { type: 'string', description: 'Note content' }, frontmatter: { type: 'object', description: 'Frontmatter metadata' }, }, required: ['vault', 'path', 'content'], }, }, { name: 'update_note', description: 'Update an existing note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, content: { type: 'string', description: 'New content' }, frontmatter: { type: 'object', description: 'Updated frontmatter' }, }, required: ['vault', 'path', 'content'], }, }, { name: 'delete_note', description: 'Delete a note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, }, required: ['vault', 'path'], }, }, { name: 'get_vault_stats', description: 'Get statistics about a vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'list_tags', description: 'List all tags in a vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'list_folders', description: 'List all folders in a vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'get_knowledge_graph', description: 'Get the complete knowledge graph for a vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'get_related_notes', description: 'Get notes related to a specific note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, maxDepth: { type: 'number', description: 'Maximum link depth (default: 2)' }, }, required: ['vault', 'path'], }, }, { name: 'analyze_graph', description: 'Analyze the knowledge graph structure', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'suggest_links', description: 'Suggest related notes for linking', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to the note' }, limit: { type: 'number', description: 'Maximum suggestions (default: 5)' }, }, required: ['vault', 'path'], }, }, // Canvas tools { name: 'get_canvas', description: 'Get canvas file contents', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path to canvas file' }, }, required: ['vault', 'path'], }, }, { name: 'create_canvas', description: 'Create a new canvas file', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Path for new canvas' }, }, required: ['vault', 'path'], }, }, { name: 'add_canvas_node', description: 'Add a node to canvas (file, text, link, or group)', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, canvasPath: { type: 'string', description: 'Path to canvas file' }, nodeType: { type: 'string', enum: ['file', 'text', 'link', 'group'], description: 'Type of node' }, x: { type: 'number', description: 'X coordinate' }, y: { type: 'number', description: 'Y coordinate' }, width: { type: 'number', description: 'Node width' }, height: { type: 'number', description: 'Node height' }, file: { type: 'string', description: 'File path (for file nodes)' }, text: { type: 'string', description: 'Text content (for text nodes)' }, url: { type: 'string', description: 'URL (for link nodes)' }, label: { type: 'string', description: 'Label (for group nodes)' }, color: { type: 'string', description: 'Node color (1-6)' }, }, required: ['vault', 'canvasPath', 'nodeType', 'x', 'y', 'width', 'height'], }, }, { name: 'add_canvas_edge', description: 'Add an edge between nodes in canvas', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, canvasPath: { type: 'string', description: 'Path to canvas file' }, fromNode: { type: 'string', description: 'Source node ID' }, toNode: { type: 'string', description: 'Target node ID' }, label: { type: 'string', description: 'Edge label' }, color: { type: 'string', description: 'Edge color (1-6)' }, }, required: ['vault', 'canvasPath', 'fromNode', 'toNode'], }, }, { name: 'list_canvas_files', description: 'List all canvas files in vault', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, // Dataview tools { name: 'dataview_query', description: 'Execute a Dataview-style query on notes', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, from: { type: 'string', description: 'Source filter (folder path or #tag)' }, where: { type: 'array', items: { type: 'object', properties: { field: { type: 'string' }, operator: { type: 'string', enum: ['eq', 'neq', 'gt', 'gte', 'lt', 'lte', 'contains', 'startsWith', 'endsWith', 'exists'] }, value: { type: 'string' } } }, description: 'Filter conditions' }, sort: { type: 'array', items: { type: 'object', properties: { field: { type: 'string' }, direction: { type: 'string', enum: ['asc', 'desc'] } } }, description: 'Sort order' }, groupBy: { type: 'string', description: 'Field to group by' }, select: { type: 'array', items: { type: 'string' }, description: 'Fields to select' }, limit: { type: 'number', description: 'Maximum results' } }, required: ['vault'], }, }, { name: 'get_note_metadata', description: 'Get metadata for a specific note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, path: { type: 'string', description: 'Note path' }, }, required: ['vault', 'path'], }, }, { name: 'get_unique_values', description: 'Get all unique values for a metadata field', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, field: { type: 'string', description: 'Metadata field name' }, }, required: ['vault', 'field'], }, }, // Template tools { name: 'list_templates', description: 'List all available templates', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, }, required: ['vault'], }, }, { name: 'render_template', description: 'Render a template with variables', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, templatePath: { type: 'string', description: 'Path to template file' }, variables: { type: 'object', description: 'Template variables' }, frontmatter: { type: 'object', description: 'Additional frontmatter' }, targetPath: { type: 'string', description: 'Target note path (for context)' }, }, required: ['vault', 'templatePath'], }, }, { name: 'create_from_template', description: 'Create a new note from a template', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, templatePath: { type: 'string', description: 'Path to template file' }, targetPath: { type: 'string', description: 'Path for new note' }, variables: { type: 'object', description: 'Template variables' }, frontmatter: { type: 'object', description: 'Additional frontmatter' }, }, required: ['vault', 'templatePath', 'targetPath'], }, }, // Periodic notes tools { name: 'create_daily_note', description: 'Create a daily note for a specific date', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, date: { type: 'string', description: 'Date (YYYY-MM-DD), defaults to today' }, variables: { type: 'object', description: 'Additional template variables' }, }, required: ['vault'], }, }, { name: 'create_weekly_note', description: 'Create a weekly note for a specific date', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, date: { type: 'string', description: 'Date in the week (YYYY-MM-DD), defaults to this week' }, variables: { type: 'object', description: 'Additional template variables' }, }, required: ['vault'], }, }, { name: 'create_monthly_note', description: 'Create a monthly note for a specific date', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, date: { type: 'string', description: 'Date in the month (YYYY-MM-DD), defaults to this month' }, variables: { type: 'object', description: 'Additional template variables' }, }, required: ['vault'], }, }, { name: 'create_yearly_note', description: 'Create a yearly note for a specific year', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, date: { type: 'string', description: 'Date in the year (YYYY-MM-DD), defaults to this year' }, variables: { type: 'object', description: 'Additional template variables' }, }, required: ['vault'], }, }, { name: 'get_periodic_note_info', description: 'Get info about a periodic note', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, type: { type: 'string', enum: ['daily', 'weekly', 'monthly', 'yearly'], description: 'Note type' }, date: { type: 'string', description: 'Date (YYYY-MM-DD), defaults to today' }, }, required: ['vault', 'type'], }, }, { name: 'list_periodic_notes', description: 'List periodic notes of a specific type', inputSchema: { type: 'object', properties: { vault: { type: 'string', description: 'Vault name' }, type: { type: 'string', enum: ['daily', 'weekly', 'monthly', 'yearly'], description: 'Note type' }, startDate: { type: 'string', description: 'Start date (YYYY-MM-DD)' }, endDate: { type: 'string', description: 'End date (YYYY-MM-DD)' }, }, required: ['vault', 'type'], }, }, ], }));