Skip to main content
Glama
199-mcp

Limitless MCP Server

by 199-mcp

limitless_search_lifelogs

Search recent lifelog recordings for specific keywords in titles and content, returning matching results from a defined scope of recent entries.

Instructions

Performs a simple text search for specific keywords/phrases within the title and content of recent logs/Pendant recordings. Use ONLY for keywords, NOT for concepts like 'action items' or 'summaries'. Searches only recent logs (limited scope).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
search_termYesThe text to search for within lifelog titles and content.
fetch_limitNoHow many *recent* lifelogs to fetch from the API to search within (Default: 20, Max: 100). This defines the scope of the search, NOT the number of results returned.
limitNoMaximum number of lifelogs to return per request (Max: 10 per API constraint). Use cursor for pagination.
timezoneNoIANA timezone for date/time parameters (defaults to server's local timezone).
includeMarkdownNoInclude markdown content in the response.
includeHeadingsNoInclude headings content in the response.
isStarredNoFilter for starred lifelogs only.

Implementation Reference

  • The handler function fetches recent lifelogs via getLifelogs API call, performs case-insensitive substring search on log.title and log.markdown, limits results, and returns formatted matches with token limit handling.
    async (args, _extra) => {
        const fetchLimit = args.fetch_limit ?? 20;
        console.error(`[Server Tool] Search initiated for term: "${args.search_term}", fetch_limit: ${fetchLimit}`);
        try {
            const logsToSearch = await getLifelogs(limitlessApiKey, { 
                limit: fetchLimit, 
                direction: 'desc', 
                timezone: args.timezone, 
                includeMarkdown: args.includeMarkdown ?? true, 
                includeHeadings: args.includeHeadings ?? true, 
                isStarred: args.isStarred 
            });
            
            if (logsToSearch.length === 0) {
                return { content: [{ type: "text", text: "No recent lifelogs found to search within." }] };
            }
            
            const searchTermLower = args.search_term.toLowerCase();
            const matchingLogs = logsToSearch.filter(log => 
                log.title?.toLowerCase().includes(searchTermLower) || 
                (log.markdown && log.markdown.toLowerCase().includes(searchTermLower))
            );
            
            const finalLimit = args.limit; // This limit applies to the *results*
            const limitedResults = finalLimit ? matchingLogs.slice(0, finalLimit) : matchingLogs;
            
            if (limitedResults.length === 0) {
                return { content: [{ type: "text", text: `No matches found for "${args.search_term}" within the ${logsToSearch.length} most recent lifelogs searched.` }] };
            }
            
            // Use createSafeResponse to handle token limits
            return createSafeResponse(
                limitedResults,
                `Found ${limitedResults.length} match(es) for "${args.search_term}" within the ${logsToSearch.length} most recent lifelogs searched${finalLimit !== undefined ? ` (displaying up to ${finalLimit})` : ''}`,
                {
                    hasMore: matchingLogs.length > limitedResults.length,
                    totalFetched: logsToSearch.length
                }
            );
        } catch (error) { 
            return handleToolApiCall(() => Promise.reject(error)); 
        }
    }
  • Input argument schema using Zod, defining search_term (required), fetch_limit (scope of lifelogs to search), and common pagination/filter options.
    const SearchArgsSchema = {
        search_term: z.string().describe("The text to search for within lifelog titles and content."),
        fetch_limit: z.number().int().positive().max(MAX_TOTAL_FETCH_LIMIT).optional().default(20).describe(`How many *recent* lifelogs to fetch from the API to search within (Default: 20, Max: ${MAX_TOTAL_FETCH_LIMIT}). This defines the scope of the search, NOT the number of results returned.`),
        limit: CommonListArgsSchema.limit,
        timezone: CommonListArgsSchema.timezone,
        includeMarkdown: CommonListArgsSchema.includeMarkdown,
        includeHeadings: CommonListArgsSchema.includeHeadings,
        isStarred: CommonListArgsSchema.isStarred,
    };
  • src/server.ts:599-645 (registration)
    MCP server registration of the tool, providing name, detailed description emphasizing keyword-only usage on recent logs, input schema, and handler callback.
    server.tool( "limitless_search_lifelogs",
        "Performs a simple text search for specific keywords/phrases within the title and content of *recent* logs/Pendant recordings. Use ONLY for keywords, NOT for concepts like 'action items' or 'summaries'. Searches only recent logs (limited scope).",
        SearchArgsSchema,
        async (args, _extra) => {
            const fetchLimit = args.fetch_limit ?? 20;
            console.error(`[Server Tool] Search initiated for term: "${args.search_term}", fetch_limit: ${fetchLimit}`);
            try {
                const logsToSearch = await getLifelogs(limitlessApiKey, { 
                    limit: fetchLimit, 
                    direction: 'desc', 
                    timezone: args.timezone, 
                    includeMarkdown: args.includeMarkdown ?? true, 
                    includeHeadings: args.includeHeadings ?? true, 
                    isStarred: args.isStarred 
                });
                
                if (logsToSearch.length === 0) {
                    return { content: [{ type: "text", text: "No recent lifelogs found to search within." }] };
                }
                
                const searchTermLower = args.search_term.toLowerCase();
                const matchingLogs = logsToSearch.filter(log => 
                    log.title?.toLowerCase().includes(searchTermLower) || 
                    (log.markdown && log.markdown.toLowerCase().includes(searchTermLower))
                );
                
                const finalLimit = args.limit; // This limit applies to the *results*
                const limitedResults = finalLimit ? matchingLogs.slice(0, finalLimit) : matchingLogs;
                
                if (limitedResults.length === 0) {
                    return { content: [{ type: "text", text: `No matches found for "${args.search_term}" within the ${logsToSearch.length} most recent lifelogs searched.` }] };
                }
                
                // Use createSafeResponse to handle token limits
                return createSafeResponse(
                    limitedResults,
                    `Found ${limitedResults.length} match(es) for "${args.search_term}" within the ${logsToSearch.length} most recent lifelogs searched${finalLimit !== undefined ? ` (displaying up to ${finalLimit})` : ''}`,
                    {
                        hasMore: matchingLogs.length > limitedResults.length,
                        totalFetched: logsToSearch.length
                    }
                );
            } catch (error) { 
                return handleToolApiCall(() => Promise.reject(error)); 
            }
        }
    );

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