| name | flowstudio-power-automate-debug |
| description | Debug failing Power Automate cloud flows using the FlowStudio MCP server. Load this skill when asked to: debug a flow, investigate a failed run, why is this flow failing, inspect action outputs, find the root cause of a flow error, fix a broken Power Automate flow, diagnose a timeout, trace a DynamicOperationRequestFailure, check connector auth errors, read error details from a run, or troubleshoot expression failures. Requires a FlowStudio MCP subscription — see https://mcp.flowstudio.app |
Power Automate Debugging with FlowStudio MCP
A step-by-step diagnostic process for investigating failing Power Automate
cloud flows through the FlowStudio MCP server.
Prerequisite: A FlowStudio MCP server must be reachable with a valid JWT.
See the flowstudio-power-automate-mcp skill for connection setup.
Subscribe at https://mcp.flowstudio.app
Source of Truth
Always call tools/list first to confirm available tool names and their
parameter schemas. Tool names and parameters may change between server versions.
This skill covers response shapes, behavioral notes, and diagnostic patterns —
things tools/list cannot tell you. If this document disagrees with tools/list
or a real API response, the API wins.
Python Helper
import json, urllib.request
MCP_URL = "https://mcp.flowstudio.app/mcp"
MCP_TOKEN = "<YOUR_JWT_TOKEN>"
def mcp(tool, **kwargs):
payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/call",
"params": {"name": tool, "arguments": kwargs}}).encode()
req = urllib.request.Request(MCP_URL, data=payload,
headers={"x-api-key": MCP_TOKEN, "Content-Type": "application/json",
"User-Agent": "FlowStudio-MCP/1.0"})
try:
resp = urllib.request.urlopen(req, timeout=120)
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
raise RuntimeError(f"MCP HTTP {e.code}: {body[:200]}") from e
raw = json.loads(resp.read())
if "error" in raw:
raise RuntimeError(f"MCP error: {json.dumps(raw['error'])}")
return json.loads(raw["result"]["content"][0]["text"])
ENV = "<environment-id>"
FlowStudio for Teams: Fast-Path Diagnosis (Skip Steps 2–4)
If you have a FlowStudio for Teams subscription, get_store_flow_errors
returns per-run failure data including action names and remediation hints
in a single call — no need to walk through live API steps.
summary = mcp("get_store_flow_summary", environmentName=ENV, flowName=FLOW_ID)
print(f"Fail rate: {summary['failRate']:.0%} over {summary['totalRuns']} runs")
errors = mcp("get_store_flow_errors", environmentName=ENV, flowName=FLOW_ID)
if errors:
for r in errors[:3]:
print(r["startTime"], "|", r.get("failedActions"), "|", r.get("remediationHint"))
else:
pass
For the full governance record (description, complexity, tier, connector list):
record = mcp("get_store_flow", environmentName=ENV, flowName=FLOW_ID)
if record.get("runError"):
last_err = json.loads(record["runError"])
print("Last run error:", last_err)
Step 1 — Locate the Flow
result = mcp("list_live_flows", environmentName=ENV)
target = next(f for f in result["flows"] if "My Flow Name" in f["displayName"])
FLOW_ID = target["id"]
print(FLOW_ID)
Step 2 — Find the Failing Run
runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=5)
for r in runs:
print(r["name"], r["status"], r["startTime"])
RUN_ID = next(r["name"] for r in runs if r["status"] == "Failed")
Step 3 — Get the Top-Level Error
err = mcp("get_live_flow_run_error",
environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID)
root = err["failedActions"][-1]
print(f"Root action: {root['actionName']} → code: {root.get('code')}")
Step 4 — Read the Flow Definition
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
actions = defn["properties"]["definition"]["actions"]
print(list(actions.keys()))
Find the failing action in the definition. Inspect its inputs expression
to understand what data it expects.
Step 5 — Inspect Action Outputs (Walk Back from Failure)
For each action leading up to the failure, inspect its runtime output:
for action_name in ["Compose_WeekEnd", "HTTP_Get_Data", "Parse_JSON"]:
result = mcp("get_live_flow_run_action_outputs",
environmentName=ENV,
flowName=FLOW_ID,
runName=RUN_ID,
actionName=action_name)
out = result[0] if result else {}
print(action_name, out.get("status"))
print(json.dumps(out.get("outputs", {}), indent=2)[:500])
⚠️ Output payloads from array-processing actions can be very large.
Always slice (e.g. [:500]) before printing.
Step 6 — Pinpoint the Root Cause
Expression Errors (e.g. split on null)
If the error mentions InvalidTemplate or a function name:
- Find the action in the definition
- Check what upstream action/expression it reads
- Inspect that upstream action's output for null / missing fields
result = mcp("get_live_flow_run_action_outputs", ..., actionName="Compose_Names")
if not result:
print("No outputs returned for Compose_Names")
names = []
else:
names = result[0].get("outputs", {}).get("body") or []
nulls = [x for x in names if x.get("Name") is None]
print(f"{len(nulls)} records with null Name")
Wrong Field Path
Expression triggerBody()?['fieldName'] returns null → fieldName is wrong.
Check the trigger output shape with:
mcp("get_live_flow_run_action_outputs", ..., actionName="<trigger-action-name>")
Connection / Auth Failures
Look for ConnectionAuthorizationFailed — the connection owner must match the
service account running the flow. Cannot fix via API; fix in PA designer.
Step 7 — Apply the Fix
For expression/data issues:
defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID)
acts = defn["properties"]["definition"]["actions"]
acts["Compose_Names"]["inputs"] = \
"@coalesce(item()?['Name'], 'Unknown')"
conn_refs = defn["properties"]["connectionReferences"]
result = mcp("update_live_flow",
environmentName=ENV,
flowName=FLOW_ID,
definition=defn["properties"]["definition"],
connectionReferences=conn_refs)
print(result.get("error"))
⚠️ update_live_flow always returns an error key.
A value of null (Python None) means success.
Step 8 — Verify the Fix
resubmit = mcp("resubmit_live_flow_run",
environmentName=ENV, flowName=FLOW_ID, runName=RUN_ID)
print(resubmit)
import time; time.sleep(30)
new_runs = mcp("get_live_flow_runs", environmentName=ENV, flowName=FLOW_ID, top=3)
print(new_runs[0]["status"])
Testing HTTP-Triggered Flows
For flows with a Request (HTTP) trigger, use trigger_live_flow instead
of resubmit_live_flow_run to test with custom payloads:
schema = mcp("get_live_flow_http_schema",
environmentName=ENV, flowName=FLOW_ID)
print("Expected body schema:", schema.get("triggerSchema"))
print("Response schemas:", schema.get("responseSchemas"))
result = mcp("trigger_live_flow",
environmentName=ENV,
flowName=FLOW_ID,
body={"name": "Test User", "value": 42})
print(f"Status: {result['status']}, Body: {result.get('body')}")
trigger_live_flow handles AAD-authenticated triggers automatically.
Only works for flows with a Request (HTTP) trigger type.
Quick-Reference Diagnostic Decision Tree
| Symptom | First Tool to Call | What to Look For |
|---|
| Flow shows as Failed | get_live_flow_run_error | failedActions[-1]["actionName"] = root cause |
| Expression crash | get_live_flow_run_action_outputs on prior action | null / wrong-type fields in output body |
| Flow never starts | get_live_flow | check properties.state = "Started" |
| Action returns wrong data | get_live_flow_run_action_outputs | actual output body vs expected |
| Fix applied but still fails | get_live_flow_runs after resubmit | new run status field |
Reference Files
Related Skills
flowstudio-power-automate-mcp — Core connection setup and operation reference
flowstudio-power-automate-build — Build and deploy new flows