powerplatform-mcp 0.2.0

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Michal Sobieraj
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,52 @@
1
+ # PowerPlatform MCP Server
2
+
3
+ A Model Context Protocol (MCP) server for PowerPlatform/Dataverse entities. This tool provides access to entity metadata and attributes in the PowerPlatform environment.
4
+
5
+ ## Installation
6
+
7
+ You can install and run this tool in two ways:
8
+
9
+ ### Option 1: Install globally
10
+
11
+ ```bash
12
+ npm install -g powerplatform-mcp
13
+ ```
14
+
15
+ Then run it:
16
+
17
+ ```bash
18
+ powerplatform-mcp
19
+ ```
20
+
21
+ ### Option 2: Run directly with npx
22
+
23
+ Run without installing:
24
+
25
+ ```bash
26
+ npx powerplatform-mcp
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ Before running, set the following environment variables:
32
+
33
+ ```bash
34
+ # PowerPlatform/Dataverse connection details
35
+ POWERPLATFORM_URL=https://yourenvironment.crm.dynamics.com
36
+ POWERPLATFORM_CLIENT_ID=your-azure-app-client-id
37
+ POWERPLATFORM_CLIENT_SECRET=your-azure-app-client-secret
38
+ POWERPLATFORM_TENANT_ID=your-azure-tenant-id
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ This is an MCP server designed to work with MCP-compatible clients like GitHub Copilot. Once running, it will expose tools for retrieving PowerPlatform entity metadata.
44
+
45
+ ### Available Tools
46
+
47
+ - `get-entity-metadata`: Get metadata about a PowerPlatform entity
48
+ - `get-entity-attributes`: Get attributes/fields of a PowerPlatform entity
49
+
50
+ ## License
51
+
52
+ MIT
@@ -0,0 +1,85 @@
1
+ import { ConfidentialClientApplication } from '@azure/msal-node';
2
+ import axios from 'axios';
3
+ export class PowerPlatformService {
4
+ config;
5
+ msalClient;
6
+ accessToken = null;
7
+ tokenExpirationTime = 0;
8
+ constructor(config) {
9
+ this.config = config;
10
+ // Initialize MSAL client
11
+ this.msalClient = new ConfidentialClientApplication({
12
+ auth: {
13
+ clientId: this.config.clientId,
14
+ clientSecret: this.config.clientSecret,
15
+ authority: `https://login.microsoftonline.com/${this.config.tenantId}`,
16
+ }
17
+ });
18
+ }
19
+ /**
20
+ * Get an access token for the PowerPlatform API
21
+ */
22
+ async getAccessToken() {
23
+ const currentTime = Date.now();
24
+ // If we have a token that isn't expired, return it
25
+ if (this.accessToken && this.tokenExpirationTime > currentTime) {
26
+ return this.accessToken;
27
+ }
28
+ try {
29
+ // Get a new token
30
+ const result = await this.msalClient.acquireTokenByClientCredential({
31
+ scopes: [`${this.config.organizationUrl}/.default`],
32
+ });
33
+ if (!result || !result.accessToken) {
34
+ throw new Error('Failed to acquire access token');
35
+ }
36
+ this.accessToken = result.accessToken;
37
+ // Set expiration time (subtract 5 minutes to refresh early)
38
+ if (result.expiresOn) {
39
+ this.tokenExpirationTime = result.expiresOn.getTime() - (5 * 60 * 1000);
40
+ }
41
+ return this.accessToken;
42
+ }
43
+ catch (error) {
44
+ console.error('Error acquiring access token:', error);
45
+ throw new Error('Authentication failed');
46
+ }
47
+ }
48
+ /**
49
+ * Make an authenticated request to the PowerPlatform API
50
+ */
51
+ async makeRequest(endpoint) {
52
+ try {
53
+ const token = await this.getAccessToken();
54
+ const response = await axios({
55
+ method: 'GET',
56
+ url: `${this.config.organizationUrl}/${endpoint}`,
57
+ headers: {
58
+ 'Authorization': `Bearer ${token}`,
59
+ 'Accept': 'application/json',
60
+ 'OData-MaxVersion': '4.0',
61
+ 'OData-Version': '4.0'
62
+ }
63
+ });
64
+ return response.data;
65
+ }
66
+ catch (error) {
67
+ console.error('PowerPlatform API request failed:', error);
68
+ throw new Error(`PowerPlatform API request failed: ${error}`);
69
+ }
70
+ }
71
+ /**
72
+ * Get metadata about an entity
73
+ * @param entityName The logical name of the entity
74
+ */
75
+ async getEntityMetadata(entityName) {
76
+ return this.makeRequest(`api/data/v9.2/EntityDefinitions(LogicalName='${entityName}')`);
77
+ }
78
+ /**
79
+ * Get metadata about entity attributes/fields
80
+ * @param entityName The logical name of the entity
81
+ */
82
+ async getEntityAttributes(entityName) {
83
+ return this.makeRequest(`api/data/v9.2/EntityDefinitions(LogicalName='${entityName}')/Attributes`);
84
+ }
85
+ }
package/build/index.js ADDED
@@ -0,0 +1,112 @@
1
+ #!/usr/bin/env node
2
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
+ import { z } from "zod";
5
+ import { PowerPlatformService } from "./PowerPlatformService.js";
6
+ // Environment configuration
7
+ // These values can be set in environment variables or loaded from a configuration file
8
+ const POWERPLATFORM_CONFIG = {
9
+ organizationUrl: process.env.POWERPLATFORM_URL || "",
10
+ clientId: process.env.POWERPLATFORM_CLIENT_ID || "",
11
+ clientSecret: process.env.POWERPLATFORM_CLIENT_SECRET || "",
12
+ tenantId: process.env.POWERPLATFORM_TENANT_ID || "",
13
+ };
14
+ // Create server instance
15
+ const server = new McpServer({
16
+ name: "powerplatform-mcp",
17
+ version: "1.0.0",
18
+ });
19
+ let powerPlatformService = null;
20
+ // Function to initialize PowerPlatformService on demand
21
+ function getPowerPlatformService() {
22
+ if (!powerPlatformService) {
23
+ // Check if configuration is complete
24
+ const missingConfig = [];
25
+ if (!POWERPLATFORM_CONFIG.organizationUrl)
26
+ missingConfig.push("organizationUrl");
27
+ if (!POWERPLATFORM_CONFIG.clientId)
28
+ missingConfig.push("clientId");
29
+ if (!POWERPLATFORM_CONFIG.clientSecret)
30
+ missingConfig.push("clientSecret");
31
+ if (!POWERPLATFORM_CONFIG.tenantId)
32
+ missingConfig.push("tenantId");
33
+ if (missingConfig.length > 0) {
34
+ throw new Error(`Missing PowerPlatform configuration: ${missingConfig.join(", ")}. Set these in environment variables.`);
35
+ }
36
+ // Initialize service
37
+ powerPlatformService = new PowerPlatformService(POWERPLATFORM_CONFIG);
38
+ console.error("PowerPlatform service initialized");
39
+ }
40
+ return powerPlatformService;
41
+ }
42
+ // PowerPlatform entity metadata
43
+ server.tool("get-entity-metadata", "Get metadata about a PowerPlatform entity", {
44
+ entityName: z.string().describe("The logical name of the entity"),
45
+ }, async ({ entityName }) => {
46
+ try {
47
+ // Get or initialize PowerPlatformService
48
+ const service = getPowerPlatformService();
49
+ const metadata = await service.getEntityMetadata(entityName);
50
+ // Format the metadata as a string for text display
51
+ const metadataStr = JSON.stringify(metadata, null, 2);
52
+ return {
53
+ content: [
54
+ {
55
+ type: "text",
56
+ text: `Entity metadata for '${entityName}':\n\n${metadataStr}`,
57
+ },
58
+ ],
59
+ };
60
+ }
61
+ catch (error) {
62
+ console.error("Error getting entity metadata:", error);
63
+ return {
64
+ content: [
65
+ {
66
+ type: "text",
67
+ text: `Failed to get entity metadata: ${error}`,
68
+ },
69
+ ],
70
+ };
71
+ }
72
+ });
73
+ // PowerPlatform entity attributes
74
+ server.tool("get-entity-attributes", "Get attributes/fields of a PowerPlatform entity", {
75
+ entityName: z.string().describe("The logical name of the entity"),
76
+ }, async ({ entityName }) => {
77
+ try {
78
+ // Get or initialize PowerPlatformService
79
+ const service = getPowerPlatformService();
80
+ const attributes = await service.getEntityAttributes(entityName);
81
+ // Format the attributes as a string for text display
82
+ const attributesStr = JSON.stringify(attributes, null, 2);
83
+ return {
84
+ content: [
85
+ {
86
+ type: "text",
87
+ text: `Attributes for entity '${entityName}':\n\n${attributesStr}`,
88
+ },
89
+ ],
90
+ };
91
+ }
92
+ catch (error) {
93
+ console.error("Error getting entity attributes:", error);
94
+ return {
95
+ content: [
96
+ {
97
+ type: "text",
98
+ text: `Failed to get entity attributes: ${error}`,
99
+ },
100
+ ],
101
+ };
102
+ }
103
+ });
104
+ async function main() {
105
+ const transport = new StdioServerTransport();
106
+ await server.connect(transport);
107
+ console.error("Initializing PowerPlatform MCP Server...");
108
+ }
109
+ main().catch((error) => {
110
+ console.error("Fatal error in main():", error);
111
+ process.exit(1);
112
+ });
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "powerplatform-mcp",
3
+ "version": "0.2.0",
4
+ "description": "PowerPlatform Model Context Protocol server",
5
+ "main": "build/index.js",
6
+ "bin": {
7
+ "powerplatform-mcp": "./build/index.js"
8
+ },
9
+ "scripts": {
10
+ "build": "tsc",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "files": [
14
+ "build",
15
+ "README.md"
16
+ ],
17
+ "keywords": [
18
+ "powerplatform",
19
+ "mcp",
20
+ "model-context-protocol",
21
+ "dynamics",
22
+ "dataverse"
23
+ ],
24
+ "author": "Michal Sobieraj",
25
+ "license": "MIT",
26
+ "type": "module",
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "repository": {
31
+ "type": "git",
32
+ "url": "git+https://github.com/michsob/powerplatform-mcp.git"
33
+ },
34
+ "engines": {
35
+ "node": ">=16.0.0"
36
+ },
37
+ "dependencies": {
38
+ "@azure/msal-node": "^3.3.0",
39
+ "@modelcontextprotocol/sdk": "^1.7.0",
40
+ "axios": "^1.8.3",
41
+ "zod": "^3.24.2"
42
+ },
43
+ "devDependencies": {
44
+ "@types/node": "^22.13.10",
45
+ "typescript": "^5.8.2"
46
+ }
47
+ }