Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/docs/intro.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ Slack channel in the Tableau #DataDev workspace.
| [get-datasource-metadata](tools/data-qna/get-datasource-metadata.md) | Fetches datasource metadata including table relationships, datasource and field descriptions, field roles and types, calculation strings, and parameters for the specified datasource ([Metadata API][meta] & [VDS API][vds]) | All SKUs\* |
| [get-workbook](tools/workbooks/get-workbook.md) | Retrieves information about a workbook for a specified workbook on a Tableau site ([REST API][get-workbook]) | All SKUs |
| [get-flow](tools/flows/get-flow.md) | Retrieves information on a Tableau Prep flow including output steps and recent runs ([REST API][get-flow]) | All SKUs |
| [list-flow-runs](tools/flows/list-flow-runs.md) | Retrieves the run history (executions) of Tableau Prep flows on a site ([REST API][list-flow-runs]) | All SKUs |
| [list-flow-tasks](tools/flows/list-flow-tasks.md) | Retrieves the scheduled flow run tasks (schedules) for Tableau Prep flows on a site ([REST API][list-flow-tasks]) | All SKUs |
| [delete-content](tools/content/delete-content.md) | Admin-only. Two-phase (preview/confirm) delete of a workbook, data source, or extract refresh task ([REST API][delete-workbook], [REST API][delete-datasource], [REST API][delete-extract-refresh-task]) | All SKUs |
| [get-view-data](tools/views/get-view-data.md) | Retrieves data in CSV format for the specified view in a Tableau workbook. *Note: the get-view-data api currently has a limitation that when used on a dashboard sheet type, it will only return data for the first worksheet in the dashboard. This will be fixed in the 26.3 fall release.* ([REST API][get-view-data]) | All SKUs |
| [get-view-image](tools/views/get-view-image.md) | Retrieves an image for the specified view in a Tableau workbook ([REST API][get-view-image]) | All SKUs |
Expand Down Expand Up @@ -83,6 +85,10 @@ Slack channel in the Tableau #DataDev workspace.
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#query_workbook
[get-flow]:
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#query_flow
[list-flow-runs]:
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#get_flow_runs
[list-flow-tasks]:
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#get_flow_run_tasks
[delete-workbook]:
https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_workbooks_and_views.htm#delete_workbook
[delete-datasource]:
Expand Down
202 changes: 202 additions & 0 deletions docs/docs/tools/flows/list-flow-runs.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
---
sidebar_position: 3
---

# List Flow Runs

Retrieves the run history (executions) of Tableau Prep flows on a site. Each flow run records one
execution attempt with its status, start/finish timestamps, progress, the flow it belongs to, and
the background job id.

This is the dedicated, filterable, site-wide run-history tool:

- [List Flows](list-flows.md) lists flow _definitions_, not executions.
- [Get Flow](get-flow.md) returns recent runs for a **single** flow (as a capped sidecar). Use
`list-flow-runs` for cross-flow questions ("all failures today") or deeper single-flow history.

## APIs called

- [Get Flow Runs](https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#get_flow_runs)
(requires Tableau REST API >= 3.10)

## Required Tableau API scopes

When the MCP server authenticates with OAuth (connected-app JWT), this tool requests:

- `tableau:flow_runs:read`
- `tableau:flows:read` — to resolve a failed run's flow `webpageUrl` into the run-history deep link
in `mcp.failureInsight`.
- `tableau:mcp_site_settings:read`

See [OAuth configuration](../../configuration/mcp-config/oauth.md) for how scopes are negotiated.

## Caller-role visibility

- **Non-admin callers** — Tableau returns runs only for flows the caller can **run** (the Execute /
"Run Flow Now" capability), _not_ flows they can only view. This is stricter than the Tableau web UI
run-history page (which needs only view permission), so a user may see a flow's runs in the browser
yet get nothing for that flow here.
- **Server / site-admin callers** — Tableau returns runs for **every** flow on the site, so
[`mcp.resultInfo.truncated`](#response-shape) is more likely to be `true` on a broad call.

## Optional arguments

### `filter`

A filter expression in the format `field:operator:value`. Multiple expressions are combined with a
comma using a logical AND.

| Field | Operators | Notes |
| ------------- | ---------------------- | --------------------------------------------------------------------------- |
| `flowId` | `eq, in` | Flow LUID (UUID). The most common filter — scope runs to one or more flows. |
| `userId` | `eq, in` | LUID of the user who initiated the run. |
| `progress` | `eq, gt, gte, lt, lte` | Percent complete (0–100). |
| `startedAt` | `eq, gt, gte, lt, lte` | ISO 8601 `YYYY-MM-DDTHH:MM:SSZ` or date-only `YYYY-MM-DD` (midnight UTC). |
| `completedAt` | `eq, gt, gte, lt, lte` | ISO 8601 `YYYY-MM-DDTHH:MM:SSZ` or date-only `YYYY-MM-DD` (midnight UTC). |
| `status` | `eq, in` | One of `Pending, InProgress, Success, Failed, Cancelled`. **Client-side.** |

Examples:

- `flowId:eq:6f8a2966-e173-11e8-ae74-ffd84c19d7f3`
- `status:eq:Failed,startedAt:gt:2025-01-01`
- `status:in:[Failed,Cancelled]`

#### `status` is applied client-side

The Tableau "Get Flow Runs" endpoint does **not** support filtering runs by `status` server-side
(verified live against REST 3.30). This tool therefore fetches runs using the rest of the filter and
applies `status` in-process. Pair `status` with a `flowId` and/or a `startedAt` window so the
client-side match operates on a bounded set of runs. Unknown `status` values are rejected with the
allowed list, and the value is case-sensitive.

#### `flowId` must be a UUID

`flowId` matches the flow's LUID (canonical 8-4-4-4-12 hex form). The Get Flow Runs endpoint responds
`404` for a `flowId` that does not resolve to a real, visible flow (a flow _name_, or a valid-format
but nonexistent UUID); the tool converts that `404` into an empty result rather than surfacing a raw
HTTP error. When the result is empty and `flowId` is not a UUID, the tool also returns a recovery hint
suggesting a [List Flows](list-flows.md) lookup by name.

#### `in:` — bracket-and-comma form

Multi-value lists use the form `flowId:in:[uuid1,uuid2]` or `status:in:[Failed,Cancelled]`, where
commas separate the items. Items are not quoted, so a single item's value cannot itself contain a
comma (every comma is read as an item separator).

<hr />

### `sort`

A sort expression in the format `field:asc` or `field:desc` using `startedAt` or `completedAt`.

When omitted, the result is ordered **newest first by run recency** — by `completedAt`, falling back
to `startedAt` for runs that haven't completed; runs with neither timestamp (e.g. `Pending`) sort
last. This is a best-effort "most recent" within the returned window.

> **Why the default isn't a plain `startedAt:desc`.** The Tableau Get Flow Runs endpoint orders rows
> whose chosen sort field is _empty_ to the **front** under `:desc`. `startedAt` is empty for every
> never-started run (e.g. `Cancelled`-before-start), so `startedAt:desc` surfaces a stale, unordered
> block of those runs ahead of genuinely recent ones. The tool fetches `completedAt:desc` (a far
> smaller empty band) and then re-orders the fetched window by `completedAt ?? startedAt`. Supplying
> an explicit `sort` is honored verbatim and bypasses this correction.

Example: `completedAt:desc`

<hr />

### `limit`

The maximum number of runs to return. The tool paginates the Tableau endpoint and returns at most
this many runs. When omitted, it falls back to the administrator cap if one is configured; otherwise
it returns the newest **100** runs as a safety backstop (reported as `truncated` with
`truncationReason: "default-cap"`) rather than walking the entire run history. Pass an explicit
`limit` to go beyond the default.

See also: [`MAX_RESULT_LIMIT`](../../configuration/mcp-config/env-vars.md#max_result_limit) and
[`MAX_RESULT_LIMITS=list-flow-runs:N`](../../configuration/mcp-config/env-vars.md#max_result_limits).

## Response shape

The tool returns a JSON object:

```json
{
"flowRuns": [
/* one record per run, see "Example result" below */
],
"mcp": {
"resultInfo": {
"returnedCount": 12,
"truncated": false
}
}
}
```

The top-level `flowRuns` array and `mcp.resultInfo` are **always present**. `resultInfo` reports
whether the returned list is complete:

- `returnedCount` — the number of runs in `flowRuns`.
- `truncated` — `false` means `flowRuns` is the **complete** set matching the request; `true` means
more matching runs exist on the server than were returned.
- `truncationReason` — present only when `truncated` is `true`:
- `"requested-limit"` — the caller's own `limit` cut the result short. Call again with a higher
`limit`.
- `"default-cap"` — the caller supplied **no `limit`** and **no admin cap** is configured, so the
tool returned the newest **100** runs as a safety backstop rather than walking the entire run
history (which accumulates quickly and would load the server). Pass a higher `limit` and/or a
narrower `filter` (e.g. a single `flowId` or a `startedAt` window) to go deeper.
- `"admin-cap"` — a site-administrator per-call cap
([`MAX_RESULT_LIMIT`](../../configuration/mcp-config/env-vars.md#max_result_limit) or
`MAX_RESULT_LIMITS=list-flow-runs:N`) cut the result short. Narrow the `filter` (e.g. a tighter
`startedAt` window or a single `flowId`), or ask the administrator to raise the cap.

Unlike [List Flows](list-flows.md), there is **no `totalAvailable`** — the Tableau Flow Runs
endpoint does not return a total count, so completeness is reported via the `truncated` flag only
(computed with a "+1 probe" — the tool fetches one more run than `limit` to detect that more exist).
When `truncated` is `true`, report "at least N" — never invent a total.

:::tip For client / LLM authors `mcp.resultInfo` is a signal **for the model**, not text to show the
user. Translate it into one plain sentence — "These are all 12 matching runs" or "Here are the first
50; more match" — and never surface the field names to the end user. :::

## Bounded context (fail-closed)

A flow run carries no project or tag, so when the server is restricted to a
[`INCLUDE_PROJECT_IDS`](../../configuration/mcp-config/tool-scoping.md#include_project_ids) or
[`INCLUDE_TAGS`](../../configuration/mcp-config/tool-scoping.md#include_tags) bounded context this tool **cannot** prove
a run belongs to the allowed set. Rather than risk leaking runs for flows outside the allow-list, it
returns no runs and explains why. To inspect a specific allowed flow's run history under a bounded
context, use [Get Flow](get-flow.md) with the flow id (it enforces the bounded context on the flow
itself).

## Limitations

- **No error details for `Failed` runs.** The `status` is available, but the underlying job error
message is not surfaced by the public Tableau REST API. Inspect the run in the Tableau UI.
- **No exact total-run count.** The endpoint does not expose `totalAvailable`; the tool reports only
whether more runs exist via `truncated`.

## Example result

```json
{
"flowRuns": [
{
"id": "a1a1a1a1-1111-1111-1111-111111111111",
"flowId": "d00700fe-28a0-4ece-a7af-5543ddf38a82",
"status": "Success",
"startedAt": "2025-04-01T10:00:00Z",
"completedAt": "2025-04-01T10:05:00Z",
"progress": 100,
"backgroundJobId": "b2b2b2b2-2222-2222-2222-222222222222"
}
],
"mcp": {
"resultInfo": {
"returnedCount": 1,
"truncated": false
}
}
}
```
143 changes: 143 additions & 0 deletions docs/docs/tools/flows/list-flow-tasks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
---
sidebar_position: 4
---

# List Flow Tasks

Retrieves the scheduled flow run tasks on a site. A flow run task is the **schedule** for a Tableau
Prep flow — when and how often it is configured to run — **not** a record of past executions. For
run history, use [List Flow Runs](list-flow-runs.md).

Each task includes the target flow (`flow.id`, `flow.name`), the schedule (frequency, next run time,
state), and the task `id` used to trigger an on-demand run.

## APIs called

- [Get Flow Run Tasks](https://help.tableau.com/current/api/rest_api/en-us/REST/rest_api_ref_flow.htm#get_flow_run_tasks)

## Required Tableau API scopes

When the MCP server authenticates with OAuth (connected-app JWT), this tool requests:

- `tableau:flow_tasks:read`
- `tableau:mcp_site_settings:read`

The `tableau:flow_tasks:read` scope was added in Tableau Cloud December 2025 / Server 2025.3. See
[OAuth configuration](../../configuration/mcp-config/oauth.md) for how scopes are negotiated.

## Caller-role visibility

- **Non-admin callers** — Tableau returns the scheduled tasks only for flows the caller owns.
- **Server / site-admin callers** — Tableau returns **every** scheduled flow task on the site.

This tool is **not** admin-gated; any authenticated user can call it and will see the tasks Tableau
exposes to them.

## Optional arguments

### `filter`

A client-side filter string in the format `field:operator:value`. Multiple expressions are combined
with a comma using a logical AND. The Tableau REST API does not support server-side filtering for
this endpoint, so all tasks are fetched and filtered in-process.

| Field | Type | Operators | Example |
| ------------------------ | ----------------- | ---------------------- | --------------------------------------------- |
| `id` | string | `eq, in` | `id:eq:1bff10bb-57ae-43df-8774-a86d14aef432` |
| `type` | string | `eq, in` | `type:eq:RunFlowTask` |
| `priority` | number | `eq, gt, gte, lt, lte` | `priority:gte:5` |
| `consecutiveFailedCount` | number | `eq, gt, gte, lt, lte` | `consecutiveFailedCount:gt:0` |
| `flow.id` | string | `eq, in` | `flow.id:eq:8a320dca-9151-41ea-8474-...` |
| `flow.name` | string | `eq, in` | `flow.name:eq:Daily Sales` |
| `schedule.id` | string | `eq, in` | `schedule.id:eq:36d6fab2-2a0a-...` |
| `schedule.name` | string | `eq, in` | `schedule.name:eq:Daily Refresh` |
| `schedule.state` | string | `eq, in` | `schedule.state:eq:Active` |
| `schedule.frequency` | string | `eq, in` | `schedule.frequency:eq:Daily` |
| `schedule.nextRunAt` | string (ISO 8601) | `eq, gt, gte, lt, lte` | `schedule.nextRunAt:lt:2026-05-25T00:00:00Z` |
| `schedule.createdAt` | string (ISO 8601) | `eq, gt, gte, lt, lte` | `schedule.createdAt:gte:2026-01-01T00:00:00Z` |
| `schedule.updatedAt` | string (ISO 8601) | `eq, gt, gte, lt, lte` | `schedule.updatedAt:gte:2026-05-01T00:00:00Z` |

The `in` operator accepts a bracket/comma list (e.g. `schedule.state:in:[Active,Suspended]`),
matching every other `list-*` tool; the legacy pipe-delimited form
(`schedule.state:in:Active|Suspended`) is also accepted. Date-time values must be full ISO 8601
(e.g. `2026-05-25T00:00:00Z`).

Examples:

- `schedule.frequency:eq:Daily,schedule.state:eq:Active`
- `consecutiveFailedCount:gt:0` (schedules that are failing repeatedly)

<hr />

### `pageSize`

The maximum number of results per page, applied client-side after filtering.

### `limit`

The maximum total number of tasks to return, applied client-side after filtering.

## Response-size guidance

The Tableau "Get Flow Run Tasks" endpoint has **no server-side filtering or pagination**, so the
tool fetches **every** scheduled task on the site and then applies `filter`/`limit` in-process. On
large sites that is a big, slow response, so the tool description steers the LLM toward the narrowest
call that answers the question:

| Question shape | Recommended arguments |
| ----------------------------------- | ---------------------------------------------------------------- |
| "When does flow X run next?" | `filter: "flow.id:eq:<uuid>"` |
| "Which schedules are failing?" | `filter: "consecutiveFailedCount:gt:0"` |
| "Which daily schedules are active?" | `filter: "schedule.frequency:eq:Daily,schedule.state:eq:Active"` |
| "Are any flows scheduled at all?" | a small `limit` (e.g. `10`) |

## Bounded context (fail-closed)

A flow run task carries the flow's id and name but no project or tag, so when the server is
restricted to an [`INCLUDE_PROJECT_IDS`](../../configuration/mcp-config/tool-scoping.md#include_project_ids) or
[`INCLUDE_TAGS`](../../configuration/mcp-config/tool-scoping.md#include_tags) bounded context this tool **cannot** prove
a task's flow belongs to the allowed set. Rather than risk leaking schedules for flows outside the
allow-list, it returns no tasks and explains why.

## Result info

The response is an object `{ flowTasks: [...], mcp: { resultInfo } }`. The `flowTasks` array holds one
record per scheduled task; `mcp.resultInfo` is **always present** and reports whether that array is
complete:

- `returnedCount` — number of tasks in `flowTasks`.
- `totalAvailable` — number of tasks matching the filter before any limit. Always exact here, because
the endpoint returns every task and filtering/limiting happen in-process.
- `truncated` — `true` when a `limit`/`pageSize` or an admin `MAX_RESULT_LIMIT` cut the list short.
- `truncationReason` — `requested-limit` (caller's `limit`/`pageSize`) or `admin-cap` (site limit), present only when `truncated` is `true`.

## Example result

```json
{
"flowTasks": [
{
"id": "1bff10bb-57ae-43df-8774-a86d14aef432",
"priority": 50,
"consecutiveFailedCount": 2,
"type": "RunFlowTask",
"schedule": {
"id": "36d6fab2-2a0a-432e-b464-9fe4229a9937",
"name": "Every 2 Minutes",
"state": "Active",
"priority": 50,
"createdAt": "2018-11-08T21:57:49Z",
"updatedAt": "2018-11-09T17:30:08Z",
"type": "Flow",
"frequency": "Hourly",
"nextRunAt": "2018-11-09T17:32:00Z"
},
"flow": {
"id": "8a320dca-9151-41ea-8474-a0bb71961cc0",
"name": "allUseCaseTFLX2"
}
}
],
"mcp": { "resultInfo": { "returnedCount": 1, "truncated": false, "totalAvailable": 1 } }
}
```
Loading
Loading