Skip to content

Tools Core

Ryan James edited this page Aug 17, 2026 · 3 revisions

Core tools

This page is generated from the code by scripts/gen_wiki_tools.py — do not edit by hand.

24 tools · category token core · enable with DATAVERSE_TOOLS=core (unset enables every category)

Tool-Index · Home

Every tool returns JSON. Errors return {"error": true, "message": "..."}. Write tools require DATAVERSE_ALLOW_WRITE=true; delete tools require DATAVERSE_ALLOW_DELETE=true.


dataverse_aggregate_table

Read · idempotent · category core

Group and aggregate Dataverse records with an OData $apply expression.

Note: Works on up to 50,000 records.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
apply str yes See note below.
filter str | None no None OData $filter expression to narrow records before aggregation.
  • apply — OData $apply expression. Examples: "groupby((statecode),aggregate($count as total))" — count rows by status; "groupby((statecode),aggregate(accountid with countdistinct as total))" — distinct count; "aggregate(revenue with sum as total_revenue)" — sum a column; "groupby((statuscode))" — distinct values. Use 'countdistinct' not 'count'. Lookup fields cannot be used in groupby. Works on up to 50,000 records. (min_len=1)

Returns {"records": ..., "count": ...}.


dataverse_associate_records

Write · idempotent · category core

Associate two Dataverse records via a collection-valued navigation property.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the primary record's table (e.g., 'accounts'). Use dataverse_get_entity_sets to discover. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes GUID of the primary record. (min_len=36)
navigation_property str yes Collection-valued navigation property name on the primary entity (case-sensitive). Use dataverse_list_relationships to discover the correct name (e.g., 'contact_customer_accounts'). (min_len=1)
related_entity_set_name str yes OData collection name of the related record's table (e.g., 'contacts'). (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
related_record_id str yes GUID of the related record to associate. (min_len=36)

Returns {"success": ...}.


dataverse_bulk_upsert

Write · idempotent · category core

Upsert many records in one call using OData $batch PATCH operations.

Note: Each record is PATCHed individually (not in a change set) so a single bad row does not roll back the rest when continue_on_error=true.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the target table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
records list[dict[str, Any]] yes List of records to upsert. Each record is a dict of column→value pairs and must include the key field(s). Maximum 1,000 records per call. (min_len=1)
key_columns list[str] | None no None Alternate key column names used to build the upsert URL. When provided, the URL is built as entity_set_name(col1='val1',col2='val2') and these fields are removed from the PATCH body. When omitted, the tool looks for a GUID-valued field in each record and uses it as the primary key. (min_len=1)
continue_on_error bool no True When True, a failed row does not stop the batch — remaining rows are still attempted and each row gets its own outcome in the results.
chunk_size int no 100 Number of records per $batch request. Keep ≤1,000 (the Dataverse batch limit). Smaller values reduce timeout risk on slow environments. (ge=1, le=1000)

Returns {"total": ..., "succeeded": ..., "failed": ..., "results": ...}.


dataverse_count_records

Read · idempotent · category core

Count records in a table (optionally filtered) and return only the integer total.

Note: The total is capped at 5,000 by Dataverse.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
filter str | None no None OData $filter expression to count only matching records. Note: the count is always capped at 5,000 by Dataverse.

Returns {"total_count": ..., "capped": ...}.


dataverse_create_record

Write · non-idempotent · category core

Create a single record in any Dataverse table and return the new record's id.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
data dict[str, Any] yes Column name/value pairs for the new record. Use logical (lowercase) column names (e.g., {'name': 'Contoso', 'telephone1': '555-0100'}). Use dataverse_list_columns to discover available columns. Must contain at least one column. (min_len=1)

Returns {"created": ..., "id": ...}.


dataverse_delete_record

Delete · idempotent · category core

Permanently delete a single Dataverse record by GUID — this action cannot be undone.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes The GUID of the record to delete. (min_len=1)

Returns {"deleted": ..., "id": ...}.


dataverse_disassociate_records

Delete · idempotent · category core

Remove an existing association between two Dataverse records.

Note: Navigation property names are case-sensitive — use dataverse_list_relationships to discover the correct name.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the primary record's table (e.g., 'accounts'). (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes GUID of the primary record. (min_len=36)
navigation_property str yes Collection-valued navigation property name on the primary entity (case-sensitive). Use dataverse_list_relationships to discover. (min_len=1)
related_record_id str yes GUID of the related record to disassociate. (min_len=36)

Returns {"success": ...}.


dataverse_execute_batch

Write · non-idempotent · category core

Execute bulk or atomic multi-operation reads and writes via the OData $batch endpoint.

Note: POST/PUT/PATCH operations require DATAVERSE_ALLOW_WRITE=true; DELETE operations require DATAVERSE_ALLOW_DELETE=true.

Note: Group operations with the same change_set_id to run them atomically (all-or-nothing, up to 1,000 operations per request).

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
operations list[BatchOperationItem] yes Ordered list of OData operations to execute in the batch. Maximum 1,000 operations per request. Operations within the same change_set_id are executed atomically. (min_len=1)
continue_on_error bool no False When True, adds 'Prefer: odata.continue-on-error' — the batch continues processing remaining operations even if one fails. When False (default), the batch stops on the first error.

Returns {"results": ..., "count": ...}.


dataverse_execute_fetchxml

Read · idempotent · category core

Execute a FetchXML query against a Dataverse table and return matching records.

Note: FetchXML supports complex joins (link-entity), aggregation, and queries that OData $filter cannot express.

Note: FetchXML uses paging cookies (not @odata.nextLink).

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes Entity set (collection) name matching the FetchXML root entity, e.g. 'accounts'. Use dataverse_get_entity_sets to discover the correct name. (pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
fetch_xml str yes The FetchXML query string
include_formatted_values bool no False When True, includes formatted (display) values for lookups, option sets, etc. Formatted values appear as 'fieldname@OData.Community.Display.V1.FormattedValue' in each record.

dataverse_get_entity_sets

Read · idempotent · category core

List OData EntitySet names from the Dataverse service document.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
contains str | None no None Case-insensitive substring filter applied to EntitySet names. Use this to narrow results (e.g., 'account' returns 'accounts', 'accountleads', etc.). If omitted, all entity sets are returned up to the 'top' limit.
top int no 50 Maximum number of entity sets to return (1–1000). (ge=1, le=1000)

Returns {"entity_sets": ..., "count": ..., "has_more": ...}.


dataverse_get_organization_info

Read · idempotent · category core

Fingerprint a Dataverse environment: server version, organization identity, endpoints.

Note: Both are strings, and their values are distinct per tier — a developer-tier org reports "Developer", not "Sandbox" — so never test only for "Sandbox" when deciding whether an environment is safe to change.

Note: If one is unavailable or privilege-gated its failure is reported in partial_errors and the remaining data is still returned; only a failure of all three yields an error response.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
access_type Literal['Default', 'Internet', 'Intranet'] no 'Default' EndpointAccessType member used when retrieving the current organization's service endpoints. 'Default' returns the endpoints for the caller's own access path; 'Internet' and 'Intranet' request the externally- and internally-facing endpoints. Only these three members are accepted.
include_solutions bool no False See note below.
  • include_solutions — Return the full list of installed solutions from RetrieveOrganizationInfo. Off by default because a real environment commonly has several hundred solutions, which would dominate the response of what is otherwise a small environment fingerprint. When false, only 'solutions_count' is returned. Prefer dataverse_list_solutions for browsing, filtering, or paging solutions — it is the purpose-built tool.

dataverse_get_record

Read · idempotent · category core

Retrieve a single Dataverse record by its GUID.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes The GUID of the record to retrieve (min_len=1)
select list[str] | None no None Columns to return. Omit to return a conservative default projection ('createdon','modifiedon'). Specify to reduce payload (e.g., ['name', 'telephone1'])
include_formatted_values bool no False When True, returns human-readable formatted values alongside raw values (e.g., option set labels, formatted dates). Formatted values appear as 'fieldname@OData.Community.Display.V1.FormattedValue' in the record.

Returns {"record": ...}.


dataverse_get_setting

Read · idempotent · category core

Read one setting's FINAL COMPUTED value for this environment.

Note: AN UNKNOWN SETTING NAME IS NOT AN ERROR. Dataverse answers HTTP 200 with SettingDetail: null.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
setting_name str yes Unique name of the setting to read (the settingdefinition's unique name, not its display label). Letters, digits, '', '.' and '-' only. (min_len=1, max_len=100, pattern=^[A-Za-z0-9.\-]+$)
app_unique_name str | None no None Optional unique name of a model-driven app, to read the value as that app sees it (an app-level override of the org-level setting). OMIT it to read the organization-level value — the parameter is then left out of the request entirely rather than sent empty, which is a different call and can return a different value. (min_len=1, max_len=100, pattern=^[A-Za-z0-9_.\-]+$)

dataverse_get_total_record_counts

Read · idempotent · category core

Get approximate row counts for many Dataverse tables in one round trip.

Note: The counts come from a snapshot Dataverse takes at most once every 24 hours, so they are approximate and can lag reality by up to a day: a table populated an hour ago may report 0, and recent deletions may still be included. Worse, on an environment where the snapshot job has not run, EVERY count comes back 0 while the tables actually hold data (observed live on an org whose real counts were in the hundreds).

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_names list[str] yes See note below.
  • entity_names — Logical names of the tables to count — singular and lowercase (e.g. ['account', 'contact', 'new_invoice']), NOT the plural OData entity set names used elsewhere. Between 1 and 50 names per call: the list is sent as a JSON array inside the request URL's query string, and a longer list risks exceeding the practical URL length limit, so split larger sets across multiple calls (with unusually long names, split sooner). Each name must match the Dataverse identifier grammar (letter or underscore, then letters/digits/underscores) and Dataverse's 50-character limit on table schema/logical names. Every name must exist: one unrecognized name fails the whole call with HTTP 400, with no partial results. (min_len=1, max_len=50)

dataverse_list_environments

Read · idempotent · category core

List Power Platform environments available to the authenticated user.

Note: Uses the Power Platform admin API — no dataverse_url required.

Param Type Req Default Notes
expand_capacity bool no False Include capacity details for each environment
expand_addons bool no False Include add-on allocation details for each environment

Returns {"environments": ..., "count": ...}.


dataverse_merge_records

Write · idempotent · category core

Merge a subordinate record into a target record for account, contact, lead, or incident.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_logical_name str yes Logical name of the entity type to merge. Must be one of: 'account', 'contact', 'lead', 'incident'. (min_len=1)
target_id str yes GUID of the target record to keep after the merge. (min_len=36)
subordinate_id str yes GUID of the subordinate record to merge into the target. The subordinate is deactivated (not deleted) after the merge. (min_len=36)
update_content dict | None no None Optional dict of field name/value pairs from the subordinate record to carry over to the target after the merge. Example: {'telephone1': '555-1234'}
perform_parenting_checks bool no False Whether to check and reparent records during the merge. Set to True only when parenting relationships must be maintained.

Returns {"success": ...}.


dataverse_query_table

Read · idempotent · category core

Query records from a Dataverse table with OData filtering, ordering, and expansion.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
select list[str] | None no None Columns to return. Omit to return a conservative default projection ('createdon','modifiedon'). Always specify this to reduce payload size (e.g., ['name', 'accountid', 'telephone1'])
filter str | None no None OData $filter expression. Use lowercase logical names. Examples: "statecode eq 0", "name eq 'Contoso'" , "createdon gt 2024-01-01"
orderby list[str] | None no None Sort order. Each entry is 'column_name asc' or 'column_name desc' (e.g., ['name asc', 'createdon desc'])
top int no 50 Maximum number of records to return (ge=1, le=5000)
expand list[str] | None no None Navigation properties to expand (case-sensitive!). Example: ['primarycontactid']
count bool no False When True, includes total_count in the response with the number of matching records. Counts are capped at 5,000 by Dataverse.
include_formatted_values bool no False When True, returns human-readable formatted values alongside raw values (e.g., option set labels, formatted dates). Formatted values appear as 'fieldname@OData.Community.Display.V1.FormattedValue' in each record.

dataverse_retrieve_principal_access

Read · idempotent · category core

Return the access rights a system user has to a specific Dataverse record.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
user_id str yes GUID of the system user to check access for. Use dataverse_whoami to get the current caller's UserId. (min_len=36)
entity_set_name str yes OData collection name of the target record's table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes GUID of the target record to check access against. (min_len=36)

Returns {"access_rights": ..., "named_rights": ..., "user_id": ..., "entity_set_name": ..., "record_id": ...}.


dataverse_retrieve_unpublished

Read · idempotent · category core

Read the UNPUBLISHED (draft) definition of one customization record.

Note: The returned column set is NOT the set you asked for, and it differs in BOTH directions.

Note: If the record has no unpublished changes, the draft and the published row are identical, which is the expected result rather than an error.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name Literal['savedqueries', 'systemforms', 'appmodules', 'webresourceset'] yes See note below.
record_id str yes GUID of the record to read — savedqueryid, formid, appmoduleid or webresourceid. Use dataverse_list_views, dataverse_list_forms, dataverse_list_apps or dataverse_list_web_resources to find one.
select list[str] | None no None See note below.
  • entity_set_name — OData collection name of the customization table to read from. Only these four support the RetrieveUnpublished message: 'savedqueries' (views), 'systemforms' (forms), 'appmodules', 'webresourceset' (note the irregular plural). Ordinary data tables such as 'accounts' have no unpublished layer, and 'sitemaps' is rejected by Dataverse itself ('the RetrieveUnpublished method does not support entities of type sitemap') — neither is accepted.
  • select — Columns to return. Defaults to a small per-table projection that deliberately EXCLUDES the large XML/binary columns (formxml, fetchxml, layoutxml, content) — a single systemform row can be hundreds of KB. Ask for them explicitly when you need them, e.g. ['formid','name','formxml'] or ['savedqueryid','name','fetchxml','layoutxml']. A requested column whose value is NULL is omitted from the returned record rather than returned as null. (min_len=1, max_len=100)

dataverse_retrieve_user_privileges

Read · idempotent · category core

Retrieve all security privileges assigned to a system user via their roles.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
user_id str yes GUID of the system user whose privileges to retrieve. Use dataverse_whoami to get the current caller's UserId. (min_len=36)

Returns {"privileges": ..., "count": ...}.


dataverse_swap_flow_connection_reference

Write · idempotent · category core

Swap a connection reference logical name inside a cloud flow's clientdata.

Note: Reads the flow's clientdata, replaces every literal occurrence of old_logical_name with new_logical_name, and PATCHes the result back — all server-side, so the multi-KB clientdata JSON never travels as a tool argument (which would otherwise risk truncation at the transport boundary and a "Flow clientdata is in invalid format" error from Dataverse).

Note: This is a literal string replace, not a JSON reparse, so unrelated formatting is preserved byte-for-byte.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
workflow_id str yes The GUID of the cloud flow (workflows entity) to update. (min_len=1)
old_logical_name str yes Connection reference logical name to replace in the flow's clientdata (e.g., 'courts_Decisions_MicrosoftDataverse'). (min_len=1)
new_logical_name str yes Replacement connection reference logical name (e.g., 'courts_Core_MicrosoftDataverse'). (min_len=1)

Returns {"updated": ..., "workflow_id": ..., "replacements": ..., "old_logical_name": ..., "new_logical_name": ...} or {"updated": ..., "workflow_id": ..., "replacements": ..., "message": ...}.


dataverse_update_record

Write · idempotent · category core

Partially update a single Dataverse record via PATCH — only supplied columns change.

Note: Unlike metadata tools, this is a PATCH partial update — no full definition needed.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
entity_set_name str yes OData collection name of the table (e.g., 'accounts', 'contacts'). Use dataverse_get_entity_sets to discover the correct name. (min_len=1, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
record_id str yes The GUID of the record to update. (min_len=1)
data dict[str, Any] yes Partial column name/value pairs to update — only the provided columns are changed, all others are left untouched. Use logical (lowercase) column names (e.g., {'name': 'New Name', 'telephone1': '555-0200'}). Must contain at least one column. (min_len=1)

Returns {"updated": ..., "id": ...}.


dataverse_validate_fetchxml

Read · idempotent · category core

Check a FetchXML query for problems and performance warnings WITHOUT running it.

Note: HTTP 200 DOES NOT MEAN THE QUERY IS VALID — check has_errors / error_count.

Note: The severity mapping is OBSERVED, NOT DOCUMENTED: live responses used 1 for performance warnings and 3 for errors, so severity >= 3 is counted as an error and < 3 as a warning.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').
fetch_xml str yes See note below.
  • fetch_xml — The FetchXml document to validate, starting with '<fetch ...>'. It is analysed by Dataverse, not executed: no records are read and nothing is modified. No entity set name is needed — the root <entity name='...'> inside the document identifies the table. Maximum 2000 characters, because the whole document is sent inside the request URL's query string as a percent-encoded OData string literal, which roughly doubles its length (typically at most triples it, and up to six times for a document that is almost all single quotes, since each quote is doubled before being encoded); beyond that the URL risks rejection by Dataverse or a proxy in front of it, which is reported back as an HTTP 414 with a shortening hint. If a query is too long, shrink it before validating: drop insignificant whitespace and comments, trim <attribute> elements to the columns actually needed, or validate expensive <link-entity> branches one at a time — the warnings are reported per construct, so a trimmed query still surfaces the same suggestions. The document must be well-formed XML and must not declare a DTD or XML entities; both are checked locally before the request is sent. (min_len=8, max_len=2000)

dataverse_whoami

Read · idempotent · category core

Return the authenticated caller's identity from the Dataverse WhoAmI endpoint.

Param Type Req Default Notes
dataverse_url str yes Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com').

Returns {"UserId": ..., "BusinessUnitId": ..., "OrganizationId": ...}.


Clone this wiki locally