Dataverse Plugin MCP
# Dataverse Plugin MCP
An [MCP](https://modelcontextprotocol.io) server that lets an AI assistant (Claude, etc.) scaffold, build, register, query, and diagnose **Microsoft Dataverse (Power Platform / Dynamics 365) plug-ins** directly from a conversation — no need to leave the editor to open the Plugin Registration Tool or hand-write Web API calls.
Instead of reimplementing the registration logic from scratch, this MCP orchestrates tools you already use and already have authenticated on your machine:
- **[Power Platform CLI (`pac`)](https://learn.microsoft.com/power-platform/developer/cli/introduction)** — project scaffolding, build, and push of already-registered packages.
- **[Azure CLI (`az`)](https://learn.microsoft.com/cli/azure/)** — reuses your already-authenticated session (same account/tenant as `pac`) to get a token and talk directly to the **Dataverse Web API** (query and register SDK message processing steps, images, execution logs, etc.).
## Why this exists
Registering a Dataverse plug-in normally means switching between several tools: `pac plugin init` for the project skeleton, the **Plugin Registration Tool** (GUI) for the first registration, and either the PRT or manual Web API calls to bind messages/entities/stages and configure pre/post images. This MCP brings that whole flow into tools an AI assistant can call directly, including operations that usually only exist in the GUI (a full assembly diagnostic report, step editing, trace logs).
## Prerequisites
| Tool | Purpose | Install |
|---|---|---|
| [Python 3.11+](https://www.python.org/) | Runs the MCP server | — |
| [`uv`](https://docs.astral.sh/uv/) | Manages the environment/dependencies | `pip install uv` or the official installer |
| [Power Platform CLI (`pac`)](https://aka.ms/PowerAppsCLI) | Scaffolding, build, push, PRT | `dotnet tool install --global Microsoft.PowerApps.CLI.Tool` |
| [Azure CLI (`az`)](https://learn.microsoft.com/cli/azure/install-azure-cli) | Web API access token | official installer |
| .NET SDK | Builds the `net462` plug-in projects | [dotnet.microsoft.com](https://dotnet.microsoft.com) |
Authenticate both CLIs **once**, with the same account that has access to the target Dataverse environment:
```bash
pac auth create --environment https://YOUR-ENVIRONMENT.crm.dynamics.com
az login
```
The server never stores or asks for credentials — it always delegates to these two already-authenticated sessions.
## Installation
```bash
git clone https://github.com/lucasjesus0311/dataverse-plugin-mcp.git
cd dataverse-plugin-mcp
uv sync
```
### Configure in Claude Code
```bash
claude mcp add dataverse-plugins -- uv --directory "PATH/TO/dataverse-plugin-mcp" run dataverse_plugins_server.py
```
### Configure in Claude Desktop
Edit `claude_desktop_config.json` (under `%APPDATA%\Claude\`, or if the app was installed from the Microsoft Store, under `%LOCALAPPDATA%\Packages\<PackageId>\LocalCache\Roaming\Claude\`):
```json
{
"mcpServers": {
"dataverse-plugins": {
"command": "C:\\PATH\\TO\\uv.exe",
"args": [
"--directory", "C:\\PATH\\TO\\dataverse-plugin-mcp",
"run", "dataverse_plugins_server.py"
]
}
}
}
```
Use the full path to `uv.exe` (find it with `where uv` on Windows or `which uv` on macOS/Linux) — GUI apps don't always inherit the shell `PATH`. Fully restart Claude Desktop after saving.
## Available tools
24 tools, organized by stage of a plug-in's lifecycle. Full reference with every parameter in **[docs/TOOLS.md](docs/TOOLS.md)**.
| Category | Tools |
|---|---|
| **Environment** | `list_environments`, `select_environment` |
| **Local development** | `create_plugin_project`, `build_plugin` |
| **Registration** | `open_registration_tool`, `push_plugin_update` |
| **Steps (CRUD)** | `create_step`, `update_step`, `delete_step`, `toggle_step`, `set_secure_configuration` |
| **Images (CRUD)** | `create_step_image`, `list_images`, `update_image`, `delete_image` |
| **Query** | `list_registered_plugins`, `list_plugin_types`, `list_steps`, `list_available_messages` |
| **Deletion** | `delete_assembly`, `delete_package` |
| **Diagnostics** | `list_execution_logs`, `configure_tracing`, `xray_assembly` |
`xray_assembly` deserves a callout: it generates a complete report of a registered assembly in a single call — classes, steps with every setting, images, and the latest trace log entries.
## ⚠️ Security notice
Several tools perform **real writes** to the configured Dataverse environment (creating/editing/deleting steps, images, assemblies, packages; toggling tracing; updating the running code via `push_plugin_update`). They act with the same permissions as your `pac`/`az` session — **always test in a development environment**, never directly in production. Each tool's docstring clearly flags when an operation is destructive or irreversible.
## Known limitations
- **First-time registration of a package/assembly**: there is no CLI command or simple Web API call for this — Microsoft reserves this step for the Plugin Registration Tool or the Visual Studio extension (which reflect over the assembly to auto-discover its classes). Use `open_registration_tool()` for this one-time step; after that, `push_plugin_update()` covers every update via CLI.
- **`PATCH` on `sdkmessageprocessingstepimages`**: the Dataverse Web API rejects direct updates to this table with a generic, undocumented error (`0x80040216`). `update_image()` works around this by deleting and recreating the image.
- **`$expand` on `packageid` of `pluginassemblies`**: returns `400 Bad Request`. The code uses `_packageid_value` plus a separate lookup instead of `$expand`.
## Project structure
```
.
├── dataverse_plugins_server.py # main server (24 tools)
├── docs/
│ └── TOOLS.md # full reference for every tool
├── examples/
│ └── hello_world_mcp_server.py # minimal example MCP (3 trivial tools)
├── plugins/ # C# plug-in projects generated/registered locally
└── pyproject.toml
```
## Minimal example
If you're just getting started with MCP, [`examples/hello_world_mcp_server.py`](examples/hello_world_mcp_server.py) is a 3-tool trivial server (add, current time, reverse text) — a good starting point before diving into the main server.
## License
[MIT](LICENSE)
TDQS
Scored across 24 tools
Each tool targets a distinct resource and action: environments, projects, builds, registrations, steps, images, assemblies, packages, available messages, logs, and tracing. Even similar delete/update/list tools are clearly differentiated by their object type (image vs assembly vs package, etc.).
All tool names follow a consistent verb_noun snake_case pattern (e.g., list_steps, create_step, update_step, delete_step, toggle_step, configure_tracing). Compound verbs like open_registration_tool and push_plugin_update still adhere to the same structural pattern, maintaining predictability throughout.
At 24 tools, the set is slightly above the typical 3-15 well-scoped range, but each tool serves a distinct purpose within the plugin development lifecycle. The count is justified by the broad domain coverage, from project creation to deployment and diagnostics, without redundant or trivial tools.
The tool set covers the full lifecycle: project scaffolding, build, registration (with a manual PRT step workaround), CRUD for steps and images, environment management, secure configuration, tracing, and a comprehensive xray_assembly report. There are no obvious dead ends or missing critical operations for the plugin development workflow.