Skip to main content
Glama
ryanmichaeljames

Dataverse MCP Server

dataverse_retrieve_access_origin

Read-onlyIdempotent

Find out why a user or team has access to a specific Dataverse record by revealing whether access comes from object ownership or explicit shares, teams, or hierarchy grants.

Instructions

Answer "WHY does this principal have access to this record?".

Calls the unbound RetrieveAccessOrigin function, which explains where a principal's rights over one specific row come from — object ownership, or the Principal Object Access (POA) table that backs explicit shares and team or hierarchy grants.

This is the companion to dataverse_retrieve_principal_access, which returns only the access MASK (which rights: Read, Write, Delete, …) and cannot say where those rights came from. When you are debugging "why can this user see this record?" or "why can't they?", the mask is the symptom and this is the cause. Use dataverse_audit_user_access for the wider picture (roles, teams, effective privileges) and dataverse_get_role_privileges for what one role permits in general rather than on one row.

Inputs:

  • object_id — the record's own GUID.

  • logical_name — the SINGULAR lowercase logical name of that record's table ('account', not 'accounts'). This is deliberately not the entity set name the record-access tools take.

  • principal_id — a systemuser id or a team id. No other principal type is accepted; use dataverse_list_users / dataverse_list_teams.

RESPONSE SHAPE (verified live). Dataverse answers with ONE scalar string property, Response — never a collection, in a raw body of roughly 286 bytes. It is surfaced as access_origin, with access_origin_source naming the property it was read from, and the payload (minus the @odata.* envelope) rides along under raw_response so you can check that for yourself. There is no count: the answer is never list-shaped. Should a future platform change move the answer somewhere unrecognizable, normalized is false, nothing is fabricated, and raw_response is the whole answer.

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. 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. Observed live in ONE org — these wordings are observations, not a documented platform contract, so treat the list as incomplete and never match on it:

  1. Access exists, with the reason. Two forms seen, both meaning "owner" — "PrincipalId is object owner ()" on a user- or team-owned row, and "PrincipalId is member of organization () who is object owner ()" on an ORGANIZATION-owned row (see the org-owned note below for why that answer is the same for every principal).

  2. NO access at all — "Access origin could not be found. Access does not come from POA table or object ownership."

  3. The record DOES NOT EXIST — still HTTP 200, carrying the platform's "Does Not Exist" exception text inside the Response string. A bad object_id is NOT a 404 from this function, so an unread string looks exactly like a successful answer. Do not report that the principal has access unless the string says so.

Other live-confirmed behaviour:

  • An unknown but grammar-valid logical_name is a clean HTTP 400 [0x80041102] "... was not found in the MetadataCache", surfaced through the standard {"error": true, "message": ...} envelope. Confirm the name with dataverse_list_tables.

  • On an ORGANIZATION-owned table (solution, role, …) the answer is the same for every principal, because ownership resolves at organization level. That is correct platform behaviour, not a defect — discrimination between principals shows up on user- and team-owned rows.

  • A nonexistent principal_id is not validated against an org-owned row: it returned the same generic ownership text as a real one. Confirm the principal exists with dataverse_get_user / dataverse_get_team first.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
paramsYes

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
resultYes
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations by disclosing critical runtime behavior: 'HTTP 200 DOES NOT MEAN "HAS ACCESS" — READ THE STRING', 'Three materially different outcomes... distinguishable ONLY by the English prose inside the string', and specific error cases like unknown logical_name returning a 400, org-owned rows returning identical answers, and nonexistent principal_id not being validated. It also explains the normalization/raw_response behavior, adding value beyond readOnlyHint and idempotentHint.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Although long, the description is well-structured with clear sections for inputs, response shape, and live-confirmed behavior. Every sentence adds necessary nuance or a critical warning. It is front-loaded with the core purpose and immediately distinguishes from the related mask-only tool. There is no fluff or redundant repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the tool's complexity and the risk of misinterpreting HTTP 200, the description is remarkably complete. It documents the response shape, the meaning of normalized flags, and multiple edge cases (nonexistent records, org-owned rows, invalid principal IDs). It also cautions that observed wordings are not a platform contract, which is crucial for an agent to avoid brittle reasoning.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The description adds meaning beyond the schema by clarifying logical_name is 'the SINGULAR lowercase logical name... deliberately not the entity set name' and principal_id 'must be a systemuser or a team — no other principal type is accepted.' It covers object_id, logical_name, and principal_id with context. However, it omits dataverse_url from the Inputs section, though the schema already provides a clear description for that parameter. The description meaningfully compensates for the schema's terse descriptions.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description explicitly frames the tool as answering 'WHY does this principal have access to this record?' and states it 'explains where a principal's rights over one specific row come from — object ownership, or the Principal Object Access (POA) table.' It differentiates from the sibling dataverse_retrieve_principal_access, which returns only the access mask. This is a specific verb+resource+scope with clear sibling distinction.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides direct comparisons: 'This is the companion to dataverse_retrieve_principal_access, which returns only the access MASK... When you are debugging "why can this user see this record?"... use this.' It also gives alternatives for broader questions: 'Use dataverse_audit_user_access for the wider picture... and dataverse_get_role_privileges for what one role permits.' It even states principal-type constraints and which list tools to use for valid IDs.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

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