Skip to main content
Glama

list_conversations

Retrieve and filter Cursor chat histories by project, keywords, or date range to analyze conversations with AI-generated summaries, titles, and metadata. Supports project-specific filtering to focus on relevant codebase discussions.

Instructions

Lists Cursor chats with summaries, titles, and metadata ordered by recency. HIGHLY RECOMMENDED: Use projectPath parameter to filter conversations by specific project/codebase - this dramatically improves relevance by finding conversations that actually worked on files in that project. Returns conversation IDs for use with get_conversation tool. WORKFLOW TIP: Start with projectPath filtering for project-specific analysis, then call get_conversation with specific IDs from results. Includes AI-generated summaries by default. Supports date range filtering (YYYY-MM-DD format).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
endDateNoEnd date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.
filePatternNoFilter conversations mentioning files matching this pattern (e.g., "*.tsx")
hasCodeBlocksNoFilter to conversations that contain code blocks
includeAiSummariesNoInclude AI-generated conversation summaries
includeEmptyNoInclude conversations with no messages
includeRelevanceScoreNoInclude relevance scores when filtering by projectPath
keywordsNoFilter conversations containing any of these exact keywords (literal text matching)
limitNoMaximum number of conversations to return (1-100)
minLengthNoMinimum conversation length in characters to include
outputModeNoOutput format: "json" for formatted JSON (default), "compact-json" for minified JSONjson
projectPathNo**RECOMMENDED** Filter conversations by project/codebase name (e.g., "my-app") or full path (e.g., "/Users/name/Projects/my-app"). This finds conversations that actually worked on files in that project, dramatically improving relevance for project-specific analysis.
relevantFilesNoFilter conversations that reference any of these specific files
startDateNoStart date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.

Implementation Reference

  • src/server.ts:51-140 (registration)
    Registration of the 'list_conversations' MCP tool, including description, inline input schema, and async handler that conditionally calls listConversations or getConversationsByProject based on projectPath and includeRelevanceScore flags.
    server.tool( 'list_conversations', 'Lists Cursor chats with summaries, titles, and metadata ordered by recency. **HIGHLY RECOMMENDED: Use projectPath parameter to filter conversations by specific project/codebase** - this dramatically improves relevance by finding conversations that actually worked on files in that project. Returns conversation IDs for use with get_conversation tool. WORKFLOW TIP: Start with projectPath filtering for project-specific analysis, then call get_conversation with specific IDs from results. Includes AI-generated summaries by default. Supports date range filtering (YYYY-MM-DD format).', { limit: z.number().min(1).max(100).optional().default(10).describe('Maximum number of conversations to return (1-100)'), minLength: z.number().min(0).optional().default(100).describe('Minimum conversation length in characters to include'), hasCodeBlocks: z.boolean().optional().describe('Filter to conversations that contain code blocks'), keywords: z.array(z.string()).optional().describe('Filter conversations containing any of these exact keywords (literal text matching)'), projectPath: z.string().optional().describe('**RECOMMENDED** Filter conversations by project/codebase name (e.g., "my-app") or full path (e.g., "/Users/name/Projects/my-app"). This finds conversations that actually worked on files in that project, dramatically improving relevance for project-specific analysis.'), filePattern: z.string().optional().describe('Filter conversations mentioning files matching this pattern (e.g., "*.tsx")'), relevantFiles: z.array(z.string()).optional().describe('Filter conversations that reference any of these specific files'), startDate: z.string().optional().describe('Start date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.'), endDate: z.string().optional().describe('End date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.'), includeEmpty: z.boolean().optional().default(false).describe('Include conversations with no messages'), includeAiSummaries: z.boolean().optional().default(true).describe('Include AI-generated conversation summaries'), includeRelevanceScore: z.boolean().optional().default(false).describe('Include relevance scores when filtering by projectPath'), 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 { if (input.projectPath && input.includeRelevanceScore) { const projectInput = { projectPath: input.projectPath, filePattern: input.filePattern, orderBy: 'recency' as const, limit: input.limit, fuzzyMatch: false }; const result = await getConversationsByProject(projectInput); const transformedResult = { conversations: result.conversations.map(conv => ({ ...conv, title: undefined, aiGeneratedSummary: undefined, relevanceScore: conv.relevanceScore })), totalFound: result.totalFound, filters: { limit: input.limit ?? 10, minLength: input.minLength ?? 100, hasCodeBlocks: input.hasCodeBlocks, keywords: input.keywords, projectPath: input.projectPath, filePattern: input.filePattern, relevantFiles: input.relevantFiles, includeAiSummaries: input.includeAiSummaries } }; return { content: [{ type: 'text', text: formatResponse(transformedResult, input.outputMode) }] }; } else { const mappedInput = { limit: input.limit, minLength: input.minLength, format: 'both' as const, hasCodeBlocks: input.hasCodeBlocks, keywords: input.keywords, projectPath: input.projectPath, filePattern: input.filePattern, relevantFiles: input.relevantFiles, startDate: input.startDate, endDate: input.endDate, includeEmpty: input.includeEmpty, includeAiSummaries: input.includeAiSummaries }; const result = await listConversations(mappedInput); 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'}` }] }; } } );
  • Core handler function that executes the list_conversations logic: validates input, connects to Cursor database, applies filters (including projectPath, keywords, dates), fetches conversation IDs and summaries, handles date post-filtering, and returns formatted output with totals and applied filters.
    export async function listConversations(input: ListConversationsInput): Promise<ListConversationsOutput> { const validatedInput = listConversationsSchema.parse(input); const dbPath = process.env.CURSOR_DB_PATH || detectCursorDatabasePath(); const reader = new CursorDatabaseReader({ dbPath }); try { await reader.connect(); const filters: ConversationFilters = { minLength: validatedInput.minLength, format: validatedInput.format, hasCodeBlocks: validatedInput.hasCodeBlocks, keywords: validatedInput.keywords, projectPath: validatedInput.projectPath, filePattern: validatedInput.filePattern, relevantFiles: validatedInput.relevantFiles }; // Add date range filter if provided if (validatedInput.startDate || validatedInput.endDate) { const start = validatedInput.startDate ? new Date(validatedInput.startDate) : new Date('1970-01-01'); const end = validatedInput.endDate ? new Date(validatedInput.endDate) : new Date(); filters.dateRange = { start, end }; } const conversationIds = await reader.getConversationIds(filters); let limitedIds = conversationIds.slice(0, validatedInput.limit); // Apply date filtering if specified (post-query filtering due to unreliable timestamps) if (validatedInput.startDate || validatedInput.endDate) { const filteredIds = []; for (const composerId of limitedIds) { try { const conversation = await reader.getConversationById(composerId); if (!conversation) continue; const hasValidDate = checkConversationDateRange( conversation, validatedInput.startDate, validatedInput.endDate ); if (hasValidDate) { filteredIds.push(composerId); } } catch (error) { // Skip conversations that can't be processed continue; } } limitedIds = filteredIds; } const conversations = []; for (const composerId of limitedIds) { try { const summary = await reader.getConversationSummary(composerId, { includeFirstMessage: true, maxFirstMessageLength: 150, includeTitle: true, includeAIGeneratedSummary: validatedInput.includeAiSummaries }); if (summary) { conversations.push({ composerId: summary.composerId, format: summary.format, messageCount: summary.messageCount, hasCodeBlocks: summary.hasCodeBlocks, relevantFiles: summary.relevantFiles || [], attachedFolders: summary.attachedFolders || [], firstMessage: summary.firstMessage, title: summary.title, aiGeneratedSummary: summary.aiGeneratedSummary, size: summary.conversationSize }); } } catch (error) { console.error(`Failed to get summary for conversation ${composerId}:`, error); } } return { conversations, totalFound: conversationIds.length, filters: { limit: validatedInput.limit ?? 10, minLength: validatedInput.minLength ?? 100, format: validatedInput.format ?? 'both', hasCodeBlocks: validatedInput.hasCodeBlocks, keywords: validatedInput.keywords, projectPath: validatedInput.projectPath, filePattern: validatedInput.filePattern, relevantFiles: validatedInput.relevantFiles, includeAiSummaries: validatedInput.includeAiSummaries } }; } finally { // Always close the database connection reader.close(); } }
  • Zod input schema defining parameters for listConversations function (exported for type safety).
    // Input schema for list_conversations tool export const listConversationsSchema = z.object({ limit: z.number().min(1).max(1000).optional(), minLength: z.number().min(0).optional(), keywords: z.array(z.string()).optional(), hasCodeBlocks: z.boolean().optional(), format: z.enum(['legacy', 'modern', 'both']).optional(), includeEmpty: z.boolean().optional(), projectPath: z.string().optional(), filePattern: z.string().optional(), relevantFiles: z.array(z.string()).optional(), startDate: z.string().optional(), endDate: z.string().optional(), includeAiSummaries: z.boolean().optional().default(true) });
  • Inline Zod schema used in MCP tool registration for input validation and descriptions.
    limit: z.number().min(1).max(100).optional().default(10).describe('Maximum number of conversations to return (1-100)'), minLength: z.number().min(0).optional().default(100).describe('Minimum conversation length in characters to include'), hasCodeBlocks: z.boolean().optional().describe('Filter to conversations that contain code blocks'), keywords: z.array(z.string()).optional().describe('Filter conversations containing any of these exact keywords (literal text matching)'), projectPath: z.string().optional().describe('**RECOMMENDED** Filter conversations by project/codebase name (e.g., "my-app") or full path (e.g., "/Users/name/Projects/my-app"). This finds conversations that actually worked on files in that project, dramatically improving relevance for project-specific analysis.'), filePattern: z.string().optional().describe('Filter conversations mentioning files matching this pattern (e.g., "*.tsx")'), relevantFiles: z.array(z.string()).optional().describe('Filter conversations that reference any of these specific files'), startDate: z.string().optional().describe('Start date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.'), endDate: z.string().optional().describe('End date for filtering (YYYY-MM-DD). Note: Timestamps may be unreliable.'), includeEmpty: z.boolean().optional().default(false).describe('Include conversations with no messages'), includeAiSummaries: z.boolean().optional().default(true).describe('Include AI-generated conversation summaries'), includeRelevanceScore: z.boolean().optional().default(false).describe('Include relevance scores when filtering by projectPath'), outputMode: z.enum(['json', 'compact-json']).optional().default('json').describe('Output format: "json" for formatted JSON (default), "compact-json" for minified JSON')

Other Tools

Related Tools

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/vltansky/cursor-conversations-mcp'

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