schedule_recurring_task
Schedule automated coding tasks to run on a cron schedule for maintenance like bug fixes and refactoring, with server-managed execution and optional plan approval.
Instructions
Schedule a Jules task to run automatically on a cron schedule. The server manages execution even when offline.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| task_name | Yes | Unique name for this schedule | |
| cron_expression | Yes | Cron expression (e.g., "0 9 * * 1" for Mondays at 9 AM) | |
| prompt | Yes | Task instruction | |
| source | Yes | Repository resource name | |
| branch | No | main | |
| auto_create_pr | No | ||
| require_plan_approval | No | ||
| timezone | No | Timezone for cron |
Implementation Reference
- src/mcp/tools.ts:268-322 (handler)The core handler function implementing schedule_recurring_task: validates input, checks for duplicates, creates and persists the ScheduledTask, schedules it with CronEngine, and returns next execution info.async scheduleRecurringTask( args: z.infer<typeof ScheduleTaskSchema> ): Promise<string> { return this.executeWithErrorHandling(async () => { // Validate cron expression if (!CronEngine.validateCronExpression(args.cron_expression)) { throw new Error( `Invalid cron expression: ${args.cron_expression}. Format: minute hour day month weekday` ); } // Check for name collision const existing = await this.storage.getTaskByName(args.task_name); if (existing) { throw new Error( `A schedule named "${args.task_name}" already exists. Use delete_schedule first or choose a different name.` ); } // SECURITY: Validate repository allowlist RepositoryValidator.validateRepository(args.source); // Create scheduled task const task: ScheduledTask = { id: randomUUID(), name: args.task_name, cron: args.cron_expression, taskPayload: { prompt: args.prompt, source: args.source, branch: args.branch, automationMode: args.auto_create_pr ? 'AUTO_CREATE_PR' : 'AUTOMATION_MODE_UNSPECIFIED', requirePlanApproval: args.require_plan_approval, }, timezone: args.timezone, createdAt: new Date().toISOString(), enabled: true, }; // Persist and schedule await this.storage.upsertTask(task); this.scheduler.scheduleTask(task); const nextRun = this.scheduler.getNextInvocation(task.id); return { message: `Task "${args.task_name}" scheduled successfully`, scheduleId: task.id, cron: args.cron_expression, nextExecution: nextRun?.toISOString() || 'Unknown', }; }); }
- src/mcp/tools.ts:75-117 (schema)Zod input validation schema for schedule_recurring_task tool parameters, including task_name, cron_expression, prompt, source, etc.export const ScheduleTaskSchema = z.object({ task_name: z .string() .min(1, 'Task name cannot be empty') .max(100, 'Task name must not exceed 100 characters') .regex(/^[\w\s-]+$/, 'Task name can only contain letters, numbers, spaces, hyphens, and underscores') .describe('Unique name for this schedule (e.g., "Weekly Dependency Update")'), cron_expression: z .string() .regex(/^[\d\s*,/-]+$/, 'Cron expression contains invalid characters') .describe( 'Standard cron expression (e.g., "0 9 * * 1" for Mondays at 9 AM). Format: minute hour day month weekday' ), prompt: z .string() .min(10, 'Prompt must be at least 10 characters') .max(10000, 'Prompt must not exceed 10,000 characters') .describe('The coding task instruction to execute'), source: z .string() .regex( /^sources\/github\/[\w-]+\/[\w-]+$/, 'Source must be in format sources/github/owner/repo' ) .describe('Repository resource name (sources/github/owner/repo)'), branch: z .string() .regex(/^[\w/-]+$/, 'Branch name contains invalid characters') .default('main') .describe('Git branch to target'), auto_create_pr: z .boolean() .default(true) .describe('Whether to auto-create PRs'), require_plan_approval: z .boolean() .default(false) .describe('Whether to require manual plan approval'), timezone: z .string() .optional() .describe('Timezone for cron execution (e.g., "America/New_York")'), });
- src/index.ts:258-286 (registration)MCP tool registration in ListToolsRequestSchema handler: defines name, description, and inputSchema for schedule_recurring_task.{ name: 'schedule_recurring_task', description: 'Schedule a Jules task to run automatically on a cron schedule. The server manages execution even when offline.', inputSchema: { type: 'object', properties: { task_name: { type: 'string', description: 'Unique name for this schedule', }, cron_expression: { type: 'string', description: 'Cron expression (e.g., "0 9 * * 1" for Mondays at 9 AM)', }, prompt: { type: 'string', description: 'Task instruction' }, source: { type: 'string', description: 'Repository resource name', }, branch: { type: 'string', default: 'main' }, auto_create_pr: { type: 'boolean', default: true }, require_plan_approval: { type: 'boolean', default: false }, timezone: { type: 'string', description: 'Timezone for cron' }, }, required: ['task_name', 'cron_expression', 'prompt', 'source'], }, },
- src/index.ts:334-337 (registration)Dispatch logic in CallToolRequestSchema handler: parses args with ScheduleTaskSchema and invokes the tool handler.case 'schedule_recurring_task': { const validated = ScheduleTaskSchema.parse(args); result = await this.tools.scheduleRecurringTask(validated); break;