Skip to main content
Glama
vltansky

Cursor Conversations MCP Server

extract_conversation_elements

Extract files, code blocks, languages, folders, metadata, and structure from Cursor conversations to build knowledge bases, analyze patterns, and prepare data for documentation.

Instructions

Extract specific elements from conversations such as file references, code blocks, programming languages, folder paths, metadata, or conversation structure. Use this to build knowledge bases, analyze code patterns, extract reusable snippets, understand project file usage, or prepare data for further analysis and documentation.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
conversationIdsNoSpecific conversation IDs to extract elements from (if not provided, extracts from all conversations)
elementsNoTypes of elements to extract from conversations
includeContextNoInclude surrounding context for extracted elements
groupByNoHow to group the extracted elements in the outputconversation
filtersNoFilters to apply when extracting elements
outputModeNoOutput format: "json" for formatted JSON (default), "compact-json" for minified JSONjson

Implementation Reference

  • The core handler function that performs the extraction logic: connects to the database reader, fetches conversation IDs if not provided, extracts specified elements with filters and context, applies grouping (by conversation, element, or flat), and handles errors.
    export async function extractConversationElements(
      input: ExtractConversationElementsInput
    ): Promise<ExtractedElements> {
      const reader = new CursorDatabaseReader();
    
      try {
        await reader.connect();
    
        // Get conversation IDs to process
        let conversationIds = input.conversationIds;
        if (!conversationIds || conversationIds.length === 0) {
          // Get all conversation IDs if none specified
          conversationIds = await reader.getConversationIds({
            format: 'both',
            minLength: 1000
          });
        }
    
        // Extract elements from conversations
        const extractedData = await reader.extractConversationElements(
          conversationIds,
          input.elements,
          {
            includeContext: input.includeContext,
            filters: input.filters
          }
        );
    
        // Group data based on groupBy parameter
        if (input.groupBy === 'conversation') {
          return { conversations: extractedData };
        } else if (input.groupBy === 'element') {
          // Group by element type
          const groupedData: Record<string, any[]> = {};
    
          for (const elementType of input.elements) {
            groupedData[elementType] = [];
    
            for (const conversation of extractedData) {
              if (conversation.elements[elementType]) {
                if (Array.isArray(conversation.elements[elementType])) {
                  groupedData[elementType].push(...conversation.elements[elementType]);
                } else {
                  groupedData[elementType].push(conversation.elements[elementType]);
                }
              }
            }
          }
    
          return { conversations: groupedData } as any;
        } else {
          // Flatten all data
          const flatData: any[] = [];
    
          for (const conversation of extractedData) {
            for (const elementType of input.elements) {
              if (conversation.elements[elementType]) {
                if (Array.isArray(conversation.elements[elementType])) {
                  flatData.push(...conversation.elements[elementType].map((item: any) => ({
                    ...item,
                    conversationId: conversation.composerId,
                    elementType
                  })));
                } else {
                  flatData.push({
                    ...conversation.elements[elementType],
                    conversationId: conversation.composerId,
                    elementType
                  });
                }
              }
            }
          }
    
          return { conversations: flatData } as any;
        }
    
      } catch (error) {
        throw new DatabaseError(`Failed to extract conversation elements: ${error instanceof Error ? error.message : 'Unknown error'}`);
      } finally {
        reader.close();
      }
    }
  • Zod schema defining the input parameters for the extractConversationElements tool, used for validation and TypeScript typing.
    export const extractConversationElementsSchema = z.object({
      conversationIds: z.array(z.string()).optional(),
      elements: z.array(z.enum(['files', 'folders', 'languages', 'codeblocks', 'metadata', 'structure'])).optional().default(['files', 'codeblocks']),
      includeContext: z.boolean().optional().default(false),
      groupBy: z.enum(['conversation', 'element', 'none']).optional().default('conversation'),
      filters: z.object({
        minCodeLength: z.number().optional(),
        fileExtensions: z.array(z.string()).optional(),
        languages: z.array(z.string()).optional()
      }).optional()
    });
  • src/server.ts:297-338 (registration)
    MCP server registration of the 'extract_conversation_elements' tool, including name, description, input schema (matching the exported schema), and wrapper async handler that maps input, calls the core extractConversationElements function, formats the response, and handles errors.
    server.tool(
      'extract_conversation_elements',
      'Extract specific elements from conversations such as file references, code blocks, programming languages, folder paths, metadata, or conversation structure. Use this to build knowledge bases, analyze code patterns, extract reusable snippets, understand project file usage, or prepare data for further analysis and documentation.',
      {
        conversationIds: z.array(z.string()).optional().describe('Specific conversation IDs to extract elements from (if not provided, extracts from all conversations)'),
        elements: z.array(z.enum(['files', 'folders', 'languages', 'codeblocks', 'metadata', 'structure'])).optional().default(['files', 'codeblocks']).describe('Types of elements to extract from conversations'),
        includeContext: z.boolean().optional().default(false).describe('Include surrounding context for extracted elements'),
        groupBy: z.enum(['conversation', 'element', 'none']).optional().default('conversation').describe('How to group the extracted elements in the output'),
        filters: z.object({
          minCodeLength: z.number().optional().describe('Minimum length for code blocks to include'),
          fileExtensions: z.array(z.string()).optional().describe('Only include files with these extensions'),
          languages: z.array(z.string()).optional().describe('Only include code blocks in these programming languages')
        }).optional().describe('Filters to apply when extracting elements'),
        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 mappedInput = {
            conversationIds: input.conversationIds,
            elements: input.elements,
            includeContext: input.includeContext,
            groupBy: input.groupBy,
            filters: input.filters
          };
    
          const result = await extractConversationElements(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'}`
            }]
          };
        }
      }
    );
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden of behavioral disclosure. It describes the tool's function and use cases but lacks details on behavioral traits such as performance characteristics, rate limits, error handling, or authentication requirements. The description adds value by explaining the tool's purpose but does not fully compensate for the absence of annotations.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is appropriately sized and front-loaded, starting with the core purpose and following with use cases. Both sentences earn their place by clarifying the tool's function and applications. It could be slightly more concise by integrating the use cases more tightly, but overall it is well-structured and efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (6 parameters, nested objects) and the absence of both annotations and an output schema, the description is somewhat incomplete. It explains what the tool does and why to use it but does not address behavioral aspects or output format, leaving gaps that could hinder an AI agent's understanding of how to invoke it effectively.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema has 100% description coverage, so the schema already documents all parameters thoroughly. The description does not add any parameter-specific information beyond what the schema provides, such as explaining the semantics of 'elements' or 'filters' in more detail. Baseline score of 3 is appropriate when schema coverage is high.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's purpose with specific verbs ('extract specific elements from conversations') and resources ('conversations'), listing concrete element types like file references, code blocks, and metadata. It distinguishes from sibling tools like 'export_conversation_data' or 'get_conversation' by focusing on element extraction rather than full export or retrieval.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides clear context for when to use this tool ('to build knowledge bases, analyze code patterns, extract reusable snippets, understand project file usage, or prepare data for further analysis and documentation'), which helps differentiate it from siblings. However, it does not explicitly state when not to use it or name specific alternatives among the sibling tools.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other 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