Skip to main content
Glama
rafteles2016

MCP Dynamics CRM Server

by rafteles2016

dynamics_add_solution_component

Adds components like entities, forms, or plugins to Microsoft Dynamics CRM solutions for deployment and management.

Instructions

Adiciona um componente a uma solução

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
solutionUniqueNameYesNome único da solução
componentIdYesID do componente
componentTypeYesTipo do componente (1=Entity, 2=Attribute, 26=View, 60=Form, 61=WebResource, 90=PluginAssembly, 91=PluginType, 92=SDKMessageProcessingStep)
addRequiredComponentsNo
doNotIncludeSubcomponentsNo

Implementation Reference

  • Handler for dynamics_add_solution_component tool, which calls the Dataverse 'AddSolutionComponent' action.
    server.tool(
      "dynamics_add_solution_component",
      "Adiciona um componente a uma solução",
      AddComponentToSolutionSchema.shape,
      async (params: z.infer<typeof AddComponentToSolutionSchema>) => {
        await client.executeAction("AddSolutionComponent", {
          ComponentId: params.componentId,
          ComponentType: params.componentType,
          SolutionUniqueName: params.solutionUniqueName,
          AddRequiredComponents: params.addRequiredComponents,
          DoNotIncludeSubcomponents: params.doNotIncludeSubcomponents,
        });
    
        const typeName = COMPONENT_TYPE_NAMES[params.componentType] || `Type ${params.componentType}`;
        return {
          content: [
            {
              type: "text" as const,
              text: `Componente adicionado à solução ${params.solutionUniqueName}!\nTipo: ${typeName}\nID: ${params.componentId}`,
            },
          ],
        };
      }
    );
  • Schema definition for the input parameters of dynamics_add_solution_component.
    export const AddComponentToSolutionSchema = z.object({
      solutionUniqueName: z.string().describe("Nome único da solução"),
      componentId: z.string().describe("ID do componente"),
      componentType: z.number().describe("Tipo do componente (1=Entity, 2=Attribute, 26=View, 60=Form, 61=WebResource, 90=PluginAssembly, 91=PluginType, 92=SDKMessageProcessingStep)"),
      addRequiredComponents: z.boolean().default(true),
      doNotIncludeSubcomponents: z.boolean().default(false),
    });
  • Registration function that registers all solution-related tools, including dynamics_add_solution_component.
    export function registerSolutionTools(
      server: { tool: Function },
      client: DataverseClient
    ) {
      // 1. Create Solution
      server.tool(
        "dynamics_create_solution",
        "Cria uma nova solução no Dynamics CRM",
        CreateSolutionSchema.shape,
        async (params: z.infer<typeof CreateSolutionSchema>) => {
          const data = {
            uniquename: params.uniqueName,
            friendlyname: params.displayName,
            version: params.version,
            description: params.description || "",
            "publisherid@odata.bind": `/publishers(${params.publisherId})`,
          };
    
          const result = await client.create("solutions", data);
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Solução criada com sucesso!\nID: ${result.entityId}\nNome: ${params.uniqueName}\nVersão: ${params.version}`,
              },
            ],
          };
        }
      );
    
      // 2. List Solutions
      server.tool(
        "dynamics_list_solutions",
        "Lista soluções instaladas no Dynamics CRM",
        ListSolutionsSchema.shape,
        async (params: z.infer<typeof ListSolutionsSchema>) => {
          const filters: string[] = ["isvisible eq true"];
          if (params.managedOnly) filters.push("ismanaged eq true");
          if (params.unmanagedOnly) filters.push("ismanaged eq false");
          if (params.nameFilter) filters.push(`contains(friendlyname,'${params.nameFilter}')`);
    
          const result = await client.list("solutions", {
            select: ["solutionid", "uniquename", "friendlyname", "version", "ismanaged", "description", "createdon", "modifiedon", "installedon"],
            filter: filters.join(" and "),
            orderby: "friendlyname asc",
            top: params.top,
            expand: "publisherid($select=friendlyname,customizationprefix)",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Soluções encontradas: ${result.value.length}\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 3. Add Component to Solution
      server.tool(
        "dynamics_add_solution_component",
        "Adiciona um componente a uma solução",
        AddComponentToSolutionSchema.shape,
        async (params: z.infer<typeof AddComponentToSolutionSchema>) => {
          await client.executeAction("AddSolutionComponent", {
            ComponentId: params.componentId,
            ComponentType: params.componentType,
            SolutionUniqueName: params.solutionUniqueName,
            AddRequiredComponents: params.addRequiredComponents,
            DoNotIncludeSubcomponents: params.doNotIncludeSubcomponents,
          });
    
          const typeName = COMPONENT_TYPE_NAMES[params.componentType] || `Type ${params.componentType}`;
          return {
            content: [
              {
                type: "text" as const,
                text: `Componente adicionado à solução ${params.solutionUniqueName}!\nTipo: ${typeName}\nID: ${params.componentId}`,
              },
            ],
          };
        }
      );
    
      // 4. Remove Component from Solution
      server.tool(
        "dynamics_remove_solution_component",
        "Remove um componente de uma solução",
        RemoveComponentFromSolutionSchema.shape,
        async (params: z.infer<typeof RemoveComponentFromSolutionSchema>) => {
          await client.executeAction("RemoveSolutionComponent", {
            ComponentId: params.componentId,
            ComponentType: params.componentType,
            SolutionUniqueName: params.solutionUniqueName,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Componente removido da solução ${params.solutionUniqueName}!`,
              },
            ],
          };
        }
      );
    
      // 5. List Solution Components
      server.tool(
        "dynamics_list_solution_components",
        "Lista componentes de uma solução",
        ListSolutionComponentsSchema.shape,
        async (params: z.infer<typeof ListSolutionComponentsSchema>) => {
          // Get solution ID first
          const solutions = await client.list("solutions", {
            select: ["solutionid"],
            filter: `uniquename eq '${params.solutionUniqueName}'`,
            top: 1,
          });
    
          if (solutions.value.length === 0) {
            return {
              content: [{ type: "text" as const, text: `Solução '${params.solutionUniqueName}' não encontrada.` }],
            };
          }
    
          const solutionId = (solutions.value[0] as Record<string, unknown>).solutionid;
          let filter = `_solutionid_value eq '${solutionId}'`;
          if (params.componentType !== undefined) {
            filter += ` and componenttype eq ${params.componentType}`;
          }
    
          const result = await client.list("solutioncomponents", {
            select: ["solutioncomponentid", "componenttype", "objectid", "rootcomponentbehavior", "ismetadata"],
            filter,
            orderby: "componenttype asc",
          });
    
          const components = result.value.map((c: Record<string, unknown>) => ({
            ...c,
            componentTypeName: COMPONENT_TYPE_NAMES[c.componenttype as number] || `Unknown (${c.componenttype})`,
          }));
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Componentes em ${params.solutionUniqueName}: ${components.length}\n\n${JSON.stringify(components, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 6. Export Solution
      server.tool(
        "dynamics_export_solution",
        "Exporta uma solução do Dynamics CRM (retorna Base64 do ZIP)",
        ExportSolutionSchema.shape,
        async (params: z.infer<typeof ExportSolutionSchema>) => {
          const result = await client.executeAction<{ ExportSolutionFile: string }>("ExportSolution", {
            SolutionName: params.solutionUniqueName,
            Managed: params.managed,
            ExportAutoNumberingSettings: params.exportAutoNumberingSettings,
            ExportCalendarSettings: params.exportCalendarSettings,
            ExportCustomizationSettings: params.exportCustomizationSettings,
            ExportEmailTrackingSettings: params.exportEmailTrackingSettings,
            ExportGeneralSettings: params.exportGeneralSettings,
            ExportIsvConfig: params.exportIsvConfig,
            ExportMarketingSettings: params.exportMarketingSettings,
            ExportOutlookSynchronizationSettings: params.exportOutlookSynchronizationSettings,
            ExportRelationshipRoles: params.exportRelationshipRoles,
            ExportSales: params.exportSales,
          });
    
          const sizeKb = Math.round((result.ExportSolutionFile?.length || 0) * 0.75 / 1024);
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Solução ${params.solutionUniqueName} exportada com sucesso!\nTipo: ${params.managed ? "Managed" : "Unmanaged"}\nTamanho: ~${sizeKb} KB\n\n(O conteúdo Base64 do ZIP está disponível para download)`,
              },
            ],
          };
        }
      );
    
      // 7. Import Solution
      server.tool(
        "dynamics_import_solution",
        "Importa uma solução para o Dynamics CRM",
        ImportSolutionSchema.shape,
        async (params: z.infer<typeof ImportSolutionSchema>) => {
          const importJobId = params.importJobId || crypto.randomUUID();
    
          await client.executeAction("ImportSolution", {
            CustomizationFile: params.customizationFile,
            OverwriteUnmanagedCustomizations: params.overwriteUnmanagedCustomizations,
            PublishWorkflows: params.publishWorkflows,
            ImportJobId: importJobId,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Importação da solução iniciada!\nImport Job ID: ${importJobId}\n\nUse dynamics_get_import_job_status para acompanhar o progresso.`,
              },
            ],
          };
        }
      );
    
      // 8. Get Import Job Status
      server.tool(
        "dynamics_get_import_job_status",
        "Verifica o status de uma importação de solução",
        z.object({ importJobId: z.string().describe("ID do job de importação") }).shape,
        async (params: { importJobId: string }) => {
          const result = await client.get<Record<string, unknown>>(
            `importjobs(${params.importJobId})?$select=importjobid,solutionname,progress,startedon,completedon,data`
          );
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Status da importação:\n${JSON.stringify(result, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 9. Clone Solution (Patch)
      server.tool(
        "dynamics_clone_solution",
        "Cria um clone/patch de uma solução com nova versão",
        CloneSolutionSchema.shape,
        async (params: z.infer<typeof CloneSolutionSchema>) => {
          const result = await client.executeAction<{ SolutionId: string }>("CloneAsSolution", {
            ParentSolutionUniqueName: params.solutionUniqueName,
            VersionNumber: params.versionNumber,
            DisplayName: `${params.solutionUniqueName} - ${params.versionNumber}`,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Solução clonada com sucesso!\nNova versão: ${params.versionNumber}\nSolution ID: ${result.SolutionId}`,
              },
            ],
          };
        }
      );
    
      // 10. List Publishers
      server.tool(
        "dynamics_list_publishers",
        "Lista publicadores disponíveis",
        ListPublishersSchema.shape,
        async (params: z.infer<typeof ListPublishersSchema>) => {
          const filter = params.customOnly ? "iscustomizable/Value eq true" : undefined;
    
          const result = await client.list("publishers", {
            select: ["publisherid", "uniquename", "friendlyname", "customizationprefix", "customizationoptionvalueprefix", "description"],
            filter,
            orderby: "friendlyname asc",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Publicadores encontrados: ${result.value.length}\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 11. Create Publisher
      server.tool(
        "dynamics_create_publisher",
        "Cria um novo publicador de soluções",
        CreatePublisherSchema.shape,
        async (params: z.infer<typeof CreatePublisherSchema>) => {
          const result = await client.create("publishers", {
            uniquename: params.uniqueName,
            friendlyname: params.friendlyName,
            customizationprefix: params.customizationPrefix,
            customizationoptionvalueprefix: params.customizationOptionValuePrefix,
            description: params.description || "",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Publicador criado!\nID: ${result.entityId}\nNome: ${params.uniqueName}\nPrefixo: ${params.customizationPrefix}`,
              },
            ],
          };
        }
      );
    
      // 12. Delete Solution
      server.tool(
        "dynamics_delete_solution",
        "Remove uma solução unmanaged do Dynamics CRM",
        DeleteSolutionSchema.shape,
        async (params: z.infer<typeof DeleteSolutionSchema>) => {
          const solutions = await client.list("solutions", {
            select: ["solutionid"],
            filter: `uniquename eq '${params.solutionUniqueName}'`,
            top: 1,
          });
    
          if (solutions.value.length === 0) {
            return {
              content: [{ type: "text" as const, text: `Solução '${params.solutionUniqueName}' não encontrada.` }],
            };
          }
    
          const solutionId = (solutions.value[0] as Record<string, unknown>).solutionid as string;
          await client.remove("solutions", solutionId);
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Solução ${params.solutionUniqueName} removida com sucesso!`,
              },
            ],
          };
        }
      );
    
      // 13. Check Solution Dependencies
      server.tool(
        "dynamics_check_solution_dependencies",
        "Verifica dependências de uma solução antes de remover",
        CheckSolutionDependenciesSchema.shape,
        async (params: z.infer<typeof CheckSolutionDependenciesSchema>) => {
          const solutions = await client.list("solutions", {
            select: ["solutionid"],
            filter: `uniquename eq '${params.solutionUniqueName}'`,
            top: 1,
          });
    
          if (solutions.value.length === 0) {
            return {
              content: [{ type: "text" as const, text: `Solução '${params.solutionUniqueName}' não encontrada.` }],
            };
          }
    
          const solutionId = (solutions.value[0] as Record<string, unknown>).solutionid as string;
    
          const dependencies = await client.get<{ value: Record<string, unknown>[] }>(
            `solutions(${solutionId})/Microsoft.Dynamics.CRM.RetrieveDependenciesForUninstall()`
          );
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Dependências da solução ${params.solutionUniqueName}: ${dependencies.value?.length || 0}\n\n${JSON.stringify(dependencies.value || [], null, 2)}`,
              },
            ],
          };
        }
      );
    }

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/rafteles2016/mcpDynamics'

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