find_related_conversations
Discover connected discussions by analyzing shared files, folders, languages, size, or timing from a reference conversation. Identify codebase-related threads, similar problem-solving sessions, or evolving ideas to enhance context and continuity.
Instructions
Find conversations related to a reference conversation based on shared files, folders, programming languages, similar size, or temporal proximity. Use this to discover related discussions, find conversations about the same codebase/project, identify similar problem-solving sessions, or trace the evolution of ideas across multiple conversations.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| includeScoreBreakdown | No | Include detailed breakdown of how similarity scores were calculated | |
| maxResults | No | Maximum number of related conversations to return (1-50) | |
| minScore | No | Minimum similarity score threshold (0.0-1.0) | |
| outputMode | No | Output format: "json" for formatted JSON (default), "compact-json" for minified JSON | json |
| referenceConversationId | Yes | ID of the conversation to find related conversations for | |
| relationshipTypes | No | Types of relationships to consider when finding related conversations |
Implementation Reference
- src/tools/analytics-tools.ts:130-199 (handler)Main handler function for the find_related_conversations tool. Queries the database for conversation summaries, extracts languages if needed, calls the utility function to compute relationships, and returns the results.export async function findRelatedConversations( input: FindRelatedConversationsInput ): Promise<RelatedConversationsResult> { const reader = new CursorDatabaseReader(); try { await reader.connect(); // Get reference conversation summary const referenceSummary = await reader.getConversationSummary(input.referenceConversationId, { includeFirstMessage: true, includeCodeBlockCount: true, includeFileList: true, includeAttachedFolders: true, maxFirstMessageLength: 150 }); if (!referenceSummary) { throw new DatabaseError(`Reference conversation ${input.referenceConversationId} not found`); } // Get all conversation IDs for comparison const allConversationIds = await reader.getConversationIds({ format: 'both', minLength: 100 }); // Get summaries for all conversations const allSummaries = await reader.getConversationSummariesForAnalytics(allConversationIds); // Extract languages from reference conversation if needed let referenceLanguages: string[] = []; if (input.relationshipTypes.includes('languages')) { const conversationsWithCode = await reader.getConversationsWithCodeBlocks([input.referenceConversationId]); if (conversationsWithCode.length > 0) { referenceLanguages = extractLanguagesFromCodeBlocks(conversationsWithCode[0].codeBlocks); } } // Find related conversations const related = findRelatedConversationsUtil( referenceSummary, allSummaries, allConversationIds, { relationshipTypes: input.relationshipTypes, maxResults: input.maxResults, minScore: input.minScore, includeScoreBreakdown: input.includeScoreBreakdown } ); return { reference: { composerId: referenceSummary.composerId, files: referenceSummary.relevantFiles, folders: referenceSummary.attachedFolders, languages: referenceLanguages, messageCount: referenceSummary.messageCount, size: referenceSummary.conversationSize }, related }; } catch (error) { throw new DatabaseError(`Failed to find related conversations: ${error instanceof Error ? error.message : 'Unknown error'}`); } finally { reader.close(); } }
- src/server.ts:266-295 (registration)MCP server tool registration for 'find_related_conversations', including description, input schema (zod), and handler that delegates to the analytics handler function.server.tool( 'find_related_conversations', 'Find conversations related to a reference conversation based on shared files, folders, programming languages, similar size, or temporal proximity. Use this to discover related discussions, find conversations about the same codebase/project, identify similar problem-solving sessions, or trace the evolution of ideas across multiple conversations.', { referenceConversationId: z.string().min(1).describe('ID of the conversation to find related conversations for'), relationshipTypes: z.array(z.enum(['files', 'folders', 'languages', 'size', 'temporal'])).optional().default(['files']).describe('Types of relationships to consider when finding related conversations'), maxResults: z.number().min(1).max(50).optional().default(10).describe('Maximum number of related conversations to return (1-50)'), minScore: z.number().min(0).max(1).optional().default(0.1).describe('Minimum similarity score threshold (0.0-1.0)'), includeScoreBreakdown: z.boolean().optional().default(false).describe('Include detailed breakdown of how similarity scores were calculated'), outputMode: z.enum(['json', 'compact-json']).optional().default('json').describe('Output format: "json" for formatted JSON (default), "compact-json" for minified JSON') }, async (input) => { try { const result = await findRelatedConversations(input); return { content: [{ type: 'text', text: formatResponse(result, input.outputMode) }] }; } catch (error) { return { content: [{ type: 'text', text: `Error: ${error instanceof Error ? error.message : 'Unknown error occurred'}` }] }; } } );
- src/tools/analytics-tools.ts:30-36 (schema)Zod schema definition for the input parameters of the findRelatedConversations function, matching the MCP tool schema.export const findRelatedConversationsSchema = z.object({ referenceConversationId: z.string().min(1), relationshipTypes: z.array(z.enum(['files', 'folders', 'languages', 'size', 'temporal'])).optional().default(['files']), maxResults: z.number().min(1).max(50).optional().default(10), minScore: z.number().min(0).max(1).optional().default(0.1), includeScoreBreakdown: z.boolean().optional().default(false) });
- src/utils/relationships.ts:33-76 (helper)Core utility function that implements the relationship scoring logic: calculates shared files/folders/languages, size similarity, temporal proximity, composite scores, and ranks related conversations.export function findRelatedConversations( referenceSummary: ConversationSummary, allSummaries: ConversationSummary[], conversationIds: string[], options: RelationshipOptions ): RelatedConversation[] { const related: RelatedConversation[] = []; // Get reference conversation index for temporal calculations const referenceIndex = conversationIds.indexOf(referenceSummary.composerId); for (const summary of allSummaries) { // Skip the reference conversation itself if (summary.composerId === referenceSummary.composerId) { continue; } const relationships = calculateRelationships( referenceSummary, summary, conversationIds, referenceIndex, options.relationshipTypes ); const score = calculateCompositeScore(relationships, options.relationshipTypes); if (score >= options.minScore) { related.push({ composerId: summary.composerId, relationshipScore: score, relationships, summary: summary.firstMessage || 'No preview available', scoreBreakdown: options.includeScoreBreakdown ? calculateScoreBreakdown(relationships, options.relationshipTypes) : undefined }); } } // Sort by score and limit results return related .sort((a, b) => b.relationshipScore - a.relationshipScore) .slice(0, options.maxResults); }