@ericrisco/rsc 0.1.37 → 0.1.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/README.md +8 -2
  2. package/manifest.json +130 -4
  3. package/package.json +1 -1
  4. package/scripts/lib/domains.js +1 -0
  5. package/scripts/lib/recommend.js +5 -0
  6. package/skills/automation-flows/SKILL.md +1 -1
  7. package/skills/automation-strategy/SKILL.md +131 -0
  8. package/skills/automation-strategy/evals/README.md +16 -0
  9. package/skills/automation-strategy/evals/cases.yaml +48 -0
  10. package/skills/automation-strategy/references/automate-decision-and-roi.md +118 -0
  11. package/skills/automation-strategy/references/orchestration-and-antipatterns.md +107 -0
  12. package/skills/automation-strategy/references/platform-selection-matrix.md +86 -0
  13. package/skills/harness/references/providers.yaml +101 -0
  14. package/skills/make/SKILL.md +255 -0
  15. package/skills/make/evals/README.md +14 -0
  16. package/skills/make/evals/cases.yaml +45 -0
  17. package/skills/make/references/api-v2-cheatsheet.md +114 -0
  18. package/skills/make/references/blueprint-round-trip.md +128 -0
  19. package/skills/make/references/make-mcp-and-auth.md +101 -0
  20. package/skills/n8n/SKILL.md +205 -0
  21. package/skills/n8n/evals/README.md +14 -0
  22. package/skills/n8n/evals/cases.yaml +45 -0
  23. package/skills/n8n/references/auth-and-selfhost.md +62 -0
  24. package/skills/n8n/references/n8n-mcp-tools.md +84 -0
  25. package/skills/n8n/references/rest-api-cheatsheet.md +94 -0
  26. package/skills/power-automate/SKILL.md +169 -0
  27. package/skills/power-automate/evals/README.md +17 -0
  28. package/skills/power-automate/evals/cases.yaml +43 -0
  29. package/skills/power-automate/references/dataverse-web-api.md +187 -0
  30. package/skills/power-automate/references/entra-auth-setup.md +75 -0
  31. package/skills/power-automate/references/flowstudio-mcp-and-limits.md +62 -0
  32. package/skills/roast-me/tools/adapters/__pycache__/__init__.cpython-312.pyc +0 -0
  33. package/skills/roast-me/tools/adapters/__pycache__/base.cpython-312.pyc +0 -0
  34. package/skills/roast-me/tools/adapters/__pycache__/claude.cpython-312.pyc +0 -0
  35. package/skills/roast-me/tools/adapters/__pycache__/codex.cpython-312.pyc +0 -0
  36. package/skills/roast-me/tools/adapters/__pycache__/gemini.cpython-312.pyc +0 -0
  37. package/skills/roast-me/tools/adapters/__pycache__/registry.cpython-312.pyc +0 -0
  38. package/skills/zapier/SKILL.md +145 -0
  39. package/skills/zapier/evals/README.md +5 -0
  40. package/skills/zapier/evals/cases.yaml +50 -0
  41. package/skills/zapier/references/programmatic-limits-and-partner-api.md +48 -0
  42. package/skills/zapier/references/when-to-use-vs-n8n-make.md +44 -0
  43. package/skills/zapier/references/zapier-mcp-tools.md +72 -0
@@ -0,0 +1,62 @@
1
+ # n8n auth, self-host vs cloud, and pointing n8n-mcp
2
+
3
+ ## Get an API key
4
+
5
+ 1. In n8n, open **Settings → n8n API**.
6
+ 2. **Create an API key.** Prefer a **scoped** key — pick only the resource scopes the automation needs
7
+ (e.g. `workflow:read`, `workflow:create`, `workflow:execute`, `execution:read`). An unscoped key can
8
+ do everything the user can, including delete.
9
+ 3. Copy it once (it is shown once) and store it as `N8N_API_KEY`. Rotate by deleting + recreating.
10
+
11
+ Every REST call carries it as a header: `X-N8N-API-KEY: <key>`. It is NOT a bearer token and NOT in
12
+ the query string.
13
+
14
+ ```bash
15
+ export N8N_API_KEY="n8n_api_..."
16
+ export N8N_API_URL="https://your-instance.app.n8n.cloud" # host root; append /api/v1 for REST
17
+ ```
18
+
19
+ ## Self-host vs cloud — what actually differs
20
+
21
+ | | Self-host | Cloud (`*.app.n8n.cloud`) |
22
+ |---|---|---|
23
+ | API base | `{host}/api/v1` (e.g. `http://localhost:5678/api/v1`) | `https://<tenant>.app.n8n.cloud/api/v1` |
24
+ | API surface | **identical** | **identical** |
25
+ | Interactive Swagger | **Yes** at `/api/v1/docs` | **No** — work from docs.n8n.io |
26
+ | Where data lives | your infra | n8n's |
27
+ | Enabling the API | on by default; can be toggled via `N8N_PUBLIC_API_DISABLED=true` | always on |
28
+ | Base URL override | `WEBHOOK_URL` / `N8N_HOST`/`N8N_PROTOCOL`/`N8N_PORT` shape the host + webhook URLs | fixed |
29
+
30
+ The only thing that changes between environments is the host and (self-host) the Swagger page.
31
+ Scripts written against one work against the other by swapping `N8N_API_URL`.
32
+
33
+ Webhook URLs on self-host derive from `WEBHOOK_URL` (or host/protocol/port). If your production webhook
34
+ URLs look wrong (localhost behind a proxy), that env var is usually why.
35
+
36
+ ## Pointing n8n-mcp at your instance
37
+
38
+ `n8n-mcp` reads the **same two env vars** for its management tier:
39
+
40
+ ```bash
41
+ N8N_API_URL=https://your-instance.app.n8n.cloud
42
+ N8N_API_KEY=n8n_api_...
43
+ ```
44
+
45
+ Ways to run it:
46
+
47
+ - **Hosted** — `dashboard.n8n-mcp.com`: add an instance (URL + key), get an MCP endpoint. Fastest trial;
48
+ free tier caps daily tool calls.
49
+ - **Local (npx)** — run the `n8n-mcp` package and register it in your MCP client's config
50
+ (Claude Code / Claude Desktop / Cursor / Windsurf), passing the two env vars.
51
+ - **Docker** — the repo ships an image; inject the env vars.
52
+
53
+ Node-knowledge tools work with **no** auth; only the management tools need the two vars. Confirm the
54
+ link with `n8n_health_check` — it reports reachability and which features (e.g. the `/execute`
55
+ endpoint) the target instance supports.
56
+
57
+ ## Governance quick-set
58
+
59
+ - **Scope the key** at creation (least privilege) — see above.
60
+ - **`DISABLED_TOOLS`** on n8n-mcp to gate destructive tools — see `n8n-mcp-tools.md`.
61
+ - **Never** commit `N8N_API_KEY` or inline node-credential secrets in a workflow payload; reference
62
+ credentials from the n8n credential store by id/name.
@@ -0,0 +1,84 @@
1
+ # n8n-mcp — tool reference & governance
2
+
3
+ `n8n-mcp` (github.com/czlonkowski/n8n-mcp, ~22k★, the de-facto community standard) is an MCP server
4
+ that gives an agent two things: **offline knowledge** of n8n's node/expression catalogue, and
5
+ **management** of a live instance via its REST API. Distinct from n8n's own first-party built-in MCP
6
+ node, which lets a *workflow* act as an MCP server/client — that is not this.
7
+
8
+ Tool names and counts move; **verify against the running server's tool list** (or
9
+ `dashboard.n8n-mcp.com` / the repo docs) before relying on any one name.
10
+
11
+ ## Two tiers, two auth requirements
12
+
13
+ | Tier | Needs auth? | Purpose |
14
+ |---|---|---|
15
+ | **Node-knowledge tools** | **No** | Search/describe nodes, get property essentials, validate a node's config, browse templates — all offline. Safe to expose broadly. |
16
+ | **Management tools** | **Yes** — `N8N_API_URL` + `N8N_API_KEY` | CRUD/validate/test/run/inspect a real instance. These are the ones governance applies to. |
17
+
18
+ Set the same two env vars the REST API uses:
19
+
20
+ ```bash
21
+ N8N_API_URL=https://your-instance.app.n8n.cloud # host root, whole value
22
+ N8N_API_KEY=n8n_api_...
23
+ ```
24
+
25
+ Without them the server still runs — you just get the node-knowledge tier only.
26
+
27
+ ## Node-knowledge tools (no auth)
28
+
29
+ - `search_nodes`, `list_nodes`, `list_ai_tools` — find the right node.
30
+ - `get_node_essentials`, `get_node_info`, `get_node_documentation` — properties & docs for a node type.
31
+ - `validate_node_operation`, `validate_node_minimal` — check a single node's config before you wire it.
32
+ - `search_templates`, `get_template` — reuse community workflow templates.
33
+
34
+ Use these to author node JSON correctly instead of guessing `typeVersion`/property shapes.
35
+
36
+ ## Management tools (need `N8N_API_URL` + `N8N_API_KEY`)
37
+
38
+ | Tool | Does |
39
+ |---|---|
40
+ | `n8n_create_workflow` | Create from a full workflow object. |
41
+ | `n8n_get_workflow` | Fetch one workflow (export before delete/replace). |
42
+ | `n8n_list_workflows` | List/filter workflows. |
43
+ | `n8n_update_full_workflow` | Replace the whole workflow (like REST `PUT`). |
44
+ | `n8n_update_partial_workflow` | **Atomic ordered batch of targeted edits** — if any op fails, nothing is saved. Prefer this for edits. |
45
+ | `n8n_delete_workflow` | **Hard delete.** Export first. |
46
+ | `n8n_validate_workflow` | Structural/connection/expression validation of a workflow object. |
47
+ | `n8n_autofix_workflow` | Repair common errors and return fixed JSON. |
48
+ | `n8n_test_workflow` | Trigger a run for testing. |
49
+ | `n8n_executions` | List/inspect execution runs. |
50
+ | `n8n_workflow_versions` | Version history of a workflow. |
51
+ | `n8n_deploy_template` | Deploy a catalogue template to the instance. |
52
+ | `n8n_manage_credentials` | Create/manage credentials (secrets not readable back). |
53
+ | `n8n_manage_datatable` | Manage n8n data tables. |
54
+ | `n8n_health_check` | Confirm API reachability + which features the instance supports. |
55
+ | `n8n_audit_instance` | Security audit (built-in audit API + deep workflow scan). |
56
+
57
+ **Note on activate/deactivate:** n8n-mcp intentionally does not surface these as tools (activation has
58
+ live side effects). Flip a workflow live with the REST `POST /workflows/{id}/activate` endpoint (see
59
+ `rest-api-cheatsheet.md`) or the UI. Verify the current tool list in case this changes.
60
+
61
+ ## Governance — `DISABLED_TOOLS`
62
+
63
+ For agent-facing deployments, disable destructive/write tools with a comma-separated env var:
64
+
65
+ ```bash
66
+ # read-only agent: no create/replace/delete/autofix/test/template/credential/datatable writes
67
+ DISABLED_TOOLS=n8n_create_workflow,n8n_update_full_workflow,n8n_update_partial_workflow,n8n_delete_workflow,n8n_autofix_workflow,n8n_deploy_template,n8n_test_workflow,n8n_manage_credentials,n8n_manage_datatable
68
+ ```
69
+
70
+ Layer it with a **scoped API key** (grant only `workflow:read`/`execution:read` for a monitoring
71
+ agent) so a disabled tool can't be worked around and the key itself can't mutate. Two independent
72
+ locks: the tool gate and the key scope.
73
+
74
+ ## Sketch: agent-driven deploy
75
+
76
+ ```
77
+ search_nodes / get_node_essentials → get the exact node property shapes
78
+ n8n_validate_workflow { workflow } → catch structural errors offline
79
+ n8n_autofix_workflow { workflow } → auto-repair, re-validate
80
+ n8n_create_workflow { name, nodes, connections, settings } → capture returned id
81
+ n8n_test_workflow { id } → confirm it runs
82
+ # then activate via REST /workflows/{id}/activate (no MCP tool for it)
83
+ n8n_executions { workflowId: id } → confirm the live run
84
+ ```
@@ -0,0 +1,94 @@
1
+ # n8n public REST API — cheat sheet
2
+
3
+ Base URL: `{host}/api/v1`. Auth header on every call: `X-N8N-API-KEY: $N8N_API_KEY`.
4
+ Same surface on self-host and `*.app.n8n.cloud`. Self-host has interactive Swagger at
5
+ `{host}/api/v1/docs`; cloud does not. Verify shapes at author time — n8n ships often.
6
+
7
+ Set once:
8
+
9
+ ```bash
10
+ export N8N_API_URL="https://your-instance.app.n8n.cloud" # or http://localhost:5678
11
+ export N8N_API_KEY="n8n_api_..."
12
+ auth=(-H "X-N8N-API-KEY: $N8N_API_KEY")
13
+ ```
14
+
15
+ ## Workflows
16
+
17
+ | Verb & path | What it does | Notes |
18
+ |---|---|---|
19
+ | `POST /workflows` | Create | Body needs `name, nodes, connections, settings`. `active` + `tags` in the body are **ignored** (read-only). Returns the new object incl. `id`. |
20
+ | `GET /workflows/{id}` | Get one | The full exportable JSON. Use to back up before delete/replace. |
21
+ | `GET /workflows` | List | Query: `limit` (default ~100), `cursor`, `active=true|false`, `tags`, `name`, `projectId`. Paginate with the returned `nextCursor`. |
22
+ | `PUT /workflows/{id}` | **Full replace** | Send the WHOLE object; omitted fields are dropped. GET → mutate → PUT. |
23
+ | `DELETE /workflows/{id}` | **Hard delete** | No trash, no undo. Export first. |
24
+ | `POST /workflows/{id}/activate` | Activate | The ONLY way to go live — the body `active` flag never does it. |
25
+ | `POST /workflows/{id}/deactivate` | Deactivate | Same, in reverse. |
26
+ | `POST /workflows/{id}/execute` | Run by id | **Recent (PR #20234); older instances 404.** Runs `executeManually`; **accepts no custom input** — needs `workflow:execute` scope. |
27
+ | `PUT /workflows/{id}/tags` | Set tags | Tags are managed here, not in the create/update body. |
28
+ | `PUT /workflows/{id}/transfer` | Move to a project | Enterprise/projects. |
29
+
30
+ ```bash
31
+ curl -sS -X POST "$N8N_API_URL/api/v1/workflows" "${auth[@]}" \
32
+ -H "Content-Type: application/json" -d @workflow.json
33
+ curl -sS "$N8N_API_URL/api/v1/workflows?limit=50&active=true" "${auth[@]}"
34
+ curl -sS "$N8N_API_URL/api/v1/workflows/$ID" "${auth[@]}" > backup-$ID.json
35
+ curl -sS -X POST "$N8N_API_URL/api/v1/workflows/$ID/activate" "${auth[@]}"
36
+ curl -sS -X POST "$N8N_API_URL/api/v1/workflows/$ID/execute" "${auth[@]}"
37
+ curl -sS -X DELETE "$N8N_API_URL/api/v1/workflows/$ID" "${auth[@]}"
38
+ ```
39
+
40
+ Paginate:
41
+
42
+ ```bash
43
+ cursor=""
44
+ while :; do
45
+ page=$(curl -sS "$N8N_API_URL/api/v1/workflows?limit=100&cursor=$cursor" "${auth[@]}")
46
+ echo "$page" | jq -r '.data[].id'
47
+ cursor=$(echo "$page" | jq -r '.nextCursor // empty')
48
+ [ -z "$cursor" ] && break
49
+ done
50
+ ```
51
+
52
+ ## Executions
53
+
54
+ | Verb & path | What it does |
55
+ |---|---|
56
+ | `GET /executions` | List runs. Query: `workflowId`, `status` (`success|error|waiting`), `limit`, `cursor`, `includeData=true`. |
57
+ | `GET /executions/{id}` | One run; `?includeData=true` for the full item data. |
58
+ | `DELETE /executions/{id}` | Delete a run's stored data. |
59
+
60
+ ```bash
61
+ curl -sS "$N8N_API_URL/api/v1/executions?workflowId=$ID&status=error&limit=20" "${auth[@]}"
62
+ ```
63
+
64
+ ## Triggering a run WITH input
65
+
66
+ `/execute` takes no body data. To pass runtime params, the workflow's trigger must be a **Webhook**
67
+ node; POST to its URL:
68
+
69
+ - Test URL (only while the editor's "Listen for test event" is armed): `{host}/webhook-test/<path>`
70
+ - Production URL (only once the workflow is active): `{host}/webhook/<path>`
71
+
72
+ ```bash
73
+ curl -sS -X POST "$N8N_HOST/webhook/my-path" -H "Content-Type: application/json" -d '{"orderId":123}'
74
+ ```
75
+
76
+ ## Other resources
77
+
78
+ - `GET/POST/DELETE /credentials` — create/delete credentials and `GET /credentials/schema/{type}` for
79
+ the field shape. **You cannot read secrets back.** Reference existing creds from a workflow by id/name.
80
+ - `GET/POST/PUT/DELETE /tags`, `/projects`, `/variables`, `/users` (admin), `/source-control/pull`,
81
+ `/audit` (instance security audit).
82
+
83
+ ## API-key scopes (least privilege)
84
+
85
+ Create a **scoped** key in Settings → n8n API. Scopes are grouped by resource, e.g. `workflow:read`,
86
+ `workflow:create`, `workflow:update`, `workflow:delete`, `workflow:execute`, `execution:read`,
87
+ `credential:create`, `tag:*`. Grant only what a given automation needs — e.g. a read-only dashboard
88
+ key gets `workflow:read` + `execution:read` and nothing that can mutate or run.
89
+
90
+ ## Error responses
91
+
92
+ `401` bad/missing key · `403` key lacks the scope · `404` no such id (or `/execute` on an instance
93
+ too old to have it) · `400` malformed body (e.g. missing `connections`) · `500` server-side (often a
94
+ node the instance doesn't have installed).
@@ -0,0 +1,169 @@
1
+ ---
2
+ name: power-automate
3
+ description: "Use when operating Microsoft Power Automate cloud flows programmatically — creating, enabling, updating, listing or deleting flows through the Dataverse Web API (the workflow table, category 5) with Entra ID / OAuth2 auth, or reading action-level run history via the third-party FlowStudio MCP. Triggers: 'create a Power Automate cloud flow with the Dataverse API', 'enable my flow by code / set statecode to 1', 'why can't I create or edit a My Flow programmatically', 'PATCH the workflow clientdata', 'automatizar el despliegue de un flujo de Power Automate desde código'. NOT designing the flow or authoring its definition (automation-flows), NOT choosing a platform by billing model (automation-strategy), NOT a generic typed REST client with auth/pagination/backoff (api-connector-builder), NOT the endpoint receiving an HTTP-trigger POST in your app (webhooks), NOT scripting Microsoft 365 / Graph mail & calendar directly (no first-party skill — api-connector-builder, or google-workspace)."
4
+ tags: [power-automate, dataverse, microsoft, flows, entra, oauth, mcp, m365, automation]
5
+ recommends: [automation-flows, automation-strategy, api-connector-builder, webhooks]
6
+ profiles: [full]
7
+ origin: risco
8
+ ---
9
+
10
+ # Power Automate — operate cloud flows through Dataverse, honestly
11
+
12
+ Drive Microsoft Power Automate **cloud flows** from code: create, enable, update, list, and delete them, plus pull run history for debugging. This skill operates the *live* surface. Deciding what the flow should do and shaping its trigger→actions→error definition is design — that lives in `../automation-flows/SKILL.md`; this skill wraps that definition, ships it, and manages it.
13
+
14
+ Read these three facts before you write a line — they set the boundary of what is even possible:
15
+
16
+ 1. **Only flows inside a Dataverse *solution* are code-manageable.** Classic personal **"My Flows"** cannot be created or edited by code — the Microsoft docs say so explicitly. If the target is a My Flow, the honest answer is: move it into a solution first, or drive it by hand. There is no API workaround.
17
+ 2. **`api.flow.microsoft.com` is unsupported.** Microsoft's own words: use it "at your own risk," it is subject to breaking changes. The supported programmatic surface is the **Dataverse Web API** (or the .NET SDK) against the `workflow` table. For admin-style operations the **Power Automate Management** connector is the other supported path.
18
+ 3. **The unified Power Platform API (`api.powerplatform.com`) is maturing fast.** It already lists cloud flows (api-version `2024-10-01`) and its Inventory API went GA in early 2026. It may eventually supersede the Dataverse path for flow management. Treat the Dataverse-vs-Power-Platform-API split as fast-moving — verify the current recommendation at author time.
19
+
20
+ ## Connect first — API vs MCP
21
+
22
+ Everything runs against your org's Dataverse Web API. **Base URL:** `https://{org}.{region}.dynamics.com/api/data/v9.2` (find yours under Power Platform admin → your environment → developer resources). Auth is **OAuth2 / Entra ID** — a user token or, for CI, a **service principal** (app registration). For a service principal the org needs a **Dataverse application user** mapped to that app plus a security role; the token audience is the Dataverse URL. Full setup, including the delegated `user_impersonation` vs app `.default` scope split and the 401/403 causes, is in `references/entra-auth-setup.md`.
23
+
24
+ Put these in `.env` (never inline a secret in a flow or a script):
25
+
26
+ ```
27
+ PA_DATAVERSE_URL=https://contoso.crm.dynamics.com # no trailing slash, no /api/...
28
+ PA_TENANT_ID=<entra-tenant-guid>
29
+ PA_CLIENT_ID=<app-registration-client-id>
30
+ PA_CLIENT_SECRET=<app-registration-secret> # service-principal flow only
31
+ ```
32
+
33
+ **When to use the REST API vs the MCP:**
34
+
35
+ | You need to… | Use | Why |
36
+ |---|---|---|
37
+ | Create / enable / update / delete / list flows | **Dataverse Web API** | The only supported CRUD surface; scriptable, CI-friendly, service-principal auth. |
38
+ | Read a flow's **action-level** run inputs/outputs to debug a failure | **FlowStudio MCP** (third-party) | Dataverse exposes run *records* (`flowrun` table) but not per-action I/O; the MCP does. See `references/flowstudio-mcp-and-limits.md`. |
39
+ | Admin-scope operations (turn on/off across an environment) | Power Automate **Management** connector | Supported management surface when raw Dataverse is awkward. |
40
+
41
+ **FlowStudio MCP is NOT Microsoft-affiliated** — it is a de-facto third-party server (`mcp.flowstudio.app/mcp`). Microsoft's own MCP story is Copilot Studio *consuming* MCP servers and a Dataverse MCP, neither of which authors Power Automate flows. Flag the third-party dependency to anyone before wiring it into a pipeline.
42
+
43
+ ## The `workflow` table — the data model
44
+
45
+ Cloud flows are rows in the Dataverse **Process (`workflow`)** table. The columns that matter:
46
+
47
+ | Column | Meaning | Values you use |
48
+ |---|---|---|
49
+ | `category` | Kind of process | **`5` = modern cloud flow** (automated / instant / scheduled). (0 classic workflow, 4 business process flow, 6 desktop flow.) |
50
+ | `type` | Definition vs template | **`1` = Definition** (a runnable flow). |
51
+ | `statecode` | On/off state | **`0` = Draft (Off)**, **`1` = Activated (On)**, `2` = Suspended. |
52
+ | `name` | Display name | your string |
53
+ | `primaryentity` | Bound table | **`"none"`** for automated/instant/scheduled flows |
54
+ | `clientdata` | The flow itself | **string-encoded JSON** (see below) |
55
+ | `workflowid` | GUID key | returned on create; used in `workflows({id})` |
56
+
57
+ List the cloud flows that are on:
58
+
59
+ ```bash
60
+ curl -s "$PA_DATAVERSE_URL/api/data/v9.2/workflows?\$filter=category eq 5 and statecode eq 1&\$select=name,statecode,type,workflowid" \
61
+ -H "Authorization: Bearer $TOKEN" -H "OData-Version: 4.0" -H "Accept: application/json"
62
+ ```
63
+
64
+ ## `clientdata` — the payload, and the trap that bites everyone
65
+
66
+ `clientdata` is **a JSON string, not a nested JSON object.** It is the serialized form of:
67
+
68
+ ```json
69
+ {
70
+ "properties": {
71
+ "connectionReferences": { "shared_commondataserviceforapps": { "runtimeSource": "embedded", "connection": {}, "api": { "name": "shared_commondataserviceforapps" } } },
72
+ "definition": { "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#", "contentVersion": "1.0.0.0", "triggers": { }, "actions": { } }
73
+ },
74
+ "schemaVersion": "1.0.0.0"
75
+ }
76
+ ```
77
+
78
+ Two load-bearing parts:
79
+
80
+ - **`definition`** — a Logic Apps workflow definition: `triggers` (exactly one) then `actions`. This is the *design* artifact. Do not invent it from scratch here — get the trigger→actions→branch→error shape from `../automation-flows/SKILL.md`, then drop it into `definition`. Fastest reliable way to get a real one: build the flow once in the maker portal, export the solution, and copy its `clientdata`.
81
+ - **`connectionReferences`** — the map from the definition's connectors to actual connections. **A flow whose connection references are not authorized will not turn on.** In a solution these are connection-reference records the target environment must resolve; unresolved references are the #1 reason a `PATCH statecode=1` "succeeds" but the flow never runs.
82
+
83
+ **The trap:** `clientdata` must be *escaped into a string* before it goes in the request body — a nested object is rejected. In a script, `JSON.stringify(clientDataObject)` and assign the result; do not paste the object raw. Full annotated example in `references/dataverse-web-api.md`.
84
+
85
+ ## Dynamic lifecycle — token → create → validate → enable → manage → delete
86
+
87
+ **1. Get a token** (service-principal / client-credentials shown):
88
+
89
+ ```bash
90
+ TOKEN=$(curl -s -X POST "https://login.microsoftonline.com/$PA_TENANT_ID/oauth2/v2.0/token" \
91
+ -d "grant_type=client_credentials" -d "client_id=$PA_CLIENT_ID" \
92
+ -d "client_secret=$PA_CLIENT_SECRET" -d "scope=$PA_DATAVERSE_URL/.default" \
93
+ | python3 -c "import sys,json;print(json.load(sys.stdin)['access_token'])")
94
+ ```
95
+
96
+ **2. Create the flow** (comes up `statecode=0`, Off — expected):
97
+
98
+ ```bash
99
+ curl -s -i -X POST "$PA_DATAVERSE_URL/api/data/v9.2/workflows" \
100
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
101
+ -H "OData-Version: 4.0" \
102
+ -d '{ "category": 5, "type": 1, "name": "Nightly sync", "primaryentity": "none", "clientdata": "<string-encoded JSON>" }'
103
+ # → 204 No Content. The workflowid is in the OData-EntityId response header:
104
+ # OData-EntityId: .../workflows(00aa00aa-bb11-cc22-dd33-44ee44ee44ee)
105
+ ```
106
+
107
+ **3. Validate before enabling.** Read it back, confirm `category`/`type` are right, and confirm every `connectionReferences` entry resolves to an authorized connection in this environment. Enabling a flow with dangling connections is the classic silent failure.
108
+
109
+ **4. Enable** — flip `statecode` to `1` (use `If-Match: *` for the update):
110
+
111
+ ```bash
112
+ curl -s -X PATCH "$PA_DATAVERSE_URL/api/data/v9.2/workflows(<workflowid>)" \
113
+ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
114
+ -H "OData-Version: 4.0" -H "If-Match: *" \
115
+ -d '{ "statecode": 1 }'
116
+ # → 204 No Content
117
+ ```
118
+
119
+ **5. Manage** — update the definition or owner with the same `PATCH` (send only the fields you change; to reassign use `"ownerid@odata.bind": "systemusers(<id>)"`). To turn a flow off, `PATCH statecode=0`.
120
+
121
+ **6. Delete — irreversible; export first.** There is no undo on `DELETE`. **Before deleting, export the containing solution** (`POST /api/data/v9.2/ExportSolution` → base64 zip you save to source control), so the flow can be reimported:
122
+
123
+ ```bash
124
+ curl -s -X DELETE "$PA_DATAVERSE_URL/api/data/v9.2/workflows(<workflowid>)" \
125
+ -H "Authorization: Bearer $TOKEN"
126
+ # → 204 No Content
127
+ ```
128
+
129
+ **Debug a run** — Dataverse's `flowrun` table lists run records but not per-action I/O. To see *which action failed and with what payload*, use FlowStudio MCP: `list_live_flows` → `get_live_flow_runs` → `get_live_flow_run_action_outputs`. See `references/flowstudio-mcp-and-limits.md`.
130
+
131
+ ## Microsoft 365 ecosystem fit
132
+
133
+ Power Automate is Microsoft's iPaaS across M365 and Dynamics; flows live in **Dataverse** and glue Outlook, Teams, SharePoint, Dynamics, and hundreds of connectors. That means the boundary is sharp: if the ask is *"send this email / read this calendar via Microsoft Graph from my own backend code,"* that is not a flow at all — build a typed Graph client with `../api-connector-builder/SKILL.md` (there is no first-party MS-Graph skill). If the equivalent is on Google, that is `../google-workspace/SKILL.md`. This skill is for when the automation genuinely *is* a Power Automate flow you must operate by code.
134
+
135
+ ## Honesty / gotchas
136
+
137
+ | Trap | Why it bites | Do instead |
138
+ |---|---|---|
139
+ | Trying to CRUD a **My Flow** by code | Unsupported — silently impossible, not a bug you can fix | Move it into a Dataverse solution, or drive it by hand |
140
+ | `clientdata` sent as a nested object | Request rejected; the column expects an escaped **string** | Serialize (`JSON.stringify`) the definition+connectionReferences before sending |
141
+ | `PATCH statecode=1` "worked" but the flow never runs | Connection references unresolved/unauthorized in the target environment | Authorize every connection reference before enabling; validate on read-back |
142
+ | Building against `api.flow.microsoft.com` | Unsupported; breaks without warning | Dataverse Web API, or the Power Automate Management connector |
143
+ | `DELETE` with no export | No undo; the flow and its history are gone | `ExportSolution` first, save the zip, then delete |
144
+ | Hardcoding the Dataverse URL / secret | Env-specific, leaks in source | `.env`: `PA_DATAVERSE_URL`, `PA_TENANT_ID`, `PA_CLIENT_ID`, `PA_CLIENT_SECRET` |
145
+ | Assuming the Dataverse path is permanent | Power Platform API is superseding surfaces piecemeal | Re-check `api.powerplatform.com` coverage at author time; the split is fast-moving |
146
+
147
+ ## Related skills
148
+
149
+ - **`../automation-flows/SKILL.md`** — design side: what the trigger→actions→branch→error should be, the importable definition. This skill *consumes* that shape as `clientdata.definition`. Design there, operate here.
150
+ - **`../automation-strategy/SKILL.md`** — choosing Power Automate vs n8n/Make/Zapier by billing and constraints. Decide there before you commit to operating here.
151
+ - **`../api-connector-builder/SKILL.md`** — a generic typed REST client with auth/pagination/backoff (including a Dataverse or MS Graph client). This skill uses the Dataverse API surgically; it does not build a general client.
152
+ - **`../webhooks/SKILL.md`** — building the inbound endpoint in *your* app that receives a flow's HTTP-trigger POST. This skill triggers/operates flows; it does not build the receiver.
153
+
154
+ ## Checklist
155
+
156
+ - [ ] `.env` set: `PA_DATAVERSE_URL` (no trailing slash), `PA_TENANT_ID`, `PA_CLIENT_ID`, `PA_CLIENT_SECRET`.
157
+ - [ ] Confirmed the target is a **solution-aware** flow, not a My Flow.
158
+ - [ ] Token acquired against scope `{PA_DATAVERSE_URL}/.default` (or delegated `user_impersonation`).
159
+ - [ ] Create payload has `category:5`, `type:1`, `primaryentity:"none"`, and `clientdata` as an **escaped string**.
160
+ - [ ] Every `connectionReferences` entry maps to an authorized connection before enabling.
161
+ - [ ] Flow enabled via `PATCH statecode=1` and verified on read-back.
162
+ - [ ] Solution **exported** before any `DELETE`.
163
+ - [ ] No secrets or org URLs hardcoded; FlowStudio MCP (if used) flagged as third-party.
164
+
165
+ ## References
166
+
167
+ - `references/dataverse-web-api.md` — endpoint cheat-sheet (token, list/filter, create, enable, update, delete, ExportSolution, share), the full annotated `clientdata`, OData headers, and error handling.
168
+ - `references/entra-auth-setup.md` — app registration, service principal vs delegated user, the Dataverse application user + security role, `.default` vs `user_impersonation`, and common 401/403 causes.
169
+ - `references/flowstudio-mcp-and-limits.md` — FlowStudio MCP tools and auth (third-party), what it exposes that Dataverse doesn't, and the platform limits (My Flows, `api.flow.microsoft.com`, Power Platform API evolution).
@@ -0,0 +1,17 @@
1
+ # Evals — power-automate
2
+
3
+ `cases.yaml` has three groups. `should_trigger` covers the programmatic operate cases: create+enable
4
+ via the Dataverse Web API, the My-Flows honesty question, enable-via-statecode, a Spanish
5
+ solution-aware CI deploy, FlowStudio-MCP run debugging, and a clientdata update. `should_not_trigger`
6
+ lists adjacent prompts owned by a named sibling — flow *design*/definition (automation-flows),
7
+ platform selection by billing (automation-strategy), generic typed-client engineering
8
+ (api-connector-builder), the inbound webhook receiver (webhooks), and direct Microsoft Graph
9
+ scripting (api-connector-builder, no first-party MS-Graph skill). `capability` is one end-to-end
10
+ lifecycle scenario whose `must_include` rubric checks the concrete API calls (token, POST, PATCH
11
+ statecode, DELETE), the string-encoded `clientdata`, the My-Flows/`api.flow.microsoft.com` honesty
12
+ limits, the ExportSolution-before-DELETE irreversibility rule, and the third-party FlowStudio-MCP
13
+ flag.
14
+
15
+ No automated runner. Score by judgement: feed each `should_trigger` / `should_not_trigger` prompt to
16
+ the routing layer and confirm it activates (or routes to the listed sibling); for `capability`, have
17
+ the skill produce the lifecycle walkthrough and check every `must_include` bullet by hand.
@@ -0,0 +1,43 @@
1
+ skill: power-automate
2
+
3
+ should_trigger:
4
+ - prompt: "Create a Power Automate cloud flow via the Dataverse Web API and turn it on from my deploy script."
5
+ why: Canonical programmatic operate — POST /workflows (category 5) then enable via statecode; the core deliverable.
6
+ - prompt: "Why can't I edit my flow under 'My Flows' with the API? Every call I make fails."
7
+ why: The load-bearing honesty limit — My Flows are not code-manageable; must route to the solution-aware answer.
8
+ - prompt: "Enable my Power Automate flow by code — set statecode to 1 after I create it."
9
+ why: Enable-via-statecode is the explicit lifecycle step new flows come up Off (0) and need PATCH to 1.
10
+ - prompt: "Automatizar el despliegue de un flujo de Power Automate dentro de una solución de Dataverse desde CI."
11
+ why: Spanish; solution-aware programmatic deployment with a service principal — squarely this skill.
12
+ - prompt: "Use FlowStudio MCP to pull the action-level inputs and outputs of my flow's last failed run."
13
+ why: MCP run-history debugging that the Dataverse API doesn't expose per action — the MCP path this skill owns.
14
+ - prompt: "PATCH the clientdata of an existing workflow row to update the flow's definition."
15
+ why: Update lifecycle against the workflow table, including the clientdata string-encoding concern.
16
+
17
+ should_not_trigger:
18
+ - prompt: "Design a 'new Stripe payment → post to Teams' automation and give me the importable definition."
19
+ route_to: automation-flows
20
+ why: Designing what the flow does and authoring its definition is the design skill; this one operates a definition, it doesn't invent it.
21
+ - prompt: "Should I use Power Automate or n8n for about 50k runs a month?"
22
+ route_to: automation-strategy
23
+ why: Platform selection by billing/constraints, not operating a live Power Automate flow.
24
+ - prompt: "Write a typed TypeScript client for the Dataverse Web API with token refresh, pagination, and exponential backoff."
25
+ route_to: api-connector-builder
26
+ why: Generic client engineering (auth/pagination/retry) even though the API is Dataverse; this skill uses endpoints surgically, it doesn't build the client.
27
+ - prompt: "Build the Express endpoint that receives my flow's HTTP-trigger POST and verifies it."
28
+ route_to: webhooks
29
+ why: Building the inbound receiver in your own app; this skill operates/triggers flows, it does not build the receiver.
30
+ - prompt: "Send an email and read a calendar via Microsoft Graph from my Node backend."
31
+ route_to: api-connector-builder
32
+ why: Scripting Microsoft 365 via Graph directly is not a Power Automate flow; no first-party MS-Graph skill, so build a typed Graph client.
33
+
34
+ capability:
35
+ - scenario: "User has an Entra app registration and wants to create an automated cloud flow inside a Dataverse solution, enable it, later update its definition, and finally remove it safely. Walk the full programmatic lifecycle."
36
+ must_include:
37
+ - "Acquire an Entra OAuth2 token from https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token (client_credentials) with scope {PA_DATAVERSE_URL}/.default."
38
+ - "POST /api/data/v9.2/workflows with category=5, type=1, primaryentity=\"none\", name, and clientdata as a STRING-encoded JSON (definition + connectionReferences), not a nested object."
39
+ - "State the honesty limit: only flows inside a Dataverse solution are code-manageable; classic My Flows cannot be created or edited by code."
40
+ - "New flow comes up statecode=0 (Off); enable with PATCH workflows({workflowid}) statecode=1 using If-Match: *; validate connection references resolve before enabling."
41
+ - "Update via PATCH (send only changed fields), and note api.flow.microsoft.com is unsupported — use the Dataverse Web API or the Power Automate Management connector; flag api.powerplatform.com as an evolving alternative."
42
+ - "Irreversibility rule: ExportSolution to a saved base64 zip BEFORE DELETE workflows({workflowid}) — deletion has no undo."
43
+ - "For action-level run debugging use the third-party FlowStudio MCP (get_live_flow_run_action_outputs), flagged as NOT Microsoft-affiliated."