Skip to main content
Glama

todoist_label_stats

Analyze label usage statistics in Todoist to identify patterns and optimize task organization.

Instructions

Get usage statistics for all labels in Todoist

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • Core handler function that fetches all labels and tasks from Todoist, computes detailed usage statistics for each label (total tasks, completed count, completion percentage, most recent usage, color), sorts by total usage descending, applies caching, and returns a formatted multi-line report.
    export async function handleGetLabelStats( todoistClient: TodoistApi ): Promise<string> { const cacheKey = "labels:stats"; const cached = labelStatsCache.get(cacheKey); let sortedStats: LabelStatistics[]; if (cached) { sortedStats = cached; } else { try { const [labelsResponse, tasksResponse] = await Promise.all([ todoistClient.getLabels(), todoistClient.getTasks(), ]); const labels = extractArrayFromResponse(labelsResponse) as TodoistLabel[]; const tasks = extractArrayFromResponse(tasksResponse) as Array<{ labels?: string[]; isCompleted?: boolean; createdAt?: string; }>; const stats = labels.map((label) => { const tasksWithLabel = tasks.filter((task) => task.labels?.includes(label.name) ); const completedTasks = tasksWithLabel.filter( (task) => task.isCompleted ).length; const mostRecentTask = tasksWithLabel .filter((task) => task.createdAt) .sort((a, b) => { const dateA = new Date(a.createdAt!).getTime(); const dateB = new Date(b.createdAt!).getTime(); return dateB - dateA; })[0]; return { label: label.name, totalTasks: tasksWithLabel.length, completedTasks, completionRate: tasksWithLabel.length > 0 ? Math.round((completedTasks / tasksWithLabel.length) * 100) : 0, color: label.color, mostRecentUse: mostRecentTask?.createdAt || null, }; }); sortedStats = stats.sort((a, b) => b.totalTasks - a.totalTasks); labelStatsCache.set(cacheKey, sortedStats); } catch (error) { throw new TodoistAPIError( "Failed to fetch label statistics", error instanceof Error ? error : undefined ); } } if (sortedStats.length === 0) { return "No labels found to generate statistics."; } const statsReport = sortedStats .map((stat) => { const lastUsed = stat.mostRecentUse ? new Date(stat.mostRecentUse).toLocaleDateString() : "Never"; return `• ${stat.label} (${stat.color || "default"}) - Total tasks: ${stat.totalTasks} - Completed: ${stat.completedTasks} (${stat.completionRate}%) - Last used: ${lastUsed}`; }) .join("\n\n"); return `Label Usage Statistics:\n\n${statsReport}`; }
  • MCP Tool definition including name, description, and input schema (empty object as no input parameters are required).
    export const GET_LABEL_STATS_TOOL: Tool = { name: "todoist_label_stats", description: "Get usage statistics for all labels in Todoist", inputSchema: { type: "object", properties: {}, }, };
  • src/index.ts:282-287 (registration)
    Dispatcher registration in the main CallToolRequest handler: validates input with isGetLabelStatsArgs and invokes the handleGetLabelStats function.
    case "todoist_label_stats": if (!isGetLabelStatsArgs(args)) { throw new Error("Invalid arguments for todoist_label_stats"); } result = await handleGetLabelStats(apiClient); break;
  • Type guard function for input validation, confirming args is a non-null object (matches empty inputSchema).
    export function isGetLabelStatsArgs( args: unknown ): args is Record<string, never> { return typeof args === "object" && args !== null; }
  • Includes the tool in the LABEL_TOOLS array, which is aggregated into ALL_TOOLS for server tool listing.
    export const LABEL_TOOLS = [ GET_LABELS_TOOL, CREATE_LABEL_TOOL, UPDATE_LABEL_TOOL, DELETE_LABEL_TOOL, GET_LABEL_STATS_TOOL, ];

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/greirson/mcp-todoist'

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