powerplatform-mcp 0.4.4 → 1.0.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # PowerPlatform MCP Server
2
2
 
3
- A Model Context Protocol (MCP) server that provides intelligent access to PowerPlatform/Dataverse entities and records. This tool offers comprehensive entity exploration, metadata access, and AI-assisted query capabilities through GitHub Copilot integration.
3
+ A Model Context Protocol (MCP) server that provides intelligent access to PowerPlatform/Dataverse entities and records. This tool offers context-aware assistance, entity exploration and metadata access.
4
4
 
5
5
  Key features:
6
6
  - Rich entity metadata exploration with formatted, context-aware prompts
@@ -9,8 +9,6 @@ Key features:
9
9
  - AI-assisted query building and data modeling through AI agent
10
10
  - Full access to entity attributes, relationships, and global option sets
11
11
 
12
- Perfect for developers working with PowerPlatform/Dataverse who want intelligent, context-aware assistance for entity exploration and data querying.
13
-
14
12
  ## Installation
15
13
 
16
14
  You can install and run this tool in two ways:
@@ -47,9 +45,29 @@ POWERPLATFORM_CLIENT_SECRET=your-azure-app-client-secret
47
45
  POWERPLATFORM_TENANT_ID=your-azure-tenant-id
48
46
  ```
49
47
 
48
+ ### For Development
49
+
50
+ 1. Clone the repository and install dependencies:
51
+ ```bash
52
+ git clone https://github.com/michsob/powerplatform-mcp.git
53
+ cd powerplatform-mcp
54
+ npm install
55
+ ```
56
+
57
+ 2. Copy `.env.example` to `.env` and fill in your credentials:
58
+ ```bash
59
+ cp .env.example .env
60
+ ```
61
+
62
+ 3. Build and test:
63
+ ```bash
64
+ npm run build
65
+ npm run inspector:debug
66
+ ```
67
+
50
68
  ## Usage
51
69
 
52
- 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.
70
+ This is an MCP server designed to work with MCP-compatible clients like Cursor, Claude App and GitHub Copilot. Once running, it will expose tools for retrieving PowerPlatform entity metadata and records.
53
71
 
54
72
  ### Available Tools
55
73
 
@@ -64,7 +82,7 @@ This is an MCP server designed to work with MCP-compatible clients like GitHub C
64
82
 
65
83
  ## MCP Prompts
66
84
 
67
- The server includes a prompts feature that provides formatted, context-rich information about PowerPlatform entities. These prompts are ideal for use with AI assistants like GitHub Copilot.
85
+ The server includes a prompts feature that provides formatted, context-rich information about PowerPlatform entities.
68
86
 
69
87
  ### Available Prompt Types
70
88
 
@@ -205,22 +223,18 @@ This shows all relationships for the 'contact' entity:
205
223
  - contactquotes_association: contact (N) ↔ quote (N)
206
224
  ```
207
225
 
208
- ## Integration with AI Assistants
209
-
210
- These prompts are particularly valuable when used with AI assistants like GitHub Copilot that can integrate with MCP.
211
-
212
- ### GitHub Copilot Examples
226
+ ## Prompt Examples
213
227
 
214
- Here are some examples of how you can interact with GitHub Copilot using the PowerPlatform MCP prompts:
228
+ Here are some examples of how you can interact with assistant using the PowerPlatform MCP prompts:
215
229
 
216
- #### 1. Entity Understanding
230
+ ### 1. Entity Understanding
217
231
 
218
- You can ask GitHub Copilot about entities in natural language:
232
+ You can ask assistant about entities in natural language:
219
233
 
220
234
  ```
221
235
  User: "Tell me about the Account entity in our PowerPlatform environment"
222
236
 
223
- GitHub Copilot: Let me fetch the entity overview for you...
237
+ Response:
224
238
  [uses ENTITY_OVERVIEW prompt internally]
225
239
 
226
240
  Here's what I found about the Account entity:
@@ -234,14 +248,14 @@ Here's what I found about the Account entity:
234
248
  - It has 42 one-to-many relationships and 8 many-to-many relationships
235
249
  ```
236
250
 
237
- #### 2. Building Queries
251
+ ### 2. Building Queries
238
252
 
239
253
  You can ask for help constructing queries:
240
254
 
241
255
  ```
242
256
  User: "Help me write a query to find active accounts with revenue over $1M in California"
243
257
 
244
- GitHub Copilot: I'll help you build that query...
258
+ Response:
245
259
  [uses QUERY_TEMPLATE prompt internally]
246
260
 
247
261
  Here's the OData query you need:
@@ -259,14 +273,14 @@ This query:
259
273
  5. Orders by revenue highest to lowest
260
274
  ```
261
275
 
262
- #### 3. Understanding Relationships
276
+ ### 3. Understanding Relationships
263
277
 
264
278
  You can explore entity relationships naturally:
265
279
 
266
280
  ```
267
281
  User: "How are Accounts and Contacts related in our system?"
268
282
 
269
- GitHub Copilot: Let me check the relationship maps...
283
+ Response:
270
284
  [uses RELATIONSHIP_MAP prompt for both entities internally]
271
285
 
272
286
  Here are the key relationships between Accounts and Contacts:
@@ -284,14 +298,14 @@ Here are the key relationships between Accounts and Contacts:
284
298
  - account_connections: For relationship management
285
299
  ```
286
300
 
287
- #### 4. Field/Attribute Investigation
301
+ ### 4. Field/Attribute Investigation
288
302
 
289
303
  You can ask about specific fields:
290
304
 
291
305
  ```
292
306
  User: "What kind of field is the revenue field on Account?"
293
307
 
294
- GitHub Copilot: Let me check the attribute details...
308
+ Response:
295
309
  [uses ATTRIBUTE_DETAILS prompt internally]
296
310
 
297
311
  The revenue field on Account is:
@@ -303,14 +317,14 @@ The revenue field on Account is:
303
317
  - Can be used in advanced find and filtered views
304
318
  ```
305
319
 
306
- #### 5. Complex Data Modeling
320
+ ### 5. Complex Data Modeling
307
321
 
308
322
  You can get help with data modeling decisions:
309
323
 
310
324
  ```
311
325
  User: "I need to design a solution for tracking product reviews. Which entities should I relate to?"
312
326
 
313
- GitHub Copilot: Let me analyze the relevant entities...
327
+ Response:
314
328
  [uses multiple ENTITY_OVERVIEW and RELATIONSHIP_MAP prompts internally]
315
329
 
316
330
  Based on the existing data model, here's a suggested approach:
@@ -326,36 +340,11 @@ Based on the existing data model, here's a suggested approach:
326
340
  - Contact (N:1) - Reviews are written by contacts
327
341
  - Account (N:1) - Optional link to company if B2B review
328
342
 
329
- Here's a sample lookup field structure...
330
- [continues with detailed implementation guidance]
331
- ```
332
-
333
- #### 6. Debugging Assistance
334
343
 
335
- You can get help troubleshooting:
336
-
337
- ```
338
- User: "Why am I getting 'invalid property' when querying account.customertypecode?"
339
344
 
340
- GitHub Copilot: Let me check the attribute details...
341
- [uses ATTRIBUTE_DETAILS prompt internally]
342
-
343
- I see the issue. The field 'customertypecode' is actually named 'customertype' in your environment. Here's the correct field information:
344
- - Logical Name: customertype
345
- - Type: OptionSetValue
346
- - Valid Values:
347
- * 1 = Competitor
348
- * 2 = Consultant
349
- * 3 = Customer
350
- * 4 = Investor
351
- * 5 = Partner
352
- * 6 = Influencer
353
-
354
- Try updating your query to use 'customertype' instead of 'customertypecode'.
355
- ```
356
345
 
357
- These examples show how GitHub Copilot can leverage the MCP prompts to provide context-aware, accurate assistance for PowerPlatform development tasks. The AI understands your environment's specific configuration and can help with both simple queries and complex architectural decisions.
346
+ These examples show how AI assistant can leverage the MCP prompts to provide context-aware, accurate assistance for PowerPlatform development tasks. The AI understands your environment's specific configuration and can help with both simple queries and complex architectural decisions.
358
347
 
359
348
  ## License
360
349
 
361
- MIT
350
+ MIT
@@ -0,0 +1,83 @@
1
+ import { ConfidentialClientApplication } from '@azure/msal-node';
2
+ import axios from 'axios';
3
+ /**
4
+ * Base client for PowerPlatform API access.
5
+ * Handles authentication and generic HTTP requests.
6
+ * Service classes should depend on this client via constructor injection.
7
+ */
8
+ export class PowerPlatformClient {
9
+ config;
10
+ msalClient;
11
+ accessToken = null;
12
+ tokenExpirationTime = 0;
13
+ constructor(config) {
14
+ this.config = config;
15
+ // Initialize MSAL client
16
+ this.msalClient = new ConfidentialClientApplication({
17
+ auth: {
18
+ clientId: this.config.clientId,
19
+ clientSecret: this.config.clientSecret,
20
+ authority: `https://login.microsoftonline.com/${this.config.tenantId}`,
21
+ }
22
+ });
23
+ }
24
+ /**
25
+ * Get the organization URL
26
+ */
27
+ get organizationUrl() {
28
+ return this.config.organizationUrl;
29
+ }
30
+ /**
31
+ * Get an access token for the PowerPlatform API
32
+ */
33
+ async getAccessToken() {
34
+ const currentTime = Date.now();
35
+ // If we have a token that isn't expired, return it
36
+ if (this.accessToken && this.tokenExpirationTime > currentTime) {
37
+ return this.accessToken;
38
+ }
39
+ try {
40
+ // Get a new token
41
+ const result = await this.msalClient.acquireTokenByClientCredential({
42
+ scopes: [`${this.config.organizationUrl}/.default`],
43
+ });
44
+ if (!result || !result.accessToken) {
45
+ throw new Error('Failed to acquire access token');
46
+ }
47
+ this.accessToken = result.accessToken;
48
+ // Set expiration time (subtract 5 minutes to refresh early)
49
+ if (result.expiresOn) {
50
+ this.tokenExpirationTime = result.expiresOn.getTime() - (5 * 60 * 1000);
51
+ }
52
+ return this.accessToken;
53
+ }
54
+ catch (error) {
55
+ console.error('Error acquiring access token:', error);
56
+ throw new Error('Authentication failed');
57
+ }
58
+ }
59
+ /**
60
+ * Make an authenticated GET request to the PowerPlatform API
61
+ * @param endpoint The API endpoint (relative to organization URL)
62
+ */
63
+ async get(endpoint) {
64
+ try {
65
+ const token = await this.getAccessToken();
66
+ const response = await axios({
67
+ method: 'GET',
68
+ url: `${this.config.organizationUrl}/${endpoint}`,
69
+ headers: {
70
+ 'Authorization': `Bearer ${token}`,
71
+ 'Accept': 'application/json',
72
+ 'OData-MaxVersion': '4.0',
73
+ 'OData-Version': '4.0'
74
+ }
75
+ });
76
+ return response.data;
77
+ }
78
+ catch (error) {
79
+ console.error('PowerPlatform API request failed:', error);
80
+ throw new Error(`PowerPlatform API request failed: ${error}`);
81
+ }
82
+ }
83
+ }