Skip to main content
Glama

get_backlinks

Find all notes linking to a specific note in your Obsidian vault to analyze connections and discover related content.

Instructions

Find all notes that link to a specific note

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
pathYesThe target note path (relative to vault root)

Implementation Reference

  • The handler function for the get_backlinks tool. It builds a link graph of the vault, resolves the target note, retrieves backlinks from the graph, finds the context of the links within those notes, and formats the output.
    // ── get_backlinks ──────────────────────────────────────────────
    server.registerTool(
      "get_backlinks",
      {
        description: "Find all notes that link to a specific note",
        inputSchema: {
          path: z.string().min(1).describe("The target note path (relative to vault root)"),
        },
      },
      async ({ path: targetPath }) => {
        try {
          const graph = await buildLinkGraph(vaultPath);
    
          // Normalize target for comparison
          const targetNormalized = targetPath.replace(/\.md$/i, "").toLowerCase();
          const targetBasename = targetNormalized.split("/").pop() ?? targetNormalized;
    
          // Find the actual note path that matches the target
          let resolvedTarget: string | null = null;
          for (const notePath of graph.allNotes) {
            const noteNormalized = notePath.replace(/\.md$/i, "").toLowerCase();
            if (noteNormalized === targetNormalized) {
              resolvedTarget = notePath;
              break;
            }
          }
    
          // Also try basename matching if exact match failed
          if (!resolvedTarget) {
            for (const notePath of graph.allNotes) {
              const noteBasename = notePath
                .replace(/\.md$/i, "")
                .split("/")
                .pop()
                ?.toLowerCase();
              if (noteBasename === targetBasename) {
                resolvedTarget = notePath;
                break;
              }
            }
          }
    
          if (!resolvedTarget) {
            return errorResult(`No note found matching path: ${targetPath}`);
          }
    
          const backlinkSources = graph.backlinks.get(resolvedTarget);
          if (!backlinkSources || backlinkSources.size === 0) {
            return {
              content: [
                {
                  type: "text" as const,
                  text: `No backlinks found for: ${resolvedTarget}`,
                },
              ],
            };
          }
    
          const results: { source: string; line: number; context: string }[] = [];
    
          for (const sourcePath of backlinkSources) {
            const lines = graph.noteLines.get(sourcePath) ?? [];
            // Find the line(s) that contain the link to the target
            const links = graph.rawLinks.get(sourcePath) ?? [];
            const relevantLinks = links.filter((l) => {
              const base = l.target.split("#")[0].trim();
              const resolved = resolveWikilink(base, sourcePath, graph.allNotes);
              return resolved === resolvedTarget;
            });
    
            if (relevantLinks.length > 0) {
              for (const link of relevantLinks) {
                const lineInfo = findLineWithLink(lines, link.target);
                results.push({
                  source: sourcePath,
                  line: lineInfo.line,
                  context: lineInfo.content,
                });
              }
            } else {
              results.push({ source: sourcePath, line: 0, context: "" });
            }
          }
    
          // Deduplicate by source+line
          const seen = new Set<string>();
          const deduped = results.filter((r) => {
            const key = `${r.source}:${r.line}`;
            if (seen.has(key)) return false;
            seen.add(key);
            return true;
          });
    
          const output = [
            `Backlinks to: ${resolvedTarget}`,
            `Found: ${deduped.length} backlink(s)\n`,
            ...deduped.map((r) => {
              const lineStr = r.line > 0 ? `:${r.line}` : "";
              const contextStr = r.context ? `  → ${r.context}` : "";
              return `- ${r.source}${lineStr}${contextStr}`;
            }),
          ].join("\n");
    
          return { content: [{ type: "text" as const, text: output }] };
        } catch (err) {
          console.error("get_backlinks error:", err);
          return errorResult(`Error finding backlinks: ${err instanceof Error ? err.message : String(err)}`);
        }
      },
    );

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/rps321321/obsidian-mcp-pro'

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