@north7/entraaware 0.0.1
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 +92 -0
- package/build/index.js +109 -0
- package/package.json +33 -0
package/README.md
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
# EntraAware MCP Server
|
2
|
+
|
3
|
+
A simple, lightweight Model Context Protocol (MCP) server for querying Microsoft Entra (Azure AD) data.
|
4
|
+
|
5
|
+
## What is EntraAware?
|
6
|
+
|
7
|
+
EntraAware is an MCP Server allows AI assistants to directly access your Microsoft Entra (Azure AD) tenant data through the Microsoft Graph API. With EntraAware, you can ask natural language questions about your Entra environment.
|
8
|
+
|
9
|
+
## Setup
|
10
|
+
|
11
|
+
### Prerequisites
|
12
|
+
|
13
|
+
- Microsoft Entra (Azure AD) tenant
|
14
|
+
- Application registration with appropriate Graph API permissions
|
15
|
+
- Node.js 18 or higher
|
16
|
+
|
17
|
+
### Installation
|
18
|
+
|
19
|
+
```bash
|
20
|
+
# Install globally
|
21
|
+
npm install -g @uniquk/entraaware
|
22
|
+
|
23
|
+
# Or use with npx (no installation needed)
|
24
|
+
npx @uniquk/entraaware
|
25
|
+
```
|
26
|
+
|
27
|
+
### Configuration
|
28
|
+
|
29
|
+
Create a `.mcp.json` file in your VS Code workspace:
|
30
|
+
|
31
|
+
```json
|
32
|
+
{
|
33
|
+
"servers": {
|
34
|
+
"EntraAware": {
|
35
|
+
"type": "stdio",
|
36
|
+
"command": "npx",
|
37
|
+
"args": [
|
38
|
+
"-y",
|
39
|
+
"@uniquk/entraaware@latest"
|
40
|
+
],
|
41
|
+
"env": {
|
42
|
+
"TENANT_ID": "your-tenant-id",
|
43
|
+
"CLIENT_ID": "your-client-id",
|
44
|
+
"CLIENT_SECRET": "your-client-secret"
|
45
|
+
}
|
46
|
+
}
|
47
|
+
}
|
48
|
+
}
|
49
|
+
```
|
50
|
+
|
51
|
+
Replace the environment variables with your own:
|
52
|
+
|
53
|
+
- `TENANT_ID` - Your Microsoft Entra tenant ID
|
54
|
+
- `CLIENT_ID` - Your Microsoft Entra client ID/application ID
|
55
|
+
- `CLIENT_SECRET` - Your Microsoft Entra client secret
|
56
|
+
|
57
|
+
## Usage
|
58
|
+
|
59
|
+
Once configured, you can use EntraAware through VS Code by typing:
|
60
|
+
|
61
|
+
```
|
62
|
+
ask EntraAware>
|
63
|
+
```
|
64
|
+
|
65
|
+
The EntraAware MCP tool provides a single function that automatically detects the right Graph API endpoint based on keywords in your question:
|
66
|
+
|
67
|
+
```json
|
68
|
+
{
|
69
|
+
"question": "Show me all conditional access policies"
|
70
|
+
}
|
71
|
+
```
|
72
|
+
|
73
|
+
### Example Queries
|
74
|
+
|
75
|
+
```
|
76
|
+
// Get organization details
|
77
|
+
Show me details about my organization
|
78
|
+
|
79
|
+
// Get conditional access policies
|
80
|
+
List all conditional access policies
|
81
|
+
|
82
|
+
// Get information about a specific user
|
83
|
+
Find user john.doe@example.com
|
84
|
+
|
85
|
+
// Get all groups
|
86
|
+
Show me all groups
|
87
|
+
```
|
88
|
+
|
89
|
+
## References
|
90
|
+
|
91
|
+
- [Microsoft Graph API Documentation](https://learn.microsoft.com/en-us/graph/api/overview)
|
92
|
+
- [EntraAware npm package](https://www.npmjs.com/package/@uniquk/entraaware)
|
package/build/index.js
ADDED
@@ -0,0 +1,109 @@
|
|
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 { Client } from "@microsoft/microsoft-graph-client";
|
6
|
+
import { ClientSecretCredential } from "@azure/identity";
|
7
|
+
import { TokenCredentialAuthenticationProvider } from "@microsoft/microsoft-graph-client/authProviders/azureTokenCredentials/index.js";
|
8
|
+
// Initialize Graph Client
|
9
|
+
let graphClient = null;
|
10
|
+
// Create server instance
|
11
|
+
const server = new McpServer({
|
12
|
+
name: "EntraAware",
|
13
|
+
version: "0.0.1",
|
14
|
+
capabilities: {
|
15
|
+
resources: {},
|
16
|
+
tools: {},
|
17
|
+
},
|
18
|
+
});
|
19
|
+
// Direct Microsoft Graph API access tool
|
20
|
+
server.tool("askEntra", "Ask any question about your Microsoft Entra (Azure AD) tenant in natural language", {
|
21
|
+
question: z.string().describe("Your natural language question about Microsoft 365 Entra (Azure AD)")
|
22
|
+
}, async ({ question }) => {
|
23
|
+
try {
|
24
|
+
// Get or initialize Graph client
|
25
|
+
if (!graphClient) {
|
26
|
+
graphClient = initGraphClient();
|
27
|
+
}
|
28
|
+
// Default path if we can't determine from the question
|
29
|
+
let path = "/organization";
|
30
|
+
// Extract any email addresses or GUIDs from the question
|
31
|
+
const emailPattern = /\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/;
|
32
|
+
const guidPattern = /\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
|
33
|
+
const emailMatch = question.match(emailPattern);
|
34
|
+
const guidMatch = question.match(guidPattern);
|
35
|
+
// Check for specific keywords in the question to determine the right path
|
36
|
+
const lowerQuestion = question.toLowerCase();
|
37
|
+
if (lowerQuestion.includes("conditional access") || lowerQuestion.includes("policies")) {
|
38
|
+
path = "/identity/conditionalAccess/policies";
|
39
|
+
}
|
40
|
+
else if (lowerQuestion.includes("users") || lowerQuestion.includes("user")) {
|
41
|
+
path = "/users";
|
42
|
+
if (emailMatch) {
|
43
|
+
path = `/users/${emailMatch[0]}`;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
else if (lowerQuestion.includes("groups") || lowerQuestion.includes("group")) {
|
47
|
+
path = "/groups";
|
48
|
+
}
|
49
|
+
else if (lowerQuestion.includes("applications") || lowerQuestion.includes("apps")) {
|
50
|
+
path = "/applications";
|
51
|
+
}
|
52
|
+
else if (lowerQuestion.includes("roles") || lowerQuestion.includes("directory roles")) {
|
53
|
+
path = "/directoryRoles";
|
54
|
+
}
|
55
|
+
// If a GUID was found and not already used in the path, append it
|
56
|
+
if (guidMatch && !path.includes(guidMatch[0])) {
|
57
|
+
path = `${path}/${guidMatch[0]}`;
|
58
|
+
}
|
59
|
+
// Build and execute the request
|
60
|
+
let request = graphClient.api(path);
|
61
|
+
// Execute the request
|
62
|
+
const result = await request.get();
|
63
|
+
// Format the response
|
64
|
+
return {
|
65
|
+
content: [
|
66
|
+
{
|
67
|
+
type: "text",
|
68
|
+
text: `📊 Entra API Result (${path}):\n\n${JSON.stringify(result, null, 2)}`,
|
69
|
+
},
|
70
|
+
],
|
71
|
+
};
|
72
|
+
}
|
73
|
+
catch (err) {
|
74
|
+
return {
|
75
|
+
content: [
|
76
|
+
{
|
77
|
+
type: "text",
|
78
|
+
text: `Error querying Entra API: ${err instanceof Error ? err.message : String(err)}`,
|
79
|
+
},
|
80
|
+
],
|
81
|
+
};
|
82
|
+
}
|
83
|
+
});
|
84
|
+
// Helper function to initialize the Microsoft Graph client
|
85
|
+
function initGraphClient() {
|
86
|
+
const tenantId = process.env.TENANT_ID;
|
87
|
+
const clientId = process.env.CLIENT_ID;
|
88
|
+
const clientSecret = process.env.CLIENT_SECRET;
|
89
|
+
if (!tenantId || !clientId || !clientSecret) {
|
90
|
+
throw new Error("Missing required Entra environment variables: TENANT_ID, CLIENT_ID, or CLIENT_SECRET");
|
91
|
+
}
|
92
|
+
const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
|
93
|
+
const authProvider = new TokenCredentialAuthenticationProvider(credential, {
|
94
|
+
scopes: ["https://graph.microsoft.com/.default"],
|
95
|
+
});
|
96
|
+
return Client.initWithMiddleware({
|
97
|
+
authProvider: authProvider,
|
98
|
+
});
|
99
|
+
}
|
100
|
+
// Start the server with stdio transport
|
101
|
+
async function main() {
|
102
|
+
const transport = new StdioServerTransport();
|
103
|
+
await server.connect(transport);
|
104
|
+
console.error("EntraAware MCP Server running on stdio");
|
105
|
+
}
|
106
|
+
main().catch((error) => {
|
107
|
+
console.error("Fatal error in main():", error);
|
108
|
+
process.exit(1);
|
109
|
+
});
|
package/package.json
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
{
|
2
|
+
"name": "@north7/entraaware",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"type": "module",
|
5
|
+
"main": "build/index.js",
|
6
|
+
"bin": {
|
7
|
+
"entraaware": "build/index.js"
|
8
|
+
},
|
9
|
+
"scripts": {
|
10
|
+
"build": "tsc && chmod 755 build/index.js",
|
11
|
+
"start": "node build/index.js"
|
12
|
+
},
|
13
|
+
"publishConfig": {
|
14
|
+
"access": "public"
|
15
|
+
},
|
16
|
+
"keywords": ["mcp-server", "entra", "azure-ad", "mcp", "microsoft-graph"],
|
17
|
+
"author": "",
|
18
|
+
"license": "ISC",
|
19
|
+
"description": "MCP server for Microsoft Entra (Azure AD) integration",
|
20
|
+
"files": [
|
21
|
+
"build"
|
22
|
+
],
|
23
|
+
"dependencies": {
|
24
|
+
"@azure/identity": "^4.9.0",
|
25
|
+
"@microsoft/microsoft-graph-client": "^3.0.7",
|
26
|
+
"@modelcontextprotocol/sdk": "^1.10.1",
|
27
|
+
"zod": "^3.24.3"
|
28
|
+
},
|
29
|
+
"devDependencies": {
|
30
|
+
"@types/node": "^22.14.1",
|
31
|
+
"typescript": "^5.8.3"
|
32
|
+
}
|
33
|
+
}
|