Skip to main content

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, the background job id, and — for Failed runs on Tableau REST API >= 3.30 — a failureReason giving the cause of the failure.

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

  • List Flows lists flow definitions, not executions.
  • Get Flow 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.

Required permissions​

  • Site Role: Requires Explorer (Can Publish) role or higher

APIs called​

Required Tableau API scopes​

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

  • tableau:flow_runs:read
  • tableau:flows:read — to resolve a failed run's flow webpageUrl into the run-history deep link in mcp.failureInsight. Only requested on that fallback path; when the runs carry a resolved failureReason the tool makes no such call.
  • tableau:mcp_site_settings:read

The primary Get Flow Runs call requests only tableau:flow_runs:read plus the always-on site-settings scope. tableau:flows:read is requested in a separate, best-effort call made only when the returned window has a Failed run and no resolved failure reason. It resolves that failed run's flow webpageUrl into the run-history deep link surfaced in mcp.failureInsight (see Failure reporting). Calls with no failures—or with at least one resolved reason—never request tableau:flows:read, so they succeed against a Connected App that grants only tableau:flow_runs:read. See OAuth configuration 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 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.

FieldOperatorsNotes
flowIdeq, inFlow LUID (UUID). The most common filter — scope runs to one or more flows.
userIdeq, inLUID of the user who initiated the run.
progresseq, gt, gte, lt, ltePercent complete (0–100).
startedAteq, gt, gte, lt, lteISO 8601 YYYY-MM-DDTHH:MM:SSZ or date-only YYYY-MM-DD (midnight UTC).
completedAteq, gt, gte, lt, lteISO 8601 YYYY-MM-DDTHH:MM:SSZ or date-only YYYY-MM-DD (midnight UTC).
statuseq, inOne of Pending, InProgress, Success, Failed, Cancelled. Server-side on REST API 3.30+; client-side fallback on older APIs.

Examples:

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

status API-version behavior​

REST API 3.30 and later support filtering and sorting flow runs by status; this tool passes those expressions through unchanged. A multi-value status:in filter on those versions may contain only terminal statuses (Success, Failed, and/or Cancelled). A mixed list such as status:in:[Pending,Success] is rejected because the underlying query builder cannot represent the required OR predicate without risking incorrect results.

On older REST API versions, the tool removes status from the server request and applies filtering in-process. Pair status with a flowId and/or a startedAt window so the fallback operates on a bounded set of runs. Status sorting is not available on older REST API versions; use startedAt, completedAt, or progress sorting instead. 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 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).


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


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 and MAX_RESULT_LIMITS=list-flow-runs:N.

Response shape​

The tool returns a JSON object:

{
"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 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, 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. :::

Failure reporting​

When the returned window contains a Failed run, the tool reports on it through up to two fields. mcp.failureSummary appears whenever a Failed run carries a reason; mcp.failureInsight is added whenever no reason resolves the failure. They therefore co-occur when every reason in the window is available: false — the summary counts the failures, the link is where the cause can actually be read.

mcp.failureSummary​

Present when the window's Failed runs carry a failureReason (Tableau REST API >= 3.30). It groups the window's failures by the reported message and whether Tableau marked the reason available, so a caller can tell one systemic problem from many unrelated ones without reading every record:

  • failedRunCount — Failed runs in the returned window.
  • failedFlowCount — distinct flows with a failure in that window.
  • reasons — one entry per distinct { message, available } pair, largest first, as { message, available, runCount, flowIds }. runCount is how many runs reported that pair, and flowIds lists the distinct flows it affected (its blast radius).

A group is not always a single root cause. Tableau reports a short localized message, and several distinct underlying errors can map to the same one — a flow-execution failure and an authentication failure both surface as Flow processing error, for example. The underlying error identifier is not exposed by the REST API, so treat a group as one symptom, which may have more than one cause.

  • available: false means Tableau could not determine the cause and message is a generic placeholder. Do not present it as a diagnosis. Unresolved groups are common on real sites, and are often the largest — to investigate one, call Get Flow on any of its flowIds and append /runHistory to the returned webpageUrl.

failedRunCount and failedFlowCount cover all Failed runs, while reasons covers only those carrying a reason, so sum(reasons[].runCount) can be less than failedRunCount. Both counts describe the returned window only — when truncated is true they are not site-wide failure totals or rates.

mcp.failureInsight​

The fallback, for failures that cannot explain themselves — either the server predates REST API 3.30 (no failureReason at all) or every reason returned has available: false. It carries the same failedRunCount / failedFlowCount (identical values, since both fields count the same window), plus an example of { flowId, runHistoryUrl } for one affected flow (the most-recent failure) when resolvable. Open runHistoryUrl in a browser and expand the failed run to read the error in the Tableau UI.

Only one flow is resolved, which costs one extra Query Flow call; use Get Flow to resolve the others if failedFlowCount is greater than 1.

In a mixed window — some reasons resolved, some not — this field is deliberately absent, since the resolved reasons already answer the question and the link would cost that extra call. An available: false group in such a window therefore has no link of its own; reach one through Get Flow as described above.

Bounded context (fail-closed)​

A flow run carries no project or tag, so when the server is restricted to a INCLUDE_PROJECT_IDS or 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 with the flow id (it enforces the bounded context on the flow itself).

Limitations​

  • Failure reasons need REST API >= 3.30, and only cover Failed runs. On older servers failureReason is absent entirely and the tool falls back to the mcp.failureInsight deep link. Even on 3.30+, there is no reason for a Cancelled run and nothing explaining why a run is slow or stuck InProgress.
  • A reason is a short message, not a log. failureReason.message is a short localized cause. The full underlying job error is not surfaced by the public REST API and reading it requires site-administrator access to the job behind backgroundJobId. Inspect the run in the Tableau UI for the detail.
  • No exact total-run count. The endpoint does not expose totalAvailable; the tool reports only whether more runs exist via truncated.

Example result​

{
"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
}
}
}

With a failure, on Tableau REST API >= 3.30:

{
"flowRuns": [
{
"id": "a2a2a2a2-2222-2222-2222-222222222222",
"flowId": "d00700fe-28a0-4ece-a7af-5543ddf38a82",
"status": "Failed",
"startedAt": "2025-04-02T10:00:00Z",
"completedAt": "2025-04-02T10:01:00Z",
"progress": 100,
"backgroundJobId": "b3b3b3b3-3333-3333-3333-333333333333",
"failureReason": {
"available": true,
"message": "Table \"orders\" was not found."
}
}
],
"mcp": {
"resultInfo": {
"returnedCount": 1,
"truncated": false
},
"failureSummary": {
"failedRunCount": 1,
"failedFlowCount": 1,
"reasons": [
{
"message": "Table \"orders\" was not found.",
"available": true,
"runCount": 1,
"flowIds": ["d00700fe-28a0-4ece-a7af-5543ddf38a82"]
}
]
}
}
}

On a server below REST API 3.30 the same window has no failureReason and the tool returns the deep link instead:

{
"mcp": {
"resultInfo": {
"returnedCount": 1,
"truncated": false
},
"failureInsight": {
"failedRunCount": 1,
"failedFlowCount": 1,
"example": {
"flowId": "d00700fe-28a0-4ece-a7af-5543ddf38a82",
"runHistoryUrl": "https://my.tableau.example.com/#/site/mysite/flows/96151/runHistory"
}
}
}
}