#
tokens: 3513/50000 7/7 files
lines: on (toggle) GitHub
raw markdown copy reset
# Directory Structure

```
├── .gitignore
├── assets
│   ├── Flow.png
│   └── mcp server.gif
├── Dockerfile
├── LICENSE
├── package.json
├── README.md
├── smithery.yaml
├── src
│   └── index.ts
└── tsconfig.json
```

# Files

--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------

```
 1 | # Dependencies
 2 | node_modules/
 3 | package-lock.json
 4 | yarn.lock
 5 | 
 6 | # Build outputs
 7 | build/
 8 | dist/
 9 | *.tsbuildinfo
10 | 
11 | # Environment variables
12 | .env
13 | .env.local
14 | 
15 | # IDE specific files
16 | .vscode/
17 | .idea/
18 | *.swp
19 | *.swo
20 | 
21 | # OS specific files
22 | .DS_Store
23 | Thumbs.db
24 | 
25 | # Logs
26 | logs/
27 | *.log
28 | npm-debug.log*
29 | yarn-debug.log*
30 | yarn-error.log*
31 | 
32 | # Coverage directory used by tools like istanbul
33 | coverage/
34 | 
35 | # Optional npm cache directory
36 | .npm
37 | 
38 | # Optional eslint cache
39 | .eslintcache
40 | 
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
  1 | # Demo
  2 | ![MCP Server Demo](./assets/mcp%20server.gif)
  3 | 
  4 | # Flow
  5 | ![Request Flow](./assets/Flow.png)
  6 | 
  7 | 
  8 | # Azure Resource Graph MCP Server
  9 | 
 10 | This is a Model Context Protocol (MCP) server that provides access to Azure Resource Graph queries. It allows you to retrieve information about Azure resources across your subscriptions using Resource Graph queries.
 11 | <a href="https://glama.ai/mcp/servers/@hardik-id/azure-resource-graph-mcp-server">
 12 |   <img width="380" height="200" src="https://glama.ai/mcp/servers/@hardik-id/azure-resource-graph-mcp-server/badge" />
 13 | </a>
 14 | 
 15 | [![MseeP.ai Security Assessment Badge](https://mseep.net/pr/hardik-id-azure-resource-graph-mcp-server-badge.png)](https://mseep.ai/app/hardik-id-azure-resource-graph-mcp-server)
 16 | 
 17 | ## Features
 18 | 
 19 | - Query Azure resources using Resource Graph queries
 20 | - Default query returns resource ID, name, type, and location
 21 | - Supports custom Resource Graph queries
 22 | - Uses Azure DefaultAzureCredential for authentication
 23 | 
 24 | ## Prerequisites
 25 | 
 26 | - Node.js installed
 27 | - Azure subscription
 28 | - Azure CLI installed and logged in, or other Azure credentials configured
 29 | 
 30 | ## Running the MCP Server
 31 | 
 32 | You can run the MCP server using either Cursor IDE or Visual Studio Code.
 33 | 
 34 | ### Option 1: Cursor IDE Integration
 35 | 
 36 | To integrate the MCP server with Cursor IDE:
 37 | 
 38 | 1. Clone this repository to your local machine (e.g., `C:\YOUR_WORKSPACE\azure-resource-graph-mcp-server`)
 39 | 2. Build the project:
 40 | ```bash 
 41 | npm install
 42 | npm run build
 43 | ```
 44 | 3. Open Cursor Settings (JSON) and add the following configuration:
 45 | ```json
 46 | {
 47 |   "mcpServers": {
 48 |     "azure-resource-graph-mcp-server": {
 49 |       "command": "node",
 50 |       "args": [
 51 |         "C:\\YOUR_WORKSPACE\\azure-resource-graph-mcp-server\\build\\index.js"
 52 |       ],
 53 |       "env": {
 54 |         "SUBSCRIPTION_ID": "xxxxxx-xx-xx-xx-xxxxxx"
 55 |       },
 56 |     }
 57 |   }
 58 | }
 59 | ```
 60 | > **Note**: Make sure to update the path to match your local repository location.
 61 | 
 62 | 4. Restart Cursor IDE to apply the changes
 63 | 
 64 | ### Option 2: VS Code Integration
 65 | 
 66 | To integrate the MCP server with Visual Studio Code:
 67 | 
 68 | 1. Clone this repository to your local machine
 69 | 2. Build the project:
 70 | ```bash 
 71 | npm install
 72 | npm run build
 73 | ```
 74 | 3. Open VS Code Settings (JSON) by pressing `Ctrl+Shift+P`, type "Settings (JSON)" and select "Preferences: Open User Settings (JSON)"
 75 | 4. Add the following configuration:
 76 | ```json
 77 | {
 78 |     "mcp": {
 79 |         "servers": {
 80 |             "azure-resource-graph": {
 81 |                 "type": "stdio",
 82 |                 "command": "node",
 83 |                 "args": [
 84 |                     "C:\\YOUR_WORKSPACE\\azure-resource-graph-mcp-server\\build\\index.js"
 85 |                 ],
 86 |                 "env": {
 87 |                   "SUBSCRIPTION_ID": "xxxxxx-xx-xx-xx-xxxxxx"
 88 |                 },
 89 |             }
 90 |         }
 91 |     }
 92 | }
 93 | ```
 94 | > **Note**: Make sure to update the path to match your local repository location.
 95 | 
 96 | 5. Save the settings.json file
 97 | 6. Restart VS Code to apply the changes
 98 | 
 99 | The MCP server will now be available to use within VS Code with cursor integration.
100 | 
101 | ## Usage
102 | 
103 | The server provides the following tool:
104 | 
105 | ### query-resources
106 | 
107 | Retrieves resources and their details from Azure Resource Graph.
108 | 
109 | Parameters:
110 | - `subscriptionId` (optional): Azure subscription ID (defaults to configured ID)
111 | - `query` (optional): Custom Resource Graph query (defaults to "Resources | project id, name, type, location")
112 | 
113 | ## Environment Setup
114 | 
115 | 1. First, make sure you're logged in to Azure CLI by running:
116 |    ```bash
117 |    az login
118 |    ```
119 |    This step is crucial for local development as the DefaultAzureCredential will automatically use your Azure CLI credentials.
120 | 
121 | 2. Set up your environment variables:
122 |    - Copy `.env.example` to `.env`
123 |    - Update `AZURE_SUBSCRIPTION_ID` in `.env` with your actual subscription ID
124 |    - Other variables (`AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`) are optional when using Azure CLI authentication
125 | 
126 | 3. Make sure you have proper Azure credentials configured. The server uses DefaultAzureCredential which supports:
127 |    - Azure CLI
128 |    - Managed Identity
129 |    - Visual Studio Code credentials
130 |    - Environment variables
131 | 
132 | 4. If using environment variables, set up:
133 |    - AZURE_SUBSCRIPTION_ID
134 |    - AZURE_TENANT_ID
135 |    - AZURE_CLIENT_ID
136 |    - AZURE_CLIENT_SECRET
137 | 
138 | ## Error Handling
139 | 
140 | The server includes robust error handling for:
141 | - Azure client initialization failures
142 | - Query execution errors
143 | - Invalid queries or parameters
144 | 
145 | ## Development
146 | 
147 | To work on this project:
148 | 
149 | 1. Make changes in the `src` directory
150 | 2. Build using `npm run build`
151 | 3. Test your changes by running the server
152 | 
153 | ## License
154 | This project is licensed under the MIT License. See the [LICENSE](./LICENSE) file for details.
155 | 
156 | 
```

--------------------------------------------------------------------------------
/Dockerfile:
--------------------------------------------------------------------------------

```dockerfile
 1 | FROM node:18-alpine
 2 | 
 3 | # Copy package files
 4 | COPY package*.json ./
 5 | 
 6 | # Install dependencies
 7 | RUN npm install
 8 | 
 9 | # Copy application code
10 | COPY . .
11 | 
12 | # Build the application
13 | RUN npm run build
14 | 
15 | # Command will be provided by smithery.yaml
16 | CMD ["node", "build/index.js"]
17 | 
```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |     "compilerOptions": {
 3 |       "target": "ES2022",
 4 |       "module": "Node16",
 5 |       "moduleResolution": "Node16",
 6 |       "outDir": "./build",
 7 |       "rootDir": "./src",
 8 |       "strict": true,
 9 |       "esModuleInterop": true,
10 |       "skipLibCheck": true,
11 |       "forceConsistentCasingInFileNames": true
12 |     },
13 |     "include": ["src/**/*"],
14 |     "exclude": ["node_modules"]
15 |   }
16 | 
```

--------------------------------------------------------------------------------
/smithery.yaml:
--------------------------------------------------------------------------------

```yaml
 1 | # Smithery.ai configuration
 2 | startCommand:
 3 |   type: stdio
 4 |   configSchema:
 5 |     # JSON Schema defining the configuration options for the MCP.
 6 |     {}
 7 |   commandFunction:
 8 |     # A function that produces the CLI command to start the MCP on stdio.
 9 |     |-
10 |     (config) => ({
11 |       "command": "node",
12 |       "args": [
13 |         "build/index.js"
14 |       ],
15 |       "env": {
16 |         "SUBSCRIPTION_ID": "xxxxxx-xx-xx-xx-xxxxxx"
17 |       }
18 |     })
19 | 
```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
 1 | {
 2 |   "type": "module",
 3 |   "bin": {
 4 |     "azure-resource-graph-mcp-server": "./build/index.js"
 5 |   },
 6 |   "files": [
 7 |     "build",
 8 |     ".env"
 9 |   ],
10 |   "name": "azure-resource-graph-mcp-server",
11 |   "version": "1.0.0",
12 |   "main": "index.js",
13 |   "scripts": {
14 |     "build": "tsc && chmod 755 build/index.js",
15 |     "start": "node build/index.js",
16 |     "test": "echo \"Error: no test specified\" && exit 1"
17 |   },
18 |   "keywords": [],
19 |   "author": "",
20 |   "license": "ISC",
21 |   "description": "",
22 |   "dependencies": {
23 |     "@azure/arm-resourcegraph": "^4.2.1",
24 |     "@azure/arm-resources": "^6.0.0",
25 |     "@azure/identity": "^4.8.0",
26 |     "@modelcontextprotocol/sdk": "^1.8.0",
27 |     "dotenv": "^16.4.7",
28 |     "zod": "^3.24.2"
29 |   },
30 |   "devDependencies": {
31 |     "@types/node": "^22.14.0",
32 |     "typescript": "^5.8.2"
33 |   }
34 | }
35 | 
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
 1 | import {
 2 |   McpServer,
 3 | } from "@modelcontextprotocol/sdk/server/mcp.js";
 4 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
 5 | import { z } from "zod";
 6 | import { ResourceGraphClient } from "@azure/arm-resourcegraph";
 7 | import { DefaultAzureCredential } from "@azure/identity";
 8 | import { config } from "dotenv";
 9 | 
10 | // Load environment variables
11 | config();
12 | 
13 | const subscriptionId = process.env.SUBSCRIPTION_ID || "";
14 | console.error("Using subscription ID:", subscriptionId);
15 | 
16 | // Create an MCP server
17 | const server = new McpServer({
18 |   name: "AzureResourceGraph",
19 |   version: "1.0.0",
20 | });
21 | 
22 | // Initialize Azure Resource Graph client
23 | let rgClient: ResourceGraphClient;
24 | 
25 | try {
26 |   // Create Azure clients using DefaultAzureCredential
27 |   const credential = new DefaultAzureCredential();
28 |   rgClient = new ResourceGraphClient(credential);
29 |   console.error("Azure Resource Graph client initialized successfully");
30 | } catch (err) {
31 |   console.error("Failed to initialize Azure Resource Graph client:", err);
32 |   process.exit(1);
33 | }
34 | 
35 | 
36 | // Add a tool to query resources
37 | server.tool(
38 |   "query-resources",
39 |   "Retrieves resources and their details from Azure Resource Graph. Use this tool to search, filter, and analyze Azure resources across subscriptions. It supports Kusto Query Language (KQL) for complex queries to find resources by type, location, tags, or properties. Useful for infrastructure auditing, resource inventory, compliance checking, and understanding your Azure environment's current state.",
40 |   {
41 |     subscriptionId: z
42 |       .string()
43 |       .describe("Azure subscription ID")
44 |       .default(process.env.SUBSCRIPTION_ID || ""),
45 |     query: z
46 |       .string()
47 |       .optional()
48 |       .describe("Resource Graph query, defaults to listing all resources"),
49 |   },
50 |   async ({ subscriptionId, query }) => {
51 |     try {
52 |       const defaultQuery = "Resources | project id, name, type, location";
53 |       const queryToUse = query || defaultQuery;
54 | 
55 |       const resources = await rgClient.resources({
56 |         subscriptions: [subscriptionId],
57 |         query: queryToUse,
58 |       });
59 | 
60 |       return {
61 |         content: [
62 |           {
63 |             type: "text",
64 |             text: JSON.stringify(resources, null, 2),
65 |           },
66 |         ],
67 |       };
68 |     } catch (err) {
69 |       return {
70 |         content: [
71 |           {
72 |             type: "text",
73 |             text: `Error querying resources: ${
74 |               err instanceof Error ? err.message : String(err)
75 |             }`,
76 |           },
77 |         ],
78 |         isError: true,
79 |       };
80 |     }
81 |   }
82 | );
83 | 
84 | async function main() {
85 |   const transport = new StdioServerTransport();
86 |   await server.connect(transport);
87 |   console.error("Azure Resource Graph MCP Server running on stdio");
88 | }
89 | 
90 | main().catch((error) => {
91 |   console.error("Fatal error in main():", error);
92 |   process.exit(1);
93 | });
94 | 
```