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
| Name | Required | Description | Default |
|---|---|---|---|
| start | Yes | Start datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS). | |
| end | Yes | End datetime filter (YYYY-MM-DD or YYYY-MM-DD HH:mm:SS). | |
| limit | No | Maximum number of lifelogs to return per request (Max: 10 per API constraint). Use cursor for pagination. | |
| cursor | No | Pagination cursor from previous response. Use to fetch next page of results. | |
| timezone | No | IANA timezone for date/time parameters (defaults to server's local timezone). | |
| includeMarkdown | No | Include markdown content in the response. | |
| includeHeadings | No | Include headings content in the response. | |
| direction | No | Sort order ('asc' for oldest first, 'desc' for newest first). | |
| isStarred | No | Filter for starred lifelogs only. |
Implementation Reference
- src/server.ts:497-549 (handler)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",
- src/server.ts:197-201 (schema)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",
- src/limitless-client.ts:267-302 (helper)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 } }; }