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';
    }
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. While it mentions required parameters per operation, it doesn't disclose important behavioral traits: whether create/delete operations are destructive, what permissions are needed, what the response format looks like, or any rate limits. For a tool with write operations and no annotation coverage, this is a significant gap.

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 appropriately concise with a single sentence that efficiently communicates the core functionality and parameter requirements per operation. It's front-loaded with the main purpose and wastes no words. However, it could be slightly more structured by separating the purpose from the parameter requirements.

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

Completeness2/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 objects, write operations) and the absence of both annotations and an output schema, the description is insufficient. It doesn't explain what the tool returns, what happens when operations succeed/fail, or important behavioral constraints. For a multi-operation tool with create/delete capabilities, this leaves critical gaps for an AI agent.

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

Parameters3/5

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

The schema description coverage is 100%, so the schema already documents all 15 parameters thoroughly. The description adds minimal value beyond the schema by listing which parameters are required for each operation. However, it doesn't provide additional semantic context about parameter relationships or usage patterns that aren't already in the schema descriptions.

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 clearly states the tool's purpose: 'Manage recurring tasks' with specific operations (list, create, delete). It distinguishes itself from sibling tools like motion_tasks by focusing on recurring tasks specifically. However, it doesn't explicitly contrast with motion_tasks which might handle non-recurring tasks.

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

Usage Guidelines4/5

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

The description provides clear guidance on when to use each operation by specifying required parameters per operation (e.g., 'list: workspaceId or workspaceName'). This helps the agent understand which parameters are needed for each use case. However, it doesn't explicitly mention when NOT to use this tool or direct users to alternatives like motion_tasks for non-recurring tasks.

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

Install Server

Other Tools

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/sergiolopez94/motion-mcp-server'

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