// Google Tasks MCP Tools
// 12 tools for managing task lists and tasks
import { z } from 'zod';
import type { TasksService } from '../services/tasks.js';
// ─────────────────────────────────────────────────────────────────────────────
// TOOL DEFINITIONS
// ─────────────────────────────────────────────────────────────────────────────
export const tasksTools = [
// ─────────────────────────────────────────────────────────────────────────
// TASK LISTS
// ─────────────────────────────────────────────────────────────────────────
{
name: 'tasks_listTaskLists',
description: 'List all Google Tasks lists for the authenticated user.',
inputSchema: {
type: 'object' as const,
properties: {
maxResults: {
type: 'number',
description: 'Maximum number of results (default: 100)'
},
pageToken: {
type: 'string',
description: 'Pagination token'
}
},
required: []
}
},
{
name: 'tasks_getTaskList',
description: 'Get details of a specific task list.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID'
}
},
required: ['taskListId']
}
},
{
name: 'tasks_createTaskList',
description: 'Create a new task list.',
inputSchema: {
type: 'object' as const,
properties: {
title: {
type: 'string',
description: 'Title for the new task list (max 1024 characters)'
}
},
required: ['title']
}
},
{
name: 'tasks_updateTaskList',
description: 'Update an existing task list.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID'
},
title: {
type: 'string',
description: 'New title for the task list'
}
},
required: ['taskListId', 'title']
}
},
{
name: 'tasks_deleteTaskList',
description: 'Delete a task list and all its tasks.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID to delete'
}
},
required: ['taskListId']
}
},
// ─────────────────────────────────────────────────────────────────────────
// TASKS
// ─────────────────────────────────────────────────────────────────────────
{
name: 'tasks_listTasks',
description: 'List tasks in a task list. By default shows only incomplete tasks.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID (default: primary list "@default")'
},
maxResults: {
type: 'number',
description: 'Maximum results per page (default: 100)'
},
pageToken: {
type: 'string',
description: 'Pagination token'
},
showCompleted: {
type: 'boolean',
description: 'Include completed tasks (default: false)'
},
showDeleted: {
type: 'boolean',
description: 'Include deleted tasks'
},
showHidden: {
type: 'boolean',
description: 'Include hidden tasks'
},
dueMin: {
type: 'string',
description: 'Minimum due date (RFC 3339 timestamp)'
},
dueMax: {
type: 'string',
description: 'Maximum due date (RFC 3339 timestamp)'
}
},
required: []
}
},
{
name: 'tasks_getTask',
description: 'Get details of a specific task.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID (default: "@default")'
},
taskId: {
type: 'string',
description: 'Task ID'
}
},
required: ['taskId']
}
},
{
name: 'tasks_createTask',
description: 'Create a new task.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID (default: "@default")'
},
title: {
type: 'string',
description: 'Task title (max 1024 characters)'
},
notes: {
type: 'string',
description: 'Task description/notes (max 8192 characters)'
},
due: {
type: 'string',
description: 'Due date (RFC 3339 timestamp, date portion only)'
},
parent: {
type: 'string',
description: 'Parent task ID for subtasks'
},
previous: {
type: 'string',
description: 'ID of task to insert after'
}
},
required: ['title']
}
},
{
name: 'tasks_updateTask',
description: 'Update an existing task.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID'
},
taskId: {
type: 'string',
description: 'Task ID to update'
},
title: {
type: 'string',
description: 'New task title'
},
notes: {
type: 'string',
description: 'New task description'
},
due: {
type: 'string',
description: 'New due date'
},
status: {
type: 'string',
enum: ['needsAction', 'completed'],
description: 'Task status'
}
},
required: ['taskId']
}
},
{
name: 'tasks_completeTask',
description: 'Mark a task as completed.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID'
},
taskId: {
type: 'string',
description: 'Task ID to complete'
}
},
required: ['taskId']
}
},
{
name: 'tasks_deleteTask',
description: 'Delete a task.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID'
},
taskId: {
type: 'string',
description: 'Task ID to delete'
}
},
required: ['taskId']
}
},
{
name: 'tasks_clearCompleted',
description: 'Clear all completed tasks from a task list.',
inputSchema: {
type: 'object' as const,
properties: {
taskListId: {
type: 'string',
description: 'Task list ID (default: "@default")'
}
},
required: []
}
},
];
// ─────────────────────────────────────────────────────────────────────────────
// ZOD SCHEMAS
// ─────────────────────────────────────────────────────────────────────────────
const ListTaskListsSchema = z.object({
maxResults: z.number().min(1).max(100).optional(),
pageToken: z.string().optional(),
});
const GetTaskListSchema = z.object({
taskListId: z.string().min(1),
});
const CreateTaskListSchema = z.object({
title: z.string().min(1).max(1024),
});
const UpdateTaskListSchema = z.object({
taskListId: z.string().min(1),
title: z.string().min(1).max(1024),
});
const DeleteTaskListSchema = z.object({
taskListId: z.string().min(1),
});
const ListTasksSchema = z.object({
taskListId: z.string().optional(),
maxResults: z.number().min(1).max(100).optional(),
pageToken: z.string().optional(),
showCompleted: z.boolean().optional(),
showDeleted: z.boolean().optional(),
showHidden: z.boolean().optional(),
dueMin: z.string().optional(),
dueMax: z.string().optional(),
});
const GetTaskSchema = z.object({
taskListId: z.string().optional(),
taskId: z.string().min(1),
});
const CreateTaskSchema = z.object({
taskListId: z.string().optional(),
title: z.string().min(1).max(1024),
notes: z.string().max(8192).optional(),
due: z.string().optional(),
parent: z.string().optional(),
previous: z.string().optional(),
});
const UpdateTaskSchema = z.object({
taskListId: z.string().optional(),
taskId: z.string().min(1),
title: z.string().max(1024).optional(),
notes: z.string().max(8192).optional(),
due: z.string().optional(),
status: z.enum(['needsAction', 'completed']).optional(),
});
const CompleteTaskSchema = z.object({
taskListId: z.string().optional(),
taskId: z.string().min(1),
});
const DeleteTaskSchema = z.object({
taskListId: z.string().optional(),
taskId: z.string().min(1),
});
const ClearCompletedSchema = z.object({
taskListId: z.string().optional(),
});
// ─────────────────────────────────────────────────────────────────────────────
// HANDLERS
// ─────────────────────────────────────────────────────────────────────────────
export function createTasksHandlers(tasksService: TasksService) {
return {
// Task Lists
tasks_listTaskLists: async (args: unknown) => {
const { maxResults, pageToken } = ListTaskListsSchema.parse(args);
const result = await tasksService.listTaskLists(maxResults, pageToken);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
taskLists: result.taskLists,
totalCount: result.taskLists.length,
nextPageToken: result.nextPageToken
}, null, 2)
}]
};
},
tasks_getTaskList: async (args: unknown) => {
const { taskListId } = GetTaskListSchema.parse(args);
const taskList = await tasksService.getTaskList(taskListId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
taskList
}, null, 2)
}]
};
},
tasks_createTaskList: async (args: unknown) => {
const { title } = CreateTaskListSchema.parse(args);
const taskList = await tasksService.createTaskList(title);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task list created successfully',
taskList
}, null, 2)
}]
};
},
tasks_updateTaskList: async (args: unknown) => {
const { taskListId, title } = UpdateTaskListSchema.parse(args);
const taskList = await tasksService.updateTaskList(taskListId, title);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task list updated successfully',
taskList
}, null, 2)
}]
};
},
tasks_deleteTaskList: async (args: unknown) => {
const { taskListId } = DeleteTaskListSchema.parse(args);
await tasksService.deleteTaskList(taskListId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task list deleted successfully'
}, null, 2)
}]
};
},
// Tasks
tasks_listTasks: async (args: unknown) => {
const params = ListTasksSchema.parse(args);
const result = await tasksService.listTasks(params);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
tasks: result.tasks.map(t => ({
id: t.id,
title: t.title,
notes: t.notes,
status: t.status,
due: t.due,
completed: t.completed,
parent: t.parent
})),
totalCount: result.tasks.length,
nextPageToken: result.nextPageToken
}, null, 2)
}]
};
},
tasks_getTask: async (args: unknown) => {
const { taskListId, taskId } = GetTaskSchema.parse(args);
const task = await tasksService.getTask(taskListId, taskId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
task
}, null, 2)
}]
};
},
tasks_createTask: async (args: unknown) => {
const params = CreateTaskSchema.parse(args);
const task = await tasksService.createTask(params);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task created successfully',
task: {
id: task.id,
title: task.title,
notes: task.notes,
status: task.status,
due: task.due
}
}, null, 2)
}]
};
},
tasks_updateTask: async (args: unknown) => {
const params = UpdateTaskSchema.parse(args);
const task = await tasksService.updateTask(params);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task updated successfully',
task: {
id: task.id,
title: task.title,
notes: task.notes,
status: task.status,
due: task.due
}
}, null, 2)
}]
};
},
tasks_completeTask: async (args: unknown) => {
const { taskListId, taskId } = CompleteTaskSchema.parse(args);
const task = await tasksService.completeTask(taskListId, taskId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task marked as completed',
task: {
id: task.id,
title: task.title,
status: task.status,
completed: task.completed
}
}, null, 2)
}]
};
},
tasks_deleteTask: async (args: unknown) => {
const { taskListId, taskId } = DeleteTaskSchema.parse(args);
await tasksService.deleteTask(taskListId, taskId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Task deleted successfully'
}, null, 2)
}]
};
},
tasks_clearCompleted: async (args: unknown) => {
const { taskListId } = ClearCompletedSchema.parse(args);
await tasksService.clearCompletedTasks(taskListId);
return {
content: [{
type: 'text' as const,
text: JSON.stringify({
success: true,
message: 'Completed tasks cleared successfully'
}, null, 2)
}]
};
},
};
}