Skip to main content
Glama

motion_recurring_tasks

Manage recurring tasks in Motion by creating, listing, or deleting them with configurable frequency, assignees, and deadlines.

Instructions

Manage recurring tasks. Required params per operation: list: workspaceId or workspaceName. create: workspaceId/workspaceName + name + assigneeId + frequency (with frequency.type). delete: recurringTaskId.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
operationYesOperation to perform
recurringTaskIdNoRecurring task ID. Required for: delete.
workspaceIdNoWorkspace ID. Required for: list, create.
workspaceNameNoWorkspace name (alternative to workspaceId). Required for: list, create.
nameNoTask name. Required for: create.
descriptionNoTask description.
projectIdNoProject ID.
assigneeIdNoUser ID to assign the recurring task to. Required for: create.
frequencyNoFrequency configuration (required for create)
deadlineTypeNoDeadline type (default: SOFT)
durationNoTask duration in minutes or REMINDER
startingOnNoStart date (ISO 8601 format)
idealTimeNoIdeal time in HH:mm format
scheduleNoSchedule name (default: Work Hours)
priorityNoTask priority (default: MEDIUM)

Implementation Reference

  • Main handler class RecurringTaskHandler that implements the motion_recurring_tasks tool logic. Extends BaseHandler and handles three operations: list (get recurring tasks for a workspace), create (create a new recurring task with frequency configuration), and delete (delete a recurring task by ID). Uses workspace resolution and Motion service for API calls.
    import { BaseHandler } from './base/BaseHandler';
    import { McpToolResponse } from '../types/mcp';
    import { MotionRecurringTasksArgs } from '../types/mcp-tool-args';
    import { CreateRecurringTaskData } from '../types/motion';
    import { formatRecurringTaskList, formatRecurringTaskDetail, formatMcpSuccess } from '../utils';
    
    export class RecurringTaskHandler extends BaseHandler {
      async handle(args: MotionRecurringTasksArgs): Promise<McpToolResponse> {
        try {
          const { operation } = args;
    
          switch(operation) {
            case 'list':
              return await this.handleList(args);
            case 'create':
              return await this.handleCreate(args);
            case 'delete':
              return await this.handleDelete(args);
            default:
              return this.handleUnknownOperation(operation);
          }
        } catch (error: unknown) {
          return this.handleError(error);
        }
      }
    
      private async handleList(args: MotionRecurringTasksArgs): Promise<McpToolResponse> {
        if (!args.workspaceId && !args.workspaceName) {
          return this.handleError(new Error('Workspace ID or workspace name is required for list operation'));
        }
        const workspace = await this.workspaceResolver.resolveWorkspace({
          workspaceId: args.workspaceId,
          workspaceName: args.workspaceName
        });
        const { items: recurringTasks, truncation } = await this.motionService.getRecurringTasks(workspace.id);
        return formatRecurringTaskList(recurringTasks, truncation);
      }
    
      private async handleCreate(args: MotionRecurringTasksArgs): Promise<McpToolResponse> {
        if (!args.name || (!args.workspaceId && !args.workspaceName) || !args.assigneeId || !args.frequency) {
          return this.handleError(new Error('Name, workspace ID/workspace name, assignee ID, and frequency are required for create operation'));
        }
    
        // Validate frequency
        if (!args.frequency.type || !['daily', 'weekly', 'biweekly', 'monthly', 'quarterly', 'yearly', 'custom'].includes(args.frequency.type)) {
          return this.handleError(new Error('Frequency type must be one of: daily, weekly, biweekly, monthly, quarterly, yearly, custom'));
        }
    
        const workspace = await this.workspaceResolver.resolveWorkspace({
          workspaceId: args.workspaceId,
          workspaceName: args.workspaceName
        });
    
        const taskData: CreateRecurringTaskData = {
          name: args.name,
          workspaceId: workspace.id,
          assigneeId: args.assigneeId,
          frequency: args.frequency,
          ...(args.description && { description: args.description }),
          ...(args.projectId && { projectId: args.projectId }),
          ...(args.deadlineType && { deadlineType: args.deadlineType }),
          ...(args.duration !== undefined && args.duration !== null && { duration: args.duration }),
          ...(args.startingOn && { startingOn: args.startingOn }),
          ...(args.idealTime && { idealTime: args.idealTime }),
          ...(args.schedule && { schedule: args.schedule }),
          ...(args.priority && { priority: args.priority })
        };
    
        const newTask = await this.motionService.createRecurringTask(taskData);
        return formatRecurringTaskDetail(newTask);
      }
    
      private async handleDelete(args: MotionRecurringTasksArgs): Promise<McpToolResponse> {
        if (!args.recurringTaskId) {
          return this.handleError(new Error('Recurring task ID is required for delete operation'));
        }
    
        await this.motionService.deleteRecurringTask(args.recurringTaskId);
        return formatMcpSuccess(`Recurring task ${args.recurringTaskId} deleted successfully`);
      }
    }
  • Tool definition for motion_recurring_tasks. Defines the input schema with operation types (list, create, delete), required parameters for each operation, and the frequency configuration object structure (type, daysOfWeek, dayOfMonth, weekOfMonth, monthOfQuarter, customPattern, etc.). Includes comprehensive parameter descriptions and constraints.
    export const recurringTasksToolDefinition: McpToolDefinition = {
      name: TOOL_NAMES.RECURRING_TASKS,
      description: "Manage recurring tasks. Required params per operation: list: workspaceId or workspaceName. create: workspaceId/workspaceName + name + assigneeId + frequency (with frequency.type). delete: recurringTaskId.",
      inputSchema: {
        type: "object",
        properties: {
          operation: {
            type: "string",
            enum: ["list", "create", "delete"],
            description: "Operation to perform"
          },
          recurringTaskId: {
            type: "string",
            description: "Recurring task ID. Required for: delete."
          },
          workspaceId: {
            type: "string",
            description: "Workspace ID. Required for: list, create."
          },
          workspaceName: {
            type: "string",
            description: "Workspace name (alternative to workspaceId). Required for: list, create."
          },
          name: {
            type: "string",
            description: "Task name. Required for: create."
          },
          description: {
            type: "string",
            description: "Task description."
          },
          projectId: {
            type: "string",
            description: "Project ID."
          },
          assigneeId: {
            type: "string",
            description: "User ID to assign the recurring task to. Required for: create."
          },
          frequency: {
            type: "object",
            properties: {
              type: {
                type: "string",
                enum: ["daily", "weekly", "biweekly", "monthly", "quarterly", "yearly", "custom"],
                description: "Frequency type - supports all Motion API patterns including biweekly and quarterly"
              },
              daysOfWeek: {
                type: "array",
                items: { type: "number" },
                description: "0-6 for Sunday-Saturday. Used with daily/weekly/biweekly for specific days, and with monthly/quarterly patterns (e.g., monthly_first_MO, quarterly_first_MO) for specifying days in those recurrence types"
              },
              dayOfMonth: {
                type: "number",
                description: "1-31 for monthly recurrence on specific day of month"
              },
              weekOfMonth: {
                type: "string",
                enum: ["first", "second", "third", "fourth", "last"],
                description: "Which week of month/quarter for monthly/quarterly patterns; daysOfWeek is optional (e.g., monthly_any_day_first_week or monthly_monday_first_week)"
              },
              monthOfQuarter: {
                type: "number",
                enum: [1, 2, 3],
                description: "Which month of quarter (1-3) for quarterly patterns"
              },
              interval: {
                type: "number",
                description: "Legacy support: weekly with interval:2 maps to biweekly patterns"
              },
              customPattern: {
                type: "string",
                description: "Direct Motion API frequency pattern string (e.g., 'monthly_any_week_day_first_week')"
              },
              endDate: {
                type: "string",
                description: "ISO 8601 format end date for the recurring task"
              }
            },
            required: ["type"],
            description: "Frequency configuration (required for create)"
          },
          deadlineType: {
            type: "string",
            enum: ["HARD", "SOFT"],
            description: "Deadline type (default: SOFT)"
          },
          duration: {
            oneOf: [
              { type: "number" },
              { type: "string", enum: ["REMINDER"] }
            ],
            description: "Task duration in minutes or REMINDER"
          },
          startingOn: {
            type: "string",
            description: "Start date (ISO 8601 format)"
          },
          idealTime: {
            type: "string",
            description: "Ideal time in HH:mm format"
          },
          schedule: {
            type: "string",
            description: "Schedule name (default: Work Hours)"
          },
          priority: {
            type: "string",
            enum: ["ASAP", "HIGH", "MEDIUM", "LOW"],
            description: "Task priority (default: MEDIUM)"
          }
        },
        required: ["operation"]
      }
    };
  • Handler registration that maps the motion_recurring_tasks tool name to the RecurringTaskHandler class. The registerHandlers() method sets up the mapping so when the tool is invoked, the factory creates an instance of RecurringTaskHandler.
    private registerHandlers(): void {
      this.handlers.set(TOOL_NAMES.TASKS, TaskHandler);
      this.handlers.set(TOOL_NAMES.PROJECTS, ProjectHandler);
      this.handlers.set(TOOL_NAMES.WORKSPACES, WorkspaceHandler);
      this.handlers.set(TOOL_NAMES.USERS, UserHandler);
      this.handlers.set(TOOL_NAMES.SEARCH, SearchHandler);
      this.handlers.set(TOOL_NAMES.COMMENTS, CommentHandler);
      this.handlers.set(TOOL_NAMES.CUSTOM_FIELDS, CustomFieldHandler);
      this.handlers.set(TOOL_NAMES.RECURRING_TASKS, RecurringTaskHandler);
      this.handlers.set(TOOL_NAMES.SCHEDULES, ScheduleHandler);
      this.handlers.set(TOOL_NAMES.STATUSES, StatusHandler);
    }
  • Zod schema MotionRecurringTaskSchema for validating recurring task data from the Motion API. Includes fields for id, name, creator, assignee, project, workspace, status, priority, and labels. Also defines RecurringTasksResponseSchema that wraps recurring task data with pagination metadata.
    // Motion Recurring Task schema - Updated to match API structure (returns task instances)
    export const MotionRecurringTaskSchema = z.object({
      id: z.string(),
      name: z.string(),
      creator: z.object({
        id: z.string(),
        name: z.string(),
        email: z.string()
      }),
      assignee: z.object({
        id: z.string(),
        name: z.string(),
        email: z.string()
      }),
      project: z.object({
        id: z.string(),
        name: z.string(),
        description: z.string(),
        workspaceId: z.string(),
        status: z.object({
          name: z.string(),
          isDefaultStatus: z.boolean(),
          isResolvedStatus: z.boolean()
        }),
        customFieldValues: z.record(z.string(), z.object({
          type: z.string(),
          value: z.unknown()
        })).optional()
      }).optional(),
      workspace: z.object({
        id: z.string(),
        name: z.string(),
        teamId: z.string().nullable(),
        type: z.string(),
        labels: z.array(z.union([
          z.string(),
          z.object({ name: z.string() })
        ])),
        statuses: z.array(z.object({
          name: z.string(),
          isDefaultStatus: z.boolean(),
          isResolvedStatus: z.boolean()
        })).optional()
      }),
      status: z.object({
        name: z.string(),
        isDefaultStatus: z.boolean(),
        isResolvedStatus: z.boolean()
      }),
      priority: z.enum(['ASAP', 'HIGH', 'MEDIUM', 'LOW']),
      labels: z.array(z.object({
        name: z.string()
      }))
    });
  • TypeScript type definitions for recurring tasks: FrequencyObject interface defines the frequency configuration (type, daysOfWeek, dayOfMonth, weekOfMonth, monthOfQuarter, customPattern, endDate), and CreateRecurringTaskData interface defines the data structure for creating new recurring tasks including all optional fields like description, deadlineType, duration, etc.
    export interface FrequencyObject {
      type: 'daily' | 'weekly' | 'biweekly' | 'monthly' | 'quarterly' | 'yearly' | 'custom';
      daysOfWeek?: number[];              // [0-6] for Sunday-Saturday
      dayOfMonth?: number;                // 1-31 for monthly patterns
      weekOfMonth?: 'first' | 'second' | 'third' | 'fourth' | 'last';  // For monthly/quarterly
      monthOfQuarter?: 1 | 2 | 3;        // For quarterly patterns
      interval?: number;                  // Legacy support: weekly + interval:2 → biweekly
      customPattern?: string;             // Direct Motion API pattern for complex cases
      endDate?: string;                   // ISO 8601 format end date
    }
    
    export interface CreateRecurringTaskData {
      name: string;
      workspaceId: string;
      projectId?: string;
      assigneeId: string;
      frequency: FrequencyObject;
      description?: string;
      deadlineType?: 'HARD' | 'SOFT';
      duration?: number | 'REMINDER';
      startingOn?: string;
      idealTime?: string;
      schedule?: string;
      priority?: 'ASAP' | 'HIGH' | 'MEDIUM' | 'LOW';
    }

Schema Changelog

Changes observed during successful MCP inspections.

  1. First observedv2.6.0

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations provided, the description carries the full burden of behavioral disclosure. It only lists required parameters per operation and does not mention side effects, permissions, rate limits, reversibility of delete, return format, or any other behavioral traits. This is a significant gap for a tool that creates and deletes recurring tasks.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded with the core purpose. It uses a semi-colon-separated list to convey operation dependencies efficiently, with no redundant or filler words. Though it could be structured with bullets for readability, it is suitably concise for the amount of information it carries.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity (15 parameters, nested frequency object, three operations, no output schema), the description covers the operation-parameter matrix but omits return behavior, error cases, and broader context. It does not explain what list returns, what create produces, or what delete affects (e.g., future occurrences). The schema fills in parameter details, but behavioral completeness is lacking.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Although the schema has 100% parameter coverage, the description adds value by grouping parameters per operation (e.g., list: workspaceId or workspaceName; create: workspaceId/workspaceName + name + assigneeId + frequency). This clarifies which parameters are needed together, which is not immediately obvious from the schema alone. The mention of frequency.type as a required sub-field is also helpful.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states 'Manage recurring tasks' with a clear resource, and the required params list enumerates the operations (list, create, delete) which define the tool's scope. It distinguishes from the likely sibling motion_tasks by focusing specifically on recurring tasks, though it does not explicitly name the alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides operation-specific parameter requirements, which gives clear context for each operation. However, it does not explicitly state when to use this tool versus alternatives (e.g., motion_tasks for non-recurring tasks) or include exclusions or when-not-to-use guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.