Deferred tasks for AI coding assistants — MCP server + daemon
Claude-cron has 5 tools with complete Zod schemas and descriptions. Tool naming is verb-based and clear (schedule_task, list_tasks, cancel_task, run_now, install_daemon). All tools have non-trivial descriptions (194-500+ chars). However, there are critical issues: (1) payload parameter in schedule_task uses a generic object with optional nested fields rather than type-discriminated unions, making it ambiguous which fields apply to which task type; (2) parameter descriptions lack actionable constraints (e.g., 'when' accepts multiple formats but does not specify precedence or fallback behavior); (3) output schemas are not formally documented, responses are text-only Content blobs rather than structured objects with typed fields; (4) no error classification (retryable vs fatal) or recovery guidance in error paths; (5) install_daemon is marked IRREVERSIBLE but has no confirmation step or dry-run mode; (6) list_tasks returns formatted text rather than structured task objects, blocking downstream tool composition. Schema completeness is present but design is not aligned with Arcade's 54 patterns for response shaping, error recovery, and command safety.
Cancela una tarea programada.
Instala el daemon de claude-cron como servicio del sistema operativo. En macOS usa launchd, en Linux systemd, en Windows Task Scheduler.
Lista las tareas programadas. Filtra por estado, próximas a ejecutar, o tags.
Ejecuta una tarea inmediatamente, independiente de su schedule.
Programa una tarea para ejecutarse en el futuro. Soporta: recordatorios, comandos shell, prompts a Claude/Codex/Copilot. La expresión 'when' acepta lenguaje natural ("tomorrow 9:00", "in 2 hours"), cron ("0 8 * * 1"), ISO 8601, o shortcuts ("every monday at 8", "daily at 9:00").
schedule_task payload parameter uses a generic object with optional fields instead of type-discriminated unions. The 'type' enum (reminder|shell|claude|codex|copilot) determines which payload fields apply, but the schema does not enforce this mapping. LLMs cannot tell which fields are valid for each type without reading descriptions, leading to incomplete or malformed payloads.
Output schemas are undocumented. All tools return text-only Content objects (type: 'text') rather than structured data with typed fields. This blocks downstream tool composition and forces LLMs to parse unstructured text to extract IDs, statuses, or metadata needed for follow-up calls. list_tasks returns formatted markdown strings instead of an array of task objects.
Error handling lacks guidance. All tools return isError:true with text messages, but do not classify errors as retryable, user-fixable, or fatal. When schedule_task fails to parse 'when', the error message does not tell the LLM whether to retry, ask the user for a clearer time, or give up.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-22 | C | 67 | 2026-07-28+ | v2 |
| 2026-03-09 | F | 47 | - | v1 |
install_daemon is an IRREVERSIBLE operation (system service installation) but lacks a dry-run or confirmation step. Agents cannot preview the installation or ask for confirmation before modifying system state. This violates the confirmation-request pattern for destructive operations.
Parameter descriptions lack actionable constraints. The 'when' parameter accepts 'natural language ("tomorrow 9:00", "in 2 hours"), cron ("0 8 * * 1"), ISO 8601, or shortcuts' but does not specify: (1) which format takes precedence if multiple patterns match? (2) what is the fallback timezone? (3) what happens if parsing fails? LLMs cannot reliably construct valid 'when' values without examples being treated as the only valid options.
list_tasks returns formatted text (markdown-style task summaries) rather than structured objects. Downstream tools cannot easily extract task IDs, status, or next_run times for further operations. A query like 'show me pending tasks and cancel the first one' requires the LLM to parse text, not extract structured data.
notify parameter accepts an array of enum values (notification|email|push) but notifyTo is a separate optional string that only applies if notify includes 'email'. This dependency is documented in the description but not enforced in the schema. LLMs may pass notifyTo without including 'email' in notify, or omit notifyTo when 'email' is selected.
No support for batch operations. If an LLM needs to schedule 10 reminders, it must call schedule_task 10 times sequentially, wasting tokens and latency. A batch_schedule_tasks tool would be more efficient and align with production patterns.
list_tasks does not document pagination or result limits. If a user has 1000 scheduled tasks, does list_tasks return all 1000? Unbounded results blow the context window. The description should state: 'Returns up to N tasks, ordered by next_run. Use offset/limit for pagination.'
run_now and cancel_task accept a task ID string but do not validate that the ID is a valid nanoid or provide guidance on how to obtain a task ID if the user only knows the task name. The description should note: 'Obtain task ID from list_tasks. Accepts both task ID and task name (if unique).'