# 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 |  3 | 4 | # Flow 5 |  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 | [](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 | ```