Dataverse MCP Server
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Dataverse MCP Serverlist the top 10 active accounts"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Dataverse MCP Server
An MCP server that gives AI agents structured access to Microsoft Dataverse — query records, bulk upsert data, inspect metadata, manage schema, analyze component dependencies, manage model-driven app forms, views, and apps, administer security roles, teams, and users, audit user access, manage plug-in trace logging, manage custom APIs, and explore Power Platform environments.
Built with FastMCP, httpx, and the Dataverse OData v4.0 Web API. Communicates over stdio and works with Claude, GitHub Copilot, and any MCP-compatible client.
Quick Start
1. Install uv
pip install uv2. Configure — add to your MCP client config:
Claude (claude_desktop_config.json or .claude/settings.json):
{
"mcpServers": {
"dataverse-mcp": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}GitHub Copilot (.vscode/mcp.json):
{
"servers": {
"dataverse-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}3. Sign in
On first use the server opens a browser for interactive sign-in. The session is cached and reused across restarts (see DATAVERSE_TOKEN_CACHE_PERSIST), so you are not prompted again while the token is valid.
That's it. Your AI agent can now query your Dataverse environments.
Prefer your existing Azure CLI session instead? Set
DATAVERSE_AUTH_TYPEtoazure_cliand runaz login.
Related MCP server: Dataverse MCP Server
Installation
Install uv
uvx is provided by uv. Install it first if you don't have it:
pip install uvRun from PyPI (recommended)
uvx dataverse-mcpuvx downloads and runs the package in an isolated environment — no virtual environment management required.
Run from a local checkout
git clone https://github.com/ryanmichaeljames/dataverse-mcp.git
cd dataverse-mcp
uv syncThis creates .venv. Use the local source MCP config shown in Client Setup to point your client at it. No build step required — code changes are picked up on the next server start.
Configuration
Set these in the env block of your MCP server entry. This project does not use a .env file.
Variable | Default | Description |
|
| Authentication method: |
|
| Set to |
|
| Set to |
| — | Comma-separated list of tool categories to register (e.g., |
| — | Comma-separated list of allowed environment hostnames (e.g., |
|
| When |
| — | Optional directory that confines the solution export/import file paths ( |
|
| Maximum seconds to wait for a credential acquisition (e.g., |
|
| Controls whether |
|
| When |
| — | Optional name that isolates the |
Leaving DATAVERSE_WHITELIST unset is risky. Tools accept a dataverse_url per call, and the server mints a bearer token for whatever environment is supplied. Without a whitelist, a compromised or misbehaving agent can direct your credentials at any Dataverse environment. Set DATAVERSE_WHITELIST to the specific environment hostnames you intend to use so the server rejects everything else. On shared or multi-tenant hosts, also set DATAVERSE_REQUIRE_WHITELIST=true so the server fails closed rather than minting tokens when the whitelist is accidentally left empty.
Authentication
Method | Description |
| Opens a browser for interactive sign-in. Supports MFA and per-account isolation, and needs no separate CLI login. The session persists across server restarts (see |
| Uses your active |
Interactive auth persistence. When DATAVERSE_TOKEN_CACHE_PERSIST=true (the default), the MSAL token cache is stored on disk using your OS secret store (Windows DPAPI, macOS Keychain, Linux libsecret). On headless Linux without libsecret, the first token acquisition will fail fast with an error. Set DATAVERSE_TOKEN_CACHE_ALLOW_UNENCRYPTED=true to permit a plaintext cache on those hosts, and see the security warning for that variable above.
Running multiple tenants/accounts at once. The default cache and sidecar filenames are shared per host, so two interactive sessions signed in to different tenants/accounts would overwrite each other's pinned account. Give each session a distinct DATAVERSE_TOKEN_CACHE_PROFILE (e.g., prod, dev) to keep their caches and AuthenticationRecord sidecars separate.
Example: two tenants side by side
Register two server entries, each with its own DATAVERSE_TOKEN_CACHE_PROFILE. The profile is a tenant-wide cache key — each entry signs in once (its own browser prompt) and then restarts silently as its own account, while tools still receive the specific dataverse_url per call. The profiles never collide.
Claude (claude_desktop_config.json or .claude/settings.json):
{
"mcpServers": {
"dataverse-prod": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_TOKEN_CACHE_PROFILE": "prod"
}
},
"dataverse-dev": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_TOKEN_CACHE_PROFILE": "dev"
}
}
}
}GitHub Copilot (.vscode/mcp.json):
{
"servers": {
"dataverse-prod": {
"type": "stdio",
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_TOKEN_CACHE_PROFILE": "prod"
}
},
"dataverse-dev": {
"type": "stdio",
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_TOKEN_CACHE_PROFILE": "dev"
}
}
}
}Each profile maps to one tenant/account sign-in; agents pass the target dataverse_url on each tool call. Omit DATAVERSE_TOKEN_CACHE_PROFILE (or leave it empty) for a single-tenant setup — the original shared cache filenames are used.
Safety Guards
Most write and delete tools are not registered by default, so they do not appear to the agent until explicitly enabled. One exception is dataverse_execute_batch, which is always visible but only allows GET requests unless DATAVERSE_ALLOW_WRITE=true. This prevents accidental mutations when you only need to read or inspect data while still allowing safe batch reads by default.
{
"servers": {
"dataverse-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive",
"DATAVERSE_ALLOW_WRITE": "true",
"DATAVERSE_ALLOW_DELETE": "true"
}
}
}
}Each flag is independent — set only DATAVERSE_ALLOW_WRITE=true to allow creates and updates while keeping deletes disabled.
Reliability and Limits
These behaviors are built in and need no configuration:
Automatic retries — requests throttled by Dataverse service-protection limits or hitting transient gateway errors are retried automatically; read-only requests are also retried on timeouts and connection failures.
Response size cap — responses larger than 5 MB are replaced with an error asking the agent to narrow the query with
select,top, orfilter.Consistent errors — every tool returns JSON; failures have the shape
{"error": true, "message": "..."}with the Dataverse error code included and the message capped in length.Server-side paging — list tools request right-sized pages from Dataverse instead of full 5,000-record pages.
Client Setup
Claude
Claude Desktop
Add to claude_desktop_config.json:
macOS:
~/Library/Application Support/Claude/claude_desktop_config.jsonWindows:
%APPDATA%\Claude\claude_desktop_config.json
{
"mcpServers": {
"dataverse-mcp": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}Claude Code
Add via the CLI:
claude mcp add dataverse-mcp --env DATAVERSE_AUTH_TYPE=interactive uvx dataverse-mcpOr add directly to .claude/settings.json (project) or ~/.claude/settings.json (user):
{
"mcpServers": {
"dataverse-mcp": {
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}Run from a local checkout
{
"mcpServers": {
"dataverse-mcp-local": {
"command": "C:\\path\\to\\dataverse-mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "dataverse_mcp.server"],
"env": {
"PYTHONPATH": "C:\\path\\to\\dataverse-mcp\\src",
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}GitHub Copilot
Add to .vscode/mcp.json in your project root.
Run from PyPI
{
"servers": {
"dataverse-mcp": {
"type": "stdio",
"command": "uvx",
"args": ["dataverse-mcp"],
"env": {
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}Run from a local checkout
{
"servers": {
"dataverse-mcp-local": {
"type": "stdio",
"command": "C:\\path\\to\\dataverse-mcp\\.venv\\Scripts\\python.exe",
"args": ["-m", "dataverse_mcp.server"],
"env": {
"PYTHONPATH": "C:\\path\\to\\dataverse-mcp\\src",
"DATAVERSE_AUTH_TYPE": "interactive"
}
}
}
}Multi-environment targeting
A single server instance can target any Dataverse org — pass dataverse_url on each tool call:
{
"dataverse_url": "https://yourorg.crm.dynamics.com",
"entity_set_name": "accounts",
"select": ["name", "accountid"],
"top": 10
}dataverse_url is required on every tool call. Use dataverse_list_environments to discover available environments if you do not yet know the URL.
Tools
184 tools grouped by domain below. Every tool returns JSON and requires dataverse_url on each call.
The Gate column shows when a tool is registered:
Gate | Meaning |
| Always registered (reads and safe queries). |
| Registered only when |
| Registered only when |
dataverse_execute_batchisdefaultbut rejects non-GET operations unlessDATAVERSE_ALLOW_WRITE=true.
Tool categories
Use DATAVERSE_TOOLS to register only the tool categories your agent needs. This shrinks the visible tool list and reduces token overhead.
Category | Tools | Description |
| 18 | Environment introspection + all record CRUD (always registered) |
| 32 | Table/column/relationship/choice/alternate-key metadata |
| 20 | Solution and publisher management, solution components, history, import/export ALM, dependency analysis |
| 8 | Cloud flow + classic process listing and activate/deactivate |
| 6 | Model-driven form management |
| 7 | Saved query / view management |
| 10 | Canvas and model-driven app management |
| 5 | Connection reference management |
| 8 | Environment variable definitions and values |
| 33 | Plugin assemblies, types, steps, step images, packages, trace logs |
| 16 | Security roles, teams, users, business units, composite access audit, audit history |
| 3 | Async operation (system job) monitoring and cancellation |
| 5 | Web resource (JS/HTML/CSS/image) CRUD — gated, not always-on |
| 13 | Custom API, request parameter, and response property management |
core is always registered even when not listed. When DATAVERSE_TOOLS is unset or empty, all categories register (current default behaviour). Category gating composes with DATAVERSE_ALLOW_WRITE and DATAVERSE_ALLOW_DELETE: a tool registers only when its category is enabled AND its write/delete flag (if any) is set.
Environment & identity
Tool | Gate | Description |
| default | List Power Platform environments accessible to the caller |
| default | Return the caller's |
| default | List OData EntitySet names from the service document |
| default | List security privileges assigned to a user |
| default | Check a user's access rights to a specific record |
Security administration
Tool | Gate | Description |
| default | List security roles, optional filter and pagination |
| default | Get one security role by GUID |
| default | List teams, optional filter and pagination |
| default | Get one team by GUID |
| default | List system users, optional filter and pagination |
| default | Get one system user by GUID |
| default | List business units, optional filter and pagination |
| default | Composite report: user identity, direct roles, team memberships + team roles, effective privileges, optional record-level access check |
| default | Query the |
| default | Get full before/after detail for a single audit record via the bound |
| default | Retrieve the full audit change history for a single record via |
| write | Assign a security role to a user or team |
| write | Remove a security role from a user or team |
| write | Add one or more users to a team |
| write | Remove one or more users from a team |
| write | Enable or disable a system user ( |
Async jobs
Tool | Gate | Description |
| default | List system jobs (asyncoperations), optional filter by statecode/statuscode/operationtype |
| default | Get one system job by GUID |
| write | Cancel a running or waiting system job (PATCH statecode=3/statuscode=32) |
Web resources
Tool | Gate | Description |
| default | List web resources; optional filter by type and/or name substring |
| default | Get one web resource by GUID; |
| write | Create a web resource (name, type, base64 content); call |
| write | PATCH content, display name, or description; call |
| delete | Permanently delete an unmanaged web resource by GUID |
Records & data
Tool | Gate | Description |
| default | Query records with filter, select, orderby, expand, top |
| default | Execute a FetchXML query (joins, aggregation, paging cookie) |
| default | Get one record by entity set name and GUID |
| default | Count rows in a table, optional filter |
| default | Aggregate (sum, avg, min, max, countdistinct) with optional grouping |
| default | Run up to 1,000 OData operations in one |
| write | Upsert many records via |
| write | Create a record and return its new GUID |
| write | Partially update a record (PATCH) |
| write | Associate two records via a collection-valued navigation property |
| write | Merge a subordinate record into a target (account, contact, lead, incident) |
| delete | Permanently delete a record |
| delete | Remove an association between two records |
Tables & columns
Tool | Gate | Description |
| default | List tables, optional metadata filter |
| default | Get full schema details for a table |
| default | List columns for a table, optional type filter |
| default | Get full metadata for one column, including type-specific properties |
| write | Create a custom table (ownership type, primary name attribute) |
| write | Update a table's display name or description |
| write | Add a typed column to a table (supports Memo, Boolean with custom labels, and Picklist/MultiSelectPicklist bound to a global choice) |
| write | Replace a column via full PUT (fetch with |
| write | Publish schema changes via |
| delete | Permanently delete a custom table and all its data |
| delete | Permanently delete a custom column and all its data |
Relationships
Tool | Gate | Description |
| default | List relationships for a table or the whole environment |
| default | Get full metadata for one relationship by schema name |
| default | Check whether a table can participate in a relationship |
| write | Create a 1:N relationship and its lookup column |
| write | Create an N:N relationship and its intersect table |
| write | Create a polymorphic lookup referencing multiple tables |
| write | Replace a relationship via full PUT (fetch with |
| delete | Delete a custom relationship by MetadataId |
Choices (option sets)
Tool | Gate | Description |
| default | List global choices (option sets) |
| default | Get a global choice and its options by name or MetadataId |
| default | Get options for a Picklist or MultiSelectPicklist column |
| write | Create a global choice with initial options |
| write | Replace a global choice via full PUT (fetch with |
| write | Add an option to a global or local choice |
| write | Update the display label of an option |
| write | Reorder all options in a choice |
| delete | Delete a global choice by logical name |
| delete | Remove one option from a global or local choice |
Alternate keys
Tool | Gate | Description |
| default | List |
| write | Create an alternate key by |
| delete | Remove an alternate key by logical name; drops the underlying SQL index |
Solutions & publishers
Tool | Gate | Description |
| default | List solutions, optional filter and pagination |
| default | Get a solution by unique name or GUID |
| default | List components in a solution, optional type filter |
| default | Get one solution history record (import/upgrade/export operation) by GUID |
| default | List solution history records, optional filter by solution GUID or unique name; |
| write | Create a publisher with customization prefixes |
| write | Update publisher fields by GUID |
| write | Create a solution (publisher binding, version) |
| write | Update solution fields by GUID or unique name |
| write | Update only a solution's version |
| write | Add a component via |
| delete | Remove a component via |
| default | Export a solution as a base64 zip; write to disk via |
| write | Import a solution asynchronously via |
| write | Single-step solution upgrade via |
| write | Two-step apply-upgrade via |
| default | Get one importjob by GUID — returns progress, completedon, solutionname; add |
| default | List importjobs, optional filter by solution unique name, ordered by createdon desc |
| write | Clone a solution as a patch via bound |
| default | Analyze component dependencies: |
Filesystem I/O note.
dataverse_export_solutioncan write the decoded .zip to a local path whenoutput_pathis supplied.dataverse_import_solutioncan read a local .zip wheninput_pathis supplied. Both paths are resolved on the machine running the MCP server. Useoutput_path/input_pathfor solutions larger than ~3 MB (the inline base64 threshold).
Cloud flows & processes
Tool | Gate | Description |
| default | Query cloud flows, optionally scoped to a solution |
| write | Enable one flow by workflow ID |
| write | Enable many flows in one |
| write | Disable one flow by workflow ID |
| write | Disable many flows in one |
| default | List classic processes (workflows, business rules, actions, BPFs) from the |
| write | Activate a classic process (sets statecode=1/Activated); idempotent |
| write | Deactivate a classic process (sets statecode=0/Draft); idempotent |
Forms
Tool | Gate | Description |
| default | List forms for a table, optional form type filter |
| default | Get a form's layout as a tabs → sections → controls tree |
| default | Validate FormXml against XSD; pass |
| write | Replace and publish a form's FormXml; returns |
| write | Add a column control to a form (auto-resolves classid) |
| write | Remove a column control by logical name |
Views
Tool | Gate | Description |
| default | List saved views (savedquery) for a table, optional query type filter |
| default | Get a view's FetchXml, LayoutXml, and column list |
| default | Validate a view's FetchXml and LayoutXml |
| write | Create a saved view with FetchXml and LayoutXml |
| write | Update a view's FetchXml, LayoutXml, name, or description |
| write | Add a column to a view's LayoutXml |
| write | Remove a column from a view's LayoutXml |
Model-driven apps
Tool | Gate | Description |
| default | List apps; |
| default | Get an app's properties and components grouped by type |
| default | Validate an app via |
| write | Create an app (sitemap, components, validation, publish) |
| write | Update an app's name or description |
| write | Add tables, forms, views, charts, or BPFs to an app |
| write | Remove components from an app |
| write | Create or replace an app's navigation sitemap |
| write | Publish an app to make it visible to users |
| write | Associate or disassociate a security role with an app |
Connection references
Tool | Gate | Description |
| default | List connection references, optional connector/status/OData filters |
| default | Get one by GUID or logical name |
| write | Create one, optional connection and solution association |
| write | Assign/clear connection, update fields, or associate with a solution |
| delete | Delete an unmanaged connection reference |
Environment variables — definitions
Tool | Gate | Description |
| default | List definitions with current values; optional solution filter or single-record name lookup (schema name / display name) |
| write | Create a definition and optional initial value |
| write | Update definition fields and/or upsert the current value |
| delete | Delete definition, value record, or both |
Environment variables — values
Tool | Gate | Description |
| default | Get value record(s) by value GUID, definition GUID, or definition name |
| write | Create a value record bound to a definition (by GUID or name) |
| write | PATCH an existing value record by value GUID, definition GUID, or definition name |
| delete | Delete a value record only (resets to default value) by value GUID, definition GUID, or definition name |
Plug-in registration
Tool | Gate | Description |
| default | List registered plug-in assemblies |
| default | Get one plug-in assembly |
| default | List NuGet plug-in packages |
| default | Get one plug-in package |
| default | List plug-in types (classes) in an assembly |
| default | Get one plug-in type |
| default | List SDK message processing step registrations |
| default | Get one processing step |
| default | List pre/post entity images on a step |
| default | Get one step image |
| default | List SDK messages (Create, Update, …) — reference |
| default | Get one SDK message |
| default | List SDK message filters (message/entity combos) — reference |
| default | Get one SDK message filter |
| write | Register a plug-in assembly |
| write | Update a plug-in assembly |
| write | Register a plug-in package |
| write | Update a plug-in package |
| write | Register a plug-in type |
| write | Update a plug-in type |
| write | Register an SDK message processing step |
| write | Update a processing step |
| write | Register a step image |
| write | Update a step image |
| delete | Delete a plug-in assembly |
| delete | Delete a plug-in package |
| delete | Delete a plug-in type |
| delete | Delete a processing step |
| delete | Delete a step image |
Plug-in tracing & statistics
Tool | Gate | Description |
| default | Runtime performance stats (execution count, failure rate, crashes) per plug-in type |
| default | Get org-wide trace log verbosity (off / exception / all) |
| default | List trace logs with filters (class, message, entity, operation, errors-only, time window) |
| write | Set org-wide trace log verbosity ( |
Custom APIs
Tool | Gate | Description |
| default | List custom APIs, optional filter and pagination |
| default | Get one custom API by GUID, including its request parameters and response properties |
| write | Create a custom API (unbound, entity-bound, or entity collection-bound) |
| write | Update mutable fields of a custom API (display name, description, visibility, allowed step types) |
| delete | Permanently delete a custom API and its child parameters and properties |
| default | List request parameters for a custom API |
| write | Add a typed request parameter to a custom API |
| write | Update mutable fields of a request parameter |
| delete | Delete a request parameter |
| default | List response properties for a custom API |
| write | Add a typed response property to a custom API |
| write | Update mutable fields of a response property |
| delete | Delete a response property |
Development
# Install dependencies
uv sync
# Run the MCP inspector (interactive testing)
uv run mcp dev src/dataverse_mcp/server.py
# Run the server directly
uv run python -m dataverse_mcp.server
# Compile check
uv run python -m py_compile src/dataverse_mcp/server.pyRestart the MCP server in VS Code after code changes to pick up the new source.
License
MIT
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Latest Blog Posts
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/ryanmichaeljames/dataverse-mcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server