@north7/entraaware 0.0.4 → 0.0.5

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 (2) hide show
  1. package/build/index.js +35 -46
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -11,7 +11,7 @@ let azureCredential = null;
11
11
  // Create server instance
12
12
  const server = new McpServer({
13
13
  name: "EntraAware",
14
- version: "0.0.3",
14
+ version: "0.0.5",
15
15
  capabilities: {
16
16
  resources: {},
17
17
  tools: {},
@@ -80,6 +80,23 @@ function formatErrorResponse(err, apiType) {
80
80
  ],
81
81
  };
82
82
  }
83
+ // Process OData parameters for Graph API
84
+ function processODataParams({ queryParams = {}, select, filter, expand, orderBy, top, count }) {
85
+ const processedParams = { ...queryParams };
86
+ if (select)
87
+ processedParams['$select'] = select;
88
+ if (filter)
89
+ processedParams['$filter'] = filter;
90
+ if (expand)
91
+ processedParams['$expand'] = expand;
92
+ if (orderBy)
93
+ processedParams['$orderby'] = orderBy;
94
+ if (top !== undefined)
95
+ processedParams['$top'] = top.toString();
96
+ if (count)
97
+ processedParams['$count'] = 'true';
98
+ return processedParams;
99
+ }
83
100
  // MICROSOFT GRAPH API TOOL
84
101
  server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra (Azure AD) data", {
85
102
  path: z.string().describe("The Graph API URL path (e.g. '/users/{id}/memberOf', '/directoryRoles')"),
@@ -97,51 +114,38 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
97
114
  top: z.number().optional().describe("Shorthand for $top query parameter"),
98
115
  count: z.boolean().optional().describe("Shorthand for $count=true to include count of items"),
99
116
  }, async ({ path, method, queryParams = {}, body, apiVersion, fetchAllPages, consistencyLevel, select, filter, expand, orderBy, top, count }) => {
100
- console.error(`[askEntra] Processing request: ${method} ${path}`);
101
117
  try {
102
118
  // Process shorthand query parameters
103
- const processedParams = { ...queryParams };
104
- if (select)
105
- processedParams['$select'] = select;
106
- if (filter)
107
- processedParams['$filter'] = filter;
108
- if (expand)
109
- processedParams['$expand'] = expand;
110
- if (orderBy)
111
- processedParams['$orderby'] = orderBy;
112
- if (top !== undefined)
113
- processedParams['$top'] = top.toString();
114
- if (count)
115
- processedParams['$count'] = 'true';
116
- console.error(`[askEntra] Getting Azure credential`);
117
- // Initialize or get Azure credential
118
- const credential = getAzureCredential();
119
- console.error(`[askEntra] Initializing Graph client`);
120
- // Initialize Graph client if not already done
119
+ const processedParams = processODataParams({
120
+ queryParams,
121
+ select,
122
+ filter,
123
+ expand,
124
+ orderBy,
125
+ top,
126
+ count
127
+ });
128
+ // Initialize client on demand
121
129
  if (!graphClient) {
130
+ const credential = getAzureCredential();
122
131
  const authProvider = new TokenCredentialAuthenticationProvider(credential, {
123
132
  scopes: ["https://graph.microsoft.com/.default"],
124
133
  });
125
134
  graphClient = Client.initWithMiddleware({ authProvider });
126
- console.error(`[askEntra] Graph client initialized`);
127
135
  }
128
136
  // Build request with API path and version
129
- console.error(`[askEntra] Creating request for ${path} with version ${apiVersion}`);
130
137
  let request = graphClient.api(path).version(apiVersion);
131
138
  // Add query parameters
132
139
  if (Object.keys(processedParams).length > 0) {
133
- console.error(`[askEntra] Adding query parameters: ${JSON.stringify(processedParams)}`);
134
140
  request = request.query(processedParams);
135
141
  }
136
142
  // Add consistency level header if provided
137
143
  if (consistencyLevel) {
138
- console.error(`[askEntra] Adding consistency level: ${consistencyLevel}`);
139
144
  request = request.header('ConsistencyLevel', consistencyLevel);
140
145
  }
141
146
  // Handle pagination for GET requests
142
147
  let result;
143
148
  if (method === 'get' && fetchAllPages) {
144
- console.error(`[askEntra] Executing GET with pagination`);
145
149
  const firstPage = await request.get();
146
150
  // If no pagination needed, return first page
147
151
  if (!firstPage["@odata.nextLink"]) {
@@ -152,7 +156,6 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
152
156
  const allItems = [...(firstPage.value || [])];
153
157
  let nextLink = firstPage["@odata.nextLink"];
154
158
  while (nextLink) {
155
- console.error(`[askEntra] Fetching next page: ${nextLink}`);
156
159
  const nextPage = await graphClient.api(nextLink).get();
157
160
  if (nextPage.value)
158
161
  allItems.push(...nextPage.value);
@@ -168,7 +171,6 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
168
171
  }
169
172
  else {
170
173
  // Execute appropriate method
171
- console.error(`[askEntra] Executing ${method} request`);
172
174
  switch (method) {
173
175
  case 'get':
174
176
  result = await request.get();
@@ -188,14 +190,9 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
188
190
  break;
189
191
  }
190
192
  }
191
- console.error(`[askEntra] Successfully executed request`);
192
193
  return formatApiResponse('Entra', method, path, result);
193
194
  }
194
195
  catch (err) {
195
- console.error(`[askEntra] ERROR: ${err instanceof Error ? err.message : String(err)}`);
196
- if (err instanceof Error && err.stack) {
197
- console.error(`[askEntra] Stack trace: ${err.stack}`);
198
- }
199
196
  return formatErrorResponse(err, 'Entra');
200
197
  }
201
198
  });
@@ -220,7 +217,6 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
220
217
  resourceGroupName: z.string().optional().describe("Resource group name for resource operations"),
221
218
  resourceName: z.string().optional().describe("Resource name for resource operations"),
222
219
  }, async ({ path, method, apiVersion, subscriptionId, body, queryParams = {}, fetchAllPages, operation = "custom", providerNamespace, resourceType, resourceGroupName, resourceName }) => {
223
- console.error(`[askAzure] Processing request: ${operation} - ${method} ${path}`);
224
220
  try {
225
221
  // Default API versions for common resource types
226
222
  const defaultApiVersions = {
@@ -234,6 +230,12 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
234
230
  'Microsoft.Network/virtualNetworks': '2023-04-01',
235
231
  'Microsoft.KeyVault/vaults': '2023-02-01'
236
232
  };
233
+ // Set default API version for common paths if not provided
234
+ if (!apiVersion && !queryParams['api-version']) {
235
+ if (path === '/subscriptions') {
236
+ apiVersion = '2022-12-01'; // Default API version for listing subscriptions
237
+ }
238
+ }
237
239
  // Handle predefined operations
238
240
  if (operation !== "custom") {
239
241
  const requiredSubscriptionId = !['listResourceProviders', 'getResourceProvider', 'registerResourceProvider'].includes(operation);
@@ -310,7 +312,6 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
310
312
  throw new Error("Azure Resource Management API requires an 'apiVersion' parameter");
311
313
  }
312
314
  // Get Azure credential
313
- console.error(`[askAzure] Getting Azure credential`);
314
315
  const credential = getAzureCredential();
315
316
  // Construct the base URL and path
316
317
  const baseUrl = "https://management.azure.com";
@@ -322,12 +323,10 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
322
323
  const params = new URLSearchParams(queryParams);
323
324
  if (apiVersion)
324
325
  params.set('api-version', apiVersion);
325
- console.error(`[askAzure] Requesting token for Azure Resource Management API`);
326
326
  // Get access token
327
327
  const tokenResponse = await credential.getToken("https://management.azure.com/.default");
328
328
  if (!tokenResponse?.token)
329
329
  throw new Error("Failed to acquire Azure access token");
330
- console.error(`[askAzure] Successfully acquired token`);
331
330
  // Prepare request options
332
331
  const headers = {
333
332
  'Authorization': `Bearer ${tokenResponse.token}`,
@@ -342,12 +341,10 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
342
341
  }
343
342
  // Construct URL
344
343
  const url = `${baseUrl}${fullPath}?${params.toString()}`;
345
- console.error(`[askAzure] Making request to ${url}`);
346
344
  // Execute request with pagination if needed
347
345
  let result;
348
346
  if (method === 'get' && fetchAllPages) {
349
347
  // Fetch first page
350
- console.error(`[askAzure] Executing GET with pagination`);
351
348
  const response = await fetch(url, options);
352
349
  if (!response.ok) {
353
350
  const errorText = await response.text();
@@ -363,7 +360,6 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
363
360
  const allItems = [...(firstPage.value || [])];
364
361
  let nextLink = firstPage.nextLink;
365
362
  while (nextLink) {
366
- console.error(`[askAzure] Fetching next page: ${nextLink}`);
367
363
  const pageResponse = await fetch(nextLink, options);
368
364
  if (!pageResponse.ok)
369
365
  throw new Error(`Azure API pagination error: ${pageResponse.status}`);
@@ -380,11 +376,9 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
380
376
  }
381
377
  else {
382
378
  // Single page request
383
- console.error(`[askAzure] Executing ${method} request`);
384
379
  const response = await fetch(url, options);
385
380
  if (!response.ok) {
386
381
  const errorText = await response.text();
387
- console.error(`[askAzure] Request failed with status ${response.status}: ${errorText}`);
388
382
  let errorDetail;
389
383
  try {
390
384
  errorDetail = JSON.parse(errorText);
@@ -400,14 +394,9 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
400
394
  const text = await response.text();
401
395
  result = text ? JSON.parse(text) : { status: "Success" };
402
396
  }
403
- console.error(`[askAzure] Successfully executed request`);
404
397
  return formatApiResponse('Azure', method, path, result);
405
398
  }
406
399
  catch (err) {
407
- console.error(`[askAzure] ERROR: ${err instanceof Error ? err.message : String(err)}`);
408
- if (err instanceof Error && err.stack) {
409
- console.error(`[askAzure] Stack trace: ${err.stack}`);
410
- }
411
400
  return formatErrorResponse(err, 'Azure');
412
401
  }
413
402
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north7/entraaware",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "type": "module",
5
5
  "main": "build/index.js",
6
6
  "bin": {