MCP server for Power Apps via the Power Platform CLI: solutions, canvas Power Fx source, Dataverse metadata, FetchXML, gated imports
- ✓Open-source license (MIT)
- ✓Actively maintained (<30d)
- ✓Clear description
- ✓Documented (README)
claude mcp add fxray -- uvx fxray{
"mcpServers": {
"fxray": {
"command": "uvx",
"args": ["fxray"]
}
}
}Resumen de MCP Servers
# fxray
<!-- mcp-name: io.github.S-CurveLabs/fxray -->
An X-ray for Power Fx: an MCP server that wraps the Power Platform CLI (`pac`) so Claude, GitHub Copilot (VS Code
agent mode) or any MCP client can inspect and work with **Power Apps solutions, canvas app source and Dataverse**:
list and export solutions, read canvas apps as text (screens, controls, Power Fx formulas, data sources), read
table / column / relationship metadata, run read-only FetchXML, diff two solution versions, run the solution
checker, and (gated, dry-run by default) pack, import and publish.
| Area | Tools |
|---|---|
| Setup & environments | `pac_status` `whoami` `list_environments` |
| Solutions (live) | `list_solutions` `solution_components` `list_canvas_apps` `export_solution` `solution_check` |
| Solutions (offline) | `unpack_solution` `solution_components` `diff_solutions` |
| Canvas app source (offline) | `canvas_overview` `list_controls` `get_control` `search_formulas` `canvas_data_sources` `app_checker_results` |
| Dataverse metadata | `list_tables` `describe_table` `list_relationships` |
| Data, **read-only** | `fetch_query` (FetchXML with a row cap) |
| Writes, **dry-run by default** | `pack_solution` `import_solution` `publish_customizations` |
## Safety model
- **Environment allowlist.** Live tools only reach environments listed in `allowed_environments`. Every call
passes `--environment` explicitly, so pac's currently selected org is never used implicitly, and `whoami` and
every write re-check that the org pac actually connected to is allowlisted. **An empty allowlist (or no config
file) disables every live tool**; offline tools still work.
- **Read-only by default.** `pack_solution`, `import_solution` and `publish_customizations` default to
`dry_run=true` and return a plan plus the exact pac command. Executing needs `allow_writes = true` in the config
**and** `dry_run=false` on the call. Have the assistant show you the plan first.
- **Imports** default to `mode="update"` (never deletes). `upgrade` (managed only) is explicit and flagged as
deleting components missing from the zip. Blockers (managed/unmanaged mismatch, managed downgrade, empty
`DatabaseReferences`) stop execution. Before importing over an unmanaged solution the current one is exported
to `out/backups/<env>/` and the result carries an undo recipe; managed targets cannot be exported, which the
plan says.
- **Local output** (exports, unpacks, packs, checker results) goes under `output_dir`; `protected_paths` are never
written to.
- FetchXML is read-only by nature; it is parsed and validated (well-formed, no DOCTYPE, one entity) before it
reaches pac.
- No secrets in the config: pac keeps its own auth profiles. pac's signed checker-results URL is not returned.
## Install
```powershell
pip install fxray # or run it without installing: uvx fxray
```
Needs Python 3.11+ and the Power Platform CLI:
```powershell
dotnet tool install --global Microsoft.PowerApps.CLI.Tool # needs the .NET SDK
pac auth create --environment https://yourorg.crm.dynamics.com/ # a person, in a terminal (browser sign-in)
```
fxray finds pac on `PATH`, then at `~\.dotnet\tools\pac.exe` (the dotnet global-tool folder); the Windows MSI
install's `pac.cmd` shim is resolved to the `pac.exe` it wraps. MCP clients often start servers with a shorter
PATH than your terminal, so if pac works in a terminal but not in fxray, set `pac_path` to the full path.
Tested on Windows with pac 2.9.3. pac is a .NET tool and runs on macOS/Linux too; fxray should, but that is untested.
Interactive sign-in is impossible from an MCP server: when pac's token expires the tools say so and stop, and a
person runs `pac auth create` (or `pac auth select`) again in a terminal.
## Configure
Copy [`fxray.example.toml`](https://github.com/S-CurveLabs/fxray/blob/main/fxray.example.toml) to `fxray.toml`
and list the environments fxray may reach. Lookup order (first file found wins):
1. `$FXRAY_CONFIG` (an explicit path; an error if it does not exist)
2. `$FXRAY_WORKSPACE\fxray.toml`
3. `.\fxray.toml` (the folder the MCP client starts the server in)
4. `%LOCALAPPDATA%\fxray\fxray.toml` (Windows; `~/.config/fxray/fxray.toml` elsewhere; override the folder with `$FXRAY_HOME`)
The per-user file is the simplest choice: then `FXRAY_CONFIG` is not needed at all. The file is re-read on every
call (no restart needed).
| Setting | Default | Meaning |
|---|---|---|
| `pac_path` | auto | full path to pac; unset = `PATH`, then `~\.dotnet\tools` |
| `allowed_environments` | `[]` | URLs or environment ids. **The only environments any tool reaches.** Empty = live tools refuse |
| `default_environment` | first allowlisted | used when a tool gets no `environment` |
| `allow_writes` | `false` | write tools only plan unless this is true **and** the call passes `dry_run=false` |
| `output_dir` | `out` (next to the config) | exports, unpacked folders, packs, checker output, import backups |
| `protected_paths` | `[]` | folders no tool may write into (e.g. a schema-as-code repo whose files are generated) |
| `max_rows` | 200 | `fetch_query` row cap (ceiling 5000) |
| `timeout_seconds` / `long_timeout_seconds` | 120 / 1800 | pac timeouts (quick calls / export, import, check) |
```toml
allowed_environments = ["https://contoso-dev.crm.dynamics.com/"]
allow_writes = false
output_dir = "out"
```
## Register
**Claude Code:**
```powershell
claude mcp add --scope user fxray -- uvx fxray
# or, with the config somewhere other than the per-user folder:
claude mcp add --scope user fxray -e FXRAY_CONFIG=C:\path\to\fxray.toml -- uvx fxray
```
**VS Code / Copilot.** Add the server to the **user-level** `%APPDATA%\Code\User\mcp.json` so it works from every
window (a workspace `.vscode/mcp.json` only loads once you trust that workspace's MCP servers):
```json
{
"servers": {
"fxray": {
"type": "stdio",
"command": "uvx",
"args": ["fxray"],
"env": { "FXRAY_CONFIG": "C:\\path\\to\\fxray.toml" }
}
}
}
```
Drop the `env` block if the config is in the per-user folder. Then ask the assistant to run `pac_status`: it shows
which config file was used, which pac was found and its version, and pac's auth profiles (each flagged as
allowlisted or not).
## Tools
`source` = a solution `.zip`, an unpacked solution folder (`pac solution unpack` / `export_solution`), a canvas
`.msapp`, or a `pac canvas unpack --layout SourceCode` folder (`Src/*.pa.yaml` + `.msapr`). Offline tools need no pac.
| Tool | Kind | What it does |
|---|---|---|
| `pac_status` | read | config, pac version, auth profiles (flags whether each profile's env is allowlisted) |
| `whoami` | live read | `pac env who` for an allowlisted env; verifies the connected org is allowlisted |
| `list_environments` | live read | environments the account sees, marked allowed / not allowed |
| `list_solutions` | live read | name, version, managed, publisher (managed system solutions hidden by default) |
| `solution_components` | live / offline | live: every component row with resolved names (tables, apps, flows, env vars, connection refs); offline: manifest, publisher prefix, root components, missing dependencies |
| `list_canvas_apps` | live / offline | `pac canvas list`, or the apps inside a solution with their AppVersion stamps |
| `export_solution` | local output | export (read-side on the env) to a timestamped folder under `out/exports/`, unpacked by default |
| `unpack_solution` | local output | `pac solution unpack` into `out/unpacked/` |
| `solution_check` | local output | `pac solution check` (cloud checker), results summarized by rule and severity |
| `diff_solutions` | offline | two versions: manifest, tables/columns/choices, relationships, canvas screens/controls/formula diffs/data sources, flows/env vars, changed files |
| `canvas_overview` | offline | screens (Studio order), control counts and types, data sources, app checker counts |
| `list_controls` | offline | control tree, filter by screen / control type |
| `get_control` | offline | one control's type, parent, children and Power Fx formulas |
| `search_formulas` | offline | substring or regex over every formula; `code_only` ignores strings and comments |
| `canvas_data_sources` | offline | each data source + the formulas using it; unreferenced ones, meta.xml `DatabaseReferences`, schema-cache drift |
| `app_checker_results` | offline | Studio's saved App Checker results (SARIF inside the msapp) |
| `list_tables` | offline / live | tables in a solution or a canvas app's cached schema; live = names only |
| `describe_table` | offline | columns (type, required, length, lookup targets, choice values), primary id/name, relationships |
| `list_relationships` | offline | 1:N (with lookup column, cascade delete) and N:N |
| `fetch_query` | live read | read-only FetchXML with a row cap |
| `pack_solution` | write (local) | `pac solution pack`; dry-run plan with canvas warnings |
| `import_solution` | write | plan: verified target org, installed vs package version/managed, install/update/upgrade, blockers, warnings, backup, exact command |
| `publish_customizations` | write | `pac solution publish` |
Typical flow: `list_solutions` → `export_solution` (zip + unpacked folder) → read offline with `source=` that
folder: `solution_components`, `describe_table`, `canvas_overview`, `search_formulas`, `canvas_data_sources` →
change the source → `pack_solution` → `import_solution` (dry run, then for real) → `publish_customizations`.
## Traps it checks for
Canvas apps kept as source (a generator or hand-maintained `.pa.yaml`, packed with `pac solution pack` and
imported) fail in ways Studio does not show:
- **Studio prunes unreferenced data sources** on the next save/publish: `canvas_data_sources` flags data sources
no formula uses (a Power Fx lexer skips strings and comments, so `"Saved to Orders"` is not a reference).
- **Empty `DatabaseReferences` in meta.xml** breaks everyLo que la gente pregunta sobre fxray
¿Qué es S-CurveLabs/fxray?
+
S-CurveLabs/fxray es mcp servers para el ecosistema de Claude AI. MCP server for Power Apps via the Power Platform CLI: solutions, canvas Power Fx source, Dataverse metadata, FetchXML, gated imports Tiene 0 estrellas en GitHub y su última actualización registrada es del 2026-09-23.
¿Cómo se instala fxray?
+
Puedes instalar fxray clonando el repositorio (https://github.com/S-CurveLabs/fxray) o siguiendo las instrucciones del README en GitHub. ClaudeWave también te ofrece bloques de instalación rápida en esta misma página.
¿Es seguro usar S-CurveLabs/fxray?
+
Nuestro agente de seguridad ha analizado S-CurveLabs/fxray y le ha asignado un Trust Score de 87/100 (tier: Trusted). Revisa el desglose completo de comprobaciones superadas y flags en esta página.
¿Quién mantiene S-CurveLabs/fxray?
+
S-CurveLabs/fxray es mantenido por S-CurveLabs. La última actividad registrada en GitHub es del 2026-09-23, con 0 issues abiertos.
¿Hay alternativas a fxray?
+
Sí. En ClaudeWave puedes explorar mcp servers similares en /categories/mcp, ordenados por popularidad o actividad reciente.
Despliega fxray en tu cloud
Lleva este repo a producción en minutos. Cada plataforma genera su propio entorno con variables de entorno editables.
¿Mantienes este repo? Añade un badge a tu README
Pega el badge en tu README de GitHub para mostrar que está auditado por ClaudeWave. Cada badge enlaza de vuelta a esta página y muestra el Trust Score actual.
[](https://claudewave.com/repo/s-curvelabs-fxray)<a href="https://claudewave.com/repo/s-curvelabs-fxray"><img src="https://claudewave.com/api/badge/s-curvelabs-fxray" alt="Featured on ClaudeWave: S-CurveLabs/fxray" width="320" height="64" /></a>Más MCP Servers
Fair-code workflow automation platform with native AI capabilities. Combine visual building with custom code, self-host or cloud, 400+ integrations.
User-friendly AI Interface (Supports Ollama, OpenAI API, ...)
An open-source AI agent that brings the power of Gemini directly into your terminal.
Real-time global intelligence dashboard. AI-powered news aggregation, geopolitical monitoring, and infrastructure tracking in a unified situational awareness interface
🕷️ An adaptive Web Scraping framework that handles everything from a single request to a full-scale crawl! Don't be shy, join here: https://discord.gg/EMgGbDceNQ and follow here for daily tips and tricks: https://x.com/Scrapling_dev
The fastest path to AI-powered full stack observability, even for lean teams.