Skip to main content
Glama

timeline

Track work sessions and project activities using checkpoints grouped by date and workspace. Supports filtering by time range, scope, and workspace for standups or task reviews.

Instructions

Show timeline of work sessions. Perfect for standups and understanding recent activity across projects. Shows checkpoints grouped by date and workspace.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
scopeNoTimeline scope: current workspace or all workspaces
sinceNoTime range to show (default: "7d")
workspaceNoSpecific workspace (optional)

Implementation Reference

  • The primary handler function for the 'timeline' MCP tool. It fetches recent checkpoints using SearchEngine, groups them chronologically by local date and workspace, generates a formatted text summary with highlights, supports VS Code visualization, and returns structured data.
    async timeline(args: { since?: string; workspace?: string; scope?: 'current' | 'all'; format?: OutputMode; }) { const { since = '7d', workspace, scope = 'current', format } = args; try { const memories = await this.searchEngine.searchMemories({ since, workspace: scope === 'all' ? undefined : workspace, scope, type: 'checkpoint', limit: 200 }); if (memories.length === 0) { const formatted = `📅 No work sessions found in the last ${since}\n\nTry extending the time range or checking other workspaces.`; const data = { scope, since, workspace, totalItems: 0, workspacesFound: 0, checkpointsFound: 0, byDate: {}, byWorkspace: {} } as const; return buildToolContent('timeline', formatted, data as any, format); } // Group by date and workspace const timelineMap = new Map<string, Map<string, { count: number; highlights: string[] }>>(); for (const memory of memories) { // Extract local date key for user-intuitive timeline grouping const date = getLocalDateKey(memory.timestamp); const ws = memory.workspace || 'unknown'; if (!timelineMap.has(date)) { timelineMap.set(date, new Map()); } const dayMap = timelineMap.get(date); if (!dayMap) continue; if (!dayMap.has(ws)) { dayMap.set(ws, { count: 0, highlights: [] }); } const wsData = dayMap.get(ws)!; wsData.count++; // Extract highlights if (typeof memory.content === 'object' && memory.content && 'highlights' in memory.content) { const contentObj = memory.content as { highlights?: string[] }; if (Array.isArray(contentObj.highlights)) { wsData.highlights.push(...contentObj.highlights); } } } // Build formatted output const output = [`📅 Work Timeline (${since})`]; const sortedDates = Array.from(timelineMap.keys()).sort().reverse(); for (const date of sortedDates) { const dayData = timelineMap.get(date)!; // Use centralized date formatting utility for consistent Today/Yesterday logic const dayName = formatDateName(date); output.push(`\n**${dayName}** (${date})`); for (const [ws, data] of dayData.entries()) { const wsDisplay = ws; // Always show actual workspace name output.push(` 📁 ${wsDisplay}: ${data.count} checkpoints`); // Show unique highlights const uniqueHighlights = [...new Set(data.highlights)]; if (uniqueHighlights.length > 0) { uniqueHighlights.slice(0, 3).forEach(highlight => { output.push(` ✨ ${highlight}`); }); if (uniqueHighlights.length > 3) { output.push(` ... and ${uniqueHighlights.length - 3} more`); } } } } // Send to VS Code if available if (this.displayHandler?.isAvailable) { try { await this.displayHandler.displayTimeline(memories, `Work Timeline (${since})`); console.error('📊 Timeline sent to VS Code'); } catch (error) { console.error('⚠️ Failed to send timeline to VS Code:', error); } } const formatted = output.join('\n'); const data = { scope, since, workspace, totalItems: memories.length, workspacesFound: new Set(memories.map(m => m.workspace || 'unknown')).size, checkpointsFound: memories.filter(m => m.type === 'checkpoint').length, byDate: Object.fromEntries(Array.from(timelineMap.entries()).map(([date, wsMap]) => [ date, Object.fromEntries(wsMap.entries()) ])), byWorkspace: {} } as const; return buildToolContent('timeline', formatted, data as any, format); } catch (error) { return { content: [ { type: 'text', text: `❌ Timeline failed: ${error instanceof Error ? error.message : String(error)}` } ] }; }
  • Defines the input schema and metadata for the 'timeline' tool, including optional parameters for time range, workspace filtering, scope, and output format.
    name: 'timeline', description: 'Review work progress chronologically. Use when user asks "what did I do" or needs timeline view for reporting.', inputSchema: { type: 'object', properties: { since: { type: 'string', description: 'Time range to show (default: "7d")', default: '7d' }, workspace: { type: 'string', description: 'Workspace name or path (e.g., "coa-goldfish-mcp" or "C:\\source\\COA Goldfish MCP"). Will be normalized automatically.' }, scope: { type: 'string', enum: ['current', 'all'], description: 'Timeline scope: current workspace or all workspaces', default: 'current' }, format: { type: 'string', enum: ['plain', 'emoji', 'json', 'dual'], description: 'Output format override (defaults to env GOLDFISH_OUTPUT_MODE or dual)' } } } },
  • Registers the runtime handler dispatch for the 'timeline' tool in the main tool call switch statement, invoking SearchTools.timeline.
    case 'timeline': return await this.searchTools.timeline(args || {});
  • Registers the 'timeline' tool schema by including SearchTools.getToolSchemas() in the list of available tools returned by ListToolsRequestHandler.
    // Search and timeline tools ...SearchTools.getToolSchemas(),

Other Tools

Related 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/anortham/coa-goldfish-mcp'

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