Skip to main content
Glama

get_conversation

Retrieve complete Cursor conversation content including messages, code blocks, file references, and AI summary. Use conversation IDs from list or search results, with summary-only option to conserve context.

Instructions

Retrieves the complete content of a specific Cursor conversation including all messages, code blocks, file references, title, and AI summary. WORKFLOW TIP: Use conversation IDs from list_conversations, search_conversations, or analytics breakdowns (files/languages arrays contain conversation IDs). Use summaryOnly=true to get enhanced summary data without full message content when you need to conserve context.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
conversationIdYesConversation ID from list_conversations, search_conversations, or analytics breakdowns
summaryOnlyNoReturn only enhanced summary data without full message content
outputModeNoOutput format: "json" for formatted JSON (default), "compact-json" for minified JSONjson

Implementation Reference

  • Main handler function that executes the get_conversation tool logic. Connects to Cursor database, fetches conversation by ID, handles both legacy and modern formats, resolves bubble messages if needed, extracts messages, code blocks, file references, title, and AI-generated summary. Supports options like summaryOnly, includeCodeBlocks, resolveBubbles, etc.
    export async function getConversation(input: GetConversationInput): Promise<GetConversationOutput> { // Validate input const validatedInput = getConversationSchema.parse(input); // Create database reader const dbPath = process.env.CURSOR_DB_PATH || detectCursorDatabasePath(); const reader = new CursorDatabaseReader({ dbPath }); try { // Connect to database await reader.connect(); // If summaryOnly is requested, return enhanced summary without full content if (validatedInput.summaryOnly) { const summary = await reader.getConversationSummary(validatedInput.conversationId, { includeTitle: true, includeAIGeneratedSummary: true, includeFirstMessage: true, includeLastMessage: true, maxFirstMessageLength: 200, maxLastMessageLength: 200 }); if (!summary) { return { conversation: null }; } return { conversation: { composerId: summary.composerId, format: summary.format, messageCount: summary.messageCount, title: summary.title, aiGeneratedSummary: summary.aiGeneratedSummary, relevantFiles: validatedInput.includeFileReferences ? summary.relevantFiles : undefined, attachedFolders: validatedInput.includeFileReferences ? summary.attachedFolders : undefined, metadata: validatedInput.includeMetadata ? { hasLoaded: true, storedSummary: summary.storedSummary, storedRichText: summary.storedRichText, size: summary.conversationSize } : undefined } }; } // Get conversation const conversation = await reader.getConversationById(validatedInput.conversationId); if (!conversation) { return { conversation: null }; } // Get conversation summary to extract title and AI summary const summary = await reader.getConversationSummary(validatedInput.conversationId, { includeTitle: true, includeAIGeneratedSummary: true }); // Determine format const format = conversation.hasOwnProperty('_v') ? 'modern' : 'legacy'; // Build response based on format if (format === 'legacy') { const legacyConv = conversation as any; const messages = legacyConv.conversation || []; // Extract data let allCodeBlocks: any[] = []; let allRelevantFiles: string[] = []; let allAttachedFolders: string[] = []; const processedMessages = messages.map((msg: any) => { if (validatedInput.includeCodeBlocks && msg.suggestedCodeBlocks) { allCodeBlocks.push(...msg.suggestedCodeBlocks); } if (validatedInput.includeFileReferences) { if (msg.relevantFiles) allRelevantFiles.push(...msg.relevantFiles); if (msg.attachedFoldersNew) allAttachedFolders.push(...msg.attachedFoldersNew); } return { type: msg.type, text: msg.text, bubbleId: msg.bubbleId, relevantFiles: validatedInput.includeFileReferences ? msg.relevantFiles : undefined, attachedFolders: validatedInput.includeFileReferences ? msg.attachedFoldersNew : undefined, codeBlocks: validatedInput.includeCodeBlocks ? msg.suggestedCodeBlocks : undefined }; }); allRelevantFiles = Array.from(new Set(allRelevantFiles)); allAttachedFolders = Array.from(new Set(allAttachedFolders)); return { conversation: { composerId: legacyConv.composerId, format: 'legacy', messageCount: messages.length, title: summary?.title, aiGeneratedSummary: summary?.aiGeneratedSummary, messages: processedMessages, codeBlocks: validatedInput.includeCodeBlocks ? allCodeBlocks : undefined, relevantFiles: validatedInput.includeFileReferences ? allRelevantFiles : undefined, attachedFolders: validatedInput.includeFileReferences ? allAttachedFolders : undefined, metadata: validatedInput.includeMetadata ? { hasLoaded: true, storedSummary: legacyConv.storedSummary, storedRichText: legacyConv.storedRichText, size: JSON.stringify(conversation).length } : undefined } }; } else { const modernConv = conversation as any; const headers = modernConv.fullConversationHeadersOnly || []; if (validatedInput.resolveBubbles) { const resolvedMessages = []; for (const header of headers.slice(0, 10)) { try { const bubbleMessage = await reader.getBubbleMessage(modernConv.composerId, header.bubbleId); if (bubbleMessage) { resolvedMessages.push({ type: header.type, text: bubbleMessage.text, bubbleId: header.bubbleId, relevantFiles: validatedInput.includeFileReferences ? bubbleMessage.relevantFiles : undefined, attachedFolders: validatedInput.includeFileReferences ? bubbleMessage.attachedFoldersNew : undefined, codeBlocks: validatedInput.includeCodeBlocks ? bubbleMessage.suggestedCodeBlocks : undefined }); } } catch (error) { console.error(`Failed to resolve bubble ${header.bubbleId}:`, error); } } return { conversation: { composerId: modernConv.composerId, format: 'modern', messageCount: headers.length, title: summary?.title, aiGeneratedSummary: summary?.aiGeneratedSummary, messages: resolvedMessages, metadata: validatedInput.includeMetadata ? { hasLoaded: true, storedSummary: modernConv.storedSummary, storedRichText: modernConv.storedRichText, size: JSON.stringify(conversation).length } : undefined } }; } else { return { conversation: { composerId: modernConv.composerId, format: 'modern', messageCount: headers.length, title: summary?.title, aiGeneratedSummary: summary?.aiGeneratedSummary, metadata: validatedInput.includeMetadata ? { hasLoaded: true, storedSummary: modernConv.storedSummary, storedRichText: modernConv.storedRichText, size: JSON.stringify(conversation).length } : undefined } }; } } } finally { // Always close the database connection reader.close(); } }
  • Zod input schema defining parameters for the get_conversation tool: conversationId (required), and optional flags for including code blocks, file references, metadata, resolving modern bubble messages, or summary-only mode.
    export const getConversationSchema = z.object({ conversationId: z.string().min(1), includeCodeBlocks: z.boolean().optional().default(true), includeFileReferences: z.boolean().optional().default(true), includeMetadata: z.boolean().optional().default(false), resolveBubbles: z.boolean().optional().default(true), summaryOnly: z.boolean().optional().default(false) });
  • src/server.ts:142-176 (registration)
    MCP server registration of the 'get_conversation' tool. Defines tool name, description, input schema (slightly extended with outputMode), and handler wrapper that calls the main getConversation function and formats the response.
    server.tool( 'get_conversation', 'Retrieves the complete content of a specific Cursor conversation including all messages, code blocks, file references, title, and AI summary. WORKFLOW TIP: Use conversation IDs from list_conversations, search_conversations, or analytics breakdowns (files/languages arrays contain conversation IDs). Use summaryOnly=true to get enhanced summary data without full message content when you need to conserve context.', { conversationId: z.string().min(1).describe('Conversation ID from list_conversations, search_conversations, or analytics breakdowns'), summaryOnly: z.boolean().optional().default(false).describe('Return only enhanced summary data without full message content'), 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 fullInput = { ...input, includeCodeBlocks: true, includeFileReferences: true, includeMetadata: false, resolveBubbles: true }; const result = await getConversation(fullInput); 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/server.ts:30-34 (registration)
    Import statement in server.ts that brings in the getConversation handler function from conversation-tools.ts for use in tool registration.
    listConversations, getConversation, searchConversations, getConversationsByProject } from './tools/conversation-tools.js';

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