feat(flowstudio): align Power Automate skills with MCP server v1.1.6 (#1564)

Foundation skill (flowstudio-power-automate-mcp) rewritten to use the
server's new tool_search and list_skills meta-tools (v1.1.5+) for
discovery instead of cataloging every tool by hand. Cut from 519 to
295 lines. New "Which Skill to Use When" intent-keyed decision tree
points at the four specialized skills.

Build/debug/governance/monitoring updated for use-case framing. Tools
that genuinely cross tiers (e.g. debug skill borrowing
get_store_flow_summary) are correct when the workflow needs them — the
split between skills is by use-case intent, not by tool partition.

Build skill: new Step 3a Resolving Dynamic Connector Values covers
get_live_dynamic_options outer-parameter auto-bridge (v1.1.6+) and the
AadGraph user-picker fallback via shared_office365users.SearchUserV2
(replaces broken builtInOperation:AadGraph.GetUsers).

Debug skill: Outlook user-picker failure note pointing at the fallback.

Monitoring skill description disambiguates from the server's monitor-flow
tool bundle (runtime control of a single flow) — this skill is
tenant-wide health analytics over the cached store.

All 5 skills validate via npm run skill:validate; line endings LF only;
codespell clean; auto-regenerated docs/README.skills.md included.
This commit is contained in:
Catherine Han
2026-04-30 10:29:31 +10:00
committed by GitHub
parent e5cc566b7a
commit fe4436cbe6
7 changed files with 280 additions and 354 deletions

View File

@@ -24,7 +24,7 @@ Step-by-step guide for constructing and deploying Power Automate cloud flows
programmatically 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.
See the `power-automate-mcp` skill for connection setup.
Subscribe at https://mcp.flowstudio.app
---
@@ -192,7 +192,7 @@ for connector in connectors_needed:
> connection_references = ref_flow["properties"]["connectionReferences"]
> ```
See the `flowstudio-power-automate-mcp` skill's **connection-references.md** reference
See the `power-automate-mcp` skill's **connection-references.md** reference
for the full connection reference structure.
---
@@ -219,6 +219,59 @@ definition = {
---
## Step 3a — Resolving Dynamic Connector Values
When an action input needs a value picked from a connector dropdown (e.g. a
SharePoint list ID, a Dataverse table name, a user's Azure AD UPN), use
`get_live_dynamic_options` to resolve it via MCP rather than hardcoding GUIDs.
```python
# Resolve a SharePoint list by site
opts = mcp("get_live_dynamic_options",
environmentName=ENV,
connectorName="shared_sharepointonline",
operationId="GetTables",
parameters={"dataset": "https://contoso.sharepoint.com/sites/HR"})
# opts["value"] → [{"Name": "<list-guid>", "DisplayName": "Employees"}, ...]
```
> **Outer-parameter auto-bridge** (server v1.1.6+): you can pass arbitrary outer
> parameters directly in `parameters` — the server now synthesizes the
> `parameterReference` mapping that PA's listEnum requires. Before 1.1.6 you had
> to declare `dynamicMetadata.parameters: {paramName: {parameterReference: "name"}}`
> manually or get `IncorrectDynamicInvokeParameter`. This makes it practical to
> invoke arbitrary connector operations through the dynamic-options pipeline
> (e.g. `shared_office365users.SearchUserV2` for AAD user lookup).
### AadGraph user-picker fallback
For Outlook actions like `GetEmailsV3` (parameters `mailboxAddress`, `to`, `cc`,
`from`), PA's listEnum uses `builtInOperation:AadGraph.GetUsers` — which is
broken and returns `DynamicListValuesUndefinedOrInvalid` for every call.
`describe_live_connector` (v1.1.6+) detects these parameters and returns a
structured `fallback` field on each affected parameter pointing at a working
alternative. **Use `shared_office365users.SearchUserV2`** to resolve the same
AAD user shape `{value: [{id, displayName, mail, userPrincipalName, ...}]}`:
```python
# Borrow a shared_office365users connection (any active one will do)
conn = next(c for c in conn_map if "office365users" in c)
users = mcp("get_live_dynamic_options",
environmentName=ENV,
connectorName="shared_office365users",
connectionName=conn_map[conn], # see Step 2a
operationId="SearchUserV2",
parameters={"searchTerm": "john", "top": 10})
# users["value"] → [{"Id": "...", "DisplayName": "John Smith", "Mail": "..."}, ...]
```
Then plug the resolved `Mail` value into the Outlook action's parameter — no
need to call `AadGraph.GetUsers` directly.
---
## Step 4 — Deploy (Create or Update)
`update_live_flow` handles both creation and updates in a single tool.
@@ -403,7 +456,7 @@ if run["status"] == "Failed":
root = err["failedActions"][-1]
print(f"Root cause: {root['actionName']}{root.get('code')}")
# Debug and fix the definition before proceeding
# See flowstudio-power-automate-debug skill for full diagnosis workflow
# See power-automate-debug skill for full diagnosis workflow
```
#### 7c — Swap to the production trigger
@@ -475,5 +528,5 @@ The `body/recipient` parameter format depends on the `location` value:
## Related Skills
- `flowstudio-power-automate-mcp`Core connection setup and tool reference
- `flowstudio-power-automate-debug` — Debug failing flows after deployment
- `power-automate-mcp`Foundation skill: connection setup, MCP helper, tool discovery
- `power-automate-debug` — Debug failing flows after deployment

View File

@@ -28,7 +28,7 @@ cloud flows through the FlowStudio MCP server.
> [Null value crashes child flow](https://github.com/ninihen1/power-automate-mcp-skills/blob/main/examples/null-child-flow.md)
**Prerequisite**: A FlowStudio MCP server must be reachable with a valid JWT.
See the `flowstudio-power-automate-mcp` skill for connection setup.
See the `power-automate-mcp` skill for connection setup.
Subscribe at https://mcp.flowstudio.app
---
@@ -309,6 +309,18 @@ print(json.dumps(out['outputs']['body'], indent=2)[:500])
Look for `ConnectionAuthorizationFailed` — the connection owner must match the
service account running the flow. Cannot fix via API; fix in PA designer.
### Outlook user-picker failures (`DynamicListValuesUndefinedOrInvalid`)
Outlook actions like `GetEmailsV3` use parameters (`mailboxAddress`, `to`, `cc`,
`from`) whose dropdown is backed by `builtInOperation:AadGraph.GetUsers` — which
is broken at the PA listEnum layer and always returns
`DynamicListValuesUndefinedOrInvalid`. This shows up when an agent rebuilds or
modifies an Outlook action via `update_live_flow` and tries to resolve a user
through dynamic options. **Don't fix it by retrying AadGraph** — switch to
`shared_office365users.SearchUserV2` instead (returns the same AAD user shape).
See the `power-automate-build` skill, **Step 3a — Resolving Dynamic Connector
Values**, for the working pattern. `describe_live_connector` (v1.1.6+) returns
this fallback as a structured `fallback` field on the affected parameter.
---
## Step 8 — Apply the Fix
@@ -421,5 +433,5 @@ print(f"Status: {result['responseStatus']}, Body: {result.get('responseBody')}")
## Related Skills
- `flowstudio-power-automate-mcp`Core connection setup and operation reference
- `flowstudio-power-automate-build` — Build and deploy new flows
- `power-automate-mcp`Foundation skill: connection setup, MCP helper, tool discovery
- `power-automate-build` — Build and deploy new flows

View File

@@ -26,14 +26,27 @@ Classify, tag, and govern Power Automate flows at scale through the FlowStudio
MCP **cached store** — without Dataverse, without the CoE Starter Kit, and
without the Power Automate portal.
This skill uses `update_store_flow` to write governance metadata and the
monitoring tools (`list_store_flows`, `get_store_flow`, `list_store_makers`,
etc.) to read tenant state. For monitoring and health-check workflows, see
the `flowstudio-power-automate-monitoring` skill.
This skill uses the same `store_*` tool family as `power-automate-monitoring`,
but with a different *intent*: governance writes metadata (`update_store_flow`)
and reads for *audit and classification* outcomes. Monitoring reads the same
tools for *operational health* outcomes. Don't try to memorize which skill
"owns" which tool — pick by what the user is doing. For health checks and
failure-rate dashboards, load `power-automate-monitoring` instead.
> **Start every session with `tools/list`** to confirm tool names and parameters.
> This skill covers workflows and patterns — things `tools/list` cannot tell you.
> If this document disagrees with `tools/list` or a real API response, the API wins.
> **⚠️ Pro+ subscription required.** This skill calls `store_*` tools that
> only work for FlowStudio for Teams or MCP Pro+ subscribers.
>
> **If the user does not have Pro+ access:** the first `store_*` tool call
> will return a 403/404 error. When that happens:
> 1. STOP calling store tools
> 2. Tell the user governance features require a Pro+ subscription
> 3. Link them to https://mcp.flowstudio.app/pricing
>
> **Discovery:** load tool schemas via the meta-tools rather than `tools/list` —
> call `tool_search` with `query: "skill:governance"` for the canonical bundle,
> or `query: "select:update_store_flow"` for a single tool. This skill covers
> workflow patterns and field semantics — things `tool_search` cannot tell you.
> If this document disagrees with a real API response, the API wins.
---
@@ -498,7 +511,7 @@ Fields marked with `*` are also available on `list_store_flows` (cheaper).
## Related Skills
- `flowstudio-power-automate-monitoring` — Health checks, failure rates, inventory (read-only)
- `flowstudio-power-automate-mcp`Core connection setup, live tool reference
- `flowstudio-power-automate-debug` — Deep diagnosis with action-level inputs/outputs
- `flowstudio-power-automate-build` — Build and deploy flow definitions
- `power-automate-monitoring` — Health checks, failure rates, inventory (read-only)
- `power-automate-mcp`Foundation skill: connection setup, MCP helper, tool discovery
- `power-automate-debug` — Deep diagnosis with action-level inputs/outputs
- `power-automate-build` — Build and deploy flow definitions

View File

@@ -1,15 +1,14 @@
---
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
Foundation skill for Power Automate via FlowStudio MCP — auth setup, the
reusable MCP helper (Python + Node.js), tool discovery via `list_skills` /
`tool_search`, and oversized-response handling. Load this skill first when
connecting an agent to Power Automate. For specialized workflows, load
`power-automate-build`, `power-automate-debug`, `power-automate-monitoring`
(Pro+), or `power-automate-governance` (Pro+) — each contains the workflow
narrative, this skill provides the plumbing they all rely on. Requires a
FlowStudio MCP subscription or compatible server — see https://mcp.flowstudio.app
metadata:
openclaw:
requires:
@@ -19,11 +18,12 @@ metadata:
homepage: https://mcp.flowstudio.app
---
# Power Automate via FlowStudio MCP
# Power Automate via FlowStudio MCP — Foundation
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.
This skill is the **plumbing layer**. It gives an AI agent a reliable way to
talk to a FlowStudio MCP server, discover what tools are available, and handle
the responses cleanly. The actual workflow narratives live in four specialized
skills that all build on this one.
> **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) |
@@ -37,141 +37,95 @@ no UI, no manual steps.
---
## Which Skill to Use When
Skills are organized by **use-case intent**, not by which tools they call.
Multiple skills reuse the same underlying tools — pick by what the user is
trying to accomplish.
| The user wants to… | Load this skill |
|---|---|
| Make or change a flow (build new, modify existing, fix a bug, deploy) | **`power-automate-build`** |
| Diagnose why a flow failed (root cause analysis on a failing run) | **`power-automate-debug`** |
| See tenant-wide flow health, failure rates, asset inventory | **`power-automate-monitoring`** *(Pro+)* |
| Tag, audit, classify, score, or offboard flows | **`power-automate-governance`** *(Pro+)* |
| Just connect, set up auth, write the helper, parse responses | this skill (foundation) |
**Same tools, different lenses.** `power-automate-build` and `power-automate-debug`
both call `update_live_flow`, `get_live_flow`, and the run-error tools — they
differ in *direction* (forward vs backward) and *intent* (compose vs diagnose).
`power-automate-monitoring` and `power-automate-governance` both call the Store
tools — they differ in *audience* (ops vs compliance) and *outcome* (read
health vs write metadata). Don't try to memorize "which tools belong to which
skill"; pick the skill by what the user is doing.
---
## 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 |
| 2 | **`tool_search` / `list_skills`** | Authoritative tool schemas, parameter names, types, required flags |
| 3 | **SKILL docs & reference files** | Workflow narrative, response shapes, non-obvious behaviors |
> **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.
If documentation disagrees with a real API response, the API wins. Tool schemas
in this skill (or any other) may lag the server — call `tool_search` to confirm
the current shape before invoking a tool you haven't used recently.
---
## How Agents Discover Tools
The FlowStudio MCP server (v1.1.5+) exposes two **non-billable** meta-tools that
let an agent load only the tools relevant to the current task. Use these in
preference to `tools/list` (which loads all 30+ schemas at once) or guessing
tool names.
| Meta-tool | When to call |
|---|---|
| `list_skills` | Cold start — see the available bundles (`build-flow`, `debug-flow`, `monitor-flow`, `discover`, `governance`) and pick one |
| `tool_search` with `query: "skill:<name>"` | Load the full schema set for one bundle (e.g. `skill:debug-flow`) |
| `tool_search` with `query: "select:tool1,tool2"` | Load specific tools by name (e.g. when chaining across bundles) |
| `tool_search` with `query: "<keywords>"` | Free-text search when the user request is ambiguous (e.g. `"cancel run"`) |
The server's `tool_search` bundles are intentionally **narrower than this
skill family** — they're starter packs of the most-likely-needed tools per
intent. A workflow skill (e.g. `power-automate-debug`) may pull a bundle and
then call `tool_search` again for additional tools as the workflow progresses.
```python
# Cold start — pick a bundle by intent
skills = mcp("list_skills", {})
# [{"name": "debug-flow", "description": "Investigate why a flow is failing...",
# "tools": ["get_live_flow_runs", "get_live_flow_run_error", ...]}, ...]
# Load schemas for the bundle
debug_tools = mcp("tool_search", {"query": "skill:debug-flow"})
```
---
## 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.
All examples in this skill family 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 async/await
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 |
| **Python** | Recommended | Clean JSON handling, no escaping issues, all skill examples use it |
| **Node.js (≥ 18)** | Recommended | Native `fetch` + `JSON.stringify`/`JSON.parse`; no extra packages |
| PowerShell | Avoid for flow operations | `ConvertTo-Json -Depth` silently truncates nested definitions; quoting and escaping break complex payloads. Acceptable for a quick connectivity smoke-test 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):
```python
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:
@@ -203,7 +157,7 @@ def mcp(tool, args, cid=1):
> **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.
> - `MCP error: {"code": -32602, ...}` → wrong or missing tool arguments. Call `tool_search` with `select:<toolname>` to confirm the schema.
---
@@ -246,192 +200,78 @@ async function mcp(tool, args, cid = 1) {
---
## List Flows
## Verify the Connection
A 3-line smoke test that confirms the token, endpoint, and helper all work:
```python
ENV = "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"])
skills = mcp("list_skills", {})
print(f"Connected — {len(skills)} skill bundles available:",
[s["name"] for s in skills])
```
Expected output:
```text
Connected — 5 skill bundles available: ['build-flow', 'debug-flow', 'monitor-flow', 'discover', 'governance']
```
If this fails, see the **Common auth errors** note above. If it succeeds, hand
off to the workflow skill matching the user's intent.
---
## Read a Flow Definition
## Handling Oversized Responses
```python
FLOW = "<flow-uuid>"
Some MCP tool responses are large enough to overflow the agent's context window:
flow = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW})
| Tool | Typical size | Cause |
|---|---|---|
| `describe_live_connector` | 100-600 KB | Full Swagger spec for a connector |
| `get_live_flow_run_action_outputs` (no `actionName`) | 50 KB several MB | All actions × all foreach iterations |
| `get_live_flow` (large flows) | 50-500 KB | Deeply nested branches |
| `list_live_flows` (large tenants) | 50-200 KB | Hundreds of flow records |
# Display name and state
print(flow["properties"]["displayName"])
print(flow["properties"]["state"])
### When the harness spills to a file
# List all action names
actions = flow["properties"]["definition"]["actions"]
print("Actions:", list(actions.keys()))
Agent harnesses (Claude Code, VS Code Copilot, etc.) save oversized responses
to a temp file (e.g. `tool-results/mcp-flowstudio-describe_live_connector-NNNN.txt`)
and return the path instead of the inline JSON. The file is **double-wrapped**
the outer MCP envelope plus the inner JSON-escaped payload:
# Inspect one action's expression
print(actions["Compose_Filter"]["inputs"])
```text
[{"type":"text","text":"<JSON-escaped payload>"}]
```
---
## Check Run History
Two parses to reach a usable object:
```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 run
run_id = next((r["name"] for r in runs if r["status"] == "Failed"), None)
import json
with open(path) as f:
raw = json.loads(f.read())
payload = json.loads(raw[0]["text"])
```
---
## Inspect an Action's Output
```python
run_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))
```powershell
$payload = ((Get-Content $path -Raw | ConvertFrom-Json)[0].text) | ConvertFrom-Json
```
---
### Rules of thumb
## Get a Run's Error
1. **Extract, don't echo.** Pull the specific field(s) you need (one `operationId`, one action's outputs) and discard the rest before reasoning about it.
2. **Always pass `actionName` to `get_live_flow_run_action_outputs`.** Omitting it fetches every action × every iteration — fine for offline debug scripts, dangerous for an agent that ingests the whole response.
3. **Reuse the spill file within a session.** Refetching the same connector swagger costs 30+ seconds and produces another spill — cache the path.
4. **Don't grep the spill file for JSON keys directly.** Strings are JSON-escaped inside the file (`\"OperationId\":`), so a plain grep for `"OperationId":` will not match. Parse first, then filter.
5. **Summarize tool output to the user.** Echo `name + state + trigger` for flow lists and `actionName + status + code` for run errors — not raw JSON, unless asked.
```python
err = 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"},
# ...
# ]}
# Good — drill into one operation in a connector swagger
conn = mcp("describe_live_connector", {"environmentName": ENV, "connectorName": "shared_sharepointonline"})
op = conn["properties"]["swagger"]["paths"]["/datasets/{dataset}/tables/{table}/items"]["get"]
print(op["operationId"], "", op.get("summary"))
# 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
```python
result = mcp("resubmit_live_flow_run", {
"environmentName": ENV,
"flowName": FLOW,
"runName": run_id
})
print(result) # {"resubmitted": true, "triggerName": "..."}
```
---
## Cancel a Running Run
```python
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
```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
# Bad — keeping the whole 500 KB swagger in context
print(json.dumps(conn, indent=2)) # don't do this
```
---
@@ -450,14 +290,6 @@ print(new_runs[0]["status"]) # Succeeded = done
## 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`)
- [tool-reference.md](references/tool-reference.md) — response shapes and behavioral notes (parameters are in `tool_search`)
- [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.

View File

@@ -1,17 +1,20 @@
---
name: flowstudio-power-automate-monitoring
description: >-
Monitor Power Automate flow health, track failure rates, and inventory tenant
assets using the FlowStudio MCP cached store. The live API only returns
top-level run status. Store tools surface aggregated stats, per-run failure
details with remediation hints, maker activity, and Power Apps inventory —
all from a fast cache with no rate-limit pressure on the PA API.
Load this skill when asked to: check flow health, find failing flows, get
failure rates, review error trends, list all flows with monitoring enabled,
check who built a flow, find inactive makers, inventory Power Apps, see
environment or connection counts, get a flow summary, or any tenant-wide
health overview. Requires a FlowStudio for Teams or MCP Pro+ subscription —
see https://mcp.flowstudio.app
**Pro+ subscription required.** Tenant-wide Power Automate flow health
monitoring, failure rate analytics, and asset inventory using the FlowStudio
MCP cached store. Load this skill ONLY for tenant-wide aggregated views — not
for listing flows in a single environment or debugging a specific run (use
power-automate-mcp or power-automate-debug for those). Not the same as the
server's `monitor-flow` tool bundle (`tool_search query: "skill:monitor-flow"`)
— that bundle is for runtime control of a single flow (start/stop/trigger/
cancel/resubmit); this skill is for tenant-wide health analytics over the
cached store.
Load when asked to: monitor tenant health, get aggregated failure rates over
a time window, review tenant-wide error trends, find inactive makers across
the tenant, inventory all Power Apps in the tenant, compute governance scores,
generate a compliance report, or run a tenant-wide health overview. Requires
a FlowStudio for Teams or MCP Pro+ subscription — see https://mcp.flowstudio.app
metadata:
openclaw:
requires:
@@ -27,13 +30,25 @@ Monitor flow health, track failure rates, and inventory tenant assets through
the FlowStudio MCP **cached store** — fast reads, no PA API rate limits, and
enriched with governance metadata and remediation hints.
> **Requires:** A [FlowStudio for Teams or MCP Pro+](https://mcp.flowstudio.app)
> subscription.
> **⚠️ Pro+ subscription required.** This skill calls `store_*` tools that
> only work for FlowStudio for Teams or MCP Pro+ subscribers.
>
> **Start every session with `tools/list`** to confirm tool names and parameters.
> This skill covers response shapes, behavioral notes, and workflow patterns —
> things `tools/list` cannot tell you. If this document disagrees with
> `tools/list` or a real API response, the API wins.
> **If the user does not have Pro+ access:** the first `store_*` tool call
> will return a 403/404 error. When that happens:
> 1. STOP calling store tools
> 2. Tell the user this feature requires a Pro+ subscription
> 3. Link them to https://mcp.flowstudio.app/pricing
> 4. If their question can be answered with live tools (e.g. "list flows in
> one environment"), offer to use the `power-automate-mcp` skill instead
>
> **Discovery:** load tool schemas via `tool_search` rather than `tools/list` —
> call with `query: "select:list_store_flows,get_store_flow_summary"` for the
> common monitoring tools, or load the full set with `query: "skill:governance"`
> (the server's governance bundle covers most monitoring reads too — this skill
> and `power-automate-governance` share the underlying tool family). This skill
> covers response shapes, behavioral notes, and workflow patterns — things
> `tool_search` cannot tell you. If this document disagrees with a real API
> response, the API wins.
---
@@ -393,7 +408,7 @@ Direct array.
## Related Skills
- `power-automate-mcp`Core connection setup, live tool reference
- `power-automate-mcp`Foundation skill: connection setup, MCP helper, tool discovery
- `power-automate-debug` — Deep diagnosis with action-level inputs/outputs (live API)
- `power-automate-build` — Build and deploy flow definitions
- `power-automate-governance` — Governance metadata, tagging, notification rules, CoE patterns