Skip to main content
Glama
mwhesse

Dataverse MCP Server

by mwhesse

Create Dataverse Relationship

create_dataverse_relationship

Create relationships between Dataverse tables to establish data connections, enable navigation, and maintain referential integrity. Supports One-to-Many and Many-to-Many relationship types.

Instructions

Creates a relationship between two Dataverse tables. Supports One-to-Many relationships (parent-child with lookup field) and Many-to-Many relationships (junction table). Use this to establish data connections between tables, enable navigation, and maintain referential integrity.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
cascadeAssignNoCascade behavior for assign operationsNoCascade
cascadeDeleteNoCascade behavior for delete operationsRemoveLink
cascadeMergeNoCascade behavior for merge operationsNoCascade
cascadeReparentNoCascade behavior for reparent operationsNoCascade
cascadeShareNoCascade behavior for share operationsNoCascade
cascadeUnshareNoCascade behavior for unshare operationsNoCascade
entity1LogicalNameNoFirst entity logical name for Many-to-Many relationships
entity2LogicalNameNoSecond entity logical name for Many-to-Many relationships
intersectEntityNameNoName for the intersect entity (auto-generated if not provided)
isHierarchicalNoWhether this is a hierarchical relationship (One-to-Many only)
isValidForAdvancedFindNoWhether the relationship is valid for Advanced Find
menuBehaviorNoHow the relationship appears in associated menusUseCollectionName
menuGroupNoMenu group for the relationshipDetails
menuLabelNoCustom label for the menu (required if menuBehavior is UseLabel)
menuOrderNoOrder in the menu
referencedEntityNoReferenced (parent) entity logical name for One-to-Many relationships
referencingAttributeDisplayNameNoDisplay name for the lookup attribute
referencingAttributeLogicalNameNoLogical name for the lookup attribute to be created
referencingEntityNoReferencing (child) entity logical name for One-to-Many relationships
relationshipTypeYesType of relationship to create
schemaNameYesSchema name for the relationship (e.g., 'new_account_contact')

Implementation Reference

  • The async handler function implementing the core logic for creating One-to-Many or Many-to-Many relationships in Dataverse by posting metadata definitions via the DataverseClient.
    async (params) => {
      try {
        if (params.relationshipType === "OneToMany") {
          if (!params.referencedEntity || !params.referencingEntity || !params.referencingAttributeLogicalName || !params.referencingAttributeDisplayName) {
            throw new Error("For One-to-Many relationships, referencedEntity, referencingEntity, referencingAttributeLogicalName, and referencingAttributeDisplayName are required");
          }
    
          const cascadeConfig = {
            Assign: getCascadeValue(params.cascadeAssign),
            Delete: getCascadeValue(params.cascadeDelete),
            Merge: getCascadeValue(params.cascadeMerge),
            Reparent: getCascadeValue(params.cascadeReparent),
            Share: getCascadeValue(params.cascadeShare),
            Unshare: getCascadeValue(params.cascadeUnshare),
            RollupView: "NoCascade"
          };
    
          const menuConfig = {
            Behavior: getMenuBehaviorValue(params.menuBehavior),
            Group: getMenuGroupValue(params.menuGroup),
            Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
            Order: params.menuOrder
          };
    
          const relationshipDefinition = {
            "@odata.type": "Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata",
            SchemaName: params.schemaName,
            ReferencedEntity: params.referencedEntity,
            ReferencingEntity: params.referencingEntity,
            CascadeConfiguration: cascadeConfig,
            AssociatedMenuConfiguration: menuConfig,
            IsValidForAdvancedFind: params.isValidForAdvancedFind,
            IsHierarchical: params.isHierarchical,
            IsCustomRelationship: true,
            Lookup: {
              "@odata.type": "Microsoft.Dynamics.CRM.LookupAttributeMetadata",
              LogicalName: params.referencingAttributeLogicalName,
              SchemaName: params.referencingAttributeLogicalName.charAt(0).toUpperCase() + params.referencingAttributeLogicalName.slice(1),
              DisplayName: createLocalizedLabel(params.referencingAttributeDisplayName),
              RequiredLevel: {
                Value: "None",
                CanBeChanged: true,
                ManagedPropertyLogicalName: "canmodifyrequirementlevelsettings"
              },
              Targets: [params.referencedEntity],
              IsCustomAttribute: true
            }
          };
    
          const result = await client.postMetadata("RelationshipDefinitions", relationshipDefinition);
    
          return {
            content: [
              {
                type: "text",
                text: `Successfully created One-to-Many relationship '${params.schemaName}' between '${params.referencedEntity}' and '${params.referencingEntity}'.\n\nResponse: ${JSON.stringify(result, null, 2)}`
              }
            ]
          };
    
        } else { // ManyToMany
          if (!params.entity1LogicalName || !params.entity2LogicalName) {
            throw new Error("For Many-to-Many relationships, entity1LogicalName and entity2LogicalName are required");
          }
    
          const intersectName = params.intersectEntityName || `${params.entity1LogicalName}_${params.entity2LogicalName}`;
    
          const menuConfig1 = {
            Behavior: getMenuBehaviorValue(params.menuBehavior),
            Group: getMenuGroupValue(params.menuGroup),
            Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
            Order: params.menuOrder
          };
    
          const menuConfig2 = {
            Behavior: getMenuBehaviorValue(params.menuBehavior),
            Group: getMenuGroupValue(params.menuGroup),
            Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
            Order: params.menuOrder
          };
    
          const relationshipDefinition = {
            "@odata.type": "Microsoft.Dynamics.CRM.ManyToManyRelationshipMetadata",
            SchemaName: params.schemaName,
            Entity1LogicalName: params.entity1LogicalName,
            Entity1AssociatedMenuConfiguration: menuConfig1,
            Entity2LogicalName: params.entity2LogicalName,
            Entity2AssociatedMenuConfiguration: menuConfig2,
            IntersectEntityName: intersectName,
            IsValidForAdvancedFind: params.isValidForAdvancedFind,
            IsCustomRelationship: true
          };
    
          const result = await client.postMetadata("RelationshipDefinitions", relationshipDefinition);
    
          return {
            content: [
              {
                type: "text",
                text: `Successfully created Many-to-Many relationship '${params.schemaName}' between '${params.entity1LogicalName}' and '${params.entity2LogicalName}'.\n\nResponse: ${JSON.stringify(result, null, 2)}`
              }
            ]
          };
        }
      } catch (error) {
        return {
          content: [
            {
              type: "text",
              text: `Error creating relationship: ${error instanceof Error ? error.message : 'Unknown error'}`
            }
          ],
          isError: true
        };
      }
    }
  • Zod schema defining the input parameters for the tool, including relationship type, entity names, attributes, cascade behaviors, menu settings, and other configurations.
    inputSchema: {
      relationshipType: z.enum(["OneToMany", "ManyToMany"]).describe("Type of relationship to create"),
      schemaName: z.string().describe("Schema name for the relationship (e.g., 'new_account_contact')"),
      
      // One-to-Many specific fields
      referencedEntity: z.string().optional().describe("Referenced (parent) entity logical name for One-to-Many relationships"),
      referencingEntity: z.string().optional().describe("Referencing (child) entity logical name for One-to-Many relationships"),
      referencingAttributeLogicalName: z.string().optional().describe("Logical name for the lookup attribute to be created"),
      referencingAttributeDisplayName: z.string().optional().describe("Display name for the lookup attribute"),
      
      // Many-to-Many specific fields
      entity1LogicalName: z.string().optional().describe("First entity logical name for Many-to-Many relationships"),
      entity2LogicalName: z.string().optional().describe("Second entity logical name for Many-to-Many relationships"),
      intersectEntityName: z.string().optional().describe("Name for the intersect entity (auto-generated if not provided)"),
      
      // Cascade configuration for One-to-Many
      cascadeAssign: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for assign operations"),
      cascadeDelete: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("RemoveLink").describe("Cascade behavior for delete operations"),
      cascadeMerge: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for merge operations"),
      cascadeReparent: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for reparent operations"),
      cascadeShare: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for share operations"),
      cascadeUnshare: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for unshare operations"),
      
      // Associated menu configuration
      menuBehavior: z.enum(["UseCollectionName", "UseLabel", "DoNotDisplay"]).default("UseCollectionName").describe("How the relationship appears in associated menus"),
      menuGroup: z.enum(["Details", "Sales", "Service", "Marketing"]).default("Details").describe("Menu group for the relationship"),
      menuLabel: z.string().optional().describe("Custom label for the menu (required if menuBehavior is UseLabel)"),
      menuOrder: z.number().optional().describe("Order in the menu"),
      
      isValidForAdvancedFind: z.boolean().default(true).describe("Whether the relationship is valid for Advanced Find"),
      isHierarchical: z.boolean().default(false).describe("Whether this is a hierarchical relationship (One-to-Many only)")
    }
  • The server.registerTool call within createRelationshipTool that registers the 'create_dataverse_relationship' tool with the MCP server, including title, description, schema, and handler.
    server.registerTool(
      "create_dataverse_relationship",
      {
        title: "Create Dataverse Relationship",
        description: "Creates a relationship between two Dataverse tables. Supports One-to-Many relationships (parent-child with lookup field) and Many-to-Many relationships (junction table). Use this to establish data connections between tables, enable navigation, and maintain referential integrity.",
        inputSchema: {
          relationshipType: z.enum(["OneToMany", "ManyToMany"]).describe("Type of relationship to create"),
          schemaName: z.string().describe("Schema name for the relationship (e.g., 'new_account_contact')"),
          
          // One-to-Many specific fields
          referencedEntity: z.string().optional().describe("Referenced (parent) entity logical name for One-to-Many relationships"),
          referencingEntity: z.string().optional().describe("Referencing (child) entity logical name for One-to-Many relationships"),
          referencingAttributeLogicalName: z.string().optional().describe("Logical name for the lookup attribute to be created"),
          referencingAttributeDisplayName: z.string().optional().describe("Display name for the lookup attribute"),
          
          // Many-to-Many specific fields
          entity1LogicalName: z.string().optional().describe("First entity logical name for Many-to-Many relationships"),
          entity2LogicalName: z.string().optional().describe("Second entity logical name for Many-to-Many relationships"),
          intersectEntityName: z.string().optional().describe("Name for the intersect entity (auto-generated if not provided)"),
          
          // Cascade configuration for One-to-Many
          cascadeAssign: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for assign operations"),
          cascadeDelete: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("RemoveLink").describe("Cascade behavior for delete operations"),
          cascadeMerge: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for merge operations"),
          cascadeReparent: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for reparent operations"),
          cascadeShare: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for share operations"),
          cascadeUnshare: z.enum(["NoCascade", "Cascade", "Active", "UserOwned", "RemoveLink", "Restrict"]).default("NoCascade").describe("Cascade behavior for unshare operations"),
          
          // Associated menu configuration
          menuBehavior: z.enum(["UseCollectionName", "UseLabel", "DoNotDisplay"]).default("UseCollectionName").describe("How the relationship appears in associated menus"),
          menuGroup: z.enum(["Details", "Sales", "Service", "Marketing"]).default("Details").describe("Menu group for the relationship"),
          menuLabel: z.string().optional().describe("Custom label for the menu (required if menuBehavior is UseLabel)"),
          menuOrder: z.number().optional().describe("Order in the menu"),
          
          isValidForAdvancedFind: z.boolean().default(true).describe("Whether the relationship is valid for Advanced Find"),
          isHierarchical: z.boolean().default(false).describe("Whether this is a hierarchical relationship (One-to-Many only)")
        }
      },
      async (params) => {
        try {
          if (params.relationshipType === "OneToMany") {
            if (!params.referencedEntity || !params.referencingEntity || !params.referencingAttributeLogicalName || !params.referencingAttributeDisplayName) {
              throw new Error("For One-to-Many relationships, referencedEntity, referencingEntity, referencingAttributeLogicalName, and referencingAttributeDisplayName are required");
            }
    
            const cascadeConfig = {
              Assign: getCascadeValue(params.cascadeAssign),
              Delete: getCascadeValue(params.cascadeDelete),
              Merge: getCascadeValue(params.cascadeMerge),
              Reparent: getCascadeValue(params.cascadeReparent),
              Share: getCascadeValue(params.cascadeShare),
              Unshare: getCascadeValue(params.cascadeUnshare),
              RollupView: "NoCascade"
            };
    
            const menuConfig = {
              Behavior: getMenuBehaviorValue(params.menuBehavior),
              Group: getMenuGroupValue(params.menuGroup),
              Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
              Order: params.menuOrder
            };
    
            const relationshipDefinition = {
              "@odata.type": "Microsoft.Dynamics.CRM.OneToManyRelationshipMetadata",
              SchemaName: params.schemaName,
              ReferencedEntity: params.referencedEntity,
              ReferencingEntity: params.referencingEntity,
              CascadeConfiguration: cascadeConfig,
              AssociatedMenuConfiguration: menuConfig,
              IsValidForAdvancedFind: params.isValidForAdvancedFind,
              IsHierarchical: params.isHierarchical,
              IsCustomRelationship: true,
              Lookup: {
                "@odata.type": "Microsoft.Dynamics.CRM.LookupAttributeMetadata",
                LogicalName: params.referencingAttributeLogicalName,
                SchemaName: params.referencingAttributeLogicalName.charAt(0).toUpperCase() + params.referencingAttributeLogicalName.slice(1),
                DisplayName: createLocalizedLabel(params.referencingAttributeDisplayName),
                RequiredLevel: {
                  Value: "None",
                  CanBeChanged: true,
                  ManagedPropertyLogicalName: "canmodifyrequirementlevelsettings"
                },
                Targets: [params.referencedEntity],
                IsCustomAttribute: true
              }
            };
    
            const result = await client.postMetadata("RelationshipDefinitions", relationshipDefinition);
    
            return {
              content: [
                {
                  type: "text",
                  text: `Successfully created One-to-Many relationship '${params.schemaName}' between '${params.referencedEntity}' and '${params.referencingEntity}'.\n\nResponse: ${JSON.stringify(result, null, 2)}`
                }
              ]
            };
    
          } else { // ManyToMany
            if (!params.entity1LogicalName || !params.entity2LogicalName) {
              throw new Error("For Many-to-Many relationships, entity1LogicalName and entity2LogicalName are required");
            }
    
            const intersectName = params.intersectEntityName || `${params.entity1LogicalName}_${params.entity2LogicalName}`;
    
            const menuConfig1 = {
              Behavior: getMenuBehaviorValue(params.menuBehavior),
              Group: getMenuGroupValue(params.menuGroup),
              Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
              Order: params.menuOrder
            };
    
            const menuConfig2 = {
              Behavior: getMenuBehaviorValue(params.menuBehavior),
              Group: getMenuGroupValue(params.menuGroup),
              Label: params.menuLabel ? createLocalizedLabel(params.menuLabel) : undefined,
              Order: params.menuOrder
            };
    
            const relationshipDefinition = {
              "@odata.type": "Microsoft.Dynamics.CRM.ManyToManyRelationshipMetadata",
              SchemaName: params.schemaName,
              Entity1LogicalName: params.entity1LogicalName,
              Entity1AssociatedMenuConfiguration: menuConfig1,
              Entity2LogicalName: params.entity2LogicalName,
              Entity2AssociatedMenuConfiguration: menuConfig2,
              IntersectEntityName: intersectName,
              IsValidForAdvancedFind: params.isValidForAdvancedFind,
              IsCustomRelationship: true
            };
    
            const result = await client.postMetadata("RelationshipDefinitions", relationshipDefinition);
    
            return {
              content: [
                {
                  type: "text",
                  text: `Successfully created Many-to-Many relationship '${params.schemaName}' between '${params.entity1LogicalName}' and '${params.entity2LogicalName}'.\n\nResponse: ${JSON.stringify(result, null, 2)}`
                }
              ]
            };
          }
        } catch (error) {
          return {
            content: [
              {
                type: "text",
                text: `Error creating relationship: ${error instanceof Error ? error.message : 'Unknown error'}`
              }
            ],
            isError: true
          };
        }
      }
    );
  • src/index.ts:25-153 (registration)
    Import of createRelationshipTool and its invocation in the main server initialization, which triggers the tool registration.
      createRelationshipTool,
      getRelationshipTool,
      deleteRelationshipTool,
      listRelationshipsTool
    } from "./tools/relationship-tools.js";
    import {
      createOptionSetTool,
      getOptionSetTool,
      updateOptionSetTool,
      deleteOptionSetTool,
      listOptionSetsTool,
      getOptionSetOptionsTool
    } from "./tools/optionset-tools.js";
    import {
      createPublisherTool,
      createSolutionTool,
      getSolutionTool,
      getPublisherTool,
      listSolutionsTool,
      listPublishersTool,
      setSolutionContextTool,
      getSolutionContextTool,
      clearSolutionContextTool
    } from "./tools/solution-tools.js";
    import {
      createRoleTool,
      getRoleTool,
      updateRoleTool,
      deleteRoleTool,
      listRolesTool,
      addPrivilegesToRoleTool,
      removePrivilegeFromRoleTool,
      replaceRolePrivilegesTool,
      getRolePrivilegesTool,
      assignRoleToUserTool,
      removeRoleFromUserTool,
      assignRoleToTeamTool,
      removeRoleFromTeamTool
    } from "./tools/role-tools.js";
    import {
      createTeamTool,
      getTeamTool,
      updateTeamTool,
      deleteTeamTool,
      listTeamsTool,
      addMembersToTeamTool,
      removeMembersFromTeamTool,
      getTeamMembersTool,
      convertOwnerTeamToAccessTeamTool
    } from "./tools/team-tools.js";
    import {
      createBusinessUnitTool,
      getBusinessUnitTool,
      updateBusinessUnitTool,
      deleteBusinessUnitTool,
      listBusinessUnitsTool,
      getBusinessUnitHierarchyTool,
      setBusinessUnitParentTool,
      getBusinessUnitUsersTool,
      getBusinessUnitTeamsTool
    } from "./tools/businessunit-tools.js";
    import {
      exportSolutionSchemaTool,
      generateMermaidDiagramTool
    } from "./tools/schema-tools.js";
    import {
      generateWebAPICallTool
    } from "./tools/webapi-tools.js";
    import {
      generatePowerPagesWebAPICallTool
    } from "./tools/powerpages-webapi-tools.js";
    import {
      managePowerPagesWebAPIConfigTool
    } from "./tools/powerpages-config-tools.js";
    import {
      createAutoNumberColumnTool,
      updateAutoNumberFormatTool,
      setAutoNumberSeedTool,
      getAutoNumberColumnTool,
      listAutoNumberColumnsTool,
      convertToAutoNumberTool
    } from "./tools/autonumber-tools.js";
    import {
      registerWebAPIResources
    } from "./resources/webapi-resources.js";
    import {
      registerPowerPagesResources
    } from "./resources/powerpages-resources.js";
    
    // Environment variables for Dataverse authentication
    const DATAVERSE_URL = process.env.DATAVERSE_URL;
    const CLIENT_ID = process.env.DATAVERSE_CLIENT_ID;
    const CLIENT_SECRET = process.env.DATAVERSE_CLIENT_SECRET;
    const TENANT_ID = process.env.DATAVERSE_TENANT_ID;
    
    if (!DATAVERSE_URL || !CLIENT_ID || !CLIENT_SECRET || !TENANT_ID) {
      throw new Error('Missing required environment variables: DATAVERSE_URL, DATAVERSE_CLIENT_ID, DATAVERSE_CLIENT_SECRET, DATAVERSE_TENANT_ID');
    }
    
    // Create MCP server
    const server = new McpServer({
      name: "dataverse-mcp",
      version: "0.2.2"
    });
    
    // Initialize Dataverse client
    const dataverseClient = new DataverseClient({
      dataverseUrl: DATAVERSE_URL,
      clientId: CLIENT_ID,
      clientSecret: CLIENT_SECRET,
      tenantId: TENANT_ID
    });
    
    // Register table tools
    createTableTool(server, dataverseClient);
    getTableTool(server, dataverseClient);
    updateTableTool(server, dataverseClient);
    deleteTableTool(server, dataverseClient);
    listTablesTool(server, dataverseClient);
    
    // Register column tools
    createColumnTool(server, dataverseClient);
    getColumnTool(server, dataverseClient);
    updateColumnTool(server, dataverseClient);
    deleteColumnTool(server, dataverseClient);
    listColumnsTool(server, dataverseClient);
    
    // Register relationship tools
    createRelationshipTool(server, dataverseClient);
  • Helper function to create standardized LocalizedLabel objects used in relationship metadata definitions for display names and labels.
    function createLocalizedLabel(text: string, languageCode: number = 1033): LocalizedLabel {
      return {
        LocalizedLabels: [
          {
            Label: text,
            LanguageCode: languageCode,
            IsManaged: false,
            MetadataId: "00000000-0000-0000-0000-000000000000"
          }
        ],
        UserLocalizedLabel: {
          Label: text,
          LanguageCode: languageCode,
          IsManaged: false,
          MetadataId: "00000000-0000-0000-0000-000000000000"
        }
      };
Behavior2/5

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

No annotations are provided, so the description carries the full burden of behavioral disclosure. While it mentions the tool 'creates' a relationship and supports specific types, it lacks critical behavioral details such as required permissions, whether the operation is idempotent, error conditions, or what happens on failure. For a complex mutation tool with 21 parameters, this is a significant gap.

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?

The description is front-loaded with the core purpose in the first sentence, followed by supporting details in two additional sentences. Every sentence earns its place by clarifying relationship types and usage context, with zero waste or redundancy.

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

Completeness2/5

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

Given the tool's complexity (21 parameters, mutation operation, no output schema, and no annotations), the description is incomplete. It lacks behavioral transparency, does not explain return values or error handling, and relies entirely on the schema for parameter details. For such a sophisticated tool, more contextual guidance is needed.

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

Parameters3/5

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

Schema description coverage is 100%, so the schema already documents all 21 parameters thoroughly. The description adds minimal value beyond the schema by mentioning relationship types (One-to-Many/Many-to-Many) and high-level purposes, but does not provide additional syntax, format, or usage details for parameters. Baseline 3 is appropriate when the schema does the heavy lifting.

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 clearly states the verb 'creates' and resource 'relationship between two Dataverse tables', specifying the supported relationship types (One-to-Many and Many-to-Many). It distinguishes from siblings like 'delete_dataverse_relationship' by focusing on creation and from other table/column tools by emphasizing data connections.

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

Usage Guidelines4/5

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

The description provides clear context for when to use this tool: 'to establish data connections between tables, enable navigation, and maintain referential integrity.' However, it does not explicitly mention when not to use it or name alternatives (e.g., vs. updating existing relationships), which prevents a perfect score.

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/mwhesse/mcp-dataverse'

If you have feedback or need assistance with the MCP directory API, please join our Discord server