> ## Documentation Index
> Fetch the complete documentation index at: https://www.integrate.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# ETL: MCP Jobs & Schedules Tools

> Reference for the Integrate.io MCP tools that inspect runs, manage schedules, and run, cancel, or retry jobs.

This page covers the MCP tools for job runs and schedules. Run inspection tools are read-only: they report on what has run and why it failed. The schedule and execution tools modify your live account: they create or change schedules, start runs, and cancel or retry jobs. Mutations take effect immediately against production; there is no sandbox or staging copy. Tools that subclass the mutation base support `dry_run`, which validates and returns the would-be outcome without applying it.

## Tool index

Each tool name links to its section below.

| Tool                                          | Class | What it does                                                                     |
| --------------------------------------------- | ----- | -------------------------------------------------------------------------------- |
| [`list_runs`](#list_runs)                     | Read  | Recent job runs with status, timing, and last error.                             |
| [`get_run`](#get_run)                         | Read  | One run's fields plus an output count and a redacted log tail.                   |
| [`explain_job_failure`](#explain_job_failure) | Read  | A failed run's primary error, detected error patterns, log tail, and next steps. |
| [`list_schedules`](#list_schedules)           | Read  | Schedules with cadence, status, target packages, and run timestamps.             |
| [`get_schedule`](#get_schedule)               | Read  | One schedule's full config, target packages with variables, and run metadata.    |
| [`toggle_schedule`](#toggle_schedule)         | Write | Enable or disable a schedule.                                                    |
| [`create_schedule`](#create_schedule)         | Write | Create a schedule (disabled by default) that runs packages on a cadence.         |
| [`update_schedule`](#update_schedule)         | Write | Change a schedule's cadence or metadata, toggle it, or append packages.          |
| [`run_package`](#run_package)                 | Write | Start a new run of a package on a cluster.                                       |
| [`cancel_job`](#cancel_job)                   | Write | Stop an in-flight run.                                                           |
| [`retry_job`](#retry_job)                     | Write | Re-run a finished run as a new sibling run.                                      |

***

## Run inspection

### list\_runs

**Read-only.** Lists recent job runs (executions) in the account, most recent first. Each run is one execution of a package. Defaults to root runs only, so child retries are excluded. Filter by `package_id` or `status`.

<ParamField body="limit" type="integer" default="50">
  Maximum runs to return. 1 to 200.
</ParamField>

<ParamField body="offset" type="integer" default="0">
  Number of runs to skip, for paging.
</ParamField>

<ParamField body="package_id" type="integer">
  Restrict to runs of a single package.
</ParamField>

<ParamField body="status" type="string">
  Filter by run status. One of `idle`, `pending`, `queued`, `running`, `completed`, `failed`, `stopped`.
</ParamField>

<ResponseField name="runs" type="array">
  Each run includes `id`, `package_id`, `status`, `owner_id`, `cluster_id`, `started_at`, `completed_at`, `failed_at`, `runtime_seconds`, `progress`, `attempts`, `created_at`, `updated_at`, and `last_error` (present for failed or stopped runs, with sensitive values redacted).
</ResponseField>

<ResponseField name="pagination" type="object">
  `offset`, `limit`, and `returned` (the number of runs on this page).
</ResponseField>

### get\_run

**Read-only.** Returns details for a single run by id: the same fields as `list_runs`, plus an output count and a redacted tail of the execution log for inline diagnosis. Run variables are deliberately not exposed.

<ParamField body="run_id" type="integer" required>
  The run to fetch.
</ParamField>

<ParamField body="log_tail_lines" type="integer" default="20">
  How many trailing log lines to return. 1 to 200.
</ParamField>

<ResponseField name="id" type="integer">
  The run id, alongside `package_id`, `status`, `owner_id`, `cluster_id`, `started_at`, `completed_at`, `failed_at`, `runtime_seconds`, `progress`, `attempts`, `created_at`, `updated_at`, and `last_error` (for failed or stopped runs, redacted).
</ResponseField>

<ResponseField name="outputs_count" type="integer">
  Number of outputs the run produced.
</ResponseField>

<ResponseField name="log_tail" type="string">
  The last N lines of the execution log, redacted. `null` when no log body exists.
</ResponseField>

### explain\_job\_failure

**Read-only.** Diagnoses a failed run without an LLM call on the server. Returns the run's primary error, programmatically detected error patterns (FATAL, ERROR, exception, connection, auth, schema, and more), a redacted log tail, and heuristic next-step suggestions. The calling agent does the final synthesis.

<ParamField body="run_id" type="integer" required>
  The run to diagnose.
</ParamField>

<ParamField body="log_tail_lines" type="integer" default="50">
  How many trailing log lines to return. 1 to 200.
</ParamField>

<ResponseField name="run_id" type="integer">
  The run id, with `package_id`, `status`, and `failed_at`.
</ResponseField>

<ResponseField name="primary_error" type="string">
  The run's primary error message (from `last_error`), redacted. `null` for runs that did not fail or stop.
</ResponseField>

<ResponseField name="detected_errors" type="array">
  Structured error patterns found in the log, each with a `type` such as `connection_failure`, `auth_failure`, `schema_error`, `destination_conflict`, `rate_limited`, `out_of_memory`, or `exception`.
</ResponseField>

<ResponseField name="log_tail" type="string">
  The redacted trailing log lines, with `log_lines_returned` and `log_truncated` alongside.
</ResponseField>

<ResponseField name="suggested_next_steps" type="array">
  Heuristic next steps tied to the detected patterns (for example, run `test_connection` on a refused connection, or `discover_schema` on a schema mismatch).
</ResponseField>

## Schedules

### list\_schedules

**Read-only.** Lists schedules in the account. Each schedule fires on a cron expression or an interval. Filter by `package_id` (schedules targeting a given package) or `status`.

<ParamField body="limit" type="integer" default="50">
  Maximum schedules to return. 1 to 200.
</ParamField>

<ParamField body="offset" type="integer" default="0">
  Number of schedules to skip, for paging.
</ParamField>

<ParamField body="status" type="string">
  Filter by schedule status. One of `enabled`, `disabled`.
</ParamField>

<ParamField body="package_id" type="integer">
  Return only schedules whose task targets this package.
</ParamField>

<ResponseField name="schedules" type="array">
  Each schedule includes `id`, `name`, `description`, `status`, `schedule_type`, `schedule_expression`, `interval_amount`, `interval_unit`, `cron_time_zone`, `start_at`, `end_at`, `next_run_at`, `last_run_at`, `last_run_status`, `execution_count`, `recurrence_count`, `package_ids`, `owner_id`, `created_at`, and `updated_at`.
</ResponseField>

<ResponseField name="pagination" type="object">
  `offset`, `limit`, and `returned`.
</ResponseField>

### get\_schedule

**Read-only.** Returns full details for a single schedule by id, including the packages it targets with their per-package variables, the task config, and run metadata.

<ParamField body="schedule_id" type="integer" required>
  The schedule to fetch.
</ParamField>

<ResponseField name="id" type="integer">
  The schedule id, with `name`, `description`, `status`, `schedule_type`, `schedule_expression`, `interval_amount`, `interval_unit`, `cron_time_zone`, `start_at`, `end_at`, `owner_id`, `execution_count`, `recurrence_count`, `next_run_at`, `last_run_at`, `last_run_id`, `last_run_status`, `auto_retry`, `auto_retry_attempts`, `created_at`, and `updated_at`.
</ResponseField>

<ResponseField name="packages" type="array">
  Each target package as `{ package_id, package_name, variables }`.
</ResponseField>

<ResponseField name="task" type="object">
  Task config: `nodes`, `terminate_on_idle`, `time_to_idle`, and `reuse_cluster_strategy`.
</ResponseField>

### toggle\_schedule

**Mutation.** Enables or disables an existing schedule. This is a pure metadata change: no credentials, no data writes, no cluster spin-up, and it is reversible by the same tool. The cron worker picks up the new state within about 60 seconds. Idempotent in both directions, an already-matching state returns `already_in_target_state: true` as a no-op. Supports `dry_run`, which returns the would-be transition without toggling.

<ParamField body="schedule_id" type="integer" required>
  The schedule to toggle.
</ParamField>

<ParamField body="enabled" type="boolean" required>
  `true` to enable, `false` to disable.
</ParamField>

<ResponseField name="schedule_id" type="integer">
  The schedule id, with `previous_status`, `new_status`, `already_in_target_state`, and `toggled_at`.
</ResponseField>

### create\_schedule

**Mutation.** Creates a schedule that runs one or more packages on a cadence. It is created **disabled by default**, so an agent call will not silently start firing recurring jobs. Pass `status: "enabled"` (or call `toggle_schedule` afterward) to activate it. Supports `dry_run`, which validates and returns the would-be schedule without creating it.

<ParamField body="name" type="string" required>
  Schedule name. Max 255 characters.
</ParamField>

<ParamField body="schedule_type" type="string" required>
  Cadence type. One of `interval`, `cron`.
</ParamField>

<ParamField body="start_at" type="string" required>
  ISO-8601 timestamp for when the schedule starts. Interpreted as UTC unless `current_time_zone` is set.
</ParamField>

<ParamField body="packages" type="array" required>
  At least one package. Each item may be `{ package_id, variables? }` or a bare package id.
</ParamField>

<ParamField body="interval_amount" type="integer" default="1">
  For `interval` schedules: how many `interval_unit` between runs. Minimum 1.
</ParamField>

<ParamField body="interval_unit" type="string" default="hours">
  For `interval` schedules: `minutes`, `hours`, `days`, `weeks`, or `months`.
</ParamField>

<ParamField body="schedule_expression" type="string">
  For `cron` schedules: the cron expression, for example `0 9 * * *`.
</ParamField>

<ParamField body="status" type="string" default="disabled">
  Initial status. One of `enabled`, `disabled`.
</ParamField>

<Expandable title="Less-common options">
  <ParamField body="cron_time_zone" type="string">
    IANA time zone for a `cron` schedule.
  </ParamField>

  <ParamField body="current_time_zone" type="string">
    IANA time zone used to interpret `start_at`. Defaults to UTC when omitted.
  </ParamField>

  <ParamField body="description" type="string">
    Free-text description. Max 1024 characters.
  </ParamField>

  <ParamField body="overlap" type="boolean">
    Whether overlapping runs are allowed.
  </ParamField>

  <ParamField body="reuse_cluster_strategy" type="string">
    Cluster reuse strategy for scheduled runs.
  </ParamField>

  <ParamField body="auto_retry_attempts" type="integer" default="0">
    Number of automatic retries. 0 to 5. Any value greater than 0 turns auto-retry on.
  </ParamField>

  <ParamField body="nodes" type="integer" default="1">
    Number of cluster nodes for scheduled runs. Minimum 1.
  </ParamField>
</Expandable>

<ResponseField name="schedule_id" type="integer">
  The new schedule id, with `name`, `status`, `schedule_type`, and `next_run_at`. On a `dry_run`, these are nested under `would_create` with a `valid` flag (and `errors` when invalid).
</ResponseField>

### update\_schedule

**Mutation.** Updates an existing schedule's cadence or metadata, toggles it, and/or appends packages. Only the fields you pass are changed. `status` goes through the proper enable/disable transition. `add_packages` only **appends** to the schedule's package list: packages already on the schedule are skipped, and nothing is removed or reordered. To change the full package set, recreate the schedule. Supports `dry_run`.

<ParamField body="schedule_id" type="integer" required>
  The schedule to update.
</ParamField>

<ParamField body="add_packages" type="array">
  Packages to add. Each item may be `{ package_id, variables? }` or a bare package id. Appends only.
</ParamField>

<ParamField body="status" type="string">
  Change the schedule status through the enable/disable transition. One of `enabled`, `disabled`.
</ParamField>

<ParamField body="schedule_type" type="string">
  Change the cadence type. One of `interval`, `cron`.
</ParamField>

<ParamField body="start_at" type="string">
  New ISO-8601 start timestamp.
</ParamField>

<Expandable title="Less-common options">
  <ParamField body="name" type="string">
    New schedule name. Max 255 characters.
  </ParamField>

  <ParamField body="interval_amount" type="integer">
    New interval amount. Minimum 1.
  </ParamField>

  <ParamField body="interval_unit" type="string">
    New interval unit.
  </ParamField>

  <ParamField body="schedule_expression" type="string">
    New cron expression.
  </ParamField>

  <ParamField body="cron_time_zone" type="string">
    New IANA time zone for a cron schedule.
  </ParamField>

  <ParamField body="description" type="string">
    New description. Max 1024 characters.
  </ParamField>

  <ParamField body="overlap" type="boolean">
    Whether overlapping runs are allowed.
  </ParamField>

  <ParamField body="reuse_cluster_strategy" type="string">
    New cluster reuse strategy.
  </ParamField>

  <ParamField body="auto_retry_attempts" type="integer">
    New automatic retry count. 0 to 5. Any value greater than 0 turns auto-retry on.
  </ParamField>
</Expandable>

<ResponseField name="schedule_id" type="integer">
  The schedule id, with `name`, `status`, `schedule_type`, `next_run_at`, and `package_ids`. On a `dry_run`, the response is nested under `would_update` with the changed `fields`, target `status`, and `add_packages`.
</ResponseField>

## Execution and recovery

### run\_package

**Mutation.** Starts a new run of a package on a given cluster and returns the `run_id` immediately, with the run in `pending`. It does not wait for completion: poll `get_run` for status. Compute charged for time the run was already executing on the cluster cannot be refunded, so cancel via `cancel_job` if needed. Supports `dry_run`, which returns the predicted state without creating a run.

<ParamField body="package_id" type="integer" required>
  The package to run. Must not be archived.
</ParamField>

<ParamField body="cluster_id" type="integer" required>
  The cluster to dispatch to. Must not be terminated or terminating.
</ParamField>

<ParamField body="variables" type="object">
  A map of variable name to value that overrides the package's defaults for this run only. String literals must be wrapped in inner single quotes (pass `"'Smith'"`, not `"Smith"`), since `$variable` references are evaluated as Pig expressions. Numbers and booleans need no quoting, and values are matched case-sensitively.
</ParamField>

<ResponseField name="run_id" type="integer">
  The new run id, with `package_id`, `package_name`, `cluster_id`, `status`, `variables_applied` (the overridden keys), and `started_at`. On a `dry_run`, the details are nested under `would_create` with a `cluster_action` hint.
</ResponseField>

### cancel\_job

**Mutation.** Stops an in-flight run by sending the cancel signal through the run's state machine. An `idle` run stops synchronously; `pending`, `queued`, or `running` runs move to `pending_stoppage` and are stopped asynchronously (poll `get_run` to confirm). Idempotent: a run already cancelling returns `already_cancelling: true`, and a run already finished returns `already_terminal: true`. Not reversible once cancelled. Supports `dry_run`.

<ParamField body="run_id" type="integer" required>
  The run to cancel.
</ParamField>

<ResponseField name="run_id" type="integer">
  The run id, with `previous_status`, `new_status`, `already_terminal`, `already_cancelling`, and `cancel_requested_at` (the time the cancel signal was sent, not when the run finished stopping). On a `dry_run`, the details are nested under `would_cancel` with a `cluster_impact` hint.
</ResponseField>

### retry\_job

**Mutation.** Re-runs a finished (failed, cancelled, or completed) run by creating a fresh run that copies the parent's package, cluster, and variables, then starts it. The new run is a sibling: the original run is preserved in its terminal status. By default, `variables` are merged onto the parent's; pass `replace_variables: true` to use only the new hash. Supports `dry_run`, which returns the resolved variable set without creating the run.

<ParamField body="run_id" type="integer" required>
  The parent run to re-run.
</ParamField>

<ParamField body="variables" type="object">
  Variable overrides. Merged onto the parent's variables by default (override wins on collision). Omit to retry exactly as the parent ran.
</ParamField>

<ParamField body="replace_variables" type="boolean" default="false">
  When `true`, use only the supplied `variables` hash instead of merging onto the parent's.
</ParamField>

<ResponseField name="new_run_id" type="integer">
  The new run id, with `parent_run_id`, `package_id`, `cluster_id`, `status`, `variables_applied`, and `started_at`. On a `dry_run`, the details are nested under `would_retry` with the fully `variables_resolved` hash.
</ResponseField>
