npx skills add https://github.com/github/awesome-copilot --skill flowstudio-power-automate-mcpHow Flowstudio Power Automate Mcp fits into a Paperclip company.
Flowstudio Power Automate Mcp drops into any Paperclip agent that handles this kind of work. Assign it to a specialist inside a pre-configured PaperclipOrg company and the skill becomes available on every heartbeat — no prompt engineering, no tool wiring.
Pre-configured AI company — 18 agents, 18 skills, one-time purchase.
SKILL.md463 linesExpandCollapse
---name: flowstudio-power-automate-mcpdescription: >- 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.appmetadata: 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 Automatecloud flows programmatically through a **FlowStudio MCP server** — no browser,no UI, no manual steps. > **Real debugging examples**: [Expression error in child flow](https://github.com/ninihen1/power-automate-mcp-skills/blob/main/examples/fix-expression-error.md) |> [Data entry, not a flow bug](https://github.com/ninihen1/power-automate-mcp-skills/blob/main/examples/data-not-flow.md) |> [Null value crashes child flow](https://github.com/ninihen1/power-automate-mcp-skills/blob/main/examples/null-child-flow.md) > **Requires:** A [FlowStudio](https://mcp.flowstudio.app) 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 **Pythonwith `urllib.request`** (stdlib — no `pip install` needed). **Node.js** is anequally valid choice: `fetch` is built-in from Node 18+, JSON handling isnative, and the async/await model maps cleanly onto the request-response patternof MCP tool calls — making it a natural fit for teams already working in aJavaScript/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 getboth the fast Azure-table store (cached snapshot data + governance metadata) andfull 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 monitoredsnapshot 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 seeexactly which tool names are available (names may vary by server version): ```pythonimport 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: ```pythonimport 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](https://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): ```jsconst 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 ```pythonENV = "Default-<tenant-guid>" result = mcp("list_live_flows", {"environmentName": ENV})# Returns wrapper object:# {"mode": "owner", "flows": [{"id": "0757041a-...", "displayName": "My Flow",# "state": "Started", "triggerType": "Request", ...}], "totalCount": 42, "error": null}for f in result["flows"]: FLOW_ID = f["id"] # plain UUID — use directly as flowName print(FLOW_ID, "|", f["displayName"], "|", f["state"])``` --- ## Read a Flow Definition ```pythonFLOW = "<flow-uuid>" flow = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW}) # Display name and stateprint(flow["properties"]["displayName"])print(flow["properties"]["state"]) # List all action namesactions = flow["properties"]["definition"]["actions"]print("Actions:", list(actions.keys())) # Inspect one action's expressionprint(actions["Compose_Filter"]["inputs"])``` --- ## Check Run History ```python# Most recent runs (newest first)runs = mcp("get_live_flow_runs", {"environmentName": ENV, "flowName": FLOW, "top": 5})# Returns direct array:# [{"name": "08584296068667933411438594643CU15",# "status": "Failed",# "startTime": "2026-02-25T06:13:38.6910688Z",# "endTime": "2026-02-25T06:15:24.1995008Z",# "triggerName": "manual",# "error": {"code": "ActionFailed", "message": "An action failed..."}},# {"name": "08584296028664130474944675379CU26",# "status": "Succeeded", "error": null, ...}] for r in runs: print(r["name"], r["status"]) # Get the name of the first failed runrun_id = next((r["name"] for r in runs if r["status"] == "Failed"), None)``` --- ## Inspect an Action's Output ```pythonrun_id = runs[0]["name"] out = mcp("get_live_flow_run_action_outputs", { "environmentName": ENV, "flowName": FLOW, "runName": run_id, "actionName": "Get_Customer_Record" # exact action name from the definition})print(json.dumps(out, indent=2))``` --- ## Get a Run's Error ```pythonerr = mcp("get_live_flow_run_error", { "environmentName": ENV, "flowName": FLOW, "runName": run_id})# Returns:# {"runName": "08584296068...",# "failedActions": [# {"actionName": "HTTP_find_AD_User_by_Name", "status": "Failed",# "code": "NotSpecified", "startTime": "...", "endTime": "..."},# {"actionName": "Scope_prepare_workers", "status": "Failed",# "error": {"code": "ActionFailed", "message": "An action failed..."}}# ],# "allActions": [# {"actionName": "Apply_to_each", "status": "Skipped"},# {"actionName": "Compose_WeekEnd", "status": "Succeeded"},# ...# ]} # The ROOT cause is usually the deepest entry in failedActions:root = err["failedActions"][-1]print(f"Root failure: {root['actionName']} → {root['code']}")``` --- ## Resubmit a Run ```pythonresult = mcp("resubmit_live_flow_run", { "environmentName": ENV, "flowName": FLOW, "runName": run_id})print(result) # {"resubmitted": true, "triggerName": "..."}``` --- ## Cancel a Running Run ```pythonmcp("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 ```python# ── 1. Find 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"] # ── 2. Get the most recent failed run ────────────────────────────────────runs = mcp("get_live_flow_runs", {"environmentName": ENV, "flowName": FLOW_ID, "top": 5})# [{"name": "08584296068...", "status": "Failed", ...}, ...]RUN_ID = next(r["name"] for r in runs if r["status"] == "Failed") # ── 3. Get per-action failure breakdown ──────────────────────────────────err = mcp("get_live_flow_run_error", {"environmentName": ENV, "flowName": FLOW_ID, "runName": RUN_ID})# {"failedActions": [{"actionName": "HTTP_find_AD_User_by_Name", "code": "NotSpecified",...}], ...}root_action = err["failedActions"][-1]["actionName"]print(f"Root failure: {root_action}") # ── 4. Read the definition and inspect the failing action's expression ───defn = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW_ID})acts = defn["properties"]["definition"]["actions"]print("Failing action inputs:", acts[root_action]["inputs"]) # ── 5. Inspect the prior action's output to find the null ────────────────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") # ── 6. Apply the fix ─────────────────────────────────────────────────────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']}"# ⚠️ error key is always present — only fail if it is NOT None # ── 7. Resubmit and verify ───────────────────────────────────────────────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"]) # Succeeded = done``` --- ## 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 - [MCP-BOOTSTRAP.md](references/MCP-BOOTSTRAP.md) — endpoint, auth, request/response format (read this first)- [tool-reference.md](references/tool-reference.md) — response shapes and behavioral notes (parameters are in `tools/list`)- [action-types.md](references/action-types.md) — Power Automate action type patterns- [connection-references.md](references/connection-references.md) — connector reference guide --- ## 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.Add Educational Comments
Takes any code file and transforms it into a teaching resource by adding educational comments that explain syntax, design choices, and language concepts. Automa
Agent Governance
When your AI agents start calling APIs, touching databases, or executing shell commands, you need guardrails before something goes sideways. This gives you comp
Agentic Eval
Implements self-critique loops where Claude generates output, evaluates it against your criteria, then refines based on its own feedback. Includes evaluator-opt