Skip to content

Scheduler User Guide

Quick Start

Schedule any MCP tool to run automatically using natural language or cron expressions.

Basic Example

bash
# Schedule a daily backup check
ncp schedule create filesystem:list_directory "every day at 2am" \
  --name "Daily Backup Check" \
  --params '{"path": "/backups"}'

# Check what's scheduled
ncp schedule list

# View execution history
ncp schedule executions

Installation & Requirements

Supported Platforms:

  • ✅ macOS (launchd - full support, no Full Disk Access required)
  • ✅ Linux/Unix (cron - full support)
  • ❌ Windows (not supported - no native scheduler integration)

Requirements:

  • Node.js environment with system access
  • macOS: launchctl command (built-in)
  • Linux/Unix: crontab command available
  • Permission to modify system scheduler

Check Availability:

bash
ncp schedule list
# If you see an error, scheduler is not available on your platform

macOS Permissions

The scheduler works automatically by default, but macOS will show a permission dialog when you create your first schedule:

"[App Name]" would like to access data from other apps.

You have two options:

  1. Simply accept the dialog each time - Click "Allow" when scheduling. The scheduler will work fine.

  2. One-time setup to prevent the dialog - Grant automation permission permanently so the dialog never appears again.

→ See detailed setup instructions if you want to configure permissions to avoid the dialog.

Why this happens: The scheduler modifies your system's crontab to ensure scheduled tasks run reliably, even when NCP is not active. macOS requires permission for this automation.

Natural Language Schedules

The scheduler understands human-friendly schedules:

Every X Minutes

bash
"every minute"
"every 5 minutes"
"every 30 minutes"

Hourly

bash
"every hour"
"hourly"

Daily

bash
"every day at 9am"
"daily at 2:30pm"
"every day at noon"
"every day at midnight"

Weekdays

bash
"every weekday at 9am"
"monday to friday at 5pm"

Weekends

bash
"every weekend at 10am"

Specific Days

bash
"every monday at 9am"
"every friday at 5pm"
"every sunday at noon"

Monthly

bash
"monthly at 9am"
"first day of the month at 10am"

One-Time (Relative)

bash
"in 5 minutes"
"in 2 hours"
"in 1 day"

Cron Expressions

For advanced scheduling, use standard cron expressions:

bash
# Format: minute hour day month weekday
"0 9 * * *"           # Every day at 9am
"*/15 * * * *"        # Every 15 minutes
"0 0 * * 0"           # Every Sunday at midnight
"30 14 * * 1-5"       # Weekdays at 2:30pm
"0 9 1 * *"           # First of month at 9am

Common Use Cases

1. Daily Backup Verification

bash
ncp schedule create filesystem:list_directory "every day at 2am" \
  --name "Daily Backup Check" \
  --description "Verify backup directory exists and has recent files" \
  --params '{"path": "/backups"}' \
  --test-run

2. Hourly Health Check

bash
ncp schedule create http:get "every hour" \
  --name "Service Health Check" \
  --description "Check if service is responding" \
  --params '{"url": "https://api.example.com/health"}'

3. Weekly Report Generation

bash
ncp schedule create database:query "every monday at 9am" \
  --name "Weekly Report" \
  --description "Generate weekly analytics report" \
  --params '{"query": "SELECT * FROM weekly_stats"}'

4. One-Time Reminder

bash
ncp schedule create slack:send_message "in 30 minutes" \
  --name "Meeting Reminder" \
  --description "Remind team about meeting" \
  --params '{"channel": "#team", "text": "Meeting in 5 minutes!"}' \
  --fire-once

5. Limited Execution Job

bash
ncp schedule create api:sync_data "every hour" \
  --name "Data Sync - 24h Test" \
  --description "Test data sync for 24 hours" \
  --params '{"source": "prod", "target": "staging"}' \
  --max-executions 24

6. Time-Boxed Campaign

bash
ncp schedule create social:post "every day at 9am" \
  --name "Holiday Campaign" \
  --description "Daily posts until Jan 1st" \
  --params '{"message": "Happy Holidays!"}' \
  --end-date "2026-01-01T00:00:00Z"

7. Data Collection with Auto-Catchup

bash
# Conference scraper that catches up if laptop was closed
ncp schedule create code:run "every day at 9am" \
  --name "MCP Conference Scraper" \
  --description "Daily scraper for MCP events - catches up if missed" \
  --params '{"code": "...scraper code..."}' \
  --catchup-missed

# When your laptop opens, missed runs automatically execute
# Perfect for data collection, analytics, backups, etc.

Job Management

Create a Job

bash
ncp schedule create <tool> <schedule> \
  --name "Job Name" \
  --params '{"param": "value"}' \
  [options]

Options:
  --description <text>      Job description
  --fire-once               Run only once
  --max-executions <num>    Max times to run
  --end-date <iso-date>     Stop after date
  --catchup-missed          Run this job even if scheduled time was missed (e.g., laptop was closed)
  --test-run                Test before scheduling
  --skip-validation         Skip parameter validation (not recommended)

List All Jobs

bash
# Simple list
ncp schedule list

# Filter by status
ncp schedule list --status active
ncp schedule list --status paused

Get Job Details

bash
ncp schedule get "Job Name"
# or
ncp schedule get job-id-123

Pause a Job

bash
ncp schedule pause "Job Name"

Resume a Job

bash
ncp schedule resume "Job Name"

Delete a Job

bash
# With confirmation
ncp schedule delete "Job Name"

# Skip confirmation
ncp schedule delete "Job Name" -y

Sync Schedules

bash
# Repair and sync all jobs with system scheduler
# Adds missing timing groups, removes orphaned entries
# Automatically sets up auto-catchup agent (macOS only)
ncp schedule sync

When to use:

  • After upgrading NCP to a new version
  • If jobs aren't executing as expected
  • To verify scheduler integration is healthy
  • After manually modifying schedule configuration

Run Catchup

bash
# Manually execute missed scheduled tasks
# Only runs tasks with --catchup-missed enabled
ncp schedule catchup

When to use:

  • After laptop was closed during scheduled time
  • To manually trigger missed data collection tasks
  • For testing catchup behavior

Note: On macOS, catchup runs automatically at login and every hour. Manual execution is usually not needed.

Execution History

View All Executions

bash
ncp schedule executions

View Job-Specific History

bash
ncp schedule executions --job-id "Job Name"

Filter by Status

bash
ncp schedule executions --status success
ncp schedule executions --status failure
ncp schedule executions --status timeout

View Specific Execution

bash
ncp schedule executions --execution-id exec-abc-123

Maintenance

Clean Old Records

bash
# Delete executions older than 30 days
ncp schedule cleanup --max-age 30

# Keep only last 10 executions per job
ncp schedule cleanup --max-per-job 10

# Combine both
ncp schedule cleanup --max-age 30 --max-per-job 10

Best Practices

1. Always Test First

bash
# Use --test-run to verify parameters work
ncp schedule create my:tool "every day at 9am" \
  --name "Important Job" \
  --params '{"key": "value"}' \
  --test-run

2. Use Descriptive Names

bash
# ❌ Bad
--name "Job 1"

# ✅ Good
--name "Daily Database Backup - Production"

3. Add Descriptions

bash
--description "Backs up production database to S3. Runs at 2am to minimize impact. Retains last 7 days."

4. Set Execution Limits

bash
# For testing
--max-executions 3

# For campaigns
--end-date "2026-01-01T00:00:00Z"

5. Monitor Execution History

bash
# Check regularly for failures
ncp schedule executions --status failure

6. Clean Up Regularly

bash
# Add to cron or run monthly
ncp schedule cleanup --max-age 90 --max-per-job 20

7. Use Catchup for Data Collection

bash
# Enable catchup for tasks that should run even if delayed
ncp schedule create data:collect "every day at 9am" \
  --name "Daily Data Sync" \
  --catchup-missed  # ✅ Good for data collection

# Don't use catchup for time-sensitive tasks
ncp schedule create notifications:send "every day at 9am" \
  --name "Morning Briefing"
  # ❌ No --catchup-missed for notifications

8. Run Sync After Upgrades

bash
# After upgrading NCP, sync to repair integration
ncp schedule sync

Validation

The scheduler validates tool parameters before scheduling to prevent silent failures.

Automatic Validation

bash
# Validation happens automatically
ncp schedule create filesystem:write_file "every day" \
  --name "Daily Log" \
  --params '{"path": "/logs/app.log", "content": "test"}'

# If validation fails, you'll see errors immediately:
# ❌ Tool validation failed:
# - Parameter 'path' must be writable
# - File '/logs' does not exist
bash
# Only if you're sure parameters are correct
--skip-validation

Test Execution

bash
# Actually run the tool once as a test
--test-run

# This executes the tool immediately to verify it works
# If successful, job is scheduled
# If fails, error is shown and job is not scheduled

Troubleshooting

"Scheduler not available"

Cause: Platform doesn't support cron (Windows) or crontab not found

Solution:

bash
# Check platform
uname -s  # Should be Darwin/Linux

# Check crontab
which crontab

# On macOS, grant Terminal full disk access:
# System Preferences → Security & Privacy → Full Disk Access → Enable Terminal

"Permission denied" on crontab

Cause: User doesn't have crontab permissions

Solution:

bash
# Check if you're in the cron group (Linux)
groups

# Add yourself to cron group
sudo usermod -a -G cron $USER

# On macOS, check System Preferences

Jobs not executing

First: Run sync to repair scheduler integration:

bash
ncp schedule sync

Check system scheduler (macOS):

bash
launchctl list | grep com.portel.ncp

# You should see agents with exit code 0
# Format: - 0 com.portel.ncp.job.daily-9am
#         ↑ ↑
#         │ └─ 0 = success, 1 = failure
#         └─ PID (- means not running now)

# Check agent logs
cat /tmp/ncp-launchd-*.log
cat /tmp/ncp-launchd-*.err

Check system scheduler (Linux):

bash
crontab -l | grep NCP

# You should see entries like:
# NCP_JOB: job-id-123
# 0 9 * * * ncp _timing-run timing-id-123

Check execution history:

bash
ncp schedule executions --job-id "Job Name"

# Look for error messages

Test manually:

bash
# Get timing ID from job
ncp schedule get "Job Name"

# Execute timing manually (macOS)
ncp _timing-run <timing-id>

# Check for errors

Validation failures

View validation errors:

bash
ncp schedule create my:tool "every day" \
  --name "Test" \
  --params '{"bad": "params"}'

# Error shows specific validation issues

Test tool directly:

bash
# Try running the tool first
ncp run my:tool --params '{"param": "value"}'

Jobs running but failing

Check execution logs:

bash
# View failed executions
ncp schedule executions --status failure

# Get specific execution details
ncp schedule executions --execution-id <exec-id>

Common issues:

  • Parameters valid at schedule time but environment changed
  • Tool depends on external service that's down
  • File paths or permissions changed

Advanced Features

Using with AI

The scheduler is exposed via ncp find, so AI can discover and use it:

AI: "Schedule a daily backup check"

You: ncp find schedule
# AI sees: scheduler:schedule tool

AI: Uses scheduler:schedule to create the job

Validation Protocol

The scheduler implements the MCP Validation Protocol, allowing MCPs to provide deep validation:

bash
# MCPs can implement tools/validate for advanced checks
# scheduler:validate is the reference implementation
ncp run scheduler:validate --params '{
  "tool": "filesystem:write_file",
  "arguments": {"path": "/test", "content": "data"}
}'

Job Statistics

bash
# View scheduler statistics
ncp run scheduler:get_stats

# Shows:
# - Total jobs
# - Active/paused/completed
# - Execution statistics
# - Success/failure rates

Storage Locations

Jobs and execution records are stored in:

~/.ncp/scheduler/
├── jobs.json              # Job definitions
└── executions/
    ├── summary.csv        # Execution summary (fast queries)
    └── results/
        └── exec-*.json    # Detailed results

System Scheduler Integration

macOS (launchd)

Jobs are registered as launchd agents in ~/Library/LaunchAgents/:

bash
# View NCP scheduler agents
launchctl list | grep com.portel.ncp

# Shows agents like:
# - com.portel.ncp.job.daily-9am
# - com.portel.ncp.job.every-15min
# - com.portel.ncp.job.__ncp_auto_catchup__

Important: Don't manually edit plist files - use ncp schedule commands instead.

Linux/Unix (cron)

Jobs are added to your user's crontab in a managed section:

bash
crontab -l

# Shows:
# === NCP SCHEDULED JOBS - DO NOT EDIT MANUALLY ===
# NCP_JOB: job-id-123
# 0 9 * * * ncp _job-run job-id-123
# === END NCP SCHEDULED JOBS ===

Important: Don't edit the NCP section manually - use ncp schedule commands instead.

Examples by Industry

DevOps

bash
# Check disk space
ncp schedule create system:disk_usage "every 6 hours" \
  --name "Disk Space Monitor" \
  --params '{"path": "/"}' \
  --max-executions 28  # 7 days

# Restart service if unhealthy
ncp schedule create http:health_check "every 5 minutes" \
  --name "Service Monitor" \
  --params '{"url": "http://localhost:8080/health"}'

Marketing

bash
# Daily social media posts
ncp schedule create social:post "every day at 9am" \
  --name "Daily Tweet" \
  --params '{"platform": "twitter", "message": "..."}'

# Weekly newsletter
ncp schedule create email:send "every monday at 8am" \
  --name "Weekly Newsletter" \
  --params '{"template": "newsletter", "list": "subscribers"}'

Data Science

bash
# Hourly data sync
ncp schedule create database:sync "every hour" \
  --name "Data Warehouse Sync" \
  --params '{"source": "prod", "target": "analytics"}'

# Daily model training
ncp schedule create ml:train_model "every day at 3am" \
  --name "Model Retraining" \
  --params '{"dataset": "latest", "model": "classifier"}'

Finance

bash
# Market data collection
ncp schedule create api:fetch_stock_prices "every weekday at 9:30am" \
  --name "Market Open Data" \
  --params '{"symbols": ["AAPL", "GOOGL"]}'

# End-of-day reconciliation
ncp schedule create finance:reconcile "every weekday at 5pm" \
  --name "Daily Reconciliation" \
  --params '{"account": "trading"}'

FAQ

Q: Can I schedule jobs to run when NCP is not running? A: Yes! Jobs run via system scheduler (launchd/cron), independent of NCP.

Q: What happens if my computer is off at execution time? A: By default, the job is skipped. However, you can enable automatic catchup:

  • Add --catchup-missed flag when creating the job
  • On macOS, an auto-catchup agent runs at login and every hour
  • Missed tasks with catchup enabled will execute when your laptop opens
  • Perfect for data collection tasks that should run even if delayed
  • Time-sensitive tasks (like notifications) should NOT use catchup

Q: Can I use this in a desktop extension? A: Yes! Desktop extensions (VS Code, Electron) have full Node.js access.

Q: Can I schedule a job to run every second? A: No. Cron's minimum interval is 1 minute.

Q: What if a job takes longer than the interval? A: Cron starts a new execution. Multiple instances may run concurrently.

Q: Can I schedule jobs in different time zones? A: Jobs use system time zone. Set via OS timezone settings.

Q: How do I backup my scheduled jobs? A: Copy ~/.ncp/scheduler/jobs.json

Q: Can I edit jobs.json manually? A: Not recommended. Use ncp schedule update instead.


Need Help?

Released under the Elastic License 2.0.