Skip to main content

flowstudio-power-automate-build

Build, scaffold, and deploy Power Automate cloud flows using the FlowStudio MCP server. Your agent constructs flow definitions, wires connections, deploys, and tests — all via MCP without opening the portal. Load this skill when asked to: create a flow, build a new flow, deploy a flow definition, scaffold a Power Automate workflow, construct a flow JSON, update an existing flow's actions, patch a flow definition, add actions to a flow, wire up connections, or generate a workflow definition from scratch. Requires a FlowStudio MCP subscription — see https://mcp.flowstudio.app

Source facts

Repository
github/awesome-copilot
Last source activity
September 7, 2026 at 02:40
Detected SKILL.md language
English
Stars
40,553
Forks
5,230

Install options

The review-first prompt is selected by default. You can switch to a direct command or download a local copy.

Review the source files

Read SKILL.md and any companion files shown by SkillsMP before deciding whether to install.

File Explorer
7 files

Showing SKILL.md

SKILL.md
Source instructions · Read-only preview
name
flowstudio-power-automate-build
description
Build, scaffold, and deploy Power Automate cloud flows using the FlowStudio MCP server. Your agent constructs flow definitions, wires connections, deploys, and tests — all via MCP without opening the portal. Load this skill when asked to: create a flow, build a new flow, deploy a flow definition, scaffold a Power Automate workflow, construct a flow JSON, update an existing flow's actions, patch a flow definition, add actions to a flow, wire up connections, or generate a workflow definition from scratch. Requires a FlowStudio MCP subscription — see https://mcp.flowstudio.app
# Build & Deploy Power Automate Flows with FlowStudio MCP 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. Subscribe at https://mcp.flowstudio.app Workflow: 1. Load current build tools. 2. Check for an existing flow. 3. Resolve connection references. 4. Build the definition. 5. Deploy. 6. Verify. 7. Test. --- ## Source of Truth > **Always call `list_skills` / `tool_search` first** to confirm available tool > names and parameter schemas. Tool names and parameters may change between > server versions. > This skill covers response shapes, behavioral notes, and build patterns — > things tool schemas cannot tell you. If this document disagrees with > `tool_search` or a real API response, the API wins. --- ## Python Helper ```python import json, urllib.request MCP_URL = "https://mcp.flowstudio.app/mcp" MCP_TOKEN = "<YOUR_JWT_TOKEN>" def mcp(tool, **kwargs): payload = json.dumps({"jsonrpc": "2.0", "id": 1, "method": "tools/call", "params": {"name": tool, "arguments": kwargs}}).encode() req = urllib.request.Request(MCP_URL, data=payload, headers={"x-api-key": MCP_TOKEN, "Content-Type": "application/json", "User-Agent": "FlowStudio-MCP/1.0"}) try: resp = urllib.request.urlopen(req, timeout=120) except urllib.error.HTTPError as e: body = e.read().decode("utf-8", errors="replace") raise RuntimeError(f"MCP HTTP {e.code}: {body[:200]}") from e raw = json.loads(resp.read()) if "error" in raw: raise RuntimeError(f"MCP error: {json.dumps(raw['error'])}") return json.loads(raw["result"]["content"][0]["text"]) ENV = "<environment-id>" # e.g. Default-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx ``` --- ## 0. Load the Current Build Tools For a brand-new flow, load the server's `create-flow` bundle. For editing an existing flow, load `build-flow`. This keeps the agent aligned with the MCP server's current schema before constructing JSON. ```python schemas = mcp("tool_search", query="skill:create-flow") # Includes list_live_environments, list_live_connections, # describe_live_connector, get_live_dynamic_options, update_live_flow. ``` If you need a tool outside the bundle, load it explicitly: ```python mcp("tool_search", query="select:get_live_dynamic_properties") ``` --- ## 1. Safety Check: Does the Flow Already Exist? Always look before you build to avoid duplicates: ```python results = mcp("list_live_flows", environmentName=ENV, mode="owner", search="My New Flow", top=20) # list_live_flows returns { "flows": [...], "mode": "...", ... } matches = [f for f in results["flows"] if "My New Flow".lower() in f["displayName"].lower()] if len(matches) > 0: # Flow exists — modify rather than create FLOW_ID = matches[0]["id"] # plain UUID from list_live_flows print(f"Existing flow: {FLOW_ID}") defn = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID) else: print("Flow not found — building from scratch") FLOW_ID = None ``` For very large environments, `list_live_flows` may return a continuation URL. Pass it back as `continuationUrl` with the same `mode` to retrieve the next batch. Use `mode="admin"` only when the user needs all environment flows and the MCP identity has admin rights. --- ## 2. Obtain Connection References Every connector action needs a `connectionName` that points to a key in the flow's `connectionReferences` map. That key links to an authenticated connection in the environment. > **MANDATORY**: You MUST call `list_live_connections` first — do NOT ask the > user for connection names or GUIDs. The API returns the exact values you need. > Only prompt the user if the API confirms that required connections are missing. ### 2a — Find active connections ```python conns = mcp("list_live_connections", environmentName=ENV) active = [c for c in conns["connections"] if c["statuses"][0]["status"] == "Connected"] conn_map = {c["connectorName"]: c["id"] for c in active} ``` For a known connector, pass `search` to reduce output and get paste-ready `connectionReferenceTemplate` and `hostTemplate` values: ```python sp_conns = mcp("list_live_connections", environmentName=ENV, search="shared_sharepointonline") ``` ### 2b — Determine which connectors the flow needs Common connector API names: SharePoint `shared_sharepointonline`, Outlook `shared_office365`, Teams `shared_teams`, Approvals `shared_approvals`, OneDrive `shared_onedriveforbusiness`, Excel `shared_excelonlinebusiness`, Dataverse `shared_commondataserviceforapps`, Forms `shared_microsoftforms`. Flows that need no connectors, such as Recurrence + Compose + HTTP only, can omit `connectionReferences`. ### 2c — If connections are missing, guide the user ```python connectors_needed = ["shared_sharepointonline", "shared_office365"] # adjust per flow missing = [c for c in connectors_needed if c not in conn_map] if missing: # STOP: connections require browser OAuth consent. # Ask the user to create the missing connector connections in the # selected environment, then re-run list_live_connections. raise Exception(f"Missing active connections: {missing}") ``` ### 2d — Build the connectionReferences block ```python connection_references = {} host_templates = {} for connector in connectors_needed: c = next(c for c in active if c["connectorName"] == connector) connection_references[connector] = c.get("connectionReferenceTemplate") or { "connectionName": c["id"], # the connection id from list_live_connections "source": "Invoker", "id": f"/providers/Microsoft.PowerApps/apis/{connector}" } host_templates[connector] = c.get("hostTemplate") or { "connectionName": connector } ``` In Step 3 action JSON, `inputs.host.connectionName` must be the map key such as `shared_teams`, not the GUID. The GUID belongs only inside the `connectionReferences[connector].connectionName` value. If an existing flow uses the same connectors, you may also copy its `properties.connectionReferences` from `get_live_flow`. --- ## 3. Build the Flow Definition Construct the definition object. See [flow-schema.md](references/flow-schema.md) for the full schema and these action pattern references for copy-paste templates: - [action-patterns-core.md](references/action-patterns-core.md) — Variables, control flow, expressions - [action-patterns-data.md](references/action-patterns-data.md) — Array transforms, HTTP, parsing - [action-patterns-connectors.md](references/action-patterns-connectors.md) — SharePoint, Outlook, Teams, Approvals ```python definition = { "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", "contentVersion": "1.0.0.0", "triggers": { ... }, # see trigger-types.md / build-patterns.md "actions": { ... } # see ACTION-PATTERNS-*.md / build-patterns.md } ``` > See [build-patterns.md](references/build-patterns.md) for complete, ready-to-use > flow definitions covering Recurrence+SharePoint+Teams, HTTP triggers, and more. ### Discover connector operations before guessing JSON For connector-backed triggers/actions, prefer the live connector describer over hand-written shapes. It can return authored hints, canonical examples, variant keys, inputs/outputs, and dynamic metadata pointers. ```python # Search across connectors when you know the user's intent but not the API. matches = mcp("describe_live_connector", environmentName=ENV, search="send email", top=5) # Describe a specific operation before copying an exampleDefinition. op = mcp("describe_live_connector", environmentName=ENV, connectorName="shared_office365", operationId="SendEmailV2") print(op.get("hint")) ``` When an operation has multiple authored variants, request the variant the flow needs: ```python teams_chat = mcp("describe_live_connector", environmentName=ENV, connectorName="shared_teams", operationId="PostMessageToConversation", variant="flowbot_chat") ``` When the operation description says a parameter has dynamic options or dynamic properties, call the indicated next tool: ```python sp_op = mcp("describe_live_connector", environmentName=ENV, connectorName="shared_sharepointonline", operationId="GetItems") sites = mcp("get_live_dynamic_options", environmentName=ENV, connectorName="shared_sharepointonline", connectionName=conn_map["shared_sharepointonline"], operationId="GetItems", parameterName="dataset", dynamicMetadata=sp_op["dynamicParameters"]["dataset"]) fields = mcp("get_live_dynamic_properties", environmentName=ENV, connectorName="shared_sharepointonline", connectionName=conn_map["shared_sharepointonline"], operationId="GetItems", parameterName="item", parameters={"dataset": "<site-url>", "table": "<list-id>"}, dynamicMetadata=sp_op["dynamicProperties"]["item"]) ``` Use dynamic options for dropdown IDs such as SharePoint sites/lists and Teams teams/channels. Use dynamic properties for schema/field shapes such as SharePoint list item columns. --- ## 4. Deploy (Create or Update) `update_live_flow` handles both creation and updates in a single tool. ### Create a new flow (no existing flow) Omit `flowName` — the server generates a new GUID and creates via PUT: ```python definition["description"] = "Weekly SharePoint → Teams notification flow, built by agent" result = mcp("update_live_flow", environmentName=ENV, # flowName omitted → creates a new flow definition=definition, connectionReferences=connection_references, displayName="Overdue Invoice Notifications" ) if result.get("error") is not None: print("Create failed:", result["error"]) else: # Capture the new flow ID for subsequent steps FLOW_ID = result["created"] print(f"✅ Flow created: {FLOW_ID}") ``` ### Update an existing flow Provide `flowName` to PATCH: ```python definition["description"] = ( "Updated by agent on " + __import__('datetime').datetime.utcnow().isoformat() ) result = mcp("update_live_flow", environmentName=ENV, flowName=FLOW_ID, definition=definition, connectionReferences=connection_references, displayName="My Updated Flow" ) if result.get("error") is not None: print("Update failed:", result["error"]) else: print("Update succeeded:", result) ``` > ⚠️ `update_live_flow` always returns an `error` key. > `null` (Python `None`) means success — do not treat the presence of the key as failure. > > ⚠️ Flow description lives at `definition["description"]`. The current server > appends `#flowstudio-mcp` for usage tracking. Do not pass a top-level > `description` argument unless `tool_search` shows one in the active schema. ### Common deployment errors | Error message (contains) | Cause | Fix | |---|---|---| | `missing from connectionReferences` | An action's `host.connectionName` references a key that doesn't exist in the `connectionReferences` map | Ensure `host.connectionName` uses the **key** from `connectionReferences` (e.g. `shared_teams`), not the raw GUID | | `ConnectionAuthorizationFailed` / 403 | The connection GUID belongs to another user or is not authorized | Re-run Step 2a and use a connection owned by the current `x-api-key` user | | `InvalidTemplate` / `InvalidDefinition` | Syntax error in the definition JSON | Check `runAfter` chains, expression syntax, and action type spelling | | `ConnectionNotConfigured` | A connector action exists but the connection GUID is invalid or expired | Re-check `list_live_connections` for a fresh GUID | --- ## 5. Verify the Deployment ```python check = mcp("get_live_flow", environmentName=ENV, flowName=FLOW_ID) # Confirm state print("State:", check["properties"]["state"]) # Should be "Started" # If state is "Stopped", use set_live_flow_state — NOT update_live_flow # mcp("set_live_flow_state", environmentName=ENV, flowName=FLOW_ID, state="Started") # Confirm the action we added is there acts = check["properties"]["definition"]["actions"] print("Actions:", list(acts.keys())) ``` --- ## 6. Test the Flow > **MANDATORY**: Before triggering any test run, **ask the user for confirmation**. > Running a flow has real side effects — it may send emails, post Teams messages, > write to SharePoint, start approvals, or call external APIs. Explain what the > flow will do and wait for explicit approval before calling `trigger_live_flow` > or `resubmit_live_flow_run`. ### Updated flows (have prior runs) — ANY trigger type > **Use `resubmit_live_flow_run` first.** It works for EVERY trigger type — > Recurrence, SharePoint, connector webhooks, Button, and HTTP. It replays > the original trigger payload. Do NOT ask the user to manually trigger the
View on GitHub
This SKILL.md is very large, so SkillsMP previews the first section here. View on GitHub