@mcp-consultant-tools/powerplatform 27.0.0 → 28.0.0-beta.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/build/PowerPlatformService.d.ts +23 -2
  2. package/build/PowerPlatformService.d.ts.map +1 -1
  3. package/build/PowerPlatformService.js +23 -1
  4. package/build/PowerPlatformService.js.map +1 -1
  5. package/build/index.d.ts +10 -2
  6. package/build/index.d.ts.map +1 -1
  7. package/build/index.js +26 -2394
  8. package/build/index.js.map +1 -1
  9. package/build/prompts/analysis-prompts.d.ts +3 -0
  10. package/build/prompts/analysis-prompts.d.ts.map +1 -0
  11. package/build/prompts/analysis-prompts.js +286 -0
  12. package/build/prompts/analysis-prompts.js.map +1 -0
  13. package/build/prompts/entity-prompts.d.ts +3 -0
  14. package/build/prompts/entity-prompts.d.ts.map +1 -0
  15. package/build/prompts/entity-prompts.js +304 -0
  16. package/build/prompts/entity-prompts.js.map +1 -0
  17. package/build/prompts/index.d.ts +8 -0
  18. package/build/prompts/index.d.ts.map +1 -0
  19. package/build/prompts/index.js +11 -0
  20. package/build/prompts/index.js.map +1 -0
  21. package/build/services/index.d.ts +5 -0
  22. package/build/services/index.d.ts.map +1 -0
  23. package/build/services/index.js +5 -0
  24. package/build/services/index.js.map +1 -0
  25. package/build/tools/app-tools.d.ts +3 -0
  26. package/build/tools/app-tools.d.ts.map +1 -0
  27. package/build/tools/app-tools.js +126 -0
  28. package/build/tools/app-tools.js.map +1 -0
  29. package/build/tools/flow-tools.d.ts +3 -0
  30. package/build/tools/flow-tools.d.ts.map +1 -0
  31. package/build/tools/flow-tools.js +373 -0
  32. package/build/tools/flow-tools.js.map +1 -0
  33. package/build/tools/form-view-tools.d.ts +3 -0
  34. package/build/tools/form-view-tools.d.ts.map +1 -0
  35. package/build/tools/form-view-tools.js +161 -0
  36. package/build/tools/form-view-tools.js.map +1 -0
  37. package/build/tools/index.d.ts +14 -0
  38. package/build/tools/index.d.ts.map +1 -0
  39. package/build/tools/index.js +29 -0
  40. package/build/tools/index.js.map +1 -0
  41. package/build/tools/integration-tools.d.ts +3 -0
  42. package/build/tools/integration-tools.d.ts.map +1 -0
  43. package/build/tools/integration-tools.js +324 -0
  44. package/build/tools/integration-tools.js.map +1 -0
  45. package/build/tools/metadata-tools.d.ts +3 -0
  46. package/build/tools/metadata-tools.d.ts.map +1 -0
  47. package/build/tools/metadata-tools.js +165 -0
  48. package/build/tools/metadata-tools.js.map +1 -0
  49. package/build/tools/plugin-tools.d.ts +3 -0
  50. package/build/tools/plugin-tools.d.ts.map +1 -0
  51. package/build/tools/plugin-tools.js +137 -0
  52. package/build/tools/plugin-tools.js.map +1 -0
  53. package/build/tools/security-tools.d.ts +3 -0
  54. package/build/tools/security-tools.d.ts.map +1 -0
  55. package/build/tools/security-tools.js +187 -0
  56. package/build/tools/security-tools.js.map +1 -0
  57. package/build/tools/solution-tools.d.ts +3 -0
  58. package/build/tools/solution-tools.d.ts.map +1 -0
  59. package/build/tools/solution-tools.js +283 -0
  60. package/build/tools/solution-tools.js.map +1 -0
  61. package/build/types.d.ts +9 -0
  62. package/build/types.d.ts.map +1 -0
  63. package/build/types.js +2 -0
  64. package/build/types.js.map +1 -0
  65. package/package.json +1 -1
@@ -0,0 +1,137 @@
1
+ /**
2
+ * Plugin Tools - 4 tools for plugin inspection
3
+ */
4
+ import { z } from 'zod';
5
+ export function registerPluginTools(server, ctx) {
6
+ server.tool("get-plugin-assemblies", "Get a list of all plugin assemblies in the environment", {
7
+ includeManaged: z.boolean().optional().describe("Include managed assemblies (default: false)"),
8
+ maxRecords: z.number().optional().describe("Maximum number of assemblies to return (default: 100)"),
9
+ }, async ({ includeManaged, maxRecords }) => {
10
+ try {
11
+ const service = ctx.pp;
12
+ const result = await service.getPluginAssemblies(includeManaged || false, maxRecords || 100);
13
+ const resultStr = JSON.stringify(result, null, 2);
14
+ return {
15
+ content: [
16
+ {
17
+ type: "text",
18
+ text: `Found ${result.totalCount} plugin assemblies:\n\n${resultStr}`,
19
+ },
20
+ ],
21
+ };
22
+ }
23
+ catch (error) {
24
+ console.error("Error getting plugin assemblies:", error);
25
+ return {
26
+ content: [
27
+ {
28
+ type: "text",
29
+ text: `Failed to get plugin assemblies: ${error.message}`,
30
+ },
31
+ ],
32
+ };
33
+ }
34
+ });
35
+ server.tool("get-plugin-asm-full", "Get comprehensive information about a plugin assembly including all types, steps, images, and validation", {
36
+ assemblyName: z.string().describe("The name of the plugin assembly"),
37
+ includeDisabled: z.boolean().optional().describe("Include disabled steps (default: false)"),
38
+ }, async ({ assemblyName, includeDisabled }) => {
39
+ try {
40
+ const service = ctx.pp;
41
+ const result = await service.getPluginAssemblyComplete(assemblyName, includeDisabled || false);
42
+ const resultStr = JSON.stringify(result, null, 2);
43
+ return {
44
+ content: [
45
+ {
46
+ type: "text",
47
+ text: `Plugin assembly '${assemblyName}' complete information:\n\n${resultStr}`,
48
+ },
49
+ ],
50
+ };
51
+ }
52
+ catch (error) {
53
+ console.error("Error getting plugin assembly:", error);
54
+ return {
55
+ content: [
56
+ {
57
+ type: "text",
58
+ text: `Failed to get plugin assembly: ${error.message}`,
59
+ },
60
+ ],
61
+ };
62
+ }
63
+ });
64
+ server.tool("get-entity-plugins", "Get all plugins that execute on a specific entity, organized by message and execution order", {
65
+ entityName: z.string().describe("The logical name of the entity"),
66
+ messageFilter: z.string().optional().describe("Filter by message name (e.g., 'Create', 'Update', 'Delete')"),
67
+ includeDisabled: z.boolean().optional().describe("Include disabled steps (default: false)"),
68
+ }, async ({ entityName, messageFilter, includeDisabled }) => {
69
+ try {
70
+ const service = ctx.pp;
71
+ const result = await service.getEntityPluginPipeline(entityName, messageFilter, includeDisabled || false);
72
+ const resultStr = JSON.stringify(result, null, 2);
73
+ return {
74
+ content: [
75
+ {
76
+ type: "text",
77
+ text: `Plugin pipeline for entity '${entityName}':\n\n${resultStr}`,
78
+ },
79
+ ],
80
+ };
81
+ }
82
+ catch (error) {
83
+ console.error("Error getting entity plugin pipeline:", error);
84
+ return {
85
+ content: [
86
+ {
87
+ type: "text",
88
+ text: `Failed to get entity plugin pipeline: ${error.message}`,
89
+ },
90
+ ],
91
+ };
92
+ }
93
+ });
94
+ server.tool("get-plugin-trace-logs", "Query plugin trace logs with filtering and exception parsing", {
95
+ entityName: z.string().optional().describe("Filter by entity logical name"),
96
+ messageName: z.string().optional().describe("Filter by message name (e.g., 'Update')"),
97
+ correlationId: z.string().optional().describe("Filter by correlation ID"),
98
+ pluginStepId: z.string().optional().describe("Filter by specific step ID"),
99
+ exceptionOnly: z.boolean().optional().describe("Only return logs with exceptions (default: false)"),
100
+ hoursBack: z.number().optional().describe("How many hours back to search (default: 24)"),
101
+ maxRecords: z.number().optional().describe("Maximum number of logs to return (default: 50)"),
102
+ }, async ({ entityName, messageName, correlationId, pluginStepId, exceptionOnly, hoursBack, maxRecords }) => {
103
+ try {
104
+ const service = ctx.pp;
105
+ const result = await service.getPluginTraceLogs({
106
+ entityName,
107
+ messageName,
108
+ correlationId,
109
+ pluginStepId,
110
+ exceptionOnly: exceptionOnly || false,
111
+ hoursBack: hoursBack || 24,
112
+ maxRecords: maxRecords || 50
113
+ });
114
+ const resultStr = JSON.stringify(result, null, 2);
115
+ return {
116
+ content: [
117
+ {
118
+ type: "text",
119
+ text: `Plugin trace logs (found ${result.totalCount}):\n\n${resultStr}`,
120
+ },
121
+ ],
122
+ };
123
+ }
124
+ catch (error) {
125
+ console.error("Error getting plugin trace logs:", error);
126
+ return {
127
+ content: [
128
+ {
129
+ type: "text",
130
+ text: `Failed to get plugin trace logs: ${error.message}`,
131
+ },
132
+ ],
133
+ };
134
+ }
135
+ });
136
+ }
137
+ //# sourceMappingURL=plugin-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"plugin-tools.js","sourceRoot":"","sources":["../../src/tools/plugin-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ServiceContext } from '../types.js';
2
+ export declare function registerSecurityTools(server: any, ctx: ServiceContext): void;
3
+ //# sourceMappingURL=security-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-tools.d.ts","sourceRoot":"","sources":["../../src/tools/security-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CAyN5E"}
@@ -0,0 +1,187 @@
1
+ /**
2
+ * Security Tools - 4 tools for connection references and security roles
3
+ */
4
+ import { z } from 'zod';
5
+ export function registerSecurityTools(server, ctx) {
6
+ server.tool("get-connection-references", `Get all connection references in the environment with their connection status and connector details.
7
+
8
+ Connection references define the connector configurations used by Power Automate flows and other components.
9
+ Returns a summary with counts by connector type, plus the full list of connection references.`, {
10
+ maxRecords: z.number().optional().describe("Maximum records to return (default: 100)"),
11
+ managedOnly: z.boolean().optional().describe("Filter to managed connection references only (default: false)"),
12
+ hasConnection: z.boolean().optional().describe("Filter: true = only with connections set, false = only without connections"),
13
+ }, async ({ maxRecords, managedOnly, hasConnection }) => {
14
+ try {
15
+ const service = ctx.pp;
16
+ const result = await service.getConnectionReferences({
17
+ maxRecords,
18
+ managedOnly,
19
+ hasConnection,
20
+ });
21
+ const summaryLines = [
22
+ `Total: ${result.summary.total}`,
23
+ `With connection: ${result.summary.withConnection}`,
24
+ `Without connection: ${result.summary.withoutConnection}`,
25
+ `Managed: ${result.summary.managed}, Unmanaged: ${result.summary.unmanaged}`,
26
+ '',
27
+ 'By connector:',
28
+ ...Object.entries(result.summary.byConnector)
29
+ .sort(([, a], [, b]) => b - a)
30
+ .map(([name, count]) => ` ${name}: ${count}`),
31
+ ];
32
+ const refLines = result.references.map((r) => `- ${r.displayName} (${r.logicalName})\n` +
33
+ ` Connector: ${r.connectorId}\n` +
34
+ ` Connection: ${r.connectionId ? r.connectionId : 'Not set'}\n` +
35
+ ` State: ${r.stateCode === 0 ? 'Active' : 'Inactive'} | Managed: ${r.isManaged}`);
36
+ return {
37
+ content: [{
38
+ type: "text",
39
+ text: `Connection References\n\n${summaryLines.join('\n')}\n\n${refLines.join('\n\n')}`,
40
+ }],
41
+ };
42
+ }
43
+ catch (error) {
44
+ console.error("Error getting connection references:", error);
45
+ return {
46
+ content: [{
47
+ type: "text",
48
+ text: `Failed to get connection references: ${error.message}`,
49
+ }],
50
+ isError: true,
51
+ };
52
+ }
53
+ });
54
+ server.tool("get-security-roles", `Get custom security roles defined in the environment. By default excludes well-known system roles (System Administrator, System Customizer, etc.).
55
+
56
+ Useful for security audits and understanding what custom roles exist in the environment.`, {
57
+ solutionUniqueName: z.string().optional().describe("Filter to roles in a specific solution"),
58
+ excludeSystemRoles: z.boolean().optional().describe("Exclude System Administrator, System Customizer, and other built-in roles (default: true)"),
59
+ maxRecords: z.number().optional().describe("Maximum records to return (default: 100)"),
60
+ }, async ({ solutionUniqueName, excludeSystemRoles, maxRecords }) => {
61
+ try {
62
+ const service = ctx.pp;
63
+ const result = await service.getSecurityRoles({
64
+ solutionUniqueName,
65
+ excludeSystemRoles,
66
+ maxRecords,
67
+ });
68
+ const summaryLines = [
69
+ `Total: ${result.summary.total}`,
70
+ `Managed: ${result.summary.managed}, Unmanaged: ${result.summary.unmanaged}`,
71
+ result.summary.systemRolesExcluded > 0
72
+ ? `System roles excluded: ${result.summary.systemRolesExcluded}`
73
+ : null,
74
+ ].filter(Boolean);
75
+ const roleLines = result.roles.map((r) => `- ${r.name}\n` +
76
+ ` ID: ${r.roleId}\n` +
77
+ ` Unique ID: ${r.roleIdUnique}\n` +
78
+ ` Managed: ${r.isManaged} | Customizable: ${r.isCustomizable}`);
79
+ return {
80
+ content: [{
81
+ type: "text",
82
+ text: `Security Roles\n\n${summaryLines.join('\n')}\n\n${roleLines.join('\n\n')}`,
83
+ }],
84
+ };
85
+ }
86
+ catch (error) {
87
+ console.error("Error getting security roles:", error);
88
+ return {
89
+ content: [{
90
+ type: "text",
91
+ text: `Failed to get security roles: ${error.message}`,
92
+ }],
93
+ isError: true,
94
+ };
95
+ }
96
+ });
97
+ server.tool("get-security-role-privileges", `Get the privilege assignments for a specific security role, showing what entities/actions the role grants access to.
98
+
99
+ Results are grouped by entity, showing the access depth (User/Business Unit/Parent:Child BU/Organization) for each action (Create, Read, Write, Delete, Append, AppendTo, Assign, Share).`, {
100
+ roleId: z.string().describe("The role ID (GUID) to get privileges for"),
101
+ entityFilter: z.string().optional().describe("Filter privileges to a specific entity name (partial match)"),
102
+ accessRightFilter: z.string().optional().describe("Filter by access right: Create, Read, Write, Delete, Append, AppendTo, Assign, Share"),
103
+ }, async ({ roleId, entityFilter, accessRightFilter }) => {
104
+ try {
105
+ const service = ctx.pp;
106
+ const result = await service.getSecurityRolePrivileges({
107
+ roleId,
108
+ entityFilter,
109
+ accessRightFilter,
110
+ });
111
+ const summaryLines = [
112
+ `Role ID: ${result.roleId}`,
113
+ `Total privileges: ${result.summary.total}`,
114
+ `Entities: ${result.summary.entityCount}`,
115
+ '',
116
+ 'By access right:',
117
+ ...Object.entries(result.summary.byAccessRight)
118
+ .sort(([, a], [, b]) => b - a)
119
+ .map(([right, count]) => ` ${right}: ${count}`),
120
+ ];
121
+ const entityLines = Object.entries(result.groupedByEntity)
122
+ .sort(([a], [b]) => a.localeCompare(b))
123
+ .map(([entity, privs]) => {
124
+ const privLines = privs.map((p) => ` ${p.accessRight}: ${p.depth}`);
125
+ return ` ${entity}:\n${privLines.join('\n')}`;
126
+ });
127
+ return {
128
+ content: [{
129
+ type: "text",
130
+ text: `Security Role Privileges\n\n${summaryLines.join('\n')}\n\nPrivileges by Entity:\n${entityLines.join('\n\n')}`,
131
+ }],
132
+ };
133
+ }
134
+ catch (error) {
135
+ console.error("Error getting security role privileges:", error);
136
+ return {
137
+ content: [{
138
+ type: "text",
139
+ text: `Failed to get security role privileges: ${error.message}`,
140
+ }],
141
+ isError: true,
142
+ };
143
+ }
144
+ });
145
+ server.tool("get-security-roles-by-solution", `Get all security roles that are components of a specific solution.
146
+
147
+ Queries solution components with componenttype=20 (Security Role) and fetches role details.
148
+ Optionally includes a privilege summary for each role (slower due to additional API calls).`, {
149
+ solutionUniqueName: z.string().describe("The solution unique name to get roles from"),
150
+ includePrivileges: z.boolean().optional().describe("Include privilege count summary per role (default: false, slower)"),
151
+ }, async ({ solutionUniqueName, includePrivileges }) => {
152
+ try {
153
+ const service = ctx.pp;
154
+ const result = await service.getSecurityRolesBySolution({
155
+ solutionUniqueName,
156
+ includePrivileges,
157
+ });
158
+ const roleLines = result.roles.map((r) => {
159
+ let line = `- ${r.name}\n` +
160
+ ` ID: ${r.roleId}\n` +
161
+ ` Managed: ${r.isManaged} | Customizable: ${r.isCustomizable}`;
162
+ if (r.privilegeSummary) {
163
+ line += `\n Privileges: ${r.privilegeSummary.total} across ${r.privilegeSummary.entityCount} entities`;
164
+ }
165
+ return line;
166
+ });
167
+ return {
168
+ content: [{
169
+ type: "text",
170
+ text: `Security Roles in Solution '${result.solutionUniqueName}'\n\n` +
171
+ `Total: ${result.summary.total}\n\n${roleLines.join('\n\n')}`,
172
+ }],
173
+ };
174
+ }
175
+ catch (error) {
176
+ console.error("Error getting security roles by solution:", error);
177
+ return {
178
+ content: [{
179
+ type: "text",
180
+ text: `Failed to get security roles by solution: ${error.message}`,
181
+ }],
182
+ isError: true,
183
+ };
184
+ }
185
+ });
186
+ }
187
+ //# sourceMappingURL=security-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-tools.js","sourceRoot":"","sources":["../../src/tools/security-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ServiceContext } from '../types.js';
2
+ export declare function registerSolutionTools(server: any, ctx: ServiceContext): void;
3
+ //# sourceMappingURL=solution-tools.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"solution-tools.d.ts","sourceRoot":"","sources":["../../src/tools/solution-tools.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,cAAc,GAAG,IAAI,CA4V5E"}
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Solution Tools - 8 tools for solution management and validation
3
+ */
4
+ import { z } from 'zod';
5
+ export function registerSolutionTools(server, ctx) {
6
+ server.tool("get-publishers", "Get all solution publishers (excluding system publishers)", {}, async () => {
7
+ try {
8
+ const service = ctx.pp;
9
+ const result = await service.getPublishers();
10
+ const publishers = result.value || [];
11
+ return {
12
+ content: [
13
+ {
14
+ type: "text",
15
+ text: `Found ${publishers.length} publisher(s):\n\n` +
16
+ publishers.map((p) => `- ${p.friendlyname} (${p.uniquename})\n Prefix: ${p.customizationprefix}\n ID: ${p.publisherid}`).join('\n')
17
+ }
18
+ ]
19
+ };
20
+ }
21
+ catch (error) {
22
+ console.error("Error getting publishers:", error);
23
+ return {
24
+ content: [{ type: "text", text: `Failed to get publishers: ${error.message}` }],
25
+ isError: true
26
+ };
27
+ }
28
+ });
29
+ server.tool("get-solutions", "Get all visible solutions in the environment", {}, async () => {
30
+ try {
31
+ const service = ctx.pp;
32
+ const result = await service.getSolutions();
33
+ const solutions = result.value || [];
34
+ return {
35
+ content: [
36
+ {
37
+ type: "text",
38
+ text: `Found ${solutions.length} solution(s):\n\n` +
39
+ solutions.map((s) => `- ${s.friendlyname} (${s.uniquename})\n Version: ${s.version}\n ID: ${s.solutionid}`).join('\n')
40
+ }
41
+ ]
42
+ };
43
+ }
44
+ catch (error) {
45
+ console.error("Error getting solutions:", error);
46
+ return {
47
+ content: [{ type: "text", text: `Failed to get solutions: ${error.message}` }],
48
+ isError: true
49
+ };
50
+ }
51
+ });
52
+ server.tool("get-solution-components", "List all components in a solution, grouped by component type. Returns component IDs, types, and behavior settings.", {
53
+ solutionUniqueName: z.string().describe("The unique name of the solution to list components for"),
54
+ }, async ({ solutionUniqueName }) => {
55
+ try {
56
+ const service = ctx.pp;
57
+ const result = await service.getSolutionComponents(solutionUniqueName);
58
+ const components = result.value || [];
59
+ const componentTypeNames = {
60
+ 1: 'Entity', 2: 'Attribute', 3: 'Relationship', 9: 'OptionSet',
61
+ 10: 'EntityRelationship', 13: 'ManagedProperty', 20: 'Policy',
62
+ 24: 'Privilege', 25: 'PrivilegeObjectTypeCode', 26: 'Role',
63
+ 29: 'Workflow', 31: 'Report', 36: 'Template', 37: 'Contract Template',
64
+ 38: 'Article Template', 39: 'Mail Merge Template', 44: 'Duplicate Rule',
65
+ 46: 'Duplicate Rule Condition', 48: 'Entity Map', 49: 'Attribute Map',
66
+ 59: 'SavedQuery', 60: 'Form', 61: 'WebResource', 62: 'SiteMap',
67
+ 63: 'Connection Role', 65: 'Hierarchy Rule', 66: 'Custom Control',
68
+ 70: 'FieldSecurityProfile', 71: 'FieldPermission', 80: 'AppModule',
69
+ 91: 'PluginAssembly', 92: 'PluginType', 93: 'SDKMessageProcessingStep',
70
+ 95: 'ServiceEndpoint', 150: 'RoutingRule', 152: 'SLA',
71
+ 154: 'ConvertRule', 300: 'Canvas App', 371: 'Connector',
72
+ 372: 'EnvironmentVariableDefinition', 373: 'EnvironmentVariableValue',
73
+ 380: 'AIModel', 381: 'AIConfiguration',
74
+ };
75
+ const grouped = {};
76
+ for (const c of components) {
77
+ const type = c.componenttype;
78
+ if (!grouped[type])
79
+ grouped[type] = [];
80
+ grouped[type].push(c);
81
+ }
82
+ const lines = [`Found ${components.length} component(s) in solution '${solutionUniqueName}':\n`];
83
+ for (const [type, items] of Object.entries(grouped)) {
84
+ const typeName = componentTypeNames[Number(type)] || `Type ${type}`;
85
+ lines.push(`\n${typeName} (${items.length}):`);
86
+ for (const item of items) {
87
+ lines.push(` - ${item.objectid} (behavior: ${item.rootcomponentbehavior ?? 'include subcomponents'})`);
88
+ }
89
+ }
90
+ return {
91
+ content: [{ type: "text", text: lines.join('\n') }]
92
+ };
93
+ }
94
+ catch (error) {
95
+ console.error("Error getting solution components:", error);
96
+ return {
97
+ content: [{ type: "text", text: `Failed to get solution components: ${error.message}` }],
98
+ isError: true
99
+ };
100
+ }
101
+ });
102
+ server.tool("check-dependencies", "Check dependencies before deleting a component", {
103
+ componentId: z.string().describe("Component ID (GUID or MetadataId)"),
104
+ componentType: z.number().describe("Component type: 1=Entity, 2=Attribute, 9=OptionSet, 24=Form, 26=SavedQuery, 29=Workflow, 60=SystemForm, 61=WebResource")
105
+ }, async ({ componentId, componentType }) => {
106
+ try {
107
+ const service = ctx.pp;
108
+ const result = await service.checkDependencies(componentId, componentType);
109
+ const dependencies = result.EntityCollection?.Entities || [];
110
+ return {
111
+ content: [
112
+ {
113
+ type: "text",
114
+ text: `Found ${dependencies.length} dependenc${dependencies.length === 1 ? 'y' : 'ies'} for component '${componentId}':\n\n` +
115
+ (dependencies.length > 0
116
+ ? dependencies.map((d) => `- ${d.Attributes?.dependentcomponentobjectid || 'Unknown'}\n Type: ${d.Attributes?.dependentcomponenttype || 'Unknown'}`).join('\n')
117
+ : 'No dependencies found - component can be safely deleted')
118
+ }
119
+ ]
120
+ };
121
+ }
122
+ catch (error) {
123
+ console.error("Error checking dependencies:", error);
124
+ return {
125
+ content: [{ type: "text", text: `Failed to check dependencies: ${error.message}` }],
126
+ isError: true
127
+ };
128
+ }
129
+ });
130
+ server.tool("validate-schema-name", "Validate a schema name against PowerPlatform naming rules", {
131
+ schemaName: z.string().describe("Schema name to validate"),
132
+ prefix: z.string().describe("Required customization prefix")
133
+ }, async ({ schemaName, prefix }) => {
134
+ try {
135
+ const service = ctx.pp;
136
+ const result = service.validateSchemaName(schemaName, prefix);
137
+ return {
138
+ content: [
139
+ {
140
+ type: "text",
141
+ text: `Schema Name Validation for '${schemaName}':\n\n` +
142
+ `Valid: ${result.valid ? '✅' : '❌'}\n\n` +
143
+ (result.errors.length > 0
144
+ ? `Errors:\n${result.errors.map(e => `- ${e}`).join('\n')}`
145
+ : 'No validation errors')
146
+ }
147
+ ]
148
+ };
149
+ }
150
+ catch (error) {
151
+ console.error("Error validating schema name:", error);
152
+ return {
153
+ content: [{ type: "text", text: `Failed to validate schema name: ${error.message}` }],
154
+ isError: true
155
+ };
156
+ }
157
+ });
158
+ server.tool("check-delete-eligibility", "Check if a component can be safely deleted", {
159
+ componentId: z.string().describe("Component ID (GUID or MetadataId)"),
160
+ componentType: z.number().describe("Component type: 1=Entity, 2=Attribute, 9=OptionSet, 24=Form, 26=SavedQuery, 29=Workflow, 60=SystemForm, 61=WebResource")
161
+ }, async ({ componentId, componentType }) => {
162
+ try {
163
+ const service = ctx.pp;
164
+ const result = await service.checkDeleteEligibility(componentId, componentType);
165
+ return {
166
+ content: [
167
+ {
168
+ type: "text",
169
+ text: `Delete Eligibility for component '${componentId}':\n\n` +
170
+ `Can Delete: ${result.canDelete ? '✅ Yes' : '❌ No'}\n` +
171
+ `Dependencies: ${result.dependencies.length}\n\n` +
172
+ (result.dependencies.length > 0
173
+ ? `Blocking Dependencies:\n${result.dependencies.map((d) => `- ${d.Attributes?.dependentcomponentobjectid || 'Unknown'}`).join('\n')}`
174
+ : 'No blocking dependencies - component can be safely deleted')
175
+ }
176
+ ]
177
+ };
178
+ }
179
+ catch (error) {
180
+ console.error("Error checking delete eligibility:", error);
181
+ return {
182
+ content: [{ type: "text", text: `Failed to check delete eligibility: ${error.message}` }],
183
+ isError: true
184
+ };
185
+ }
186
+ });
187
+ server.tool("validate-dataverse", "Validate Dataverse entities against internal best practices for column naming, prefixes, configuration, and entity icons. Checks schema name casing, lookup naming conventions, option set scope (all must be global), required columns, publisher prefix compliance, and entity icon assignment. Supports solution-based validation or explicit entity list with configurable time range filtering.", {
188
+ solutionUniqueName: z.string().optional().describe("Solution unique name to validate (e.g., 'RTPICore', 'MCPTestCore'). Mutually exclusive with entityLogicalNames."),
189
+ entityLogicalNames: z.array(z.string()).optional().describe("Explicit list of entity logical names to validate (e.g., ['sic_strikeaction', 'sic_application']). Mutually exclusive with solutionUniqueName."),
190
+ publisherPrefix: z.string().describe("Publisher prefix to validate against (e.g., 'sic_'). Required."),
191
+ recentDays: z.number().optional().describe("Only validate columns created in the last N days. Set to 0 to validate all columns regardless of age. Default: 30."),
192
+ includeRefDataTables: z.boolean().optional().describe("Include RefData tables (schema starts with prefix + 'ref_') in validation. Default: true."),
193
+ rules: z.array(z.string()).optional().describe("Specific rules to validate: 'prefix', 'lowercase', 'lookup', 'optionset', 'required-column', 'entity-icon'. Default: all rules."),
194
+ maxEntities: z.number().optional().describe("Maximum number of entities to validate (safety limit). Default: 0 (unlimited)."),
195
+ requiredColumns: z.array(z.string()).optional().describe("List of required column schema names to check for (without prefix). Use '{prefix}' placeholder which will be replaced with publisherPrefix at runtime. Default: ['{prefix}updatedbyprocess']. Example: ['{prefix}sqlcreatedon', '{prefix}sqlmodifiedon'] for SQL timestamp columns.")
196
+ }, async ({ solutionUniqueName, entityLogicalNames, publisherPrefix, recentDays, includeRefDataTables, rules, maxEntities, requiredColumns }) => {
197
+ try {
198
+ if (!solutionUniqueName && !entityLogicalNames) {
199
+ return {
200
+ content: [{ type: "text", text: "Error: Either solutionUniqueName or entityLogicalNames must be provided" }],
201
+ isError: true
202
+ };
203
+ }
204
+ if (solutionUniqueName && entityLogicalNames) {
205
+ return {
206
+ content: [{ type: "text", text: "Error: solutionUniqueName and entityLogicalNames are mutually exclusive" }],
207
+ isError: true
208
+ };
209
+ }
210
+ const service = ctx.pp;
211
+ const result = await service.validateBestPractices(solutionUniqueName, entityLogicalNames, publisherPrefix, recentDays ?? 30, includeRefDataTables ?? true, rules ?? ['prefix', 'lowercase', 'lookup', 'optionset', 'required-column', 'entity-icon'], maxEntities ?? 0, requiredColumns ?? ['{prefix}updatedbyprocess']);
212
+ return {
213
+ content: [{ type: "text", text: JSON.stringify(result, null, 2) }]
214
+ };
215
+ }
216
+ catch (error) {
217
+ console.error("Error validating best practices:", error);
218
+ return {
219
+ content: [{ type: "text", text: `Failed to validate best practices: ${error.message}` }],
220
+ isError: true
221
+ };
222
+ }
223
+ });
224
+ server.tool("generate-dbml-schema", `Generates DBML (Database Markup Language) schema from Dataverse entities.
225
+
226
+ Accepts solution names, explicit entity lists, or both. Returns DBML text
227
+ and a clickable dbdiagram.io URL for visualization.
228
+
229
+ DBML output includes:
230
+ - Table definitions with columns and types
231
+ - Primary key markers [pk]
232
+ - Foreign key relationships (Ref: statements) for all lookups
233
+
234
+ Example output:
235
+ \`\`\`dbml
236
+ Table si_directdebit {
237
+ si_directdebitid uniqueidentifier [pk]
238
+ si_name nvarchar
239
+ si_accountid lookup
240
+ }
241
+ Ref: si_directdebit.si_accountid > account.accountid
242
+ \`\`\``, {
243
+ solutions: z.array(z.string()).optional()
244
+ .describe('One or more solution unique names to extract entities from'),
245
+ entities: z.array(z.string()).optional()
246
+ .describe('Explicit list of entity logical names to include'),
247
+ includeSystemColumns: z.boolean().optional()
248
+ .describe('Include system columns like createdon, modifiedon (default: false)'),
249
+ includeStateStatus: z.boolean().optional()
250
+ .describe('Include statecode/statuscode columns (default: false)'),
251
+ prefix: z.string().optional()
252
+ .describe('Only include columns matching this prefix (e.g., "si_")'),
253
+ depth: z.number().optional()
254
+ .describe('Relationship traversal depth for discovering related entities (default: 0)'),
255
+ includePolymorphicLookups: z.boolean().optional()
256
+ .describe('Include Customer/Owner/PartyList lookups (default: true)'),
257
+ }, async (params) => {
258
+ try {
259
+ const service = ctx.pp;
260
+ const result = await service.generateDbmlSchema(params);
261
+ return {
262
+ content: [
263
+ {
264
+ type: "text",
265
+ text: JSON.stringify(result, null, 2),
266
+ },
267
+ ],
268
+ };
269
+ }
270
+ catch (error) {
271
+ console.error("Error generating DBML schema:", error);
272
+ return {
273
+ content: [
274
+ {
275
+ type: "text",
276
+ text: `Failed to generate DBML schema: ${error.message}`,
277
+ },
278
+ ],
279
+ };
280
+ }
281
+ });
282
+ }
283
+ //# sourceMappingURL=solution-tools.js.map