import { z } from 'zod';
import { LimitlessClient } from '../../lib/limitless-client.js';
import { LifelogsResponse, GetLifelogsParams } from '../../types/limitless.js';
import { Tool } from '@modelcontextprotocol/sdk/types.js';
export const listLifelogsSchema = z.object({
timezone: z.string().optional().describe('Timezone for date filtering (e.g., "America/New_York")'),
date: z.string().optional().describe('Filter by specific date (YYYY-MM-DD format)'),
startTime: z.string().optional().describe('Start time filter (HH:MM format, requires date)'),
endTime: z.string().optional().describe('End time filter (HH:MM format, requires date)'),
cursor: z.string().optional().describe('Pagination cursor from previous request'),
direction: z.enum(['asc', 'desc']).optional().describe('Sort direction for results'),
includeMarkdown: z.boolean().optional().describe('Include markdown content in response'),
includeHeadings: z.boolean().optional().describe('Include content headings in response'),
limit: z.number().min(1).max(100).optional().describe('Number of results to return (max 100)'),
isStarred: z.boolean().optional().describe('Filter by starred status'),
});
export type ListLifelogsParams = z.infer<typeof listLifelogsSchema>;
export const listLifelogsTool: Tool = {
name: 'limitless_list_lifelogs',
description: 'List lifelogs from Limitless with optional filtering by date, time, and other criteria',
inputSchema: {
type: 'object',
properties: {
timezone: { type: 'string', description: 'Timezone for date filtering (e.g., "America/New_York")' },
date: { type: 'string', description: 'Filter by specific date (YYYY-MM-DD format)' },
startTime: { type: 'string', description: 'Start time filter (HH:MM format, requires date)' },
endTime: { type: 'string', description: 'End time filter (HH:MM format, requires date)' },
cursor: { type: 'string', description: 'Pagination cursor from previous request' },
direction: { type: 'string', enum: ['asc', 'desc'], description: 'Sort direction for results' },
includeMarkdown: { type: 'boolean', description: 'Include markdown content in response' },
includeHeadings: { type: 'boolean', description: 'Include content headings in response' },
limit: { type: 'number', description: 'Number of results to return (max 100)' },
isStarred: { type: 'boolean', description: 'Filter by starred status' },
},
},
};
export async function listLifelogs(params: ListLifelogsParams, client: LimitlessClient): Promise<LifelogsResponse> {
const queryParams: GetLifelogsParams = {};
// Only add defined parameters
if (params.timezone) queryParams.timezone = params.timezone;
if (params.date) queryParams.date = params.date;
if (params.startTime) queryParams.startTime = params.startTime;
if (params.endTime) queryParams.endTime = params.endTime;
if (params.cursor) queryParams.cursor = params.cursor;
if (params.direction) queryParams.direction = params.direction;
if (params.includeMarkdown !== undefined) queryParams.includeMarkdown = params.includeMarkdown;
if (params.includeHeadings !== undefined) queryParams.includeHeadings = params.includeHeadings;
if (params.limit) queryParams.limit = params.limit;
if (params.isStarred !== undefined) queryParams.isStarred = params.isStarred;
return await client.get<LifelogsResponse>('/lifelogs', queryParams);
}