toggl_workspace_summary
Calculate total hours per workspace for specified date ranges to track time allocation and productivity across projects.
Instructions
Get total hours per workspace for a date range
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| end_date | No | End date (YYYY-MM-DD format) | |
| period | No | Predefined period | |
| start_date | No | Start date (YYYY-MM-DD format) |
Implementation Reference
- src/index.ts:661-700 (handler)Main execution logic for the toggl_workspace_summary tool: fetches time entries for specified period or date range (default current week), hydrates with workspace/project names, groups by workspace, generates summaries, sorts by total hours descending, and returns JSON with counts and summaries.case 'toggl_workspace_summary': { await ensureCache(); let entries: TimeEntry[]; if (args?.period) { const range = getDateRange(args.period as any); entries = await api.getTimeEntriesForDateRange(range.start, range.end); } else if (args?.start_date && args?.end_date) { const start = new Date(args.start_date as string); const end = new Date(args.end_date as string); entries = await api.getTimeEntriesForDateRange(start, end); } else { // Default to current week entries = await api.getTimeEntriesForWeek(0); } const hydrated = await cache.hydrateTimeEntries(entries); const byWorkspace = groupEntriesByWorkspace(hydrated); const summaries: any[] = []; byWorkspace.forEach((wsEntries, wsName) => { const wsId = wsEntries[0]?.workspace_id || 0; summaries.push(generateWorkspaceSummary(wsName, wsId, wsEntries)); }); // Sort by total hours descending summaries.sort((a, b) => b.total_seconds - a.total_seconds); return { content: [{ type: 'text', text: JSON.stringify({ workspace_count: summaries.length, total_hours: secondsToHours(summaries.reduce((t, s) => t + s.total_seconds, 0)), workspaces: summaries }, null, 2) }] }; }
- src/index.ts:291-312 (schema)Tool schema definition including name, description, and input schema with optional period enum or custom date range parameters.{ name: 'toggl_workspace_summary', description: 'Get total hours per workspace for a date range', inputSchema: { type: 'object', properties: { period: { type: 'string', enum: ['week', 'lastWeek', 'month', 'lastMonth'], description: 'Predefined period' }, start_date: { type: 'string', description: 'Start date (YYYY-MM-DD format)' }, end_date: { type: 'string', description: 'End date (YYYY-MM-DD format)' } } }, },
- src/utils.ts:198-220 (helper)Helper function that computes workspace summary statistics from a list of hydrated time entries: total/billable hours/seconds, project count, entry count.export function generateWorkspaceSummary( workspaceName: string, workspaceId: number, entries: HydratedTimeEntry[] ): WorkspaceSummary { const totalSeconds = calculateTotalDuration(entries); const billableSeconds = entries .filter(e => e.billable) .reduce((total, e) => total + (e.duration < 0 ? 0 : e.duration), 0); const projectIds = new Set(entries.map(e => e.project_id).filter(Boolean)); return { workspace_id: workspaceId, workspace_name: workspaceName, total_hours: secondsToHours(totalSeconds), total_seconds: totalSeconds, billable_hours: secondsToHours(billableSeconds), billable_seconds: billableSeconds, project_count: projectIds.size, entry_count: entries.length }; }
- src/utils.ts:127-139 (helper)Utility function to group hydrated time entries by their workspace name into a Map.export function groupEntriesByWorkspace(entries: HydratedTimeEntry[]): Map<string, HydratedTimeEntry[]> { const grouped = new Map<string, HydratedTimeEntry[]>(); entries.forEach(entry => { const key = entry.workspace_name; if (!grouped.has(key)) { grouped.set(key, []); } grouped.get(key)!.push(entry); }); return grouped; }
- src/index.ts:386-388 (registration)Registers all tools including toggl_workspace_summary for the ListToolsRequest by returning the tools array.server.setRequestHandler(ListToolsRequestSchema, async () => { return { tools }; });