| name | pp |
| description | Use pp, the Microsoft Power Platform CLI/MCP/Desktop/Setup Manager toolchain, for account auth, environment management, Dataverse, Power Automate, Microsoft Graph, SharePoint REST, BAP, Power Apps, Canvas Authoring, jq-filtered API requests, and Power Platform investigation workflows. Trigger when the user mentions pp, Power Platform APIs, Dataverse, Power Automate flows, SharePoint REST, Canvas apps, Power Apps authoring, or asks to query/inspect/mutate a configured environment. |
pp
pp is a Node 22+ CLI, library, MCP server, lightweight Setup Manager, and Electron desktop app for Microsoft Power Platform work. It provides authenticated requests against Dataverse, Power Automate, Microsoft Graph, SharePoint REST, BAP, Power Apps, and the internal Canvas Authoring service.
Source repo on this machine: /home/calluma/projects/pp.
First Choice
If pp MCP tools are available in the current assistant, prefer them for account,
environment, and API requests. They avoid shell quoting problems and support the
same request options as the CLI, including jq, readIntent, rawBody,
responseType, query, and allowInteractiveAuth.
Use the CLI when the user asks for terminal commands, when MCP tools are not available, when the user wants to launch a local host such as pp setup or pp mcp, or for commands not exposed by MCP such as pp canvas-authoring yaml fetch --out.
Invocation
pp --version
pp --help
pp-setup --help
node /home/calluma/projects/pp/dist/index.cjs --help
Installed entry points expose:
pp - full CLI
pp-mcp - MCP server entry point
pp-setup - browser Setup Manager launcher
PP Desktop - Electron app packaged separately from the CLI binaries
From source:
cd /home/calluma/projects/pp
pnpm install
pnpm build
Config Model
pp stores accounts, environments, MSAL cache, browser profiles, and Canvas sessions in a global config directory. PP Desktop, Setup Manager, CLI, and MCP all share this config and auth state.
- Linux/macOS default:
$XDG_CONFIG_HOME/pp or ~/.config/pp
- Windows default:
%APPDATA%\pp
- Override any command with
--config-dir DIR
- Main config file:
config.json
Do not assume a repo-local pp.config.yaml; migrate old configs with
pp migrate-config [--source-config PATH|--source-dir DIR] --apply.
Use pp auth list and pp env list for current state instead of hard-coding
account or environment names in this skill.
Accounts
pp auth list
pp auth inspect <account>
pp auth login <account>
pp auth login <account> --device-code
pp auth login <account> --client-secret --tenant-id <tenant> --client-id <client> --client-secret-env SECRET_ENV_VAR
pp auth login <account> --env-token --env-var ACCESS_TOKEN_ENV_VAR
pp auth login <account> --static-token --token <token>
pp auth remove <account>
Useful login flags:
--login-hint USER
--prompt select_account|login|consent|none
--device-code-fallback
--force-prompt
--no-interactive-auth
When browser auth hangs or the tenant blocks the localhost flow, retry with
--device-code. If a noninteractive request fails because a token expired,
rerun without --no-interactive-auth or refresh with pp auth login.
Environments
pp env list
pp env inspect <alias>
pp env discover <account>
pp env add <alias> --url https://org.crm.dynamics.com --account <account>
pp env add <alias> --url https://org.crm.dynamics.com --account <account> --access read-only
pp env remove <alias>
pp env add discovers and stores the Maker environment id and tenant id. Most
runtime commands take --env <alias> and optionally --account <account> to
override the environment's default account.
Read-only environments block non-GET/HEAD requests unless --read is passed.
Use --read only for POST endpoints that are known to be read-only, such as
some metadata, WhoAmI, or authoring read endpoints.
Connectivity
pp whoami --env <alias>
pp ping --env <alias> --api dv|flow|graph|bap|powerapps|canvas-authoring
pp token --env <alias> --api dv|flow|graph|bap|powerapps|canvas-authoring
pp token --env <alias> --api canvas-authoring --device-code
pp whoami uses the Dataverse WhoAmI operation. If it is not enough for a
tenant-specific issue, make an explicit Dataverse request:
pp dv /WhoAmI --env <alias> --method GET
Request Commands
General form:
pp request [dv|flow|graph|sharepoint|bap|powerapps|canvas-authoring|custom] <path|url> [--env <alias>|--account <account>]
pp <api> <path|url> [--env <alias>|--account <account>]
Common flags:
--method GET|POST|PATCH|DELETE
--query K=V repeated
--query-json JSON for a shell-friendly equivalent of the MCP query object
--header 'Name: value' repeated
--body JSON or --body-file FILE for JSON bodies
--raw-body TEXT or --raw-body-file FILE for non-JSON bodies
--response-type json|text|void
--timeout-ms MS
--jq EXPR
--jq-raw
--jq-scope response|envelope
--jq-timeout-ms MS
--jq-max-output-bytes BYTES
--format json|yaml|text
--read
--no-log
--log-results
--no-log-results
--no-interactive-auth
--query K=V and --query-json '{"key":"value"}' both map to the MCP
query object. Repeated --query flags override matching keys from
--query-json.
--jq runs in-process with jq-wasm; use API-native $select, $filter, and
$top first, then use --jq to reshape returned JSON. By default, jq sees
only the API response body and pp keeps its normal { request, response, status, headers } envelope with response replaced by the jq output. Use
--jq-scope envelope when jq should see the whole pp envelope and return jq's
output directly.
MCP request tools accept the same concepts as structured JSON: query: {"$top":"50"} and jq as either a string or an object such as
{"expr": ".value[].name", "raw": true, "scope": "response", "timeoutMs": 2000, "maxOutputBytes": 50000}. Use scope: "envelope" for
expressions like {status, rows: .response.value} that need status, headers,
or request metadata.
Absolute URLs are allowed for all APIs. If no API is specified, pp auto-detects
Graph, SharePoint, Power Apps, Canvas Authoring, BAP, Flow, Dataverse API URLs,
or falls back to custom for other absolute URLs and dv for relative paths.
Dataverse, Flow, BAP, Power Apps, Canvas Authoring, and custom requests are
environment-scoped and require --env. Graph and SharePoint are account-scoped:
use --account directly, or pass --env as a shorthand for the environment's
configured account.
Query Logging
pp writes a JSONL query log for explicit request surfaces by default: CLI
request commands and API aliases, MCP request tools, and Desktop requests that
opt into the shared request executor. Passive update checks, health checks,
setup loads, and other background traffic should not be treated as query-log
content.
The log lives in the shared config directory:
- Linux/macOS:
$XDG_CONFIG_HOME/pp/query-log.jsonl or ~/.config/pp/query-log.jsonl
- Windows:
%APPDATA%\pp\query-log.jsonl
--config-dir DIR changes the log path to DIR/query-log.jsonl
The active file rotates to query-log.jsonl.1 at 25 MiB by default. Entries
include timestamp, source, API, method, environment/account, redacted path,
query, headers, prepared request metadata, status, elapsed time, and
diagnostics. Names that look like auth headers, cookies, tokens, secrets,
passwords, API keys, client secrets, or session ids are redacted before writing.
Default capture policy is metadata-only:
{
"settings": {
"queryLog": {
"enabled": true,
"captureResults": false,
"captureRequestBody": false,
"maxResultBytes": 262144,
"maxFileBytes": 26214400
}
}
}
Use --no-log when a one-off CLI request should not write query-log metadata.
Use --log-results to capture a redacted response preview for that CLI request,
and --no-log-results to suppress response capture even when global settings
enable it. CLI request bodies are captured only through global settings, not a
per-command body flag.
MCP request tools use log: false to opt out for one request and
logResults: true or false to override response capture for that request.
When logResults is omitted, the saved settings.queryLog.captureResults
value applies.
PP Desktop has a Log tab with the settings editor, clear action, filterable
entry list, and detail panel. The Desktop settings toggles save the shared
settings.queryLog values, so they affect later CLI, MCP, and Desktop
requests that do not pass a per-request override. The Log detail view can show
stored response and request-body previews only for entries captured while the
corresponding setting or override was enabled.
Dataverse
pp dv roots relative paths at /api/data/v9.2 and authenticates against the
environment URL.
pp dv /accounts --env <alias> --query '$select=name,accountid' --query '$top=10'
pp dv /accounts --env <alias> --query '$filter=statecode eq 0'
pp dv /accounts(<guid>) --env <alias>
pp dv /accounts --env <alias> --method POST --body '{"name":"Test"}'
pp dv /accounts(<guid>) --env <alias> --method PATCH --body '{"name":"Updated"}'
pp dv /accounts(<guid>) --env <alias> --method DELETE --response-type void
pp dv /EntityDefinitions --env <alias> --query '$select=LogicalName,EntitySetName'
PowerShell, zsh, and bash quote $select, $filter, and $top differently.
Prefer single quotes around OData query arguments in POSIX shells. In Git Bash
on Windows, prefix commands with MSYS_NO_PATHCONV=1 when paths beginning with
/ are being rewritten.
Power Automate
pp flow is a Flow API request shortcut. It does not wrap workflow-definition
inspection or validation behind custom CLI verbs; agents should construct the
canonical Flow API requests directly.
API examples:
pp flow /flows --env <alias>
pp flow /flows/<flow-id> --env <alias>
pp flow /flows/<flow-id>/runs --env <alias>
pp flow /flows/<flow-id>/runs/<run-id>/actions/<action-name> --env <alias>
pp flow /flows/<flow-id>/triggers/manual/listCallbackUrl --env <alias> --method POST
Relative Flow paths are rooted at
/providers/Microsoft.ProcessSimple/environments/<makerEnvironmentId>.
api-version=2016-11-01 is added automatically.
For non-standard Flow URLs under https://api.flow.microsoft.com/providers/...,
pass the full URL with pp flow <url> or pp request flow <url> so pp keeps
the Flow auth resource but does not prepend the environment path.
For canonical Power Automate definition validation, call the Flow service
validation endpoints with the candidate flow payload. Use the existing flow id
when validating an update; for pre-create checks, the all-zero flow id has been
observed to work with the same request shape.
pp flow /flows/<flow-id>/checkFlowErrors --env <alias> --method POST --body-file payload.json
pp flow /flows/<flow-id>/checkFlowWarnings --env <alias> --method POST --body-file payload.json
pp flow /flows/00000000-0000-0000-0000-000000000000/checkFlowErrors --env <alias> --method POST --body-file payload.json
pp flow /flows/00000000-0000-0000-0000-000000000000/checkFlowWarnings --env <alias> --method POST --body-file payload.json
The validation body should use the Power Automate service shape, not a bare
workflow definition: {"properties":{"definition":...,"connectionReferences":{},"displayName":...}}.
For connector and operation metadata, prefer the catalog endpoints rather than
hard-coded connector schemas:
pp flow /operationGroups --env <alias> --method POST --body '{"searchText":"","visibleHideKeys":[],"usage":"Action","allTagsToInclude":[],"anyTagsToExclude":["ToS","Agentic"]}'
pp flow /operations --env <alias> --method POST --query '$top=250' --body '{"searchText":"","visibleHideKeys":[],"allTagsToInclude":["Action","Important"],"anyTagsToExclude":["Deprecated","Agentic","Trigger"]}'
pp flow /operationGroups/<group>/operations/<operation> --env <alias>
pp flow /apis/<connector>/apiOperations/<operation> --env <alias>
pp flow /apis/<connector> --env <alias>
Creating And Activating Solution Cloud Flows
For solution cloud flows, prefer the supported Dataverse workflow table over
raw api.flow.microsoft.com /flows creation. Microsoft documents
api.flow.microsoft.com as unsupported for code-based solution flow management;
use Dataverse Web API or the management connectors instead.
Create the flow with Dataverse:
pp dv /workflows --env <alias> --method POST --header 'Prefer:return=representation' --body-file create-flow.json
Minimum create payload:
{
"category": 5,
"name": "My scheduled Dataverse probe",
"type": 1,
"primaryentity": "none",
"clientdata": "{\"properties\":{\"connectionReferences\":{},\"definition\":{}},\"schemaVersion\":\"1.0.0.0\"}"
}
category: 5 means Modern Flow, type: 1 means Definition, and
primaryentity: "none" is used for automated, instant, and scheduled cloud
flows. clientdata is a JSON string containing properties.definition and
properties.connectionReferences.
For connector-backed actions in solution flows, the connection reference should
normally point at a Dataverse connection reference logical name, not at the
concrete API Hub connection name. A Dataverse action reference should look like:
{
"runtimeSource": "embedded",
"connection": {
"connectionReferenceLogicalName": "new_sharedcommondataserviceforapps_7f348"
},
"api": {
"name": "shared_commondataserviceforapps"
}
}
Do not include connection.name in the stored clientdata unless you have
evidence the target endpoint expects it. In live testing, flows created with the
concrete API Hub connection name could validate and appear installed, but failed
activation with InvalidOpenApiFlow or Flow /start returned
CannotStartUnpublishedSolutionFlow.
The workflow definition must include the normal $connections and
$authentication parameters, and connector actions should reference the
connection-reference key through inputs.host.connectionName:
{
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"$connections": { "defaultValue": {}, "type": "Object" },
"$authentication": { "defaultValue": {}, "type": "SecureObject" }
},
"triggers": {
"Recurrence": {
"recurrence": { "frequency": "Day", "interval": 1 },
"metadata": { "operationMetadataId": "<uuid>" },
"type": "Recurrence"
}
},
"actions": {
"List_accounts": {
"runAfter": {},
"metadata": { "operationMetadataId": "<uuid>" },
"type": "OpenApiConnection",
"inputs": {
"host": {
"connectionName": "shared_commondataserviceforapps",
"operationId": "ListRecords",
"apiId": "/providers/Microsoft.PowerApps/apis/shared_commondataserviceforapps"
},
"parameters": { "entityName": "accounts", "$top": 1 },
"authentication": "@parameters('$authentication')"
}
}
}
}
Activate with Dataverse, not Flow /start:
pp dv '/workflows(<workflowid>)' --env <alias> --method PATCH --body '{"statecode":1}' --response-type void
After activation, verify through the Flow API:
pp flow /flows/<workflowid> --env <alias> --jq '{name, resourceId:.properties.resourceId, state:.properties.state, installationStatus:.properties.installationStatus, installed:.properties.installedConnectionReferences}'
A successfully activated connector-backed flow should report state: "Started",
installationStatus: "Installed", a non-empty resourceId, and
installedConnectionReferences.*.impersonation.objectId. If resourceId is
set, runtime operations such as trigger run and run history may need the
runtime id rather than the Dataverse workflowid:
pp flow /flows/<resourceId>/triggers/Recurrence/run --env <alias> --method POST --response-type void
pp flow '/flows/<resourceId>/runs?$top=5' --env <alias>
PvaShareConnection is an internal Dataverse action on connectionreference;
do not rely on it for ordinary flow activation. If it returns a permission error
for the same caller that owns the API Hub connection, treat that as a sign the
wrong activation path is being used rather than as a missing share to fix.
For run investigations, inspect both /runs and trigger histories. Polling
triggers may show useful state in
/flows/<flow-id>/triggers/<trigger-name>/histories even when no parent run was
created. Action inputsLink and outputsLink URLs are pre-signed; fetch them
directly without auth headers.
Graph, SharePoint, BAP, And Power Apps
pp graph /me --env <alias>
pp graph /me --account <account>
pp graph /users --env <alias> --query '$top=5'
pp sp https://contoso.sharepoint.com/sites/site/_api/web --account <account>
pp sharepoint https://contoso.sharepoint.com/sites/site/_api/web/lists --env <alias>
pp bap /environments --env <alias>
pp bap /environments/<maker-environment-id> --env <alias>
pp powerapps /apps --env <alias>
pp powerapps /apps/<app-id> --env <alias>
pp powerapps /connections --env <alias>
Graph relative paths are rooted at /v1.0 unless the path starts with
/v1.0/ or /beta/. SharePoint REST requests require a full SharePoint URL.
The SharePoint token audience is the URL origin, such as
https://contoso.sharepoint.com for
https://contoso.sharepoint.com/sites/site/_api/web. BAP paths are rooted at
/providers/Microsoft.BusinessAppPlatform with default
api-version=2020-10-01. Power Apps paths are rooted at
/providers/Microsoft.PowerApps with default api-version=2016-11-01; the
literal {environment} in a path is replaced with the Maker environment id.
Canvas Authoring
pp canvas-authoring targets the internal Power Apps Studio authoring service.
These APIs are stateful, versioned, and not a public contract. Treat mutation
commands carefully because valid YAML/RPC calls can update the dirty draft open
in Maker/Studio.
Start with a live session:
pp canvas-authoring /gateway/cluster --env <alias> --read
pp canvas-authoring session start --env <alias> --app <app-id>
pp canvas-authoring session list
pp canvas-authoring session request --env <alias> --app <app-id> --path /api/yaml/fetch --read
YAML and metadata helpers:
pp canvas-authoring yaml fetch --env <alias> --app <app-id> --out ./canvas-src
pp canvas-authoring yaml validate --env <alias> --app <app-id> --dir ./canvas-src
pp canvas-authoring yaml validate --env <alias> --app <app-id> --dir ./canvas-src --with-signalr
pp canvas-authoring controls list --env <alias> --app <app-id>
pp canvas-authoring controls describe --env <alias> --app <app-id> Label
pp canvas-authoring apis list --env <alias> --app <app-id>
pp canvas-authoring datasources list --env <alias> --app <app-id>
pp canvas-authoring accessibility --env <alias> --app <app-id>
Low-level document-server calls:
pp canvas-authoring invoke --env <alias> --app <app-id> --class documentservicev2 --oid 1 --method keepalive
pp canvas-authoring rpc --env <alias> --app <app-id> --class document --oid 2 --method geterrorsasync
Use rpc for query-style methods that return a document-server result over the
authoring SignalR channel. Use invoke for direct /api/v2/invoke calls where
HTTP success is sufficient. Object ids such as document/2 come from the live
session and are not stable across all contexts.
Canvas Authoring uses a first-party client and a separate token cache for user
and device-code accounts. Device code is normal here because the Studio client
does not support pp's localhost browser callback.
Known limitation: the YAML round trip is unreliable for apps that use Canvas
components or component libraries. Use yaml fetch/validate primarily for
apps and screens without components, and require clean diagnostics plus
hasActiveCoauthoringSession: true before trusting a validate result.
Custom Requests
Use custom only for arbitrary full URLs such as webhook URLs or Flow HTTP
trigger callback URLs:
pp request custom https://prod-xx.logic.azure.com/workflows/... --env <alias> --method POST --body '{}' --response-type void
The auth resource for custom is the URL origin. For anonymous pre-signed URLs,
curl may be simpler.
Setup Manager
pp setup
pp setup --port 4734
pp setup --no-open
pp setup --idle-timeout-ms 600000
pp-setup --help
Setup Manager is the lightweight local browser surface for account management,
environment management, access checks, and MCP setup guidance. It does not
include the Console, Dataverse, Automate, Apps, Canvas, or Platform
workspaces.
Setup Manager binds to 127.0.0.1, uses a random port by default, and
requires a random per-run token for API requests. There is no LAN mode,
pairing flow, or pp ui compatibility path.
Desktop App
PP Desktop is the full Electron workspace for Setup, Console, Dataverse,
Automate, Apps, Platform, and related investigation workflows. It shares the
same config and auth cache as the CLI, Setup Manager, and MCP server. Launch
it from the installed app bundle or packaged desktop archive; there is no
pp desktop CLI subcommand.
Use the Desktop Log tab to inspect stored query-log entries and edit logging
settings. The Console can also force result capture on for a single request
without changing the global settings.
MCP Server
pp mcp
pp mcp --allow-interactive-auth
pp-mcp --tool-name-style underscore
Default MCP tool names are dotted:
pp.account.list, pp.account.inspect, pp.account.login, pp.account.remove
pp.environment.list, pp.environment.inspect, pp.environment.add, pp.environment.discover, pp.environment.remove
pp.request, pp.dv_request, pp.flow_request, pp.graph_request, pp.sharepoint_request, pp.bap_request, pp.powerapps_request
pp.whoami, pp.ping, pp.token
Use --tool-name-style underscore for clients that reject dotted tool names,
such as GitHub Copilot MCP integrations.
Updates And Completion
pp update
pp version
pp completion zsh
pp completion bash
pp completion powershell
Most commands passively check for update notices in the background. mcp,
token, completion, update, and version skip passive notices.
Gotchas
- The current source path is
/home/calluma/projects/pp; older references to
power-platform-devkit or packages/cli/dist/index.cjs are stale.
pp request and API shortcuts now return { request, response, status, headers }; update old scripts that read .body to read .response.
- The old
pp dv request <path> style is gone; use pp dv <path>.
- Graph and SharePoint are account-scoped and can use
--account without
--env; environment-scoped APIs still require --env.
pp sharepoint and pp sp require full SharePoint REST URLs and authenticate
to the SharePoint origin.
- Flow, BAP, and Power Apps add default
api-version query values
automatically. Passing the same query key overrides the default.
- For read-only environment aliases, pass
--read only when a POST is known to
be semantically read-only.
- Prefer
--response-type text for non-JSON responses and --response-type void for deletes, trigger calls, or endpoints where the body is irrelevant.
--body parses JSON; use --raw-body for XML, text, or already encoded
payloads.
pp is not published on npm; do not suggest npx pp. Use the installed
binaries, packaged desktop app, or the source checkout directly.
- There is no
pp ui or pp-ui; use pp setup / pp-setup for the
lightweight browser setup surface and PP Desktop for full graphical
workspaces.
Keeping This Skill Current
When pp changes, update this skill before ending the session if the change
affects user-facing commands, flags, auth behavior, MCP tools, Canvas Authoring
workflow, or common failure modes. Keep local customer/environment names out of
the skill unless the user explicitly asks for a personal operating note; prefer
pp env list and pp auth list for live state.