Skip to main content
Glama
199-mcp

Limitless MCP Server

by 199-mcp

limitless_list_lifelogs_by_date

Retrieve paginated lifelog recordings for a specific date to analyze raw data for summaries, action items, and topics.

Instructions

Lists logs/recordings for a specific date. 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
dateYesThe date to retrieve lifelogs for, in YYYY-MM-DD format.
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

  • src/server.ts:443-496 (registration)
    Registration of the 'limitless_list_lifelogs_by_date' tool, including the handler function that validates input, fetches paginated lifelogs for a specific date using getLifelogsWithPagination, handles response truncation for token limits, and formats the output with pagination info.
    server.tool( "limitless_list_lifelogs_by_date",
        "Lists logs/recordings for a specific date. 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.",
        ListByDateArgsSchema,
        async (args, _extra) => {
            try {
                const validation = validateApiConstraints(args);
                if (!validation.valid) {
                    return { content: [{ type: "text", text: validation.error! }], isError: true };
                }
                
                // Use pagination-aware function
                const result = await getLifelogsWithPagination(limitlessApiKey, {
                    date: args.date,
                    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
                });
                
                // Check if response might be too large
                const estimatedSize = estimateTokens(JSON.stringify(result.lifelogs));
                if (estimatedSize > MAX_RESPONSE_TOKENS * 0.8 && result.lifelogs.length > 1) {
                    // Return partial data with strong cursor guidance
                    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 for ${args.date}, showing first ${partialCount} to avoid token limits`,
                        {
                            nextCursor: result.pagination.nextCursor,
                            hasMore: true,
                            totalFetched: partialCount
                        }
                    );
                }
                
                return createSafeResponse(
                    result.lifelogs,
                    `Found ${result.lifelogs.length} lifelogs for ${args.date}`,
                    {
                        nextCursor: result.pagination.nextCursor,
                        hasMore: result.pagination.hasMore,
                        totalFetched: result.lifelogs.length
                    }
                );
            } catch (error) {
                return handleToolApiCall(() => Promise.reject(error));
            }
        }
    );
  • Zod schemas defining the input parameters for the tool: ListByDateArgsSchema (requires 'date' in YYYY-MM-DD) extending CommonListArgsSchema (limit, cursor, timezone, etc.).
    const CommonListArgsSchema = {
        limit: z.number().int().positive().max(MAX_API_LIMIT).optional().default(MAX_API_LIMIT).describe(`Maximum number of lifelogs to return per request (Max: ${MAX_API_LIMIT} per API constraint). Use cursor for pagination.`),
        cursor: z.string().optional().describe("Pagination cursor from previous response. Use to fetch next page of results."),
        timezone: z.string().optional().describe("IANA timezone for date/time parameters (defaults to server's local timezone)."),
        includeMarkdown: z.boolean().optional().default(true).describe("Include markdown content in the response."),
        includeHeadings: z.boolean().optional().default(true).describe("Include headings content in the response."),
        direction: z.enum(["asc", "desc"]).optional().describe("Sort order ('asc' for oldest first, 'desc' for newest first)."),
        isStarred: z.boolean().optional().describe("Filter for starred lifelogs only."),
    };
    const GetByIdArgsSchema = {
        lifelog_id: z.string().describe("The unique identifier of the lifelog to retrieve."),
        includeMarkdown: z.boolean().optional().default(true).describe("Include markdown content in the response."),
        includeHeadings: z.boolean().optional().default(true).describe("Include headings content in the response."),
    };
    const ListByDateArgsSchema = {
        date: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "Date must be in YYYY-MM-DD format.").describe("The date to retrieve lifelogs for, in YYYY-MM-DD format."),
        ...CommonListArgsSchema
    };
  • Core helper function getLifelogsWithPagination that makes the API request to Limitless /v1/lifelogs endpoint with parameters including date filter, handles response parsing, and returns lifelogs with pagination metadata. Called directly 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
            }
        };
    }
  • TypeScript interface LifelogParams defining the parameters passed to API functions, matching the tool's input schema (used by getLifelogsWithPagination).
    export interface LifelogParams {
        limit?: number;
        batch_size?: number; // Used internally for pagination fetching
        includeMarkdown?: boolean;
        includeHeadings?: boolean;
        date?: string; // YYYY-MM-DD
        start?: string; // YYYY-MM-DD or YYYY-MM-DD HH:mm:SS
        end?: string; // YYYY-MM-DD or YYYY-MM-DD HH:mm:SS
        timezone?: string;
        direction?: "asc" | "desc";
        cursor?: string;
        isStarred?: boolean; // Filter for starred lifelogs only
    }
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 behavioral traits: 'Returns paginated results to avoid token limits. Use cursor to fetch next page.' This covers pagination behavior and token limit avoidance, which are crucial for understanding how to handle large datasets. However, it does not mention permissions, rate limits, or error handling.

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 appropriately sized and front-loaded: the first sentence states the core purpose, followed by pagination details and usage guidance. Every sentence earns its place by adding value without redundancy, making it efficient and well-structured.

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?

Given the tool's complexity (8 parameters, pagination, no output schema, and no annotations), the description is mostly complete. It covers purpose, pagination behavior, and usage context. However, it lacks details on response format (e.g., what fields are returned) and error scenarios, which would enhance completeness for a tool with many parameters.

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 schema description coverage is 100%, so the schema already documents all 8 parameters thoroughly. The description does not add any parameter-specific semantics beyond what the schema provides (e.g., it does not explain the 'date' parameter's format or 'cursor' usage in more detail). Baseline 3 is appropriate when the schema does the heavy lifting.

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: 'Lists logs/recordings for a specific date.' It specifies the verb ('Lists'), resource ('logs/recordings'), and scope ('for a specific date'), distinguishing it from siblings like 'limitless_list_lifelogs_by_range' (date range) and 'limitless_list_recent_lifelogs' (recent logs).

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 usage: 'Best for getting raw log data which you can then analyze for summaries, action items, topics, etc.' This implicitly suggests when to use it (for raw data analysis) versus alternatives like 'limitless_get_daily_summary' or 'limitless_extract_action_items', but it does not explicitly name alternatives or state exclusions.

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