-
Notifications
You must be signed in to change notification settings - Fork 0
Safety and Permissions
Four server-side flags decide what an agent connected to this server can do. They are the guardrail between a prompt-injected or simply confused agent and your data: with the defaults, there is no tool it can call that deletes a record, drops a column, or overwrites a file on your disk.
They are not a substitute for Dataverse security roles — both apply, and the stricter wins.
| Flag | Default | Stops |
|---|---|---|
DATAVERSE_ALLOW_WRITE |
off | Creating, updating, publishing, and all schema/solution/plug-in mutation |
DATAVERSE_ALLOW_DELETE |
off | Deleting records, tables, columns, relationships, components |
DATAVERSE_WHITELIST |
(empty — allows all) | Tool calls aimed at an environment you did not approve |
DATAVERSE_FILE_BASE_DIR |
(unset — allows all) | Solution export/import reading or writing outside one directory |
The gates work by registration, not refusal. A gated tool is defined in the code but never exposed over MCP, so the agent cannot see it, cannot call it, and cannot be talked into calling it. The tool list itself is the enforcement.
| Configuration | Tools registered |
|---|---|
| Neither flag | 97 |
DATAVERSE_ALLOW_WRITE=true |
177 |
| Both flags | 200 |
Only the exact string true (any case) enables a flag — 1 and yes silently mean off.
Two behaviours do not follow the pattern:
-
dataverse_execute_batchis always registered so that read-only batch queries stay available. It inspects the operations it is given and refuses at call time:Batch operations containing POST/PUT/PATCH methods require DATAVERSE_ALLOW_WRITE=true in the MCP server environment., and the equivalent for DELETE. -
dataverse_export_solutionneeds no write flag. It does not mutate the org — but withoutput_pathit does write a.zipto the server's filesystem. That is whatDATAVERSE_FILE_BASE_DIRis for.
Every tool call carries its own dataverse_url, and the server mints a bearer token for whatever host it is given. Without a whitelist, an agent that has been fed a hostile instruction can point your credentials at any Dataverse environment in the world.
"DATAVERSE_WHITELIST": "yourorg.crm.dynamics.com,yourorg-uat.crm.dynamics.com"Comma-separated hostnames. A scheme or trailing path is tolerated and stripped; hosts are canonicalised (trailing dot removed, IDNA-encoded, lowercased) on both sides before comparison, so Unicode and punycode spellings of the same host match. Invalid entries are skipped with a warning rather than failing startup. A rejected call returns:
dataverse_url host 'other.crm.dynamics.com' is not in the configured DATAVERSE_WHITELIST. Add it to DATAVERSE_WHITELIST to permit access to this environment.
Independently of the whitelist, every dataverse_url must be https, carry no credentials, path, query or fragment, and use no port other than 443 — a non-standard port is rejected outright so it cannot be used to sidestep host matching.
DATAVERSE_REQUIRE_WHITELIST=true rejects every tool call while DATAVERSE_WHITELIST is empty, instead of falling back to "allow everything":
DATAVERSE_REQUIRE_WHITELIST is set but DATAVERSE_WHITELIST is empty; refusing to mint a token for an unapproved host. Populate DATAVERSE_WHITELIST with the allowed environment hostname(s).
Set it wherever a config mistake could otherwise open the server to every environment — shared hosts, multi-tenant deployments, anything not your own laptop. The startup log makes the state obvious either way: the allowed hosts are listed when the whitelist is set, an ERROR is logged when it is required but empty, and a WARNING when it is neither.
dataverse_list_environmentsis not covered. It takes nodataverse_url— it queries the Power Platform admin API for the environments you can administer — so the whitelist does not apply to it. It reads metadata only, no Dataverse data. Drop thecorecategory if that matters, but note thatcorecannot be disabled viaDATAVERSE_TOOLS.
DATAVERSE_FILE_BASE_DIR confines the output_path and input_path arguments on dataverse_export_solution, dataverse_import_solution and dataverse_stage_and_upgrade_solution. Paths are resolved (~ expanded, symlinks and .. collapsed) and must land inside the directory:
"DATAVERSE_FILE_BASE_DIR": "C:\\dataverse-solutions"Anything outside it — .. traversal or an absolute path elsewhere — is rejected with Path is outside the permitted DATAVERSE_FILE_BASE_DIR directory (<base>); refusing to access '<path>'. Unset, these paths are unrestricted, which means an agent can be steered into overwriting a startup script or reading an SSH key.
Nothing can be changed and nothing can leave the org. The whitelist is required rather than merely set, so a later edit that empties it fails closed instead of opening up.
{
"mcpServers": {
"dataverse-prod": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_WHITELIST": "yourorg.crm.dynamics.com",
"DATAVERSE_REQUIRE_WHITELIST": "true",
"DATAVERSE_TOKEN_CACHE_PROFILE": "prod"
}
}
}
}Omitting DATAVERSE_ALLOW_WRITE and DATAVERSE_ALLOW_DELETE is the point — do not set them to "false" and assume that is stronger; absent and "false" are identical here.
{
"mcpServers": {
"dataverse-dev": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_ALLOW_WRITE": "true",
"DATAVERSE_ALLOW_DELETE": "true",
"DATAVERSE_WHITELIST": "yourorg-dev.crm.dynamics.com",
"DATAVERSE_REQUIRE_WHITELIST": "true",
"DATAVERSE_FILE_BASE_DIR": "C:\\dataverse-solutions",
"DATAVERSE_TOKEN_CACHE_PROFILE": "dev"
}
}
}
}The whitelist matters more here, not less: this is the entry that can delete things, so it must not be able to reach production. Run both entries side by side and the agent picks the right one by name.
Deletes in Dataverse are permanent and cascade — dataverse_delete_table takes the table's data with it. Enable DATAVERSE_ALLOW_DELETE where you would be comfortable letting a colleague run the same command unsupervised.
dataverse-mcp 3.9.1 — Repository · PyPI · Issues · Changelog · MIT
Get started
Configure
Tools
- Tool-Index
- Tools-Core
- Tools-Schema
- Tools-Solutions
- Tools-Plugins
- Tools-Security
- Tools-Custom-APIs
- Tools-Apps
- Tools-Variables
- Tools-Flows
- Tools-Views
- Tools-Forms
- Tools-Connections
- Tools-Web-Resources
- Tools-Jobs
Understand