find_related
Find other files that share tags with a given file, ranked by shared tag count. Navigate related content based on tag associations.
Instructions
Find other files sharing tags with the given file, ranked by shared_tag_count descending. Read-only; no side effects, auth, or rate limits. Returns annotated file rows with shared_tag_count and shared_tags. Empty result means the file has no tags or no other file shares them — try search/regex_search for content-based discovery, or suggest_tags to bootstrap labels first. Default limit 10.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file_id | Yes | ID of the file to find relations for | |
| limit | No | Maximum number of related files to return (default 10) |
Implementation Reference
- apps/mcp/src/index.ts:1235-1254 (handler)MCP tool handler for 'find_related'. Registers the tool with Zod schema (file_id required, limit optional), calls core findRelated(), annotates results with tokens, and returns JSON.
server.tool( "find_related", "Find other files sharing tags with the given file, ranked by `shared_tag_count` descending. Read-only; no side effects, auth, or rate limits. Returns annotated file rows with `shared_tag_count` and `shared_tags`. Empty result means the file has no tags or no other file shares them — try `search`/`regex_search` for content-based discovery, or `suggest_tags` to bootstrap labels first. Default limit 10.", { file_id: z.number().describe("ID of the file to find relations for"), limit: z.number().optional().describe("Maximum number of related files to return (default 10)"), }, async ({ file_id, limit }) => { const related = findRelated(file_id, limit ?? 10); const annotated = related.map((r) => ({ ...annotateTokens(r), shared_tag_count: r.shared_tag_count, shared_tags: r.shared_tags })); return { content: [ { type: "text", text: JSON.stringify({ file_id, related: annotated }, null, 2), }, ], }; } ); - apps/mcp/src/index.ts:1238-1241 (schema)Zod schema for find_related tool parameters: file_id (number) required, limit (number) optional.
{ file_id: z.number().describe("ID of the file to find relations for"), limit: z.number().optional().describe("Maximum number of related files to return (default 10)"), }, - Core implementation of findRelated(). Executes SQL query joining file_tags to find files sharing tags, ordered by shared_tag_count descending.
export function findRelated(fileId: number, limit: number = 10): RelatedFileRecord[] { const db = getDatabase(); const rows = db .prepare( ` SELECT f.*, COUNT(ft2.tag_id) AS shared_tag_count, GROUP_CONCAT(t.name) AS shared_tags_csv FROM file_tags ft1 JOIN file_tags ft2 ON ft1.tag_id = ft2.tag_id JOIN files f ON f.id = ft2.file_id JOIN tags t ON t.id = ft2.tag_id WHERE ft1.file_id = ? AND ft2.file_id != ? GROUP BY f.id ORDER BY shared_tag_count DESC, f.updated_at DESC LIMIT ? ` ) .all(fileId, fileId, limit) as Array<FileRecord & { shared_tag_count: number; shared_tags_csv: string }>; return rows.map(({ shared_tags_csv, ...rest }) => ({ ...rest, shared_tags: shared_tags_csv ? shared_tags_csv.split(",") : [], })); } - RelatedFileRecord interface extending FileRecord with shared_tag_count and shared_tags.
export interface RelatedFileRecord extends FileRecord { shared_tag_count: number; shared_tags: string[]; } - packages/core/src/index.ts:9-10 (registration)Export of findRelated and RelatedFileRecord from core package.
findRelated, getTagsForFiles, type RelatedFileRecord, } from "./metadata/index.js";