Skip to content

Async Jobs

github-actions[bot] edited this page Mar 22, 2026 · 11 revisions

Async Jobs

Long-running MATLAB code is automatically handled through the async job system.

How It Works

  1. You call execute_code with your MATLAB code
  2. The server starts executing synchronously in a background task
  3. If execution exceeds sync_timeout (default 30 seconds), the job is promoted to async
  4. You get back a job_id immediately
  5. Poll get_job_status for progress updates
  6. Call get_job_result when the job completes

Job Lifecycle

PENDING → RUNNING → COMPLETED
                  → FAILED
                  → CANCELLED

State Transitions

  • PENDING: Job created, waiting for engine acquisition and execution start
  • RUNNING: Engine acquired, code execution in progress
  • COMPLETED: Code execution finished successfully with result
  • FAILED: Code execution raised an error (MATLAB or system error)
  • CANCELLED: Job was explicitly cancelled via cancel_job

Sync vs. Async Execution

Synchronous Execution (< sync_timeout)

When your code completes within sync_timeout (default 30 seconds):

  1. Code executes in a background task with stdout/stderr capture
  2. Server waits for completion
  3. Result returned immediately with status: "completed"
  4. No polling required

Response example:

{
  "status": "completed",
  "job_id": "j-abc123",
  "text": "0.5023"
}

Asynchronous Promotion (>= sync_timeout)

When code exceeds sync_timeout:

  1. Server stops waiting and returns immediately with status: "pending"
  2. Code continues executing in the background
  3. You must poll get_job_status to monitor progress
  4. Call get_job_result when ready to retrieve the result

Initial response:

{
  "status": "pending",
  "job_id": "j-abc123"
}

After promotion, the job continues running in the background while you poll for status.

Progress Reporting

Use the mcp_progress() helper function in your MATLAB code to report progress back to the agent. This is especially useful for long-running jobs:

mcp_progress(__mcp_job_id__, percentage, message)
  • __mcp_job_id__ — automatically injected into the workspace by the server
  • percentage — number from 0 to 100
  • message — optional status message

Example

n = 1e6;
results = zeros(n, 1);
for i = 1:n
    results(i) = process_item(i);
    if mod(i, 1e5) == 0
        mcp_progress(__mcp_job_id__, i/n*100, ...
            sprintf('Processed %d/%d items', i, n));
    end
end
disp(mean(results));

The agent sees:

get_job_status → {status: "running", progress: 10, message: "Processed 100000/1000000 items"}
get_job_status → {status: "running", progress: 50, message: "Processed 500000/1000000 items"}
get_job_status → {status: "running", progress: 100, message: "Processed 1000000/1000000 items"}
get_job_result → {status: "completed", text: "0.5023"}

How Progress Works Internally

  1. mcp_progress.m writes a JSON file to __mcp_temp_dir__/<job_id>.progress
  2. get_job_status reads this file and includes progress in the response
  3. The file is cleaned up when the job reaches a terminal state (completed, failed, or cancelled)

Job Status Polling

Use get_job_status to check on a job's progress:

{
  "status": "running",
  "progress": 45,
  "message": "Processing batch 3 of 7"
}

Or when complete:

{
  "status": "completed",
  "progress": 100
}

Job Result Retrieval

Call get_job_result to retrieve the full result of a completed job:

{
  "status": "completed",
  "text": "0.5023",
  "variables": {
    "mean_result": 0.5023
  }
}

For failed jobs:

{
  "status": "failed",
  "error": {
    "type": "MATLABExecutionException",
    "message": "Undefined function or variable 'x'.",
    "matlab_id": "MATLAB:UndefinedFunction",
    "stack_trace": "Error in line 5: ..."
  }
}

Job Cancellation

Call cancel_job to stop a pending or running job:

  • If the job is PENDING: transitions immediately to CANCELLED
  • If the job is RUNNING: attempts to interrupt the background execution and transitions to CANCELLED
  • If the job is already COMPLETED, FAILED, or CANCELLED: no-op

Cancellation is best-effort; the underlying engine may not interrupt immediately.

Job Retention and Cleanup

Job metadata is retained in the tracker for a configurable duration after reaching a terminal state (COMPLETED, FAILED, or CANCELLED). This allows clients time to poll for results.

How Cleanup Works

  • Jobs enter the retention period when they reach a terminal state
  • The prune operation (run periodically by the server) removes jobs older than job_retention_seconds
  • Default retention: 24 hours (86400 seconds)
  • After a job is pruned, it can no longer be queried

Tips for Production

  • Set appropriate retention: Balance between client query windows and memory usage
  • Poll promptly: Retrieve results before the retention period expires
  • Monitor active jobs: Use list_jobs to track pending/running jobs

Job Management Tools

Tool Description
execute_code Execute MATLAB code (sync or async promotion)
get_job_status Current status + progress percentage and message
get_job_result Full result of a completed job (or error details if failed)
cancel_job Cancel a pending or running job
list_jobs List all jobs in the session (or globally)

Configuration

execution:
  sync_timeout: 30           # Seconds before async promotion
  max_execution_time: 86400  # Hard limit (24h)

sessions:
  job_retention_seconds: 86400  # Keep job metadata for 24h after terminal state

Tips

  • Short code (< 30s): Results return inline, no job ID needed
  • Medium code (30s - minutes): Auto-promoted, poll with get_job_status
  • Long code (hours): Add mcp_progress() calls so the agent can report status
  • Cancel: Call cancel_job if you need to stop a running job
  • Increase timeout: Set sync_timeout: 60 if most of your code takes 30-60s
  • Monitor engine load: Check active jobs before submitting additional long-running tasks

Clone this wiki locally