Skip to main content
Glama

find_orphans

Identify notes without incoming or outgoing links to maintain a well-connected knowledge base.

Instructions

Find notes that have no incoming or outgoing links

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
includeOutlinksCheckNoAlso check for notes with no outgoing links
maxResultsNoMaximum results to return

Implementation Reference

  • Registration of the 'find_orphans' tool, including its description and input schema.
    server.registerTool(
      "find_orphans",
      {
        description: "Find notes that have no incoming or outgoing links",
        inputSchema: {
          includeOutlinksCheck: z
            .boolean()
            .optional()
            .default(true)
            .describe("Also check for notes with no outgoing links"),
          maxResults: z
            .number()
            .optional()
            .default(200)
            .describe("Maximum results to return"),
        },
      },
  • The handler implementation for 'find_orphans', which builds a link graph and categorizes notes as orphaned based on their connections.
    async ({ includeOutlinksCheck, maxResults }) => {
      try {
        const graph = await buildLinkGraph(vaultPath);
    
        const noBacklinks: OrphanNote[] = [];
        const noOutlinks: OrphanNote[] = [];
        const fullyIsolated: OrphanNote[] = [];
    
        for (const notePath of graph.allNotes) {
          const hasBacklinks = (graph.backlinks.get(notePath)?.size ?? 0) > 0;
          const hasOutlinks = (graph.outlinks.get(notePath)?.size ?? 0) > 0;
    
          if (!hasBacklinks && !hasOutlinks) {
            fullyIsolated.push({ path: notePath, hasOutlinks: false, hasBacklinks: false });
          } else if (!hasBacklinks) {
            noBacklinks.push({ path: notePath, hasOutlinks, hasBacklinks: false });
          } else if (!hasOutlinks && includeOutlinksCheck) {
            noOutlinks.push({ path: notePath, hasOutlinks: false, hasBacklinks });
          }
        }
    
        // Apply maxResults cap across all categories
        let remaining = maxResults;
    
        const cappedIsolated = fullyIsolated.slice(0, remaining);
        remaining -= cappedIsolated.length;
        const cappedNoBacklinks = noBacklinks.slice(0, Math.max(0, remaining));
        remaining -= cappedNoBacklinks.length;
        const cappedNoOutlinks = includeOutlinksCheck ? noOutlinks.slice(0, Math.max(0, remaining)) : [];
    
        const lines: string[] = [
          `Orphan analysis for vault (${graph.allNotes.length} notes total)\n`,
        ];
    
        lines.push(`Fully isolated (no links in or out): ${fullyIsolated.length}`);
        for (const note of cappedIsolated) {
          lines.push(`  - ${note.path}`);
        }
        if (cappedIsolated.length < fullyIsolated.length) {
          lines.push(`  ... and ${fullyIsolated.length - cappedIsolated.length} more`);
        }
    
        lines.push(`\nNo backlinks (not linked by any note): ${noBacklinks.length}`);
        for (const note of cappedNoBacklinks) {
          lines.push(`  - ${note.path}`);
        }
        if (cappedNoBacklinks.length < noBacklinks.length) {
          lines.push(`  ... and ${noBacklinks.length - cappedNoBacklinks.length} more`);
        }
    
        if (includeOutlinksCheck) {
          lines.push(`\nNo outlinks (links to no other notes): ${noOutlinks.length}`);
          for (const note of cappedNoOutlinks) {
            lines.push(`  - ${note.path}`);
          }
          if (cappedNoOutlinks.length < noOutlinks.length) {
            lines.push(`  ... and ${noOutlinks.length - cappedNoOutlinks.length} more`);
          }
        }
    
        const totalOrphans = fullyIsolated.length + noBacklinks.length + (includeOutlinksCheck ? noOutlinks.length : 0);
        lines.push(`\nTotal orphan entries: ${totalOrphans}`);
    
        return { content: [{ type: "text" as const, text: lines.join("\n") }] };
      } catch (err) {
        console.error("find_orphans error:", err);
        return errorResult(`Error finding orphans: ${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