powerappscontrol-demo.mp4
An MCP server for UX testing of Power Apps. It drives a canvas or model-driven app exactly like a real user — synthesized mouse + keyboard, DWM-aware screenshots, UI-Automation element lookup — then records the session to video, replays a test script any number of times (optionally across several windows at once for light load testing), and writes a self-contained HTML report summarizing the runs.
It is a specialization of the TotalControl desktop-control engine: the whole low-level interaction layer is reused, with a UX-testing layer (sessions, scripts, smoke tests, recording, reporting) built on top.
Built for Microsoft Scout, GitHub Copilot CLI and any MCP-compatible host. Windows only (.NET 10, PerMonitor-V2 DPI-aware).
-
Install. Download the latest Release:
- Installer (recommended): grab
PowerAppsControl-<ver>-setup.zip, unzip, run the.exe, follow the wizard. It auto-registers the server (and the/PowerAppsControlskill) with Microsoft Scout and the GitHub Copilot CLI, and offers to install FFmpeg (needed for the video recording). - Portable: grab
PowerAppsControl-<ver>-portable-win-x64.zip, unzip, then runPowerAppsControl.exe --registeronce. - Unsigned build → Windows SmartScreen may warn: More info → Run anyway.
- Installer (recommended): grab
-
Restart your host (Scout / Copilot CLI) so it loads the new server + skill.
-
Just ask. In the chat, say:
Test my Power App https://apps.powerapps.com/play/…
The agent will open and verify the app, ask how you want to test it (smoke test / propose a plan / your own plan) with clickable buttons, then run it in a recorded session and hand you an HTML report.
That's it — you don't need to learn the tools; the companion skill drives the workflow.
This tool controls your REAL mouse, keyboard, and screen, and drives your REAL, signed-in Power App. There is no sandbox. By using it you accept the following:
- It acts on live data. Runs happen against whatever tenant/app/records you point it at. It defaults to read-only navigation, but any test that clicks Save, Submit, Delete, Send, or a command-bar action can create, modify, delete, or send real data. Only approve such steps when you are certain, and prefer a non-production / developer environment for anything destructive.
- It takes over input. While a session is active the tool moves your cursor and types. Don't use the machine for other work during a run. You can stop instantly by clicking the ✕ on the crimson "Under Agent Control" frame around the app window.
- It records your screen. Session videos and screenshots are written to
%USERPROFILE%\PowerAppsControl\Sessions\…. They may capture sensitive on-screen data (records, names, tokens visible in the app). Review before sharing; nothing is uploaded anywhere by this tool. - It downloads from the internet. The updater and FFmpeg installer fetch from GitHub /
winget / a static FFmpeg build. Only run
--updateif you trust the source repo. - No warranty. This software is provided "AS IS", without warranty of any kind, and is licensed under the GPL-3.0 (see Sections 15–16 of the LICENSE — Disclaimer of Warranty and Limitation of Liability). You are solely responsible for what you test, in which environment, and for any consequences. The authors accept no liability for data loss, unintended changes, downtime, or any other damages.
- Use only where you're authorised. Test apps and tenants you own or have explicit permission to test. Respect your organisation's policies and any applicable regulations.
If you don't accept these terms, don't run it.
You describe what you want in plain language — you never write JSON or scripts. Both modes produce a recorded session and an HTML report.
Point the agent at an app and say "smoke test it". It explores the app in depth and read-only — opening menus, inspecting forms, sorting/filtering grids, opening records, navigating screens — without saving, submitting, or deleting anything. It then hands you a repeatable, plain-English test plan (a natural-language script both you and an agent can read and re-run), included in the report and saveable to reuse as a regression test.
Tell the agent what to test in plain language (e.g. "open the first warehouse, check the Name field, go back, sort by Created On"), or point it at a saved plan. It runs the plan — optionally N times or across several windows at once for a light load test — with per-step pass/fail and timing.
Under the hood the agent compiles your plain-language plan into precise UI steps at run time. That machine form is an internal detail — you only ever read and write natural language.
While a session is live the user always sees what's happening:
- Crimson "Under Agent Control" frame around every window being driven — a rounded frame that hugs the window border (works for maximized windows too), with an integrated status pill on its top edge showing a pulsing REC dot and the current step.
- Instant abort: click the ✕ on any control frame to stop everything. The next
tool call returns
⛔ ABORTED BY USER, the recording finalizes, and the agent stops.
The server drives the workflow's decision points as clickable buttons using the MCP elicitation capability — the choice logic lives in the server, not the agent prompt:
open_power_appverifies the URL, then asks which mode to run (Smoke test / Run my plan) as buttons and returns the user's pick.ask_user_choice(question, options[])is a reusable prompt for any decision — approve a plan, re-run vs. fix, etc.
If the connected MCP client doesn't support elicitation, these gracefully fall back to returning the options as text so the agent can ask in chat.
Testing tools are gated on an active session, so every action is framed, recorded and reported.
start_test_session ──► run_test_script / smoke_step ──► end_test_session
(control + REC + HUD) (do the testing) (stop REC, write report)
| Tool | Purpose |
|---|---|
start_test_session(appName, windowQuery?, maxWindows?, fps?, recordVideo?) |
Resolve + control the app window(s), start recording, show the frame status pill. |
test_session_status() |
Current session: app, windows, mode, runs so far, exploration steps. |
end_test_session() |
Stop recording, release windows, write report.html + report.json. |
smoke_step(action, description?, …) |
Perform one read-only exploratory action and record it to the exploration log. |
get_exploration_log(name?) |
Return the plain-English exploration log (author your test plan from it). |
save_test_plan(name, plan) |
Save a natural-language plan to the library and attach it to the report. |
load_test_plan(name) / list_test_plans() |
Read / list saved natural-language plans. |
run_test_script(scriptJson, runs?, parallelWindows?) |
Execute a plan (the agent compiles the plan to steps) runs times across parallelWindows windows. |
The desktop engine tools are also available for free-form exploration:
find_window, control_window, release_window, screenshot_window,
click_in_window, send_keys, scroll_mouse, find_element, hover_preview,
record_window, crop_screenshot, and the absolute mouse/keyboard tools.
You describe a test in plain language — a numbered list of steps that name each control by its visible label and state the expected outcome. The agent (or a smoke test) produces plans in exactly this form, and the report shows them this way too:
# Contoso Referrals — submit a referral
1. Wait for the app to finish loading — the "New referral" button should be visible.
2. Click "New referral" — the referral form opens.
3. Enter "Jane Doe" in the "Patient name" field, then Tab.
4. Click "Submit".
5. Verify a "Thank you" confirmation appears.
That's the whole authoring model — no JSON, no coordinates. Behind the scenes the agent compiles each line into precise UI-Automation actions at run time (preferring controls by name so the plan survives layout, DPI, and theme changes); that machine form is never shown to you and never the saved artifact.
- Repeat: ask to run a plan N times in the same window to check consistency.
- Load: ask to run it across M windows at once to simulate concurrent users (open M copies of the app first).
Because Windows serializes real synthesized input (one cursor, one foreground window), a load pass interleaves: for each step the runner executes it on every window in turn, so all M windows advance through the plan together. The report breaks results down per window and per run.
Everything for a session lands in one portable folder:
%USERPROFILE%\PowerAppsControl\
├─ Plans\ saved natural-language test plans (*.md)
└─ Sessions\<app>_<timestamp>\
├─ session.mp4 the session recording
├─ report.html self-contained HTML report (open in any browser)
├─ report.json the raw result data
└─ screenshots\ per-step captures (failures + screenshot steps)
The HTML report includes KPI tiles (runs, pass rate, avg duration, windows), the embedded video, per-run expandable step tables with inline screenshots, and — for smoke sessions — the repeatable, plain-English test plan.
- Windows 10/11, .NET 10 SDK (
net10.0-windows). - FFmpeg for video recording. You don't have to install it by hand — the installer
offers to fetch it, and you can run
PowerAppsControl.exe --ensure-ffmpegor call theensure_ffmpegMCP tool at any time (winget first, then a per-user direct download). Without FFmpeg, sessions still run and report — they just have no video. To point at an existing binary, setPOWERAPPSCONTROL_FFMPEGtoffmpeg.exe.
Grab the latest build from the Releases page:
- Installer (recommended): download
PowerAppsControl-<ver>-setup.zip, unzip, run the.exe, follow the wizard. The build is unsigned, so Windows SmartScreen may show "unknown publisher" — choose More info → Run anyway. The installer automatically registers PowerAppsControl as an MCP server with Microsoft Scout and the GitHub Copilot CLI (see below) and unregisters it on uninstall. - Portable: download
PowerAppsControl-<ver>-portable-win-x64.zip, unzip anywhere, runPowerAppsControl.exe. No admin rights, no installer. It's self-contained (bundles the .NET runtime), so it runs on a clean machine. Register it with one command:.\PowerAppsControl.exe --register
Verify your download against SHA256SUMS.txt attached to the release.
PowerAppsControl can register itself with the two supported MCP hosts — no manual JSON editing required:
PowerAppsControl.exe --register # add server + skill to Scout + GitHub Copilot CLI
PowerAppsControl.exe --unregister # remove from both
PowerAppsControl.exe --ensure-ffmpeg # install FFmpeg if missing (video recording)
PowerAppsControl.exe --check-update # check GitHub Releases for a newer version
PowerAppsControl.exe --update # download + install the latest (with a progress bar)
PowerAppsControl.exe --help # usage--register merges an entry into (preserving everything else already there):
| Host | Config file | Entry |
|---|---|---|
| GitHub Copilot CLI | %USERPROFILE%\.copilot\mcp-config.json |
mcpServers["PowerAppsControl"] |
| Microsoft Scout | %USERPROFILE%\.copilot\m-mcp-servers.json |
servers["powerappscontrol"] |
The Scout entry is only written if that file already exists (i.e. Scout is installed). The tool list is discovered by reflection, so it always matches what the server exposes. Restart Scout / the Copilot CLI after registering for the change to take effect.
Registering also installs a companion skill that teaches the agent the end-to-end
workflow (open & verify → choose a mode → recorded session → report). Without it, agents
see the tools but don't know how to sequence them. It's installed for both hosts —
%USERPROFILE%\.copilot\m-skills\PowerAppsControl\ (Scout, plus a skills-metadata entry)
and %USERPROFILE%\.copilot\skills\PowerAppsControl\ (GitHub Copilot CLI). Invoke it
explicitly with /PowerAppsControl, or just say "test my power app ". --unregister
removes it from both.
The skill also drives all clickable decisions (mode choice, plan approval) through the
host's native picker (m_ask_user in Scout), because most hosts don't advertise the
MCP elicitation capability that the server's own ask_user_choice relies on.
PowerAppsControl updates itself from GitHub Releases (no backend). --check-update
reports whether a newer version exists; --update downloads the right asset (portable zip
or installer, matching how you installed) with a progress bar and applies it via a helper
that waits for the host to close, then re-registers. Agents can also call the
check_for_update / update_server MCP tools. After an update, restart your MCP host
to load the new version.
dotnet build PowerAppsControl.sln -c Release
# run directly as an MCP stdio server:
dotnet run --project src/PowerAppsControl -c ReleasePowerAppsControl.sln solution (root)
global.json .NET SDK pin
src/PowerAppsControl/ the MCP server project (source + skill/)
installer/ Inno Setup script + update helper
.github/workflows/release.yml tag-triggered release pipeline
docs/ demo video + assets
{
"mcpServers": {
"PowerAppsControl": {
"command": "C:\\path\\to\\PowerAppsControl.exe"
}
}
}Point command at the installed/portable PowerAppsControl.exe (or the bin\Release\net10.0-windows\ build output during development).
| Variable | Effect |
|---|---|
POWERAPPSCONTROL_FFMPEG |
Explicit path to ffmpeg.exe for recording. |
POWERAPPSCONTROL_REQUIRE_WINDOW_SELECTION |
0/false/off disables the desktop-engine window-selection gate (on by default). |
These tools drive the user's real desktop and real Power App — there is no sandbox. The agent is instructed not to submit forms that create/delete real records, send messages, or make purchases without explicit confirmation, and to avoid destructive actions during multi-window load runs.
Licensed under the GNU General Public License v3.0 or later (GPL-3.0-or-later) — see LICENSE. Author: Ilya Fainberg.