Skip to main content
Glama
199-mcp

Limitless MCP Server

by 199-mcp

limitless_list_lifelogs_by_range

Retrieve paginated lifelog recordings within a specified date/time range for analysis, summaries, or action item extraction.

Instructions

Lists logs/recordings within a date/time range. Returns paginated results to avoid token limits. Use cursor to fetch next page. Best for getting raw log data which you can then analyze for summaries, action items, topics, etc.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
startYesStart datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS).
endYesEnd datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS).
limitNoMaximum number of lifelogs to return per request (Max: 10 per API constraint). Use cursor for pagination.
cursorNoPagination cursor from previous response. Use to fetch next page of results.
timezoneNoIANA timezone for date/time parameters (defaults to server's local timezone).
includeMarkdownNoInclude markdown content in the response.
includeHeadingsNoInclude headings content in the response.
directionNoSort order ('asc' for oldest first, 'desc' for newest first).
isStarredNoFilter for starred lifelogs only.

Implementation Reference

  • The core handler function registered for the 'limitless_list_lifelogs_by_range' tool. It validates input parameters, fetches lifelogs using getLifelogsWithPagination with the provided start/end range, handles token-based truncation and pagination info in responses.
    server.tool( "limitless_list_lifelogs_by_range",
        "Lists logs/recordings within a date/time range. Returns paginated results to avoid token limits. Use cursor to fetch next page. Best for getting raw log data which you can then analyze for summaries, action items, topics, etc.",
        ListByRangeArgsSchema,
        async (args, _extra) => {
            try {
                const validation = validateApiConstraints(args);
                if (!validation.valid) {
                    return { content: [{ type: "text", text: validation.error! }], isError: true };
                }
                
                const result = await getLifelogsWithPagination(limitlessApiKey, {
                    start: args.start,
                    end: args.end,
                    limit: args.limit || MAX_API_LIMIT,
                    timezone: args.timezone,
                    includeMarkdown: args.includeMarkdown,
                    includeHeadings: args.includeHeadings,
                    direction: args.direction ?? 'asc',
                    isStarred: args.isStarred,
                    cursor: args.cursor
                });
                
                const estimatedSize = estimateTokens(JSON.stringify(result.lifelogs));
                if (estimatedSize > MAX_RESPONSE_TOKENS * 0.8 && result.lifelogs.length > 1) {
                    const partialCount = Math.max(1, Math.floor(result.lifelogs.length * 0.5));
                    const partialLifelogs = result.lifelogs.slice(0, partialCount);
                    
                    return createSafeResponse(
                        partialLifelogs,
                        `Found ${result.lifelogs.length} lifelogs in range, showing first ${partialCount} to avoid token limits`,
                        {
                            nextCursor: result.pagination.nextCursor,
                            hasMore: true,
                            totalFetched: partialCount
                        }
                    );
                }
                
                return createSafeResponse(
                    result.lifelogs,
                    `Found ${result.lifelogs.length} lifelogs in the specified range`,
                    {
                        nextCursor: result.pagination.nextCursor,
                        hasMore: result.pagination.hasMore,
                        totalFetched: result.lifelogs.length
                    }
                );
            } catch (error) {
                return handleToolApiCall(() => Promise.reject(error));
            }
        }
    );
    server.tool( "limitless_list_recent_lifelogs",
  • Zod schema defining the input parameters for the tool, including required 'start' and 'end' datetime filters, extending common list arguments like limit, cursor, etc.
    const ListByRangeArgsSchema = {
        start: z.string().describe("Start datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS)."),
        end: z.string().describe("End datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS)."),
        ...CommonListArgsSchema
    };
  • src/server.ts:497-549 (registration)
    MCP server tool registration for 'limitless_list_lifelogs_by_range', specifying name, description, input schema, and handler function.
    server.tool( "limitless_list_lifelogs_by_range",
        "Lists logs/recordings within a date/time range. Returns paginated results to avoid token limits. Use cursor to fetch next page. Best for getting raw log data which you can then analyze for summaries, action items, topics, etc.",
        ListByRangeArgsSchema,
        async (args, _extra) => {
            try {
                const validation = validateApiConstraints(args);
                if (!validation.valid) {
                    return { content: [{ type: "text", text: validation.error! }], isError: true };
                }
                
                const result = await getLifelogsWithPagination(limitlessApiKey, {
                    start: args.start,
                    end: args.end,
                    limit: args.limit || MAX_API_LIMIT,
                    timezone: args.timezone,
                    includeMarkdown: args.includeMarkdown,
                    includeHeadings: args.includeHeadings,
                    direction: args.direction ?? 'asc',
                    isStarred: args.isStarred,
                    cursor: args.cursor
                });
                
                const estimatedSize = estimateTokens(JSON.stringify(result.lifelogs));
                if (estimatedSize > MAX_RESPONSE_TOKENS * 0.8 && result.lifelogs.length > 1) {
                    const partialCount = Math.max(1, Math.floor(result.lifelogs.length * 0.5));
                    const partialLifelogs = result.lifelogs.slice(0, partialCount);
                    
                    return createSafeResponse(
                        partialLifelogs,
                        `Found ${result.lifelogs.length} lifelogs in range, showing first ${partialCount} to avoid token limits`,
                        {
                            nextCursor: result.pagination.nextCursor,
                            hasMore: true,
                            totalFetched: partialCount
                        }
                    );
                }
                
                return createSafeResponse(
                    result.lifelogs,
                    `Found ${result.lifelogs.length} lifelogs in the specified range`,
                    {
                        nextCursor: result.pagination.nextCursor,
                        hasMore: result.pagination.hasMore,
                        totalFetched: result.lifelogs.length
                    }
                );
            } catch (error) {
                return handleToolApiCall(() => Promise.reject(error));
            }
        }
    );
    server.tool( "limitless_list_recent_lifelogs",
  • Helper function that performs the actual Limitless API call for fetching lifelogs by date range or other filters, returning paginated results with cursor. Used by the tool handler.
    export async function getLifelogsWithPagination(apiKey: string, options: LifelogParams = {}): Promise<LifelogsWithPagination> {
        const defaultTimezone = getDefaultTimezone();
        const batchSize = options.limit || 10; // Use requested limit as batch size
    
        const params: Record<string, string | number | boolean | undefined> = {
            limit: batchSize,
            includeMarkdown: options.includeMarkdown ?? true,
            includeHeadings: options.includeHeadings ?? true,
            date: options.date,
            start: options.start,
            end: options.end,
            direction: options.direction ?? 'desc',
            timezone: options.timezone ?? defaultTimezone,
            cursor: options.cursor,
            isStarred: options.isStarred,
        };
    
        // Clean up undefined values
        Object.keys(params).forEach(key => {
            if (params[key] === undefined) delete params[key];
        });
    
        const response = await makeApiRequest<LifelogsResponse>(apiKey, "v1/lifelogs", params);
        const lifelogs = response.data?.lifelogs ?? [];
        const nextCursor = response.meta?.lifelogs?.nextCursor;
        const count = response.meta?.lifelogs?.count ?? lifelogs.length;
    
        return {
            lifelogs,
            pagination: {
                nextCursor,
                hasMore: !!nextCursor,
                count
            }
        };
    }
Behavior4/5

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

With no annotations provided, the description carries the full burden of behavioral disclosure. It effectively describes key behaviors: pagination ('Returns paginated results to avoid token limits. Use cursor to fetch next page.') and the nature of returned data ('raw log data'). It doesn't mention rate limits, authentication needs, or error handling, but covers essential operational aspects well for a read operation.

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

Conciseness5/5

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

The description is efficiently structured in three sentences: purpose statement, pagination behavior, and usage recommendation. Each sentence adds distinct value without redundancy. It's appropriately sized and front-loaded with the core functionality.

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

Completeness4/5

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

For a read operation with 9 parameters and no output schema, the description provides good context about pagination and data format. It doesn't explain return values or error cases, but given the tool's complexity and lack of annotations, it covers the essential operational aspects adequately. The gap in output details prevents a perfect score.

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 description adds no parameter-specific information beyond what's already in the schema (which has 100% coverage). It mentions 'cursor' and 'date/time range' generally, but doesn't provide additional context about parameter interactions, default behaviors, or semantic nuances. With complete schema coverage, the baseline is 3.

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

Purpose4/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: 'Lists logs/recordings within a date/time range.' It specifies the resource (logs/recordings) and verb (lists) with a scope (date/time range). However, it doesn't explicitly differentiate from sibling tools like 'limitless_list_lifelogs_by_date' or 'limitless_list_recent_lifelogs', which likely have overlapping functionality.

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 usage context: 'Best for getting raw log data which you can then analyze for summaries, action items, topics, etc.' This implies when to use it (for raw data analysis) and suggests alternatives (like analysis-specific tools among siblings). However, it doesn't explicitly state when NOT to use it or name specific alternative 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/199-mcp/mcp-limitless'

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