Skip to main content
Glama
rafteles2016

MCP Dynamics CRM Server

by rafteles2016

dynamics_list_plugin_assemblies

Lists registered plugin assemblies in Dynamics CRM to manage custom business logic and integrations. Filter by assembly name or entity to organize development workflows.

Instructions

Lista os assemblies de plugins registrados no Dynamics CRM

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
assemblyNameNoFiltrar por nome do assembly
entityLogicalNameNoFiltrar por entidade

Implementation Reference

  • The handler implementation for the dynamics_list_plugin_assemblies tool.
    server.tool(
      "dynamics_list_plugin_assemblies",
      "Lista os assemblies de plugins registrados no Dynamics CRM",
      ListPluginsSchema.shape,
      async (params: z.infer<typeof ListPluginsSchema>) => {
        let filter = "ishidden/Value eq false";
        if (params.assemblyName) {
          filter += ` and contains(name,'${params.assemblyName}')`;
        }
    
        const result = await client.list("pluginassemblies", {
          select: ["pluginassemblyid", "name", "version", "publickeytoken", "culture", "description", "createdon", "modifiedon"],
          filter,
          orderby: "name asc",
        });
    
        return {
          content: [
            {
              type: "text" as const,
              text: `Encontrados ${result.value.length} assemblies:\n\n${JSON.stringify(result.value, null, 2)}`,
            },
          ],
        };
      }
    );
  • The input schema definition for the tool.
    export const ListPluginsSchema = z.object({
      assemblyName: z.string().optional().describe("Filtrar por nome do assembly"),
      entityLogicalName: z.string().optional().describe("Filtrar por entidade"),
    });
  • Registration of the plugin tools, including dynamics_list_plugin_assemblies.
    export function registerPluginTools(
      server: { tool: Function },
      client: DataverseClient
    ) {
      // 1. Generate Plugin Code
      server.tool(
        "dynamics_generate_plugin_code",
        "Gera código C# para um plugin do Dynamics CRM com base nos parâmetros fornecidos",
        CreatePluginSchema.shape,
        async (params: z.infer<typeof CreatePluginSchema>) => {
          const stageValue = STAGE_MAP[params.stage] || 40;
          const template = PLUGIN_TEMPLATES.standard;
    
          const code = template
            .replace(/{{CLASS_NAME}}/g, params.name)
            .replace(/{{ENTITY_LOGICAL_NAME}}/g, params.entityLogicalName)
            .replace(/{{MESSAGE}}/g, params.message)
            .replace(/{{STAGE}}/g, String(stageValue))
            .replace(/{{EXECUTION_MODE}}/g, params.executionMode === "Synchronous" ? "0" : "1")
            .replace(/{{FILTERING_ATTRIBUTES}}/g, params.filteringAttributes || "")
            .replace(/{{DESCRIPTION}}/g, params.description || `Plugin ${params.name} for ${params.message} on ${params.entityLogicalName}`)
            .replace(/{{BUSINESS_LOGIC}}/g, params.businessLogic || "// TODO: Implement business logic here");
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Plugin C# gerado com sucesso:\n\n\`\`\`csharp\n${code}\n\`\`\`\n\n**Configuração:**\n- Entidade: ${params.entityLogicalName}\n- Mensagem: ${params.message}\n- Estágio: ${params.stage} (${stageValue})\n- Modo: ${params.executionMode}\n${params.filteringAttributes ? `- Filtro: ${params.filteringAttributes}` : ""}`,
              },
            ],
          };
        }
      );
    
      // 2. List Plugin Assemblies
      server.tool(
        "dynamics_list_plugin_assemblies",
        "Lista os assemblies de plugins registrados no Dynamics CRM",
        ListPluginsSchema.shape,
        async (params: z.infer<typeof ListPluginsSchema>) => {
          let filter = "ishidden/Value eq false";
          if (params.assemblyName) {
            filter += ` and contains(name,'${params.assemblyName}')`;
          }
    
          const result = await client.list("pluginassemblies", {
            select: ["pluginassemblyid", "name", "version", "publickeytoken", "culture", "description", "createdon", "modifiedon"],
            filter,
            orderby: "name asc",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Encontrados ${result.value.length} assemblies:\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 3. List Plugin Types
      server.tool(
        "dynamics_list_plugin_types",
        "Lista os tipos de plugins (classes) de um assembly",
        z.object({ assemblyId: z.string().describe("ID do assembly") }).shape,
        async (params: { assemblyId: string }) => {
          const result = await client.list("plugintypes", {
            select: ["plugintypeid", "name", "friendlyname", "typename", "assemblyname", "description"],
            filter: `pluginassemblyid eq '${params.assemblyId}'`,
            orderby: "name asc",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Tipos de plugin encontrados: ${result.value.length}\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 4. List Plugin Steps
      server.tool(
        "dynamics_list_plugin_steps",
        "Lista os steps registrados para plugins, opcionalmente filtrados por entidade",
        z.object({
          entityLogicalName: z.string().optional().describe("Filtrar por entidade"),
          pluginTypeId: z.string().optional().describe("Filtrar por tipo de plugin"),
        }).shape,
        async (params: { entityLogicalName?: string; pluginTypeId?: string }) => {
          const filters: string[] = [];
          if (params.entityLogicalName) {
            filters.push(`configuration eq '${params.entityLogicalName}' or sdkmessagefilterid/primaryobjecttypecode eq '${params.entityLogicalName}'`);
          }
          if (params.pluginTypeId) {
            filters.push(`_plugintypeid_value eq '${params.pluginTypeId}'`);
          }
    
          const result = await client.list("sdkmessageprocessingsteps", {
            select: [
              "sdkmessageprocessingstepid", "name", "stage", "mode",
              "rank", "statecode", "filteringattributes", "description",
              "_sdkmessageid_value", "_plugintypeid_value",
            ],
            filter: filters.length > 0 ? filters.join(" and ") : undefined,
            orderby: "name asc",
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Steps encontrados: ${result.value.length}\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 5. Register Plugin Step
      server.tool(
        "dynamics_register_plugin_step",
        "Registra um novo step de plugin no Dynamics CRM",
        RegisterPluginStepSchema.shape,
        async (params: z.infer<typeof RegisterPluginStepSchema>) => {
          const stepData = {
            name: params.name,
            stage: params.stage,
            mode: params.executionMode,
            rank: params.rank,
            "plugintypeid@odata.bind": `/plugintypes(${params.pluginTypeId})`,
            "sdkmessageid@odata.bind": `/sdkmessages?$filter=name eq '${params.message}'`,
            filteringattributes: params.filteringAttributes || null,
            supporteddeployment: 0, // Server only
          };
    
          // Get the message filter for the entity
          const messageFilter = await client.list("sdkmessagefilters", {
            select: ["sdkmessagefilterid"],
            filter: `primaryobjecttypecode eq '${params.entityLogicalName}' and sdkmessageid/name eq '${params.message}'`,
            top: 1,
          });
    
          if (messageFilter.value.length > 0) {
            const filterId = (messageFilter.value[0] as Record<string, unknown>).sdkmessagefilterid;
            (stepData as Record<string, unknown>)["sdkmessagefilterid@odata.bind"] = `/sdkmessagefilters(${filterId})`;
          }
    
          const result = await client.create("sdkmessageprocessingsteps", stepData);
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Step registrado com sucesso!\nID: ${result.entityId}\nNome: ${params.name}\nMensagem: ${params.message}\nEntidade: ${params.entityLogicalName}\nEstágio: ${params.stage}`,
              },
            ],
          };
        }
      );
    
      // 6. Enable/Disable Plugin Step
      server.tool(
        "dynamics_toggle_plugin_step",
        "Ativa ou desativa um step de plugin",
        EnableDisablePluginStepSchema.shape,
        async (params: z.infer<typeof EnableDisablePluginStepSchema>) => {
          await client.update("sdkmessageprocessingsteps", params.stepId, {
            statecode: params.enabled ? 0 : 1,
            statuscode: params.enabled ? 1 : 2,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Step ${params.stepId} ${params.enabled ? "ativado" : "desativado"} com sucesso!`,
              },
            ],
          };
        }
      );
    
      // 7. Delete Plugin Step
      server.tool(
        "dynamics_delete_plugin_step",
        "Remove um step de plugin registrado",
        DeletePluginStepSchema.shape,
        async (params: z.infer<typeof DeletePluginStepSchema>) => {
          await client.remove("sdkmessageprocessingsteps", params.stepId);
          return {
            content: [
              {
                type: "text" as const,
                text: `Step ${params.stepId} removido com sucesso!`,
              },
            ],
          };
        }
      );
    
      // 8. Get Plugin Trace Logs
      server.tool(
        "dynamics_get_plugin_trace_logs",
        "Recupera logs de rastreamento de plugins para diagnóstico",
        GetPluginTraceLogsSchema.shape,
        async (params: z.infer<typeof GetPluginTraceLogsSchema>) => {
          const filters: string[] = [];
          if (params.pluginTypeName) {
            filters.push(`contains(typename,'${params.pluginTypeName}')`);
          }
          if (params.correlationId) {
            filters.push(`correlationid eq '${params.correlationId}'`);
          }
    
          const result = await client.list("plugintracelogs", {
            select: [
              "plugintracelogid", "typename", "messagename", "performanceexecutionstarttime",
              "performanceexecutionduration", "operationtype", "messageblock",
              "exceptiondetails", "correlationid", "depth", "createdon",
            ],
            filter: filters.length > 0 ? filters.join(" and ") : undefined,
            orderby: "createdon desc",
            top: params.top,
          });
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Logs de plugin encontrados: ${result.value.length}\n\n${JSON.stringify(result.value, null, 2)}`,
              },
            ],
          };
        }
      );
    
      // 9. Generate Plugin Project
      server.tool(
        "dynamics_generate_plugin_project",
        "Gera a estrutura completa de um projeto de plugin C# (.csproj, classes, etc.)",
        z.object({
          projectName: z.string().describe("Nome do projeto"),
          namespace: z.string().describe("Namespace do projeto"),
          plugins: z.array(CreatePluginSchema).describe("Lista de plugins a serem gerados"),
        }).shape,
        async (params: { projectName: string; namespace: string; plugins: z.infer<typeof CreatePluginSchema>[] }) => {
          const csproj = PLUGIN_TEMPLATES.csproj
            .replace(/{{PROJECT_NAME}}/g, params.projectName)
            .replace(/{{NAMESPACE}}/g, params.namespace);
    
          const pluginFiles: string[] = [];
          for (const plugin of params.plugins) {
            const stageValue = STAGE_MAP[plugin.stage] || 40;
            const code = PLUGIN_TEMPLATES.standard
              .replace(/{{NAMESPACE}}/g, params.namespace)
              .replace(/{{CLASS_NAME}}/g, plugin.name)
              .replace(/{{ENTITY_LOGICAL_NAME}}/g, plugin.entityLogicalName)
              .replace(/{{MESSAGE}}/g, plugin.message)
              .replace(/{{STAGE}}/g, String(stageValue))
              .replace(/{{EXECUTION_MODE}}/g, plugin.executionMode === "Synchronous" ? "0" : "1")
              .replace(/{{FILTERING_ATTRIBUTES}}/g, plugin.filteringAttributes || "")
              .replace(/{{DESCRIPTION}}/g, plugin.description || `Plugin ${plugin.name}`)
              .replace(/{{BUSINESS_LOGIC}}/g, plugin.businessLogic || "// TODO: Implement business logic");
            pluginFiles.push(`// File: ${plugin.name}.cs\n${code}`);
          }
    
          return {
            content: [
              {
                type: "text" as const,
                text: `Projeto gerado: **${params.projectName}**\n\n## ${params.projectName}.csproj\n\`\`\`xml\n${csproj}\n\`\`\`\n\n## Plugins\n${pluginFiles.map((f) => `\`\`\`csharp\n${f}\n\`\`\``).join("\n\n")}`,
              },
            ],
          };
        }
      );
    }

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