Strong schema definitions with Zod validation and comprehensive parameter descriptions. All 18 tools have explicit descriptions and typed input schemas. Naming follows verb_noun convention (invoke_action, create_record, query_records). However, output schemas are not formally documented, responses are JSON-stringified without declared field structures. Error handling is present but lacks recovery guidance (e.g., 'try search_users() first'). Tool descriptions average ~150 chars, within the 10 - 1024 baseline. Parameter descriptions are detailed and include constraints (e.g., GUID validation, OData filter syntax). No security issues detected, credentials are environment-injected, not parameters. Composition is clean: each tool has one responsibility. Missing: output schema documentation, actionable error messages, and confirmation patterns for destructive ops (delete_record, delete_picklist_option).
Add an option to an existing Local or Global OptionSet (Dataverse InsertOptionValue action). Requires Customizer or System Administrator role; HTTP 403 otherwise.
Create a new attribute (column) on an existing Dataverse entity. Supports String, Integer, BigInt, Decimal, Double, Money, DateTime, Uniqueidentifier, Memo, Boolean, and Picklist types. Requires Customizer or System Administrator role.
Create a new custom entity (table) in Dataverse. Requires Customizer or System Administrator role.
Create a new Global OptionSet (shared picklist) in Dataverse. Requires Customizer or System Administrator role.
Create a new record in a Dataverse table. Returns the created record's GUID in @odata.entityId.
Dataverse MCP server is not configured. Call this tool to see setup instructions.
Output schemas not formally documented. Tools return JSON.stringify(result) without declaring field structures, types, or pagination info. LLMs cannot plan downstream calls or extract chaining IDs (e.g., record_id from create_record).
Destructive operations (delete_record, delete_picklist_option) lack confirmation or dry-run patterns. No guidance for recovery if deletion is unintended. Descriptions warn but do not offer confirmation_required or preview step.
Error responses are not documented. No guidance on error classification (retryable vs fatal), actionable recovery steps, or how LLMs should interpret failures. E.g., 'Invalid GUID' vs 'Permission denied' vs 'Record not found' all return raw errors.
| Scored | Grade | Overall | Spec posture | Rubric |
|---|---|---|---|---|
| 2026-09-23 | C | 62 | 2026-07-28+ | v2 |
Remove an option from a Local or Global OptionSet (Dataverse DeleteOptionValue action). WARNING: existing records that hold this integer value are NOT updated and will retain the now-orphan number — warn the user before deleting.
Delete a record from a Dataverse table. WARNING: this is permanent and cannot be undone.
Get attributes (columns) of a specific Dataverse table. Choice-style columns (Choice, Status, State, MultiSelect) carry an option_set summary with is_global and option_count, so one dump shows which choice lists are shared org-wide. Read the option values per column with get_picklist_options.
Read a Local or Global OptionSet as { option_set: { name, is_global, metadata_id }, options: [{ value, label }] }. Use is_global to tell whether a column holds a local copy of the values or is bound to a shared Global OptionSet — matching values alone do not prove a binding. Works for Choice, Status, State and MultiSelect columns.
Invoke a Dataverse Web API action (POST) — bound or unbound. Use for operations that are not plain CRUD, e.g. PublishDuplicateRule (bound to a duplicaterule) or QualifyLead (bound to a lead), or UnpublishDuplicateRule (unbound, takes DuplicateRuleId). Whether an action is bound is defined in the Web API $metadata. Pass entity_set+id for bound actions, neither for unbound. parameters becomes the JSON request body.
Invoke a Dataverse Web API function (GET) — bound or unbound. Use for read-only operations exposed as functions, e.g. WhoAmI (unbound) or RetrieveDuplicates. Pass entity_set+id for bound functions, neither for unbound. parameters are inlined into the URL as OData function arguments.
List Dataverse tables (entities) with optional prefix and solution filters
List Dataverse solutions (uniquename is used to filter list_entities)
Query records from a Dataverse table using OData filters, select, orderby, and pagination.
Read a single record from a Dataverse table by GUID. Optionally select specific columns.
Update an existing option's label/description on a Local or Global OptionSet (Dataverse UpdateOptionValue action). Requires Customizer or System Administrator role.
Update an existing record in a Dataverse table.
query_records lacks pagination documentation. No mention of total count, next_cursor, or how to handle large result sets. Default top=100 may exhaust context window; no guidance on chunking strategy.
dataverse_setup tool is a placeholder with minimal description (60 chars). Its purpose is unclear, is it a discovery tool, a configuration helper, or an error handler? Naming 'dataverse_setup' is vague; consider 'show_setup_instructions' or 'check_configuration'.