Dataverse MCP Server
Local Model Context Protocol server for Microsoft Dataverse. It exposes 171 tools
covering data access, schema/solution (ALM) authoring, model-driven app and form
design, security, plug-ins, theming, and demo-environment generation — all with a
dry-run-first safety model.
Setup
npm install
cp .env.example .env
Edit .env with your Dataverse URL and Azure app registration values.
For local interactive auth (device code flow):
DATAVERSE_AUTH_MODE=device_code
AZURE_CLIENT_ID=
AZURE_TENANT_ID=
For app-only auth (service principal):
DATAVERSE_AUTH_MODE=client_credentials
AZURE_CLIENT_ID=
AZURE_TENANT_ID=
AZURE_CLIENT_SECRET=
Run
npm run dev # development (tsx)
npm run build # compile to dist/
npm start # run the compiled server
npm test # vitest unit tests
npm run typecheck # tsc --noEmit
MCP Client Command
Use this server over stdio:
{
"mcpServers": {
"dataverse": {
"command": "npm",
"args": ["run", "dev"],
"cwd": ""
}
}
}
Streamable HTTP
Set DATAVERSE_MCP_TRANSPORT=http and run npm run dev; the endpoint defaults to
http://127.0.0.1:3000/mcp (host/port/path configurable below).
Configuration Reference
All settings are environment variables (loaded from .env via dotenv).
Connection & authentication
| Variable |
Default |
Description |
DATAVERSE_BASE_URL |
(required) |
Environment URL, e.g. https://yourorg.crm4.dynamics.com (no trailing slash needed). |
DATAVERSE_API_VERSION |
v9.2 |
Web API version segment used for every request. |
DATAVERSE_AUTH_MODE |
device_code |
device_code (interactive, public client) or client_credentials (app-only; requires the secret). |
AZURE_CLIENT_ID |
(required) |
Entra ID app registration (client) id. |
AZURE_TENANT_ID |
(required) |
Entra ID tenant id. |
AZURE_CLIENT_SECRET |
— |
Client secret; required only for client_credentials. |
DATAVERSE_TOKEN_CACHE_PATH |
.dataverse-token-cache.json |
MSAL token cache file so re-auth is rare. Set empty to disable persistence. |
Transport
| Variable |
Default |
Description |
DATAVERSE_MCP_TRANSPORT |
stdio |
stdio for editor/CLI clients, http for Streamable HTTP. |
DATAVERSE_MCP_HTTP_HOST |
127.0.0.1 |
HTTP listen host. |
DATAVERSE_MCP_HTTP_PORT |
3000 |
HTTP listen port. |
DATAVERSE_MCP_HTTP_PATH |
/mcp |
HTTP endpoint path. |
Safety gates & allowlists
Every write tool is dry-run by default: without dryRun: false plus
confirmWrite: true (or confirmDelete: true for deletions) it only returns the
exact request it would send. Executing additionally requires the matching gate
flag below — so an agent can always plan, but writing is a deliberate, layered
opt-in.
| Variable |
Default |
Description |
DATAVERSE_ALLOWED_TABLES |
(empty) |
Comma-separated entity set names readable by record tools (e.g. accounts,contacts). Empty = record tools refuse. |
DATAVERSE_WRITE_ALLOWED_TABLES |
(empty) |
Entity sets writable by record create/update/upsert/assign tools. |
DATAVERSE_DELETE_ALLOWED_TABLES |
(empty) |
Entity sets deletable by record delete tools. |
DATAVERSE_ENABLE_WRITES |
false |
Master switch for record data writes. |
DATAVERSE_ENABLE_DELETES |
false |
Master switch for record deletions. |
DATAVERSE_ENABLE_METADATA_WRITES |
false |
Gates schema/form/app/sitemap/solution-component authoring (tables, columns, forms, apps, views, business rule state, …). |
DATAVERSE_ENABLE_ADMIN_WRITES |
false |
Gates org-level operations: publish customizations, publishers, security roles, themes, web resources, localized labels. |
DATAVERSE_ENABLE_DESTRUCTIVE_WRITES |
false |
Extra gate on hard-to-undo operations: plug-in registration, app/form deletion, solution import with overwrite. |
Paging, batching & retry
| Variable |
Default |
Description |
DATAVERSE_MAX_PAGE_SIZE |
100 |
Max records per page for query tools (1–5000). |
DATAVERSE_MAX_PAGES |
5 |
Max pages fetched per query (1–100). |
DATAVERSE_MAX_BATCH_SIZE |
25 |
Max operations per $batch request (1–1000). |
DATAVERSE_RETRY_MAX_ATTEMPTS |
4 |
Attempts for throttled/transient failures (429/5xx, honors Retry-After). |
DATAVERSE_RETRY_BASE_DELAY_MS |
1000 |
Exponential backoff base delay. |
DATAVERSE_RETRY_MAX_DELAY_MS |
16000 |
Backoff ceiling. |
Response shaping
Tool results default to compact YAML to reduce token usage. Every tool accepts
per-call overrides (responseMode: full, outputFormat: json) when raw Dataverse
payloads are needed. See docs/COMPACT_RESPONSES.md.
| Variable |
Default |
Description |
DATAVERSE_MCP_RESPONSE_MODE |
compact |
compact (normalized, trimmed), standard, or full (raw payloads). |
DATAVERSE_MCP_OUTPUT_FORMAT |
yaml |
yaml or json. |
DATAVERSE_MCP_INCLUDE_ODATA_METADATA |
false |
Keep @odata.* fields in results. |
DATAVERSE_MCP_INCLUDE_ANNOTATIONS |
false |
Request formatted-value annotations. |
DATAVERSE_MCP_MAX_TEXT_LENGTH |
1000 |
Truncate long text values in compact mode (0 = no truncation). |
Observability
| Variable |
Default |
Description |
DATAVERSE_AUDIT_LOG_PATH |
logs/dataverse-audit.jsonl |
Every tool call logged as JSONL (tool, args, outcome, duration). Set empty to disable. |
171 tools, grouped by area. Unless marked read-only, write tools are dry-run by
default and gated as described above. The dataverse://environment MCP resource
exposes the effective configuration (without secrets).
Connection & environment
| Tool |
Description |
dataverse_test_connection |
Calls WhoAmI to verify authentication. |
dataverse_environment |
Resource: configured environment without secrets. |
| Tool |
Description |
dataverse_list_tables |
Lists usable table metadata. |
dataverse_list_tables_summary |
Lists normalized table summaries. |
dataverse_describe_table |
Table metadata and attributes for a logical name. |
dataverse_describe_table_summary |
Normalized table + attribute metadata. |
dataverse_generate_table_schema |
Generates a JSON Schema from table metadata. |
dataverse_describe_relationships |
1:N and N:N relationship metadata lookup. |
Records: read & query
| Tool |
Description |
dataverse_query_records |
Queries an allowed entity set (filter/select/order/paging). |
dataverse_get_record |
Gets one record by id. |
dataverse_execute_fetchxml |
Executes FetchXML against an allowed entity set. |
dataverse_analyze_fetchxml |
Read-safety and performance analysis of FetchXML (read-only). |
dataverse_resolve_record_by_alternate_key |
Gets one record via an alternate-key predicate. |
Records: write (write-gated + allowlisted)
| Tool |
Description |
dataverse_create_record / dataverse_update_record / dataverse_delete_record |
Single-record create/patch/delete with safety checks. |
dataverse_upsert_record / dataverse_batch_upsert |
Alternate-key upserts, single or batched. |
dataverse_batch_create / dataverse_batch_delete |
$batch create/delete. |
dataverse_assign_record |
Assigns a record to a user or team. |
dataverse_set_state |
Sets state/status on a record. |
dataverse_associate_records / dataverse_disassociate_records |
Relationship (dis)association. |
dataverse_validate_upsert_payload |
Validates upsert inputs without writing. |
Views
| Tool |
Description |
dataverse_list_views / dataverse_get_view_by_name |
List/find system views for a table. |
dataverse_get_view_data / dataverse_get_view_data_by_name |
Run a saved query by id or by table + view name. |
dataverse_create_system_view |
Creates a system saved query. |
| Tool |
Description |
dataverse_list_forms |
Lists active main forms for a table. |
dataverse_get_form_layout |
Raw formxml/formjson for a system form. |
dataverse_describe_form_layout |
Digested outline: tabs → sections → fields (+ header/footer). |
dataverse_create_form |
Creates a form; formType: main, quickCreate, quickView, or card. |
dataverse_copy_form |
“Save As” — copy a form (the safe way to customize managed forms). |
dataverse_create_form_tab / dataverse_create_form_section |
Append tabs/sections (multi-language labels supported). |
dataverse_add_columns_to_form / dataverse_remove_columns_from_form |
Add/remove field cells, optionally targeting a tab/section. |
dataverse_move_form_column |
Moves a field to a target tab/section. |
| Tool |
Description |
dataverse_add_subgrid_to_form |
Related-records subgrid (view + optional relationship filter). |
dataverse_add_quick_view_to_form |
Quick view control bound to a lookup column. |
dataverse_add_timeline_to_form |
Timeline (activities/notes) control. |
dataverse_add_columns_to_form_header / dataverse_remove_columns_from_form_header |
Read-only header/footer field cells (region selects header or footer; header shows max 4). |
dataverse_set_form_tab_properties |
Tab label, show-label, expanded, visible, phone availability. |
dataverse_set_form_section_properties |
Section label, visibility, 1–4 columns, label position. |
dataverse_set_form_field_properties |
Field label override, read-only, hidden, colspan/rowspan, fill height. Not a security mechanism — use column security for that. |
| Tool |
Description |
dataverse_set_form_state |
Activate/deactivate a main form. |
dataverse_delete_form |
Deletes a form (refuses the last main form of a table). |
dataverse_set_form_access |
Security-role visibility + fallback flag for a main form. |
dataverse_set_form_order |
Default-form ordering per form set (main/quickCreate/quickView/card). |
dataverse_add_form_event_handler / dataverse_remove_form_event_handler |
Wire/unwire JS web resource functions to onload/onsave/onchange/tabstatechange. |
dataverse_list_form_event_handlers |
Lists form libraries and handlers (read-only). |
dataverse_get_form_xml / dataverse_update_form_xml |
Raw FormXML escape hatch: read source-of-truth XML; replace with well-formedness check + before/after summary diff. |
PCF / code components
| Tool |
Description |
dataverse_list_custom_controls |
Lists installed code components; with name, parses the manifest into its property list. |
dataverse_add_pcf_control_to_form |
Binds a code component to a form column (per form factor, with parameters). |
dataverse_set_table_default_control |
Makes a code component the default grid renderer for a table. |
Business rules & localization
| Tool |
Description |
dataverse_list_business_rules |
Lists business rules, optionally per table (read-only). |
dataverse_set_business_rule_state |
Activates/deactivates a business rule. |
dataverse_list_provisioned_languages |
Valid LCIDs for label translations (read-only). |
dataverse_get_localized_labels / dataverse_set_localized_labels |
Read/write localized labels for component attributes (e.g. form display names). |
Solutions & ALM
| Tool |
Description |
dataverse_list_solutions / dataverse_get_solution |
Solution inventory and detail. |
dataverse_list_solution_components / dataverse_get_solution_dependencies / dataverse_find_component_solutions |
Component and dependency inspection. |
dataverse_export_solution_metadata |
Read-only metadata inventory (not a ZIP). |
dataverse_export_solution / dataverse_import_solution / dataverse_get_solution_import_status |
ZIP export/import (sync or async with polling). |
dataverse_publish_customizations |
Publish-all (admin-gated). |
dataverse_create_publisher / dataverse_create_solution / dataverse_add_solution_component |
Publisher/solution authoring. |
dataverse_validate_deployment_settings |
Validates env-var and connection-reference deployment settings. |
Schema authoring
| Tool |
Description |
dataverse_create_table / dataverse_create_column / dataverse_create_relationship |
Table, column, and relationship metadata creation. |
dataverse_create_global_choice |
Global option set creation. |
dataverse_create_alternate_key / dataverse_list_alternate_keys / dataverse_get_alternate_key |
Alternate key authoring and inspection. |
dataverse_create_schema_bundle |
Orchestrated choices + table + columns + relationships + keys in one call. |
dataverse_generate_schema_diff / dataverse_validate_schema_change / dataverse_create_schema_change_plan |
Non-executing schema planning/validation. |
dataverse_generate_import_template / dataverse_validate_import_file |
CSV import shape generation and validation. |
Environment variables & connection references
| Tool |
Description |
dataverse_list_environment_variables / dataverse_get_environment_variable |
Definitions with optional current values. |
dataverse_set_environment_variable_value |
Sets a current value. |
dataverse_list_connection_references / dataverse_get_connection_reference_usage |
Connector bindings and usage hints. |
Security & access
| Tool |
Description |
dataverse_list_security_roles / dataverse_get_security_role_privileges / dataverse_compare_security_roles |
Role inventory, privileges, and diffs. |
dataverse_create_security_role / dataverse_add_role_privileges |
Role authoring with validated privilege names/depths (admin-gated). |
dataverse_list_teams / dataverse_list_business_units |
Org structure lookups. |
dataverse_get_user_access_summary / dataverse_explain_user_record_access |
Why a user can (not) see a record. |
dataverse_list_table_privileges |
Privilege records for a table. |
Auditing
| Tool |
Description |
dataverse_get_audit_settings / dataverse_list_audited_tables |
Org audit configuration. |
dataverse_get_record_audit_history / dataverse_summarize_record_changes |
Per-record change history. |
dataverse_get_user_access_audit / dataverse_get_security_role_change_history |
Access and role-change audit trails. |
Plug-ins & event pipeline
| Tool |
Description |
dataverse_list_plugin_assemblies / dataverse_list_plugin_types / dataverse_list_plugin_steps / dataverse_get_plugin_step |
Plug-in inventory. |
dataverse_find_plugin_steps_for_table / dataverse_find_plugin_steps_for_message |
Step lookup by table or SDK message. |
dataverse_list_webhooks |
Service endpoints/webhooks. |
dataverse_get_event_pipeline_for_table / dataverse_explain_event_pipeline / dataverse_explain_table_automation |
Pipeline explanation and sync-risk analysis. |
dataverse_register_plugin_assembly / dataverse_register_plugin_type / dataverse_register_plugin_step / dataverse_register_plugin_step_image |
Registration (admin + destructive gated). |
Model-driven apps & navigation
| Tool |
Description |
dataverse_list_apps / dataverse_describe_app / dataverse_find_tables_used_by_app |
App inventory and composition. |
dataverse_create_app_module / dataverse_validate_app / dataverse_publish_app / dataverse_delete_app / dataverse_set_app_client_type |
App lifecycle. |
dataverse_add_app_components / dataverse_remove_app_components |
Register forms/views/charts/dashboards/sitemap into an app. |
dataverse_add_app_security_role / dataverse_remove_app_security_role |
App visibility by role. |
dataverse_create_sitemap / dataverse_describe_sitemap / dataverse_create_sitemap_area / dataverse_create_sitemap_group / dataverse_update_sitemap / dataverse_remove_sitemap_subarea |
Site map authoring. |
Theming & web resources
| Tool |
Description |
dataverse_set_modern_app_theme / dataverse_get_modern_app_theme |
Modern (Fluent/Unified Interface) theming, per app or environment-wide. |
dataverse_create_web_resource |
Upload/upsert images, HTML, JS, CSS (base64 or local file), optionally into a solution. |
dataverse_list_legacy_themes / dataverse_create_legacy_theme / dataverse_publish_legacy_theme |
Classic org-wide themes. |
Virtual tables
| Tool |
Description |
dataverse_list_virtual_table_providers / dataverse_list_virtual_table_data_sources |
Provider and data source inventory. |
dataverse_describe_virtual_table / dataverse_create_virtual_table |
Inspect/create virtual tables (OData v4 provider). |
Demo environments & seed data
| Tool |
Description |
dataverse_build_demo_environment |
One-shot orchestrator: solution → schema → forms/views → publish → seed data → app. Each phase individually gated. |
dataverse_plan_demo_data / dataverse_seed_demo_data |
Plan record counts, then create relationship-aware demo records. |
dataverse_generate_environment_health_report |
Aggregated read-only ALM health signals. |
Customer Service & Sales packs (read-mostly domain helpers)
| Tool |
Description |
dataverse_cs_list_cases / dataverse_cs_get_case_timeline / dataverse_cs_get_case_sla_status |
Case inspection with merged timeline and SLA KPIs. |
dataverse_cs_list_queues / dataverse_cs_get_queue_items |
Queue inventory and contents. |
dataverse_cs_search_knowledge_articles |
Knowledge article search. |
dataverse_cs_assign_case / dataverse_cs_route_case_to_queue |
Case assignment/routing (write-gated). |
dataverse_cs_describe_unified_routing_setup |
Best-effort unified routing readout. |
dataverse_sales_list_opportunities / dataverse_sales_get_pipeline_summary |
Opportunity list and pipeline rollup. |
dataverse_sales_get_opportunity_products / dataverse_sales_list_products |
Line items and product catalog. |
Further Documentation