Skip to main content
Glama

Todoist MCP Server

type-guards.ts11.7 kB
import { CreateTaskArgs, GetTasksArgs, UpdateTaskArgs, TaskNameArgs, GetSectionsArgs, CreateProjectArgs, CreateSectionArgs, BulkCreateTasksArgs, BulkUpdateTasksArgs, BulkTaskFilterArgs, CreateCommentArgs, GetCommentsArgs, CreateLabelArgs, UpdateLabelArgs, LabelNameArgs, CreateSubtaskArgs, BulkCreateSubtasksArgs, ConvertToSubtaskArgs, PromoteSubtaskArgs, GetTaskHierarchyArgs, } from "./types.js"; export function isCreateTaskArgs(args: unknown): args is CreateTaskArgs { return ( typeof args === "object" && args !== null && "content" in args && typeof (args as { content: string }).content === "string" ); } export function isGetTasksArgs(args: unknown): args is GetTasksArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.project_id === undefined || typeof obj.project_id === "string") && (obj.filter === undefined || typeof obj.filter === "string") && (obj.label_id === undefined || typeof obj.label_id === "string") && (obj.priority === undefined || typeof obj.priority === "number") && (obj.limit === undefined || typeof obj.limit === "number") && (obj.due_before === undefined || typeof obj.due_before === "string") && (obj.due_after === undefined || typeof obj.due_after === "string") && (obj.lang === undefined || typeof obj.lang === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") ); } export function isUpdateTaskArgs(args: unknown): args is UpdateTaskArgs { if (typeof args !== "object" || args === null) { return false; } const obj = args as Record<string, unknown>; // Must have either task_id/taskId or task_name/taskName // Check both snake_case and camelCase since MCP might transform them const hasTaskId = ("task_id" in obj && typeof obj.task_id === "string") || ("taskId" in obj && typeof obj.taskId === "string"); const hasTaskName = ("task_name" in obj && typeof obj.task_name === "string") || ("taskName" in obj && typeof obj.taskName === "string"); if (!hasTaskId && !hasTaskName) { return false; } // Check optional fields return ( (obj.content === undefined || typeof obj.content === "string") && (obj.description === undefined || typeof obj.description === "string") && (obj.due_string === undefined || typeof obj.due_string === "string") && (obj.priority === undefined || typeof obj.priority === "number") && (obj.project_id === undefined || typeof obj.project_id === "string") && (obj.section_id === undefined || typeof obj.section_id === "string") && (obj.labels === undefined || (Array.isArray(obj.labels) && obj.labels.every((label) => typeof label === "string"))) ); } export function isTaskNameArgs(args: unknown): args is TaskNameArgs { if (typeof args !== "object" || args === null) { return false; } const obj = args as Record<string, unknown>; // Must have either task_id/taskId or task_name/taskName // Check both snake_case and camelCase since MCP might transform them const hasTaskId = ("task_id" in obj && typeof obj.task_id === "string") || ("taskId" in obj && typeof obj.taskId === "string"); const hasTaskName = ("task_name" in obj && typeof obj.task_name === "string") || ("taskName" in obj && typeof obj.taskName === "string"); return hasTaskId || hasTaskName; } export function isGetProjectsArgs( args: unknown ): args is Record<string, never> { return typeof args === "object" && args !== null; } export function isGetSectionsArgs(args: unknown): args is GetSectionsArgs { return typeof args === "object" && args !== null; } export function isCreateProjectArgs(args: unknown): args is CreateProjectArgs { return ( typeof args === "object" && args !== null && "name" in args && typeof (args as { name: string }).name === "string" ); } export function isCreateSectionArgs(args: unknown): args is CreateSectionArgs { return ( typeof args === "object" && args !== null && "name" in args && "project_id" in args && typeof (args as { name: string }).name === "string" && typeof (args as { project_id: string }).project_id === "string" ); } export function isBulkCreateTasksArgs( args: unknown ): args is BulkCreateTasksArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( "tasks" in obj && Array.isArray(obj.tasks) && obj.tasks.length > 0 && obj.tasks.every((task) => isCreateTaskArgs(task)) ); } export function isBulkUpdateTasksArgs( args: unknown ): args is BulkUpdateTasksArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( "search_criteria" in obj && "updates" in obj && typeof obj.search_criteria === "object" && obj.search_criteria !== null && typeof obj.updates === "object" && obj.updates !== null ); } export function isBulkTaskFilterArgs( args: unknown ): args is BulkTaskFilterArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; // The tool expects parameters at the top level, not in search_criteria // We need to wrap them into search_criteria for the handler if ( (obj.project_id === undefined || typeof obj.project_id === "string") && (obj.priority === undefined || typeof obj.priority === "number") && (obj.due_before === undefined || typeof obj.due_before === "string") && (obj.due_after === undefined || typeof obj.due_after === "string") && (obj.content_contains === undefined || typeof obj.content_contains === "string") ) { // Transform the flat structure to match BulkTaskFilterArgs (args as any).search_criteria = { project_id: obj.project_id, priority: obj.priority, due_before: obj.due_before, due_after: obj.due_after, content_contains: obj.content_contains, }; return true; } // Also support the old format with search_criteria return ( "search_criteria" in obj && typeof obj.search_criteria === "object" && obj.search_criteria !== null ); } export function isCreateCommentArgs(args: unknown): args is CreateCommentArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( "content" in obj && typeof obj.content === "string" && (obj.task_id === undefined || typeof obj.task_id === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") && (obj.task_id !== undefined || obj.task_name !== undefined) ); } export function isGetCommentsArgs(args: unknown): args is GetCommentsArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.task_id === undefined || typeof obj.task_id === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") && (obj.project_id === undefined || typeof obj.project_id === "string") ); } export function isCreateLabelArgs(args: unknown): args is CreateLabelArgs { return ( typeof args === "object" && args !== null && "name" in args && typeof (args as { name: string }).name === "string" ); } export function isUpdateLabelArgs(args: unknown): args is UpdateLabelArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.label_id === undefined || typeof obj.label_id === "string") && (obj.label_name === undefined || typeof obj.label_name === "string") && (obj.label_id !== undefined || obj.label_name !== undefined) ); } export function isLabelNameArgs(args: unknown): args is LabelNameArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.label_id === undefined || typeof obj.label_id === "string") && (obj.label_name === undefined || typeof obj.label_name === "string") && (obj.label_id !== undefined || obj.label_name !== undefined) ); } export function isGetLabelsArgs(args: unknown): args is Record<string, never> { return typeof args === "object" && args !== null; } export function isGetLabelStatsArgs( args: unknown ): args is Record<string, never> { return typeof args === "object" && args !== null; } export function isCreateSubtaskArgs(args: unknown): args is CreateSubtaskArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( "content" in obj && typeof obj.content === "string" && (obj.parent_task_id === undefined || typeof obj.parent_task_id === "string") && (obj.parent_task_name === undefined || typeof obj.parent_task_name === "string") && (obj.parent_task_id !== undefined || obj.parent_task_name !== undefined) ); } export function isBulkCreateSubtasksArgs( args: unknown ): args is BulkCreateSubtasksArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( "subtasks" in obj && Array.isArray(obj.subtasks) && obj.subtasks.length > 0 && obj.subtasks.every( (subtask) => typeof subtask === "object" && subtask !== null && "content" in subtask && typeof (subtask as { content: string }).content === "string" ) && (obj.parent_task_id === undefined || typeof obj.parent_task_id === "string") && (obj.parent_task_name === undefined || typeof obj.parent_task_name === "string") && (obj.parent_task_id !== undefined || obj.parent_task_name !== undefined) ); } export function isConvertToSubtaskArgs( args: unknown ): args is ConvertToSubtaskArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.task_id === undefined || typeof obj.task_id === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") && (obj.task_id !== undefined || obj.task_name !== undefined) && (obj.parent_task_id === undefined || typeof obj.parent_task_id === "string") && (obj.parent_task_name === undefined || typeof obj.parent_task_name === "string") && (obj.parent_task_id !== undefined || obj.parent_task_name !== undefined) ); } export function isPromoteSubtaskArgs( args: unknown ): args is PromoteSubtaskArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.subtask_id === undefined || typeof obj.subtask_id === "string") && (obj.subtask_name === undefined || typeof obj.subtask_name === "string") && (obj.subtask_id !== undefined || obj.subtask_name !== undefined) && (obj.project_id === undefined || typeof obj.project_id === "string") && (obj.section_id === undefined || typeof obj.section_id === "string") ); } export function isGetTaskHierarchyArgs( args: unknown ): args is GetTaskHierarchyArgs { if (typeof args !== "object" || args === null) return false; const obj = args as Record<string, unknown>; return ( (obj.task_id === undefined || typeof obj.task_id === "string") && (obj.task_name === undefined || typeof obj.task_name === "string") && (obj.task_id !== undefined || obj.task_name !== undefined) && (obj.include_completed === undefined || typeof obj.include_completed === "boolean") ); }

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