| name | flowstudio-power-automate-mcp |
| description | Give your AI agent the same visibility you have in the Power Automate portal — plus a bit more. The Graph API only returns top-level run status. Flow Studio MCP exposes action-level inputs, outputs, loop iterations, and nested child flow failures. Use when asked to: list flows, read a flow definition, check run history, inspect action outputs, resubmit a run, cancel a running flow, view connections, get a trigger URL, validate a definition, monitor flow health, or any task that requires talking to the Power Automate API through an MCP tool. Also use for Power Platform environment discovery and connection management. Requires a FlowStudio MCP subscription or compatible server — see https://mcp.flowstudio.app |
| metadata | {"openclaw":{"requires":{"env":["FLOWSTUDIO_MCP_TOKEN"]},"primaryEnv":"FLOWSTUDIO_MCP_TOKEN","homepage":"https://mcp.flowstudio.app"}} |
Power Automate via FlowStudio MCP
This skill lets AI agents read, monitor, and operate Microsoft Power Automate
cloud flows programmatically through a FlowStudio MCP server — no browser,
no UI, no manual steps.
Real debugging examples: Expression error in child flow |
Data entry, not a flow bug |
Null value crashes child flow
Requires: A FlowStudio MCP subscription (or
compatible Power Automate MCP server). You will need:
- MCP endpoint:
https://mcp.flowstudio.app/mcp (same for all subscribers)
- API key / JWT token (
x-api-key header — NOT Bearer)
- Power Platform environment name (e.g.
Default-<tenant-guid>)
Source of Truth
| Priority | Source | Covers |
|---|
| 1 | Real API response | Always trust what the server actually returns |
| 2 | tools/list | Tool names, parameter names, types, required flags |
| 3 | SKILL docs & reference files | Response shapes, behavioral notes, workflow recipes |
Start every new session with tools/list.
It returns the authoritative, up-to-date schema for every tool — parameter names,
types, and required flags. The SKILL docs cover what tools/list cannot tell you:
response shapes, non-obvious behaviors, and end-to-end workflow patterns.
If any documentation disagrees with tools/list or a real API response,
the API wins.
Recommended Language: Python or Node.js
All examples in this skill and the companion build / debug skills use Python
with urllib.request (stdlib — no pip install needed). Node.js is an
equally valid choice: fetch is built-in from Node 18+, JSON handling is
native, and the async/await model maps cleanly onto the request-response pattern
of MCP tool calls — making it a natural fit for teams already working in a
JavaScript/TypeScript stack.
| Language | Verdict | Notes |
|---|
| Python | ✅ Recommended | Clean JSON handling, no escaping issues, all skill examples use it |
| Node.js (≥ 18) | ✅ Recommended | Native fetch + JSON.stringify/JSON.parse; async/await fits MCP call patterns well; no extra packages needed |
| PowerShell | ⚠️ Avoid for flow operations | ConvertTo-Json -Depth silently truncates nested definitions; quoting and escaping break complex payloads. Acceptable for a quick tools/list discovery call but not for building or updating flows. |
| cURL / Bash | ⚠️ Possible but fragile | Shell-escaping nested JSON is error-prone; no native JSON parser |
TL;DR — use the Core MCP Helper (Python or Node.js) below. Both handle
JSON-RPC framing, auth, and response parsing in a single reusable function.
What You Can Do
FlowStudio MCP has two access tiers. FlowStudio for Teams subscribers get
both the fast Azure-table store (cached snapshot data + governance metadata) and
full live Power Automate API access. MCP-only subscribers get the live tools —
more than enough to build, debug, and operate flows.
Live Tools — Available to All MCP Subscribers
| Tool | What it does |
|---|
list_live_flows | List flows in an environment directly from the PA API (always current) |
list_live_environments | List all Power Platform environments visible to the service account |
list_live_connections | List all connections in an environment from the PA API |
get_live_flow | Fetch the complete flow definition (triggers, actions, parameters) |
get_live_flow_http_schema | Inspect the JSON body schema and response schemas of an HTTP-triggered flow |
get_live_flow_trigger_url | Get the current signed callback URL for an HTTP-triggered flow |
trigger_live_flow | POST to an HTTP-triggered flow's callback URL (AAD auth handled automatically) |
update_live_flow | Create a new flow or patch an existing definition in one call |
add_live_flow_to_solution | Migrate a non-solution flow into a solution |
get_live_flow_runs | List recent run history with status, start/end times, and errors |
get_live_flow_run_error | Get structured error details (per-action) for a failed run |
get_live_flow_run_action_outputs | Inspect inputs/outputs of any action (or every foreach iteration) in a run |
resubmit_live_flow_run | Re-run a failed or cancelled run using its original trigger payload |
cancel_live_flow_run | Cancel a currently running flow execution |
Store Tools — FlowStudio for Teams Subscribers Only
These tools read from (and write to) the FlowStudio Azure table — a monitored
snapshot of your tenant's flows enriched with governance metadata and run statistics.
| Tool | What it does |
|---|
list_store_flows | Search flows from the cache with governance flags, run failure rates, and owner metadata |
get_store_flow | Get full cached details for a single flow including run stats and governance fields |
get_store_flow_trigger_url | Get the trigger URL from the cache (instant, no PA API call) |
get_store_flow_runs | Cached run history for the last N days with duration and remediation hints |
get_store_flow_errors | Cached failed-only runs with failed action names and remediation hints |
get_store_flow_summary | Aggregated stats: success rate, failure count, avg/max duration |
set_store_flow_state | Start or stop a flow via the PA API and sync the result back to the store |
update_store_flow | Update governance metadata (description, tags, monitor flag, notification rules, business impact) |
list_store_environments | List all environments from the cache |
list_store_makers | List all makers (citizen developers) from the cache |
get_store_maker | Get a maker's flow/app counts and account status |
list_store_power_apps | List all Power Apps canvas apps from the cache |
list_store_connections | List all Power Platform connections from the cache |
Which Tool Tier to Call First
| Task | Tool | Notes |
|---|
| List flows | list_live_flows | Always current — calls PA API directly |
| Read a definition | get_live_flow | Always fetched live — not cached |
| Debug a failure | get_live_flow_runs → get_live_flow_run_error | Use live run data |
⚠️ list_live_flows returns a wrapper object with a flows array — access via result["flows"].
Store tools (list_store_flows, get_store_flow, etc.) are available to FlowStudio for Teams subscribers and provide cached governance metadata. Use live tools when in doubt — they work for all subscription tiers.
Step 0 — Discover Available Tools
Always start by calling tools/list to confirm the server is reachable and see
exactly which tool names are available (names may vary by server version):
import json, urllib.request
TOKEN = "<YOUR_JWT_TOKEN>"
MCP = "https://mcp.flowstudio.app/mcp"
def mcp_raw(method, params=None, cid=1):
payload = {"jsonrpc": "2.0", "method": method, "id": cid}
if params:
payload["params"] = params
req = urllib.request.Request(MCP, data=json.dumps(payload).encode(),
headers={"x-api-key": TOKEN, "Content-Type": "application/json",
"User-Agent": "FlowStudio-MCP/1.0"})
try:
resp = urllib.request.urlopen(req, timeout=30)
except urllib.error.HTTPError as e:
raise RuntimeError(f"MCP HTTP {e.code} — check token and endpoint") from e
return json.loads(resp.read())
raw = mcp_raw("tools/list")
if "error" in raw:
print("ERROR:", raw["error"]); raise SystemExit(1)
for t in raw["result"]["tools"]:
print(t["name"], "—", t["description"][:60])
Core MCP Helper (Python)
Use this helper throughout all subsequent operations:
import json, urllib.request
TOKEN = "<YOUR_JWT_TOKEN>"
MCP = "https://mcp.flowstudio.app/mcp"
def mcp(tool, args, cid=1):
payload = {"jsonrpc": "2.0", "method": "tools/call", "id": cid,
"params": {"name": tool, "arguments": args}}
req = urllib.request.Request(MCP, data=json.dumps(payload).encode(),
headers={"x-api-key": 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'])}")
text = raw["result"]["content"][0]["text"]
return json.loads(text)
Common auth errors:
- HTTP 401/403 → token is missing, expired, or malformed. Get a fresh JWT from mcp.flowstudio.app.
- HTTP 400 → malformed JSON-RPC payload. Check
Content-Type: application/json and body structure.
MCP error: {"code": -32602, ...} → wrong or missing tool arguments.
Core MCP Helper (Node.js)
Equivalent helper for Node.js 18+ (built-in fetch — no packages required):
const TOKEN = "<YOUR_JWT_TOKEN>";
const MCP = "https://mcp.flowstudio.app/mcp";
async function mcp(tool, args, cid = 1) {
const payload = {
jsonrpc: "2.0",
method: "tools/call",
id: cid,
params: { name: tool, arguments: args },
};
const res = await fetch(MCP, {
method: "POST",
headers: {
"x-api-key": TOKEN,
"Content-Type": "application/json",
"User-Agent": "FlowStudio-MCP/1.0",
},
body: JSON.stringify(payload),
});
if (!res.ok) {
const body = await res.text();
throw new Error(`MCP HTTP ${res.status}: ${body.slice(0, 200)}`);
}
const raw = await res.json();
if (raw.error) throw new Error(`MCP error: ${JSON.stringify(raw.error)}`);
return JSON.parse(raw.result.content[0].text);
}
Requires Node.js 18+. For older Node, replace fetch with https.request
from the stdlib or install node-fetch.
List Flows
ENV = "Default-<tenant-guid>"
result = mcp("list_live_flows", {"environmentName": ENV})
for f in result["flows"]:
FLOW_ID = f["id"]
print(FLOW_ID, "|", f["displayName"], "|", f["state"])
Read a Flow Definition
FLOW = "<flow-uuid>"
flow = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW})
print(flow["properties"]["displayName"])
print(flow["properties"]["state"])
actions = flow["properties"]["definition"]["actions"]
print("Actions:", list(actions.keys()))
print(actions["Compose_Filter"]["inputs"])
Check Run History
runs = mcp("get_live_flow_runs", {"environmentName": ENV, "flowName": FLOW, "top": 5})
for r in runs:
print(r["name"], r["status"])
run_id = next((r["name"] for r in runs if r["status"] == "Failed"), None)
Inspect an Action's Output
run_id = runs[0]["name"]
out = mcp("get_live_flow_run_action_outputs", {
"environmentName": ENV,
"flowName": FLOW,
"runName": run_id,
"actionName": "Get_Customer_Record"
})
print(json.dumps(out, indent=2))
Get a Run's Error
err = mcp("get_live_flow_run_error", {
"environmentName": ENV,
"flowName": FLOW,
"runName": run_id
})
root = err["failedActions"][-1]
print(f"Root failure: {root['actionName']} → {root['code']}")
Resubmit a Run
result = mcp("resubmit_live_flow_run", {
"environmentName": ENV,
"flowName": FLOW,
"runName": run_id
})
print(result)
Cancel a Running Run
mcp("cancel_live_flow_run", {
"environmentName": ENV,
"flowName": FLOW,
"runName": run_id
})
⚠️ Do NOT cancel a run that shows Running because it is waiting for an
adaptive card response. That status is normal — the flow is paused waiting
for a human to respond in Teams. Cancelling it will discard the pending card.
Full Round-Trip Example — Debug and Fix a Failing 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"]
runs = mcp("get_live_flow_runs", {"environmentName": ENV, "flowName": FLOW_ID, "top": 5})
RUN_ID = next(r["name"] for r in runs if r["status"] == "Failed")
err = mcp("get_live_flow_run_error", {"environmentName": ENV, "flowName": FLOW_ID, "runName": RUN_ID})
root_action = err["failedActions"][-1]["actionName"]
print(f"Root failure: {root_action}")
defn = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW_ID})
acts = defn["properties"]["definition"]["actions"]
print("Failing action inputs:", acts[root_action]["inputs"])
out = mcp("get_live_flow_run_action_outputs", {
"environmentName": ENV, "flowName": FLOW_ID,
"runName": RUN_ID, "actionName": "Compose_Names"
})
nulls = [x for x in out.get("body", []) if x.get("Name") is None]
print(f"{len(nulls)} records with null Name")
acts[root_action]["inputs"]["parameters"]["searchName"] = \
"@coalesce(item()?['Name'], '')"
conn_refs = defn["properties"]["connectionReferences"]
result = mcp("update_live_flow", {
"environmentName": ENV, "flowName": FLOW_ID,
"definition": defn["properties"]["definition"],
"connectionReferences": conn_refs
})
assert result.get("error") is None, f"Deploy failed: {result['error']}"
mcp("resubmit_live_flow_run", {"environmentName": ENV, "flowName": FLOW_ID, "runName": RUN_ID})
import time; time.sleep(30)
new_runs = mcp("get_live_flow_runs", {"environmentName": ENV, "flowName": FLOW_ID, "top": 1})
print(new_runs[0]["status"])
Auth & Connection Notes
| Field | Value |
|---|
| Auth header | x-api-key: <JWT> — not Authorization: Bearer |
| Token format | Plain JWT — do not strip, alter, or prefix it |
| Timeout | Use ≥ 120 s for get_live_flow_run_action_outputs (large outputs) |
| Environment name | Default-<tenant-guid> (find it via list_live_environments or list_live_flows response) |
Reference Files
More Capabilities
For diagnosing failing flows end-to-end → load the flowstudio-power-automate-debug skill.
For building and deploying new flows → load the flowstudio-power-automate-build skill.