-
Notifications
You must be signed in to change notification settings - Fork 0
Tools Security
This page is generated from the code by scripts/gen_wiki_tools.py — do not edit by hand.
22 tools · category token security · enable with DATAVERSE_TOOLS=security (unset enables every category)
Every tool returns JSON. Errors return {"error": true, "message": "..."}. Write tools require DATAVERSE_ALLOW_WRITE=true; delete tools require DATAVERSE_ALLOW_DELETE=true.
Write · idempotent · category security
Add one or more system users to a Dataverse team.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| team_id | str |
yes | — | GUID of the team to add members to. (min_len=36) |
| user_ids | list[str] |
yes | — | List of system user GUIDs to add as team members. At least one user_id must be provided. (min_len=1) |
Returns {"team_id": ..., "results": ..., "total": ..., "succeeded": ..., "failed": ...}.
Write · idempotent · category security
Assign a security role to a user or team via the Web API $ref association.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| role_id | str |
yes | — | GUID of the security role to assign. (min_len=36) |
| user_id | str | None |
no | None |
GUID of the system user to assign the role to. Provide exactly one of user_id or team_id. |
| team_id | str | None |
no | None |
GUID of the team to assign the role to. Provide exactly one of user_id or team_id. |
Read · idempotent · category security
Return a composite access report for a Dataverse system user.
| 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 | None |
no | None |
GUID of the system user to audit. Provide either user_id or user_domain_name, not both. (min_len=36) |
| user_domain_name | str | None |
no | None |
Domain name of the user to audit (e.g., 'user@contoso.com'). Provide either user_id or user_domain_name, not both. (min_len=1) |
| target_entity_set_name | str | None |
no | None |
OData collection name of a specific record to check access against (e.g., 'accounts'). Requires target_record_id. (pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| target_record_id | str | None |
no | None |
GUID of the specific record to check access against. Requires target_entity_set_name. (min_len=36) |
| include_privileges | bool |
no | True |
When True, includes the user's effective privilege list. Set False to skip this call and speed up the report. |
Read · idempotent · category security
Retrieve the audit trail for ONE COLUMN of ONE RECORD — who changed this field.
Note: MIND THE SINGULAR/PLURAL SPLIT — this tool takes the SAME TABLE TWICE, under two different names, and they are NOT interchangeable.
Note: ON A 404, READ THE ERROR CODE — DO NOT ASSUME WHICH FAILURE IT IS.
| 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 record's table — the PLURAL entity set name ('accounts', 'contacts', 'new_projects'), NOT the singular logical name this tool ALSO takes as table_logical_name. Use dataverse_get_entity_sets to confirm it; the plural is irregular often enough that guessing it costs a 404. (min_len=1, max_len=64, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| record_id | str |
yes | — | GUID of the record whose column history to retrieve (the row's primary key, e.g. an accountid). It becomes the key predicate inside the target EntityReference, so it must be a well-formed GUID. |
| table_logical_name | str |
yes | — | SINGULAR lowercase logical name of the record's table ('account', not 'accounts'). It is NOT sent to the function — it is used only to probe whether auditing is enabled on the table and the column when the result comes back empty, which is what turns an empty answer into a usable one. (min_len=1, max_len=50, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| column_logical_name | str |
yes | — | Lowercase logical name of the column whose changes to retrieve ('name', 'telephone1', 'new_status'). (min_len=1, max_len=50, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| top | int |
no | 50 |
Maximum number of audit detail entries to return. The function is called without PagingInfo, so the list is trimmed here; has_more reports whether anything was cut. (ge=1, le=5000) |
Read · idempotent · category security
Retrieve full details from a single audit record.
Note: Requires auditing enabled on the org. If auditing is disabled, Dataverse returns an HTTP error — check the error message for guidance.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| audit_id | str |
yes | — | GUID of the audit record whose full details to retrieve (e.g., 'a1b2c3d4-1234-5678-abcd-ef0123456789'). Obtain audit record GUIDs from dataverse_list_audit or dataverse_retrieve_record_change_history. (min_len=36) |
Returns {"audit_id": ..., "audit_detail": ...}.
Read · idempotent · category security
Answer "what can this security role actually DO?" — list a role's privileges.
Note: A well-formed but nonexistent role id returns an ERROR, not an empty list: Dataverse answers HTTP 404 [0x80040217] "Entity 'role' With Id = ... Does Not Exist", surfaced through the standard {"error": true, "message": ...} envelope.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| role_id | str |
yes | — | GUID of the security role whose privileges to list. Use dataverse_list_security_roles to find a role id by name, or dataverse_get_security_role if you already have one and want the role record itself. |
| top | int |
no | 50 |
See note below. |
- top — Maximum number of privilege entries to return. RetrieveRolePrivilegesRole has no server-side paging — it returns every privilege in one response, and a System Administrator role was measured live at 4,132 privileges in a ~1 MB payload — so the list is trimmed here. total_count always reports the full number Dataverse returned and has_more says whether anything was trimmed, so the magnitude is never hidden. depth_summary is computed over ALL entries, not just the returned page. Raise this to see more. (ge=1, le=1000)
Read · idempotent · category security
Retrieve a single Dataverse security role 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'). |
| role_id | str |
yes | — | GUID of the security role to retrieve. (min_len=36) |
| select | list[str] | None |
no | None |
Columns to return. Defaults to roleid, name, _businessunitid_value, ismanaged, modifiedon. |
Returns {"record": ...}.
Read · idempotent · category security
Retrieve a single Dataverse team 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'). |
| team_id | str |
yes | — | GUID of the team to retrieve. (min_len=36) |
| select | list[str] | None |
no | None |
Columns to return. Defaults to teamid, name, teamtype, _businessunitid_value, isdefault, modifiedon. |
Returns {"record": ...}.
Read · idempotent · category security
Answer "what can this TEAM actually DO?" — list a team's privileges.
Note: AN EMPTY LIST IS A REAL ANSWER, NOT A FAILURE. count: 0 with normalized: true means the team has NO DIRECTLY-ASSIGNED SECURITY ROLES — a common and entirely normal state, and the usual one: most teams get their access from their members' own roles rather than from a role assigned to the team itself.
Note: A well-formed but nonexistent team id returns an ERROR, not an empty list — VERIFIED LIVE: Dataverse answers HTTP 404 [0x80040217] "Does Not Exist", as the role function does, and it is surfaced through the standard {"error": true, "message": ...} envelope.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| team_id | str |
yes | — | GUID of the team whose privileges to list. Use dataverse_list_teams to find a team id by name, or dataverse_get_team if you already have one and want the team record itself. |
| top | int |
no | 50 |
See note below. |
- top — Maximum number of privilege entries to return. RetrieveTeamPrivileges has no server-side paging — it returns every privilege in one response, and its sibling RetrieveRolePrivilegesRole was measured live at 4,132 privileges in a ~1 MB payload for a broad role — so the list is trimmed here. total_count always reports the full number Dataverse returned and has_more says whether anything was trimmed, so the magnitude is never hidden. depth_summary is computed over ALL entries, not just the returned page. Raise this to see more. (ge=1, le=1000)
Read · idempotent · category security
Retrieve a single Dataverse system user by their GUID.
| 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 retrieve. Use dataverse_whoami to get the current caller's UserId. (min_len=36) |
| select | list[str] | None |
no | None |
Columns to return. Defaults to systemuserid, fullname, domainname, internalemailaddress, isdisabled, _businessunitid_value. |
Returns {"record": ...}.
Read · idempotent · category security
Query the audit table with optional OData filters.
Note: Requires auditing enabled on the org. If auditing is disabled, Dataverse may return an empty result set or an HTTP error.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| filter | str | None |
no | None |
OData $filter expression to narrow results. Use lowercase logical names. Examples: "operation eq 2" (Updates only), "objecttypecode eq 'account'", "createdon gt 2024-01-01T00:00:00Z", "_userid_value eq '<guid>'" |
| select | list[str] | None |
no | None |
Columns to return. Defaults to auditid, createdon, operation, action, objecttypecode, _userid_value, _objectid_value, transactionid. |
| orderby | list[str] | None |
no | None |
Sort order. Each entry is 'column_name asc' or 'column_name desc'. Example: ['createdon desc'] |
| top | int |
no | 50 |
Maximum number of audit records to return. (ge=1, le=5000) |
Returns {"records": ..., "count": ..., "has_more": ...}.
Read · idempotent · category security
List business units in the Dataverse environment.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| filter | str | None |
no | None |
OData $filter expression to narrow results (e.g., "isdisabled eq false"). |
| select | list[str] | None |
no | None |
Columns to return. Defaults to businessunitid, name, _parentbusinessunitid_value, isdisabled, modifiedon. |
| top | int |
no | 50 |
Maximum number of business units to return. (ge=1, le=5000) |
Returns {"records": ..., "count": ..., "has_more": ...}.
Read · idempotent · category security
List the privileges DEFINED in the environment — the catalogue of what CAN be granted.
Note: ACCESS RIGHTS ARE DECODED BY A HAND-ROLLED MAP, AND THAT IS THE POINT. The accessright column is an integer with NO option set behind it anywhere in Dataverse: the PicklistAttributeMetadata cast 404s, GlobalOptionSetDefinitions for it 404s, and annotation-included FormattedValues return only the integer with thousands separators.
Note: total_count COMES FROM AN AGGREGATION, NOT @odata.count. On this collection @odata.count CAPS AT 5,000 and lies — ?$count=true reports 5,000 where the true catalogue is ~7,346 — so the count is taken with $apply=aggregate($count as c), which bypasses the cap.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| table_logical_name | str | None |
no | None |
See note below. |
| name_startswith | str | None |
no | None |
Optional prefix of the privilege NAME to filter on, case-insensitively ('prvRead', 'prvCreate', 'prvAppendTo'). Privilege names follow the prv{Verb}{Table} form, so a prefix is the natural way to ask 'every read privilege'. Combine it with table_logical_name to narrow one table's privileges further. (min_len=1, max_len=100) |
| access_right | Literal['None', 'ReadAccess', 'WriteAccess', 'AppendAccess', 'AppendToAccess', 'CreateAccess', 'DeleteAccess', 'ShareAccess', 'AssignAccess'] | None |
no | None |
Optional access right to filter on, given by NAME. The name is translated to its integer here — no caller text is ever interpolated into the query. Note that 'None' is a REAL access right (the value 0, carried by non-CRUD privileges such as prvActOnBehalfOfAnotherUser), not a way of saying 'no filter' — omit the field entirely for that. |
| top | int |
no | 50 |
Maximum number of privileges to return. The environment-wide catalogue runs to roughly 7,300 rows, so the list is trimmed. total_count reports the TRUE total (obtained by aggregation, because @odata.count caps at 5,000 on this collection and under-reports) and has_more says whether anything was trimmed, so the magnitude is never hidden. (ge=1, le=5000) |
- table_logical_name — Optional SINGULAR logical name of a table ('account', not 'accounts') to scope the list to that table's privileges. The value is LOWERCASED for you — Dataverse logical names are always lowercase and it rejects 'Account' outright — so only the singular/plural distinction is yours to get right. Scoping goes through a join table, NOT by matching privilege names: matching on the name is wrong in general (endswith(name,'Role') returns 25 privileges spanning role, connectionrole, relationshiprole and mspp_webrole), it just happens to look right on the tables people test with. Omit it to list the whole environment-wide privilege catalogue. (min_len=1, max_len=50, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$)
Read · idempotent · category security
List security roles in the Dataverse environment.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| filter | str | None |
no | None |
OData $filter expression to narrow results. Use lowercase logical names (e.g., "ismanaged eq false", "_businessunitid_value eq '<guid>'") |
| select | list[str] | None |
no | None |
Columns to return. Defaults to roleid, name, _businessunitid_value, ismanaged, modifiedon. |
| top | int |
no | 50 |
Maximum number of roles to return. (ge=1, le=5000) |
Returns {"records": ..., "count": ..., "has_more": ...}.
Read · idempotent · category security
Answer "WHO has this record because it was SHARED with them?".
Note: A WRONG ENTITY SET NAME LOOKS EXACTLY LIKE A MISSING RECORD. VERIFIED LIVE: a nonexistent record id and a VALID id paired with the WRONG entity set both return HTTP 404 [0x80040217] "Entity '<Type>' With Id = <guid> Does Not Exist" from BOTH functions — the same status, the same error code, indistinguishable text.
Note: So when this tool errors with "Does Not Exist", CHECK THE ENTITY SET NAME FIRST (plural — 'accounts', not 'account'; see the asymmetry note above) before concluding the record is gone.
| 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 record's table — the PLURAL entity set name ('accounts', 'contacts', 'new_projects'), NOT the singular logical name dataverse_retrieve_access_origin takes. Use dataverse_get_entity_sets to confirm it ('account' -> 'accounts'); the plural is irregular often enough that guessing it costs a 404. (min_len=1, max_len=64, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| record_id | str |
yes | — | GUID of the record whose shares to list (the row's primary key, e.g. an accountid). It becomes the key predicate inside the target EntityReference, so it must be a well-formed GUID. |
| top | int |
no | 50 |
Maximum number of entries to return from EACH of the two functions. Neither has server-side paging, and a heavily shared record can carry many principals, so each list is trimmed here. total_count and has_more are reported per list and always describe the full set, so the true magnitude is never hidden. (ge=1, le=1000) |
Read · idempotent · category security
List teams in the Dataverse environment.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| filter | str | None |
no | None |
OData $filter expression to narrow results (e.g., "teamtype eq 0" for owner teams, "isdefault eq false"). |
| select | list[str] | None |
no | None |
Columns to return. Defaults to teamid, name, teamtype, _businessunitid_value, isdefault, modifiedon. |
| top | int |
no | 50 |
Maximum number of teams to return. (ge=1, le=5000) |
Returns {"records": ..., "count": ..., "has_more": ...}.
Read · idempotent · category security
List system users (systemusers) in the Dataverse environment.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| filter | str | None |
no | None |
OData $filter expression to narrow results (e.g., "isdisabled eq false", "domainname eq 'user@contoso.com'"). |
| select | list[str] | None |
no | None |
Columns to return. Defaults to systemuserid, fullname, domainname, internalemailaddress, isdisabled, _businessunitid_value. |
| top | int |
no | 50 |
Maximum number of users to return. (ge=1, le=5000) |
Returns {"records": ..., "count": ..., "has_more": ...}.
Delete · idempotent · category security
Remove a security role from a user or team via the Web API $ref disassociation.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| role_id | str |
yes | — | GUID of the security role to remove. (min_len=36) |
| user_id | str | None |
no | None |
GUID of the system user to remove the role from. Provide exactly one of user_id or team_id. |
| team_id | str | None |
no | None |
GUID of the team to remove the role from. Provide exactly one of user_id or team_id. |
Delete · idempotent · category security
Remove one or more system users from a Dataverse team.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| team_id | str |
yes | — | GUID of the team to remove members from. (min_len=36) |
| user_ids | list[str] |
yes | — | List of system user GUIDs to remove from the team. At least one user_id must be provided. (min_len=1) |
Returns {"team_id": ..., "results": ..., "total": ..., "succeeded": ..., "failed": ...}.
Read · idempotent · category security
Answer "WHY does this principal have access to this record?".
Note: HTTP 200 DOES NOT MEAN "HAS ACCESS" — READ THE STRING. Three materially different outcomes all come back as a successful call with normalized true, and they are distinguishable ONLY by the English prose inside the string.
Note: The text is passed through verbatim and deliberately NOT classified into a boolean: pattern-matching platform prose is fragile and locale-dependent, and a wrong security verdict is worse than none.
| Param | Type | Req | Default | Notes |
|---|---|---|---|---|
| dataverse_url | str |
yes | — | Required Dataverse organization URL for this request (e.g., 'https://yourorg.crm.dynamics.com'). |
| object_id | str |
yes | — | GUID of the record whose access is being explained (the row's primary key, e.g. an accountid or an incidentid). |
| logical_name | str |
yes | — | Lowercase logical name of the table that record belongs to (e.g. 'account', 'incident', 'new_project') — the singular logical name, NOT the plural entity set name. Use dataverse_list_tables to confirm it. (min_len=1, max_len=50, pattern=^[a-zA-Z_][a-zA-Z0-9_]*$) |
| principal_id | str |
yes | — | GUID of the principal whose access is being explained. Must be a systemuser or a team — no other principal type is accepted. Use dataverse_list_users or dataverse_list_teams to find one, or dataverse_whoami for the current caller's own UserId. |
Read · idempotent · category security
Retrieve the full audit change history for a specific record.
Note: AN HTTP 200 IS NOT PROOF OF ANYTHING, AND ON A 404 READ THE ERROR CODE.
Note: NOT EVERY ENTRY IS A RESULT. Dataverse MAY add org-level audit-CONFIGURATION rows (records of auditing itself being switched on or off) to a response.
| 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 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 record whose change history to retrieve (e.g., 'a1b2c3d4-1234-5678-abcd-ef0123456789'). (min_len=36) |
| top | int |
no | 50 |
Maximum number of audit detail entries to return. (ge=1, le=5000) |
Write · idempotent · category security
Enable or disable a Dataverse system user.
Note: The caller must hold the System Administrator role, and a user cannot disable their own account. In online environments user lifecycle is also governed by Microsoft Entra ID.
| 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 enable or disable. Use dataverse_whoami to get the current caller's UserId. (min_len=36) |
| disabled | bool |
yes | — | True to disable the user (statecode=1, statuscode=2); False to enable the user (statecode=0, statuscode=1). |
Returns {"updated": ..., "user_id": ..., "disabled": ...}.
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