@north7/entraaware 0.0.2 → 0.0.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 (2) hide show
  1. package/build/index.js +52 -6
  2. package/package.json +1 -1
package/build/index.js CHANGED
@@ -3,7 +3,7 @@ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
3
3
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
4
4
  import { z } from "zod";
5
5
  import { Client } from "@microsoft/microsoft-graph-client";
6
- import { ClientSecretCredential } from "@azure/identity";
6
+ import { ClientSecretCredential, DefaultAzureCredential } from "@azure/identity";
7
7
  import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials/index.js";
8
8
  // Initialize clients
9
9
  let graphClient = null;
@@ -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.1",
14
+ version: "0.0.3",
15
15
  capabilities: {
16
16
  resources: {},
17
17
  tools: {},
@@ -29,8 +29,24 @@ function getCredentials() {
29
29
  }
30
30
  function getAzureCredential() {
31
31
  if (!azureCredential) {
32
- const { tenantId, clientId, clientSecret } = getCredentials();
33
- azureCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
32
+ try {
33
+ // Try DefaultAzureCredential which includes CLI credentials
34
+ console.error("Attempting to use DefaultAzureCredential (will try Azure CLI if environment variables not set)");
35
+ azureCredential = new DefaultAzureCredential();
36
+ }
37
+ catch (error) {
38
+ // Fall back to ClientSecretCredential
39
+ console.error(`DefaultAzureCredential failed: ${error instanceof Error ? error.message : String(error)}`);
40
+ console.error("Falling back to ClientSecretCredential");
41
+ try {
42
+ const { tenantId, clientId, clientSecret } = getCredentials();
43
+ azureCredential = new ClientSecretCredential(tenantId, clientId, clientSecret);
44
+ }
45
+ catch (secretError) {
46
+ console.error(`ClientSecretCredential failed: ${secretError instanceof Error ? secretError.message : String(secretError)}`);
47
+ throw new Error("Failed to initialize any Azure credential. Please ensure you are logged in with 'az login' or have set environment variables.");
48
+ }
49
+ }
34
50
  }
35
51
  return azureCredential;
36
52
  }
@@ -81,6 +97,7 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
81
97
  top: z.number().optional().describe("Shorthand for $top query parameter"),
82
98
  count: z.boolean().optional().describe("Shorthand for $count=true to include count of items"),
83
99
  }, async ({ path, method, queryParams = {}, body, apiVersion, fetchAllPages, consistencyLevel, select, filter, expand, orderBy, top, count }) => {
100
+ console.error(`[askEntra] Processing request: ${method} ${path}`);
84
101
  try {
85
102
  // Process shorthand query parameters
86
103
  const processedParams = { ...queryParams };
@@ -96,27 +113,35 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
96
113
  processedParams['$top'] = top.toString();
97
114
  if (count)
98
115
  processedParams['$count'] = 'true';
99
- // Initialize or get Graph client
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
100
121
  if (!graphClient) {
101
- const credential = getAzureCredential();
102
122
  const authProvider = new TokenCredentialAuthenticationProvider(credential, {
103
123
  scopes: ["https://graph.microsoft.com/.default"],
104
124
  });
105
125
  graphClient = Client.initWithMiddleware({ authProvider });
126
+ console.error(`[askEntra] Graph client initialized`);
106
127
  }
107
128
  // Build request with API path and version
129
+ console.error(`[askEntra] Creating request for ${path} with version ${apiVersion}`);
108
130
  let request = graphClient.api(path).version(apiVersion);
109
131
  // Add query parameters
110
132
  if (Object.keys(processedParams).length > 0) {
133
+ console.error(`[askEntra] Adding query parameters: ${JSON.stringify(processedParams)}`);
111
134
  request = request.query(processedParams);
112
135
  }
113
136
  // Add consistency level header if provided
114
137
  if (consistencyLevel) {
138
+ console.error(`[askEntra] Adding consistency level: ${consistencyLevel}`);
115
139
  request = request.header('ConsistencyLevel', consistencyLevel);
116
140
  }
117
141
  // Handle pagination for GET requests
118
142
  let result;
119
143
  if (method === 'get' && fetchAllPages) {
144
+ console.error(`[askEntra] Executing GET with pagination`);
120
145
  const firstPage = await request.get();
121
146
  // If no pagination needed, return first page
122
147
  if (!firstPage["@odata.nextLink"]) {
@@ -127,6 +152,7 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
127
152
  const allItems = [...(firstPage.value || [])];
128
153
  let nextLink = firstPage["@odata.nextLink"];
129
154
  while (nextLink) {
155
+ console.error(`[askEntra] Fetching next page: ${nextLink}`);
130
156
  const nextPage = await graphClient.api(nextLink).get();
131
157
  if (nextPage.value)
132
158
  allItems.push(...nextPage.value);
@@ -142,6 +168,7 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
142
168
  }
143
169
  else {
144
170
  // Execute appropriate method
171
+ console.error(`[askEntra] Executing ${method} request`);
145
172
  switch (method) {
146
173
  case 'get':
147
174
  result = await request.get();
@@ -161,9 +188,14 @@ server.tool("askEntra", "Direct access to Microsoft Graph API for accurate Entra
161
188
  break;
162
189
  }
163
190
  }
191
+ console.error(`[askEntra] Successfully executed request`);
164
192
  return formatApiResponse('Entra', method, path, result);
165
193
  }
166
194
  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
+ }
167
199
  return formatErrorResponse(err, 'Entra');
168
200
  }
169
201
  });
@@ -188,6 +220,7 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
188
220
  resourceGroupName: z.string().optional().describe("Resource group name for resource operations"),
189
221
  resourceName: z.string().optional().describe("Resource name for resource operations"),
190
222
  }, async ({ path, method, apiVersion, subscriptionId, body, queryParams = {}, fetchAllPages, operation = "custom", providerNamespace, resourceType, resourceGroupName, resourceName }) => {
223
+ console.error(`[askAzure] Processing request: ${operation} - ${method} ${path}`);
191
224
  try {
192
225
  // Default API versions for common resource types
193
226
  const defaultApiVersions = {
@@ -277,6 +310,7 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
277
310
  throw new Error("Azure Resource Management API requires an 'apiVersion' parameter");
278
311
  }
279
312
  // Get Azure credential
313
+ console.error(`[askAzure] Getting Azure credential`);
280
314
  const credential = getAzureCredential();
281
315
  // Construct the base URL and path
282
316
  const baseUrl = "https://management.azure.com";
@@ -288,10 +322,12 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
288
322
  const params = new URLSearchParams(queryParams);
289
323
  if (apiVersion)
290
324
  params.set('api-version', apiVersion);
325
+ console.error(`[askAzure] Requesting token for Azure Resource Management API`);
291
326
  // Get access token
292
327
  const tokenResponse = await credential.getToken("https://management.azure.com/.default");
293
328
  if (!tokenResponse?.token)
294
329
  throw new Error("Failed to acquire Azure access token");
330
+ console.error(`[askAzure] Successfully acquired token`);
295
331
  // Prepare request options
296
332
  const headers = {
297
333
  'Authorization': `Bearer ${tokenResponse.token}`,
@@ -306,10 +342,12 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
306
342
  }
307
343
  // Construct URL
308
344
  const url = `${baseUrl}${fullPath}?${params.toString()}`;
345
+ console.error(`[askAzure] Making request to ${url}`);
309
346
  // Execute request with pagination if needed
310
347
  let result;
311
348
  if (method === 'get' && fetchAllPages) {
312
349
  // Fetch first page
350
+ console.error(`[askAzure] Executing GET with pagination`);
313
351
  const response = await fetch(url, options);
314
352
  if (!response.ok) {
315
353
  const errorText = await response.text();
@@ -325,6 +363,7 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
325
363
  const allItems = [...(firstPage.value || [])];
326
364
  let nextLink = firstPage.nextLink;
327
365
  while (nextLink) {
366
+ console.error(`[askAzure] Fetching next page: ${nextLink}`);
328
367
  const pageResponse = await fetch(nextLink, options);
329
368
  if (!pageResponse.ok)
330
369
  throw new Error(`Azure API pagination error: ${pageResponse.status}`);
@@ -341,9 +380,11 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
341
380
  }
342
381
  else {
343
382
  // Single page request
383
+ console.error(`[askAzure] Executing ${method} request`);
344
384
  const response = await fetch(url, options);
345
385
  if (!response.ok) {
346
386
  const errorText = await response.text();
387
+ console.error(`[askAzure] Request failed with status ${response.status}: ${errorText}`);
347
388
  let errorDetail;
348
389
  try {
349
390
  errorDetail = JSON.parse(errorText);
@@ -359,9 +400,14 @@ server.tool("askAzure", "Direct access to Azure Resource Management API for mana
359
400
  const text = await response.text();
360
401
  result = text ? JSON.parse(text) : { status: "Success" };
361
402
  }
403
+ console.error(`[askAzure] Successfully executed request`);
362
404
  return formatApiResponse('Azure', method, path, result);
363
405
  }
364
406
  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
+ }
365
411
  return formatErrorResponse(err, 'Azure');
366
412
  }
367
413
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north7/entraaware",
3
- "version": "0.0.2",
3
+ "version": "0.0.4",
4
4
  "type": "module",
5
5
  "main": "build/index.js",
6
6
  "bin": {