mirror of
https://github.com/github/awesome-copilot.git
synced 2026-03-12 04:05:12 +00:00
feat: add power-automate-mcp skill (#896)
* feat: add power-automate-mcp skill
Connect to and operate Power Automate cloud flows via a FlowStudio MCP server.
Includes tool reference, action types, connection references, and bootstrap guide.
* fix: rename skill & address review feedback
- Rename power-automate-mcp → flowstudio-power-automate-mcp
- Fix list_live_flows docs: returns wrapper object {mode, flows, totalCount, error}, not direct array
- Fix next() syntax: add parens for generator with default arg
- Add User-Agent header to tools/list discovery example
- Standardize User-Agent to FlowStudio-MCP/1.0 (required by Cloudflare)
- Add environmentName note for list_live_connections (required despite schema)
- Update list_live_flows response shape in tool-reference.md
All response shapes verified against live MCP server.
This commit is contained in:
450
skills/flowstudio-power-automate-mcp/SKILL.md
Normal file
450
skills/flowstudio-power-automate-mcp/SKILL.md
Normal file
@@ -0,0 +1,450 @@
|
||||
---
|
||||
name: flowstudio-power-automate-mcp
|
||||
description: >-
|
||||
Connect to and operate Power Automate cloud flows via a FlowStudio MCP server.
|
||||
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
|
||||
---
|
||||
|
||||
# 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.
|
||||
|
||||
> **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 **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):
|
||||
|
||||
```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:
|
||||
|
||||
```python
|
||||
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](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):
|
||||
|
||||
```js
|
||||
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
|
||||
|
||||
```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"])
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Read a Flow Definition
|
||||
|
||||
```python
|
||||
FLOW = "<flow-uuid>"
|
||||
|
||||
flow = mcp("get_live_flow", {"environmentName": ENV, "flowName": FLOW})
|
||||
|
||||
# Display name and state
|
||||
print(flow["properties"]["displayName"])
|
||||
print(flow["properties"]["state"])
|
||||
|
||||
# List all action names
|
||||
actions = flow["properties"]["definition"]["actions"]
|
||||
print("Actions:", list(actions.keys()))
|
||||
|
||||
# Inspect one action's expression
|
||||
print(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 run
|
||||
run_id = next((r["name"] for r in runs if r["status"] == "Failed"), None)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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))
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Get a Run's Error
|
||||
|
||||
```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"},
|
||||
# ...
|
||||
# ]}
|
||||
|
||||
# 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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 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 `power-automate-debug` skill.
|
||||
|
||||
For **building and deploying new flows** → load the `power-automate-build` skill.
|
||||
@@ -0,0 +1,53 @@
|
||||
# MCP Bootstrap — Quick Reference
|
||||
|
||||
Everything an agent needs to start calling the FlowStudio MCP server.
|
||||
|
||||
```
|
||||
Endpoint: https://mcp.flowstudio.app/mcp
|
||||
Protocol: JSON-RPC 2.0 over HTTP POST
|
||||
Transport: Streamable HTTP — single POST per request, no SSE, no WebSocket
|
||||
Auth: x-api-key header with JWT token (NOT Bearer)
|
||||
```
|
||||
|
||||
## Required Headers
|
||||
|
||||
```
|
||||
Content-Type: application/json
|
||||
x-api-key: <token>
|
||||
User-Agent: FlowStudio-MCP/1.0 ← required, or Cloudflare blocks you
|
||||
```
|
||||
|
||||
## Step 1 — Discover Tools
|
||||
|
||||
```json
|
||||
POST {"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}
|
||||
```
|
||||
|
||||
Returns all tools with names, descriptions, and input schemas.
|
||||
Free — not counted against plan limits.
|
||||
|
||||
## Step 2 — Call a Tool
|
||||
|
||||
```json
|
||||
POST {"jsonrpc":"2.0","id":1,"method":"tools/call",
|
||||
"params":{"name":"<tool_name>","arguments":{...}}}
|
||||
```
|
||||
|
||||
## Response Shape
|
||||
|
||||
```
|
||||
Success → {"result":{"content":[{"type":"text","text":"<JSON string>"}]}}
|
||||
Error → {"result":{"content":[{"type":"text","text":"{\"error\":{...}}"}]}}
|
||||
```
|
||||
|
||||
Always parse `result.content[0].text` as JSON to get the actual data.
|
||||
|
||||
## Key Tips
|
||||
|
||||
- Tool results are JSON strings inside the text field — **double-parse needed**
|
||||
- `"error"` field in parsed body: `null` = success, object = failure
|
||||
- `environmentName` is required for most tools, but **not** for:
|
||||
`list_live_environments`, `list_live_connections`, `list_store_flows`,
|
||||
`list_store_environments`, `list_store_makers`, `get_store_maker`,
|
||||
`list_store_power_apps`, `list_store_connections`
|
||||
- When in doubt, check the `required` array in each tool's schema from `tools/list`
|
||||
@@ -0,0 +1,79 @@
|
||||
# FlowStudio MCP — Action Types Reference
|
||||
|
||||
Compact lookup for recognising action types returned by `get_live_flow`.
|
||||
Use this to **read and understand** existing flow definitions.
|
||||
|
||||
> For full copy-paste construction patterns, see the `power-automate-build` skill.
|
||||
|
||||
---
|
||||
|
||||
## How to Read a Flow Definition
|
||||
|
||||
Every action has `"type"`, `"runAfter"`, and `"inputs"`. The `runAfter` object
|
||||
declares dependencies: `{"Previous": ["Succeeded"]}`. Valid statuses:
|
||||
`Succeeded`, `Failed`, `Skipped`, `TimedOut`.
|
||||
|
||||
---
|
||||
|
||||
## Action Type Quick Reference
|
||||
|
||||
| Type | Purpose | Key fields to inspect | Output reference |
|
||||
|---|---|---|---|
|
||||
| `Compose` | Store/transform a value | `inputs` (any expression) | `outputs('Name')` |
|
||||
| `InitializeVariable` | Declare a variable | `inputs.variables[].{name, type, value}` | `variables('name')` |
|
||||
| `SetVariable` | Update a variable | `inputs.{name, value}` | `variables('name')` |
|
||||
| `IncrementVariable` | Increment a numeric variable | `inputs.{name, value}` | `variables('name')` |
|
||||
| `AppendToArrayVariable` | Push to an array variable | `inputs.{name, value}` | `variables('name')` |
|
||||
| `If` | Conditional branch | `expression.and/or`, `actions`, `else.actions` | — |
|
||||
| `Switch` | Multi-way branch | `expression`, `cases.{case, actions}`, `default` | — |
|
||||
| `Foreach` | Loop over array | `foreach`, `actions`, `operationOptions` | `item()` / `items('Name')` |
|
||||
| `Until` | Loop until condition | `expression`, `limit.{count, timeout}`, `actions` | — |
|
||||
| `Wait` | Delay | `inputs.interval.{count, unit}` | — |
|
||||
| `Scope` | Group / try-catch | `actions` (nested action map) | `result('Name')` |
|
||||
| `Terminate` | End run | `inputs.{runStatus, runError}` | — |
|
||||
| `OpenApiConnection` | Connector call (SP, Outlook, Teams…) | `inputs.host.{apiId, connectionName, operationId}`, `inputs.parameters` | `outputs('Name')?['body/...']` |
|
||||
| `OpenApiConnectionWebhook` | Webhook wait (approvals, adaptive cards) | same as above | `body('Name')?['...']` |
|
||||
| `Http` | External HTTP call | `inputs.{method, uri, headers, body}` | `outputs('Name')?['body']` |
|
||||
| `Response` | Return to HTTP caller | `inputs.{statusCode, headers, body}` | — |
|
||||
| `Query` | Filter array | `inputs.{from, where}` | `body('Name')` (filtered array) |
|
||||
| `Select` | Reshape/project array | `inputs.{from, select}` | `body('Name')` (projected array) |
|
||||
| `Table` | Array → CSV/HTML string | `inputs.{from, format, columns}` | `body('Name')` (string) |
|
||||
| `ParseJson` | Parse JSON with schema | `inputs.{content, schema}` | `body('Name')?['field']` |
|
||||
| `Expression` | Built-in function (e.g. ConvertTimeZone) | `kind`, `inputs` | `body('Name')` |
|
||||
|
||||
---
|
||||
|
||||
## Connector Identification
|
||||
|
||||
When you see `type: OpenApiConnection`, identify the connector from `host.apiId`:
|
||||
|
||||
| apiId suffix | Connector |
|
||||
|---|---|
|
||||
| `shared_sharepointonline` | SharePoint |
|
||||
| `shared_office365` | Outlook / Office 365 |
|
||||
| `shared_teams` | Microsoft Teams |
|
||||
| `shared_approvals` | Approvals |
|
||||
| `shared_office365users` | Office 365 Users |
|
||||
| `shared_flowmanagement` | Flow Management |
|
||||
|
||||
The `operationId` tells you the specific operation (e.g. `GetItems`, `SendEmailV2`,
|
||||
`PostMessageToConversation`). The `connectionName` maps to a GUID in
|
||||
`properties.connectionReferences`.
|
||||
|
||||
---
|
||||
|
||||
## Common Expressions (Reading Cheat Sheet)
|
||||
|
||||
| Expression | Meaning |
|
||||
|---|---|
|
||||
| `@outputs('X')?['body/value']` | Array result from connector action X |
|
||||
| `@body('X')` | Direct body of action X (Query, Select, ParseJson) |
|
||||
| `@item()?['Field']` | Current loop item's field |
|
||||
| `@triggerBody()?['Field']` | Trigger payload field |
|
||||
| `@variables('name')` | Variable value |
|
||||
| `@coalesce(a, b)` | First non-null of a, b |
|
||||
| `@first(array)` | First element (null if empty) |
|
||||
| `@length(array)` | Array count |
|
||||
| `@empty(value)` | True if null/empty string/empty array |
|
||||
| `@union(a, b)` | Merge arrays — **first wins** on duplicates |
|
||||
| `@result('Scope')` | Array of action outcomes inside a Scope |
|
||||
@@ -0,0 +1,115 @@
|
||||
# FlowStudio MCP — Connection References
|
||||
|
||||
Connection references wire a flow's connector actions to real authenticated
|
||||
connections in the Power Platform. They are required whenever you call
|
||||
`update_live_flow` with a definition that uses connector actions.
|
||||
|
||||
---
|
||||
|
||||
## Structure in a Flow Definition
|
||||
|
||||
```json
|
||||
{
|
||||
"properties": {
|
||||
"definition": { ... },
|
||||
"connectionReferences": {
|
||||
"shared_sharepointonline": {
|
||||
"connectionName": "shared-sharepointonl-62599557c-1f33-4aec-b4c0-a6e4afcae3be",
|
||||
"id": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline",
|
||||
"displayName": "SharePoint"
|
||||
},
|
||||
"shared_office365": {
|
||||
"connectionName": "shared-office365-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
||||
"id": "/providers/Microsoft.PowerApps/apis/shared_office365",
|
||||
"displayName": "Office 365 Outlook"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Keys are **logical reference names** (e.g. `shared_sharepointonline`).
|
||||
These match the `connectionName` field inside each action's `host` block.
|
||||
|
||||
---
|
||||
|
||||
## Finding Connection GUIDs
|
||||
|
||||
Call `get_live_flow` on **any existing flow** that uses the same connection
|
||||
and copy the `connectionReferences` block. The GUID after the connector prefix is
|
||||
the connection instance owned by the authenticating user.
|
||||
|
||||
```python
|
||||
flow = mcp("get_live_flow", environmentName=ENV, flowName=EXISTING_FLOW_ID)
|
||||
conn_refs = flow["properties"]["connectionReferences"]
|
||||
# conn_refs["shared_sharepointonline"]["connectionName"]
|
||||
# → "shared-sharepointonl-62599557c-1f33-4aec-b4c0-a6e4afcae3be"
|
||||
```
|
||||
|
||||
> ⚠️ Connection references are **user-scoped**. If a connection is owned
|
||||
> by another account, `update_live_flow` will return 403
|
||||
> `ConnectionAuthorizationFailed`. You must use a connection belonging to
|
||||
> the account whose token is in the `x-api-key` header.
|
||||
|
||||
---
|
||||
|
||||
## Passing `connectionReferences` to `update_live_flow`
|
||||
|
||||
```python
|
||||
result = mcp("update_live_flow",
|
||||
environmentName=ENV,
|
||||
flowName=FLOW_ID,
|
||||
definition=modified_definition,
|
||||
connectionReferences={
|
||||
"shared_sharepointonline": {
|
||||
"connectionName": "shared-sharepointonl-62599557c-1f33-4aec-b4c0-a6e4afcae3be",
|
||||
"id": "/providers/Microsoft.PowerApps/apis/shared_sharepointonline"
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Only include connections that the definition actually uses.
|
||||
|
||||
---
|
||||
|
||||
## Common Connector API IDs
|
||||
|
||||
| Service | API ID |
|
||||
|---|---|
|
||||
| SharePoint Online | `/providers/Microsoft.PowerApps/apis/shared_sharepointonline` |
|
||||
| Office 365 Outlook | `/providers/Microsoft.PowerApps/apis/shared_office365` |
|
||||
| Microsoft Teams | `/providers/Microsoft.PowerApps/apis/shared_teams` |
|
||||
| OneDrive for Business | `/providers/Microsoft.PowerApps/apis/shared_onedriveforbusiness` |
|
||||
| Azure AD | `/providers/Microsoft.PowerApps/apis/shared_azuread` |
|
||||
| HTTP with Azure AD | `/providers/Microsoft.PowerApps/apis/shared_webcontents` |
|
||||
| SQL Server | `/providers/Microsoft.PowerApps/apis/shared_sql` |
|
||||
| Dataverse | `/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps` |
|
||||
| Azure Blob Storage | `/providers/Microsoft.PowerApps/apis/shared_azureblob` |
|
||||
| Approvals | `/providers/Microsoft.PowerApps/apis/shared_approvals` |
|
||||
| Office 365 Users | `/providers/Microsoft.PowerApps/apis/shared_office365users` |
|
||||
| Flow Management | `/providers/Microsoft.PowerApps/apis/shared_flowmanagement` |
|
||||
|
||||
---
|
||||
|
||||
## Teams Adaptive Card Dual-Connection Requirement
|
||||
|
||||
Flows that send adaptive cards **and** post follow-up messages require two
|
||||
separate Teams connections:
|
||||
|
||||
```json
|
||||
"connectionReferences": {
|
||||
"shared_teams": {
|
||||
"connectionName": "shared-teams-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
|
||||
"id": "/providers/Microsoft.PowerApps/apis/shared_teams"
|
||||
},
|
||||
"shared_teams_1": {
|
||||
"connectionName": "shared-teams-yyyyyyyy-yyyy-yyyy-yyyy-yyyyyyyyyyyy",
|
||||
"id": "/providers/Microsoft.PowerApps/apis/shared_teams"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Both can point to the **same underlying Teams account** but must be registered
|
||||
as two distinct connection references. The webhook (`OpenApiConnectionWebhook`)
|
||||
uses `shared_teams` and subsequent message actions use `shared_teams_1`.
|
||||
@@ -0,0 +1,445 @@
|
||||
# FlowStudio MCP — Tool Response Catalog
|
||||
|
||||
Response shapes and behavioral notes for the FlowStudio Power Automate MCP server.
|
||||
|
||||
> **For tool names and parameters**: Always call `tools/list` on the server.
|
||||
> It returns the authoritative, up-to-date schema for every tool.
|
||||
> This document covers what `tools/list` does NOT tell you: **response shapes**
|
||||
> and **non-obvious behaviors** discovered through real usage.
|
||||
|
||||
---
|
||||
|
||||
## 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 | **This document** | Response shapes, behavioral notes, gotchas |
|
||||
|
||||
> If this document disagrees with `tools/list` or real API behavior,
|
||||
> the API wins. Update this document accordingly.
|
||||
|
||||
---
|
||||
|
||||
## Environment & Tenant Discovery
|
||||
|
||||
### `list_live_environments`
|
||||
|
||||
Response: direct array of environments.
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "Default-26e65220-5561-46ef-9783-ce5f20489241",
|
||||
"displayName": "FlowStudio (default)",
|
||||
"sku": "Production",
|
||||
"location": "australia",
|
||||
"state": "Enabled",
|
||||
"isDefault": true,
|
||||
"isAdmin": true,
|
||||
"isMember": true,
|
||||
"createdTime": "2023-08-18T00:41:05Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
> Use the `id` value as `environmentName` in all other tools.
|
||||
|
||||
### `list_store_environments`
|
||||
|
||||
Same shape as `list_live_environments` but read from cache (faster).
|
||||
|
||||
---
|
||||
|
||||
## Connection Discovery
|
||||
|
||||
### `list_live_connections`
|
||||
|
||||
Response: wrapper object with `connections` array.
|
||||
```json
|
||||
{
|
||||
"connections": [
|
||||
{
|
||||
"id": "shared-office365-9f9d2c8e-55f1-49c9-9f9c-1c45d1fbbdce",
|
||||
"displayName": "user@contoso.com",
|
||||
"connectorName": "shared_office365",
|
||||
"createdBy": "User Name",
|
||||
"statuses": [{"status": "Connected"}],
|
||||
"createdTime": "2024-03-12T21:23:55.206815Z"
|
||||
}
|
||||
],
|
||||
"totalCount": 56,
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
> **Key field**: `id` is the `connectionName` value used in `connectionReferences`.
|
||||
>
|
||||
> **Key field**: `connectorName` maps to apiId:
|
||||
> `"/providers/Microsoft.PowerApps/apis/" + connectorName`
|
||||
>
|
||||
> Filter by status: `statuses[0].status == "Connected"`.
|
||||
>
|
||||
> **Note**: `tools/list` marks `environmentName` as optional, but the server
|
||||
> returns `MissingEnvironmentFilter` (HTTP 400) if you omit it. Always pass
|
||||
> `environmentName`.
|
||||
|
||||
### `list_store_connections`
|
||||
|
||||
Same connection data from cache.
|
||||
|
||||
---
|
||||
|
||||
## Flow Discovery & Listing
|
||||
|
||||
### `list_live_flows`
|
||||
|
||||
Response: wrapper object with `flows` array.
|
||||
```json
|
||||
{
|
||||
"mode": "owner",
|
||||
"flows": [
|
||||
{
|
||||
"id": "0757041a-8ef2-cf74-ef06-06881916f371",
|
||||
"displayName": "My Flow",
|
||||
"state": "Started",
|
||||
"triggerType": "Request",
|
||||
"triggerKind": "Http",
|
||||
"createdTime": "2023-08-18T01:18:17Z",
|
||||
"lastModifiedTime": "2023-08-18T12:47:42Z",
|
||||
"owners": "<aad-object-id>",
|
||||
"definitionAvailable": true
|
||||
}
|
||||
],
|
||||
"totalCount": 100,
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
> Access via `result["flows"]`. `id` is a plain UUID --- use directly as `flowName`.
|
||||
>
|
||||
> `mode` indicates the access scope used (`"owner"` or `"admin"`).
|
||||
|
||||
### `list_store_flows`
|
||||
|
||||
Response: **direct array** (no wrapper).
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": "3991358a-f603-e49d-b1ed-a9e4f72e2dcb.0757041a-8ef2-cf74-ef06-06881916f371",
|
||||
"displayName": "Admin | Sync Template v3 (Solutions)",
|
||||
"state": "Started",
|
||||
"triggerType": "OpenApiConnectionWebhook",
|
||||
"environmentName": "3991358a-f603-e49d-b1ed-a9e4f72e2dcb",
|
||||
"runPeriodTotal": 100,
|
||||
"createdTime": "2023-08-18T01:18:17Z",
|
||||
"lastModifiedTime": "2023-08-18T12:47:42Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
> **`id` format**: `envId.flowId` --- split on the first `.` to extract the flow UUID:
|
||||
> `flow_id = item["id"].split(".", 1)[1]`
|
||||
|
||||
### `get_store_flow`
|
||||
|
||||
Response: single flow metadata from cache (selected fields).
|
||||
```json
|
||||
{
|
||||
"id": "envId.flowId",
|
||||
"displayName": "My Flow",
|
||||
"state": "Started",
|
||||
"triggerType": "Recurrence",
|
||||
"runPeriodTotal": 100,
|
||||
"runPeriodFailRate": 0.1,
|
||||
"runPeriodSuccessRate": 0.9,
|
||||
"runPeriodFails": 10,
|
||||
"runPeriodSuccess": 90,
|
||||
"runPeriodDurationAverage": 29410.8,
|
||||
"runPeriodDurationMax": 158900.0,
|
||||
"runError": "{\"code\": \"EACCES\", ...}",
|
||||
"description": "Flow description",
|
||||
"tier": "Premium",
|
||||
"complexity": "{...}",
|
||||
"actions": 42,
|
||||
"connections": ["sharepointonline", "office365"],
|
||||
"owners": ["user@contoso.com"],
|
||||
"createdBy": "user@contoso.com"
|
||||
}
|
||||
```
|
||||
|
||||
> `runPeriodDurationAverage` / `runPeriodDurationMax` are in **milliseconds** (divide by 1000).
|
||||
> `runError` is a **JSON string** --- parse with `json.loads()`.
|
||||
|
||||
---
|
||||
|
||||
## Flow Definition (Live API)
|
||||
|
||||
### `get_live_flow`
|
||||
|
||||
Response: full flow definition from PA API.
|
||||
```json
|
||||
{
|
||||
"name": "<flow-guid>",
|
||||
"properties": {
|
||||
"displayName": "My Flow",
|
||||
"state": "Started",
|
||||
"definition": {
|
||||
"triggers": { "..." },
|
||||
"actions": { "..." },
|
||||
"parameters": { "..." }
|
||||
},
|
||||
"connectionReferences": { "..." }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### `update_live_flow`
|
||||
|
||||
**Create mode**: Omit `flowName` --- creates a new flow. `definition` and `displayName` required.
|
||||
|
||||
**Update mode**: Provide `flowName` --- PATCHes existing flow.
|
||||
|
||||
Response:
|
||||
```json
|
||||
{
|
||||
"created": false,
|
||||
"flowKey": "envId.flowId",
|
||||
"updated": ["definition", "connectionReferences"],
|
||||
"displayName": "My Flow",
|
||||
"state": "Started",
|
||||
"definition": { "...full definition..." },
|
||||
"error": null
|
||||
}
|
||||
```
|
||||
|
||||
> `error` is **always present** but may be `null`. Check `result.get("error") is not None`.
|
||||
>
|
||||
> On create: `created` is the new flow GUID (string). On update: `created` is `false`.
|
||||
>
|
||||
> `description` is **always required** (create and update).
|
||||
|
||||
### `add_live_flow_to_solution`
|
||||
|
||||
Migrates a non-solution flow into a solution. Returns error if already in a solution.
|
||||
|
||||
---
|
||||
|
||||
## Run History & Monitoring
|
||||
|
||||
### `get_live_flow_runs`
|
||||
|
||||
Response: direct array of runs (newest first).
|
||||
```json
|
||||
[{
|
||||
"name": "<run-id>",
|
||||
"status": "Succeeded|Failed|Running|Cancelled",
|
||||
"startTime": "2026-02-25T06:13:38Z",
|
||||
"endTime": "2026-02-25T06:14:02Z",
|
||||
"triggerName": "Recurrence",
|
||||
"error": null
|
||||
}]
|
||||
```
|
||||
|
||||
> `top` defaults to **30** and auto-paginates for higher values. Set `top: 300`
|
||||
> for 24-hour coverage on flows running every 5 minutes.
|
||||
>
|
||||
> Run ID field is **`name`** (not `runName`). Use this value as the `runName`
|
||||
> parameter in other tools.
|
||||
|
||||
### `get_live_flow_run_error`
|
||||
|
||||
Response: structured error breakdown for a failed run.
|
||||
```json
|
||||
{
|
||||
"runName": "08584296068667933411438594643CU15",
|
||||
"failedActions": [
|
||||
{
|
||||
"actionName": "Apply_to_each_prepare_workers",
|
||||
"status": "Failed",
|
||||
"error": {"code": "ActionFailed", "message": "An action failed."},
|
||||
"code": "ActionFailed",
|
||||
"startTime": "2026-02-25T06:13:52Z",
|
||||
"endTime": "2026-02-25T06:15:24Z"
|
||||
},
|
||||
{
|
||||
"actionName": "HTTP_find_AD_User_by_Name",
|
||||
"status": "Failed",
|
||||
"code": "NotSpecified",
|
||||
"startTime": "2026-02-25T06:14:01Z",
|
||||
"endTime": "2026-02-25T06:14:05Z"
|
||||
}
|
||||
],
|
||||
"allActions": [
|
||||
{"actionName": "Apply_to_each", "status": "Skipped"},
|
||||
{"actionName": "Compose_WeekEnd", "status": "Succeeded"},
|
||||
{"actionName": "HTTP_find_AD_User_by_Name", "status": "Failed"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
> `failedActions` is ordered outer-to-inner --- the **last entry is the root cause**.
|
||||
> Use `failedActions[-1]["actionName"]` as the starting point for diagnosis.
|
||||
|
||||
### `get_live_flow_run_action_outputs`
|
||||
|
||||
Response: array of action detail objects.
|
||||
```json
|
||||
[
|
||||
{
|
||||
"actionName": "Compose_WeekEnd_now",
|
||||
"status": "Succeeded",
|
||||
"startTime": "2026-02-25T06:13:52Z",
|
||||
"endTime": "2026-02-25T06:13:52Z",
|
||||
"error": null,
|
||||
"inputs": "Mon, 25 Feb 2026 06:13:52 GMT",
|
||||
"outputs": "Mon, 25 Feb 2026 06:13:52 GMT"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
> **`actionName` is optional**: omit it to return ALL actions in the run;
|
||||
> provide it to return a single-element array for that action only.
|
||||
>
|
||||
> Outputs can be very large (50 MB+) for bulk-data actions. Use 120s+ timeout.
|
||||
|
||||
---
|
||||
|
||||
## Run Control
|
||||
|
||||
### `resubmit_live_flow_run`
|
||||
|
||||
Response: `{ flowKey, resubmitted: true, runName, triggerName }`
|
||||
|
||||
### `cancel_live_flow_run`
|
||||
|
||||
Cancels a `Running` flow run.
|
||||
|
||||
> Do NOT cancel runs waiting for an adaptive card response --- status `Running`
|
||||
> is normal while a Teams card is awaiting user input.
|
||||
|
||||
---
|
||||
|
||||
## HTTP Trigger Tools
|
||||
|
||||
### `get_live_flow_http_schema`
|
||||
|
||||
Response keys:
|
||||
```
|
||||
flowKey - Flow GUID
|
||||
displayName - Flow display name
|
||||
triggerName - Trigger action name (e.g. "manual")
|
||||
triggerType - Trigger type (e.g. "Request")
|
||||
triggerKind - Trigger kind (e.g. "Http")
|
||||
requestMethod - HTTP method (e.g. "POST")
|
||||
relativePath - Relative path configured on the trigger (if any)
|
||||
requestSchema - JSON schema the trigger expects as POST body
|
||||
requestHeaders - Headers the trigger expects
|
||||
responseSchemas - Array of JSON schemas defined on Response action(s)
|
||||
responseSchemaCount - Number of Response actions that define output schemas
|
||||
```
|
||||
|
||||
> The request body schema is in `requestSchema` (not `triggerSchema`).
|
||||
|
||||
### `get_live_flow_trigger_url`
|
||||
|
||||
Returns the signed callback URL for HTTP-triggered flows. Response includes
|
||||
`flowKey`, `triggerName`, `triggerType`, `triggerKind`, `triggerMethod`, `triggerUrl`.
|
||||
|
||||
### `trigger_live_flow`
|
||||
|
||||
Response keys: `flowKey`, `triggerName`, `triggerUrl`, `requiresAadAuth`, `authType`,
|
||||
`responseStatus`, `responseBody`.
|
||||
|
||||
> **Only works for `Request` (HTTP) triggers.** Returns an error for Recurrence
|
||||
> and other trigger types: `"only HTTP Request triggers can be invoked via this tool"`.
|
||||
>
|
||||
> `responseStatus` + `responseBody` contain the flow's Response action output.
|
||||
> AAD-authenticated triggers are handled automatically.
|
||||
|
||||
---
|
||||
|
||||
## Flow State Management
|
||||
|
||||
### `set_store_flow_state`
|
||||
|
||||
Start or stop a flow. Pass `state: "Started"` or `state: "Stopped"`.
|
||||
|
||||
---
|
||||
|
||||
## Store Tools --- FlowStudio for Teams Only
|
||||
|
||||
### `get_store_flow_summary`
|
||||
|
||||
Response: aggregated run statistics.
|
||||
```json
|
||||
{
|
||||
"totalRuns": 100,
|
||||
"failRuns": 10,
|
||||
"failRate": 0.1,
|
||||
"averageDurationSeconds": 29.4,
|
||||
"maxDurationSeconds": 158.9,
|
||||
"firstFailRunRemediation": "<hint or null>"
|
||||
}
|
||||
```
|
||||
|
||||
### `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_trigger_url`
|
||||
|
||||
Trigger URL from cache (instant, no PA API call).
|
||||
|
||||
### `update_store_flow`
|
||||
|
||||
Update governance metadata (description, tags, monitor flag, notification rules, business impact).
|
||||
|
||||
### `list_store_makers` / `get_store_maker`
|
||||
|
||||
Maker (citizen developer) discovery and detail.
|
||||
|
||||
### `list_store_power_apps`
|
||||
|
||||
List all Power Apps canvas apps from the cache.
|
||||
|
||||
---
|
||||
|
||||
## Behavioral Notes
|
||||
|
||||
Non-obvious behaviors discovered through real API usage. These are things
|
||||
`tools/list` cannot tell you.
|
||||
|
||||
### `get_live_flow_run_action_outputs`
|
||||
- **`actionName` is optional**: omit to get all actions, provide to get one.
|
||||
This changes the response from N elements to 1 element (still an array).
|
||||
- Outputs can be 50 MB+ for bulk-data actions --- always use 120s+ timeout.
|
||||
|
||||
### `update_live_flow`
|
||||
- `description` is **always required** (create and update modes).
|
||||
- `error` key is **always present** in response --- `null` means success.
|
||||
Do NOT check `if "error" in result`; check `result.get("error") is not None`.
|
||||
- On create, `created` = new flow GUID (string). On update, `created` = `false`.
|
||||
|
||||
### `trigger_live_flow`
|
||||
- **Only works for HTTP Request triggers.** Returns error for Recurrence, connector,
|
||||
and other trigger types.
|
||||
- AAD-authenticated triggers are handled automatically (impersonated Bearer token).
|
||||
|
||||
### `get_live_flow_runs`
|
||||
- `top` defaults to **30** with automatic pagination for higher values.
|
||||
- Run ID field is `name`, not `runName`. Use this value as `runName` in other tools.
|
||||
- Runs are returned newest-first.
|
||||
|
||||
### Teams `PostMessageToConversation` (via `update_live_flow`)
|
||||
- **"Chat with Flow bot"**: `body/recipient` = `"user@domain.com;"` (string with trailing semicolon).
|
||||
- **"Channel"**: `body/recipient` = `{"groupId": "...", "channelId": "..."}` (object).
|
||||
- `poster`: `"Flow bot"` for Workflows bot identity, `"User"` for user identity.
|
||||
|
||||
### `list_live_connections`
|
||||
- `id` is the value you need for `connectionName` in `connectionReferences`.
|
||||
- `connectorName` maps to apiId: `"/providers/Microsoft.PowerApps/apis/" + connectorName`.
|
||||
Reference in New Issue
Block a user