avm-mcp-server 0.1.5
MCP Server for discovering and exploring Azure Verified Modules (AVM)
License: MIT
Requires Python: >=3.10

# 🏗️ avm-mcp-server

MCP Server for discovering and exploring Azure Verified Modules (AVM) from the Bicep Public Registry.

## 🎯 Overview

This MCP server enables AI agents and tools to search, discover, and retrieve detailed information about Azure Verified Modules (AVM) via the Model Context Protocol (MCP). It connects directly to the Microsoft Container Registry (MCR) and GitHub to provide up-to-date module information, versions, parameters, and usage examples.

## ❓ Why AVM MCP Server?

Azure Verified Modules (AVM) are a collection of standardized, validated, and well-documented Infrastructure as Code (IaC) modules for deploying Azure resources using Bicep. However, discovering the right module and understanding its parameters can be challenging:

- **Discovery Challenge**: With hundreds of AVM modules available, finding the right module for your use case requires searching through documentation
- **Parameter Complexity**: Each module has numerous parameters with specific requirements and defaults
- **Version Management**: Keeping track of module versions and updates across the registry
- **Documentation Access**: Module documentation is scattered across GitHub repositories

This MCP server solves these challenges by:

- Providing fast, intelligent search across all AVM modules
- Retrieving module versions directly from the registry
- Extracting detailed parameter information and usage examples
- Enabling AI agents to help you find and use the right modules

## Comparison with Microsoft Bicep MCP Server

Microsoft provides an [official Bicep MCP Server](https://github.com/Azure/bicep) that includes a `ListAvmMetadata` tool. So why create a separate AVM MCP Server?

### Key Differences

| Feature | Microsoft Bicep MCP Server | AVM MCP Server (This Project) |
|---------|---------------------------|-------------------------------|
| **Primary Focus** | Bicep language tools & Azure resource schemas | AVM module discovery & documentation |
| **AVM Module Search** | Lists all modules (no filtering) | Intelligent search with multiple query formats |
| **Module Details** | Basic metadata (name, description, versions) | Deep documentation extraction (parameters, resource types, examples) |
| **Installation** | Requires .NET runtime & Bicep CLI | Lightweight Python with minimal dependencies |
| **Response Format** | Newline-separated text summary | Structured JSON with rich metadata |
| **Documentation Access** | External links only | Extracted and formatted markdown from module READMs |

### Why This Server Exists

While the official Bicep MCP Server is excellent for **authoring Bicep templates** and accessing Azure resource type schemas, it provides limited functionality for **discovering and understanding AVM modules**:

1. **No Search Capability**: The `ListAvmMetadata` tool returns ALL modules without filtering, making it difficult to find relevant modules when there are hundreds available. This server provides intelligent search that handles variations like "key vault", "key-vault", and "keyvault".

2. **Limited Documentation**: The official tool provides only basic metadata (name, description, versions, documentation URI). This server extracts the actual documentation content including:
   - Complete parameter reference with types and descriptions
   - Resource types deployed by the module
   - Real-world usage examples with large parameter sets

3. **Different Use Cases**:
   - **Use Bicep MCP Server when**: Writing Bicep code, checking Azure resource schemas, following Bicep best practices
   - **Use AVM MCP Server when**: Discovering which AVM module to use, understanding module parameters, exploring module capabilities

4. **Complementary Tools**: These servers can work together! Use the Bicep MCP Server for template authoring and this server for module discovery and documentation.

### When to Use Each

**Choose Microsoft Bicep MCP Server if you need:**

- Bicep authoring best practices
- Azure resource type schemas and API versions
- Comprehensive Bicep ecosystem tools

**Choose AVM MCP Server if you need:**

- Find AVM modules for specific Azure services
- Understand module parameters before using them
- Extract usage examples and documentation
- Quick filtered search across the AVM catalog

**Use both servers together for a complete Bicep + AVM development experience!**

## 🛠️ Features

- **Search AVM Modules**: Intelligent search supporting multiple query formats (e.g., "key vault", "key-vault", "keyvault")
- **List Module Versions**: Retrieve all available versions for any AVM module
- **Module Details**: Extract resource types, parameters, and usage examples from module documentation
- **Fast Filtering**: Optimized search that quickly narrows down results from thousands of repositories
- **Direct Registry Access**: Connects to Microsoft Container Registry for real-time module information

## 📋 Prerequisites

- Python 3.11 or higher
- UV package manager
- Internet connectivity (to access Microsoft Container Registry and GitHub)
- Node.js and npm (for MCP inspector tools, optional)

### 1. Python

- **Official Download Page:**  
  [https://www.python.org/downloads/](https://www.python.org/downloads/)

- **Direct Download for Python 3.11.14:**  
  [Python 3.11.14 Release Page](https://www.python.org/downloads/release/python-31114/)

- Download the installer for your OS (Windows, macOS, Linux) and follow the setup instructions.

---

### 2. UV (Python Package Manager)

- **Official Documentation & Source:**  
  [https://github.com/astral-sh/uv](https://github.com/astral-sh/uv)  
  [UV Documentation](https://docs.astral.sh/uv/)

- **Installation (Windows):**

  ```powershell
  irm https://astral.sh/uv/install.ps1 | iex
  ```

    Or, using pip (if you already have Python and pip installed):

  ```powershell
  pip install uv
  ```

- **Installation (macOS/Linux):**

  ```bash
  curl -LsSf https://astral.sh/uv/install.sh | sh
  ```

- **More Info:**  
  [UV Installation Guide](https://docs.astral.sh/uv/getting-started/installation/)

### 3. Claude Desktop (Optional)

- **Official Download Page:**  
  [https://claude.ai/download](https://claude.ai/download)

- Download the installer for your OS (Windows, macOS) and follow the setup instructions.

## 🚀 Installation

1. Clone the repository:

   ```powershell
   git clone https://github.com/stefanstranger/avm-mcp-server.git
   cd avm-mcp-server
   ```

2. Create a virtual environment:

   ```powershell
   uv venv .venv --python 3.13
   ```

3. Activate the virtual environment:
   - **Windows PowerShell:**
  
     ```powershell
     .\.venv\Scripts\Activate.ps1
     ```

   - **macOS/Linux:**

     ```bash
     source .venv/bin/activate
     ```

4. Install dependencies:

   ```powershell
   uv pip install fastmcp requests
   ```

## ⚙️ Configuration

### 🔧 Claude Desktop Setup

#### Option 1: Using uvx with GitHub Repository (Recommended)

Use the following command to add the AVM MCP server to your local environment. This assumes uvx is in your $PATH; if not, then you need to provide the full path to uvx.

Add the following to your `claude_desktop_config.json` file:

```json
{
  "mcpServers": {
    "avm-mcp-server": {
      "type": "stdio",
      "command": "uvx",
      "args": [
        "--from",
        "git+https://github.com/stefanstranger/avm-mcp-server",
        "avm-mcp-server"
      ]
    }
  }
}
```

or mcp.json for Visual Code mcp configuration.

```json
{
 "servers": {
  "avm-mcp-server-github": {
   "type": "stdio",
   "command": "uvx",
   "args": [
    "--from",
    "git+https://github.com/stefanstranger/avm-mcp-server@v0.1.5",
    "avm-mcp-server"
   ]
  }
 },
 "inputs": []
}
```

This approach:

- ✅ No local installation required
- ✅ Always uses the latest version from the main branch
- ✅ No need to manage virtual environments
- ✅ Works across different machines with the same config

To use a specific version/tag, modify the GitHub URL:

```json
"git+https://github.com/stefanstranger/avm-mcp-server@v0.1.5"
```

#### Option 2: Using Local Installation

If you prefer to run from a local clone:

```json
{
  "mcpServers": {
    "avm-mcp-server": {
      "type": "stdio",
      "command": "uv",
      "args": [
        "run",
        "--with",
        "mcp[cli]",
        "--with",
        "requests",
        "mcp",
        "run",
        "C:\\Github\\avm-mcp-server\\server.py"
      ]
    }
  }
}
```

**Note**: Adjust the path in the last `args` element to match your installation location.

## 🏃 Running the Server

### Using uvx (No Installation Required)

Run directly from GitHub:

```powershell
uvx --from git+https://github.com/stefanstranger/avm-mcp-server avm-mcp-server
```

Or with a specific version:

```powershell
uvx --from git+https://github.com/stefanstranger/avm-mcp-server@v0.1.5 avm-mcp-server
```

### Using Local Installation

If you cloned the repository:

```powershell
uv run .\server.py
```

### Running with Different Transports

The server now supports multiple transport methods for different use cases:

#### 1. STDIO Transport (Default)

Standard input/output - ideal for Claude Desktop and MCP Inspector:

```bash
python server.py --transport stdio
```

This is the default mode and is used when no transport is specified.

#### 2. HTTP Transport

Streamable HTTP transport - ideal for web applications and REST API integrations:

```bash
python server.py --transport http --host 0.0.0.0 --port 8080
```

Test the server is running:
```bash
# Simple tools listing endpoint (GET request)
curl http://localhost:8080/tools

# MCP protocol endpoint (requires POST with JSON-RPC format)
curl -X POST http://localhost:8080/mcp/ \
  -H "Content-Type: application/json" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "initialize",
    "params": {
      "protocolVersion": "2024-11-05",
      "capabilities": {},
      "clientInfo": {"name": "test-client", "version": "1.0.0"}
    }
  }'
```

**Note**: The MCP endpoint (`/mcp/`) requires a trailing slash and expects POST requests with JSON-RPC formatted data.


#### 3. SSE Transport

Server-Sent Events transport - ideal for real-time streaming applications:

```bash
python server.py --transport sse --host 0.0.0.0 --port 8080
```

#### Additional Options

- `--debug`: Enable debug logging
- `--host`: Host address to bind to (default: 0.0.0.0 for HTTP/SSE)
- `--port`: Port to use (default: 8080 for HTTP/SSE)

Example with debug mode:
```bash
python server.py --transport http --port 8081 --debug
```

#### Configuration via Environment Variables

You can also configure the server using a `.env` file:

```env
MCP_HOST=0.0.0.0
MCP_PORT=8080
MCP_DEBUG=false
LOG_LEVEL=INFO
```

### Running with Docker

For containerized deployments, use the included Dockerfile:

```bash
# Build the image
docker build -t avm-mcp-server .

# Run the container
docker run -p 8080:8080 avm-mcp-server
```

The container runs in HTTP transport mode on port 8080 by default. To use a different port:

```bash
docker run -p 9000:8080 avm-mcp-server
```

To run with SSE transport instead:

```bash
docker run -p 8080:8080 avm-mcp-server python server.py --transport sse --port 8080
```

### Quick Setup for Linux/macOS

For local development on Linux or macOS, use the setup script to quickly create a virtual environment and install dependencies:

```bash
chmod +x setup.sh
./setup.sh
```

This script:

- Checks for Python 3 installation
- Creates a virtual environment (`.venv`)
- Installs all dependencies from `requirements.txt`
- Verifies imports work correctly

**Note**: For Windows users or those using UV, follow the standard [Installation](#-installation) steps instead.

### Inspect MCP Server

The [MCP Inspector](https://github.com/modelcontextprotocol/inspector) is a useful tool for testing and debugging MCP servers.

#### STDIO Transport (Default)

Using uvx from GitHub:

```powershell
npx @modelcontextprotocol/inspector uvx --from git+https://github.com/stefanstranger/avm-mcp-server avm-mcp-server
```

Using local installation:

```powershell
npx @modelcontextprotocol/inspector uv run --with mcp[cli] mcp run c://github//avm-mcp-server//server.py
```

#### HTTP Transport

First, start the server in HTTP mode:

```powershell
python server.py --transport http --port 8080
```

Then open the MCP Inspector web UI and connect to the HTTP endpoint:

```powershell
npx @modelcontextprotocol/inspector
```

In the Inspector UI, enter `http://localhost:8080/mcp/` as the server URL and select "Streamable HTTP" as the transport type.

Alternatively, use curl to verify the server is running:

```powershell
# Check the tools endpoint
curl http://localhost:8080/tools

# Or test the MCP endpoint directly
curl -X POST http://localhost:8080/mcp/ `
  -H "Content-Type: application/json" `
  -d '{"jsonrpc": "2.0", "id": 1, "method": "tools/list", "params": {}}'
```

#### SSE Transport

First, start the server in SSE mode:

```powershell
python server.py --transport sse --port 8080
```

Then open the MCP Inspector web UI:

```powershell
npx @modelcontextprotocol/inspector
```

In the Inspector UI, enter `http://localhost:8080/sse` as the server URL and select "SSE" as the transport type.

#### Using mcptools

[mcptools](https://github.com/mcptools/mcptools) provides an alternative way to inspect MCP servers:

```powershell
# STDIO transport
mcptools web cmd /c "uvx.exe --from git+https://github.com/stefanstranger/avm-mcp-server avm-mcp-server"

# List tools
mcptools tools cmd /c "uvx.exe --from git+https://github.com/stefanstranger/avm-mcp-server avm-mcp-server"

# Call a specific tool
mcptools call list_avm_modules --modulename "storage" cmd /c "uvx.exe --from git+https://github.com/stefanstranger/avm-mcp-server avm-mcp-server"
```

## 📖 Available Tools

### 1. `list_avm_modules`

Search and list Azure Verified Modules from the Bicep Public Registry.

**Parameters:**

- `modulename` (optional): Module name to filter by. Supports multiple formats:
  - Exact match: `"storage-account"`
  - Hyphenated: `"key-vault"`
  - Space-separated: `"key vault"` (matches "key-vault", "keyvault", "key", or "vault")
  - Compact: `"keyvault"`

**Returns:**
JSON array with module information including:

- Module name (registry path)
- Available versions
- Description
- Documentation link

**Example Usage:**

```text
"List all AVM modules for storage accounts"
"Find Azure Verified Modules for key vault"
"Show me AVM modules related to networking"
```

**Example Response:**

```json
[
  {
    "name": "bicep/avm/res/storage/storage-account",
    "versions": ["0.9.1", "0.9.0", "0.8.3"],
    "description": "Azure Verified Module",
    "documentation": "https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/storage/storage-account"
  }
]
```

### 2. `scrape_avm_module_details`

Fetch detailed information from an AVM module's README documentation.

**Parameters:**

- `url` (required): GitHub URL of the AVM module repository
  - Example: `https://github.com/Azure/bicep-registry-modules/tree/main/avm/res/storage/storage-account`

**Returns:**
Formatted markdown containing:

- **Resource Types**: Azure resources deployed by the module
- **Parameters**: Complete parameter reference with types, defaults, and descriptions
- **Usage Examples**: Large parameter set examples showing real-world usage

**Example Usage:**

```text
"Get the details for the storage account AVM module"
"Show me the parameters for the key vault module"
"What resources does the virtual network module deploy?"
```

**Example Response:**

```markdown
## Resource Types

| Resource Type | API Version |
| :-- | :-- |
| `Microsoft.Storage/storageAccounts` | [2022-09-01] |
| `Microsoft.Storage/storageAccounts/blobServices` | [2022-09-01] |

## Parameters

**Required parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`name`](#parameter-name) | string | Name of the Storage Account. |

**Optional parameters**

| Parameter | Type | Description |
| :-- | :-- | :-- |
| [`location`](#parameter-location) | string | Location for all resources. |
...
```

## 📖 Available Prompts

### 1. `find_avm_module_prompt`

A prompt to find Azure Verified Modules (AVM).

**Parameters:**

- `search_term` (optional): The search term to use to find AVM modules.

**Example Usage:**

```text
"Find AVM modules for 'storage account'"
```

### 2. `get_avm_module_details_prompt`

A prompt to get the details of a specific AVM.

**Parameters:**

- `module_name` (required): The name of the AVM module.

**Example Usage:**

```text
"Get details for the 'storage-account' AVM module"
```

### 3. `suggest_avm_for_service_prompt`

A prompt to suggest an AVM for a specific Azure service.

**Parameters:**

- `azure_service` (required): The Azure service to find an AVM for.

**Example Usage:**

```text
"Suggest an AVM for 'Azure Key Vault'"
```

## 💡 Usage Examples

### Search for modules

```text
"Find all AVM modules for storage"
"List Azure Verified Modules for Key Vault"
"Show me networking modules"
```

### Get module versions

```text
"What versions are available for the storage account module?"
"List all versions of the AVM key vault module"
```

### Explore module details

```text
"Show me the parameters for bicep/avm/res/storage/storage-account"
"What resources does the virtual network module deploy?"
"Get usage examples for the key vault module"
```

### Combined workflows

```text
"Find the storage account AVM module and show me its parameters"
"I need to deploy a key vault - find the module and explain its parameters"
"Search for virtual network modules and show me usage examples"
```

## 🔍 How It Works

### Module Discovery

1. Queries Microsoft Container Registry's catalog endpoint (`mcr.microsoft.com/v2/_catalog`)
2. Filters repositories starting with `bicep/avm/`
3. Applies intelligent search matching:
   - Normalizes search terms (lowercase, hyphenated, compact)
   - Matches any token from multi-word queries
   - Returns all matching modules

### Version Retrieval

1. For each matching module, queries the registry's tags endpoint
2. Retrieves all available semantic versions
3. Returns version information with module metadata

### Documentation Extraction

1. Converts GitHub tree URLs to raw content URLs
2. Fetches README.md content from the bicep-registry-modules repository
3. Extracts relevant sections using regex patterns:
   - Resource Types tables
   - Parameters documentation
   - Usage examples with large parameter sets

## 🐛 Troubleshooting

### Common Issues

1. **"Failed to fetch modules" error**
   - Check internet connectivity
   - Verify access to `mcr.microsoft.com`
   - Check for firewall/proxy restrictions

2. **"Could not fetch README.md" error**
   - Verify the GitHub URL format is correct
   - Ensure the module documentation exists in the repository
   - Check internet connectivity to `raw.githubusercontent.com`

3. **No modules found for search query**
   - Try different search terms (e.g., "storage" instead of "storage-account")
   - Use partial names (e.g., "key" to find "key-vault")
   - List all modules without a filter first

4. **Server won't start in Claude Desktop**
   - Verify Python 3.11+ is installed
   - Check that UV is properly installed
   - Ensure the path in `claude_desktop_config.json` is correct
   - Review Claude Desktop logs for detailed error messages

## 🧪 Testing

The project includes a comprehensive test suite to ensure code quality and catch issues before release.

### Running Tests

```powershell
# Install dev dependencies
uv sync --dev

# Run all tests
uv run pytest

# Run tests with verbose output
uv run pytest -v
```

### What the Tests Check

The test suite (`tests/test_distribution.py`) validates:

| Test | Purpose |
|------|---------|
| `test_required_files_in_wheel` | Ensures `server.py` and `config.py` are included in the wheel |
| `test_required_dependencies` | Verifies all runtime dependencies are listed |
| `test_entry_point_configured` | Confirms CLI entry point is defined |
| `test_modules_import` | Catches import errors from missing files/dependencies |

These tests specifically target issues that have caused runtime failures (missing modules, missing dependencies).

### Continuous Integration

Tests run automatically on:

- Every push to `main` and `feature/**` branches
- Every pull request to `main`
- Before publishing to PyPI (publishing is blocked if tests fail)

The CI workflow tests against Python 3.10, 3.11, 3.12, and 3.13 to ensure compatibility.

## Publishing & Distribution

This server is published to both PyPI and the MCP Registry for easy installation and discovery.

### Installing from PyPI

The recommended way to use this server is via `uvx` from PyPI:

```powershell
# Run directly without installation
uvx avm-mcp-server

# Or install globally
uv tool install avm-mcp-server
```

### MCP Registry

This server is registered in the [MCP Registry](https://registry.modelcontextprotocol.io/), making it discoverable by MCP clients and AI assistants.

**Registry Entry**: `io.github.stefanstranger/avm-mcp-server`

### For Developers: Publishing Updates

The project uses automated GitHub Actions workflows to publish new versions. Publishing is triggered automatically when a feature branch is merged to `main` with a version bump.

1. **Update Version Numbers** (in your feature branch):
   - `pyproject.toml` - Package version
   - `server.py` - FastMCP instance version

2. **Create PR and Merge**:

   ```powershell
   # On your feature branch
   git add pyproject.toml server.py
   git commit -m "Bump version to X.Y.Z"
   git push
   # Create PR and merge to main
   ```

3. **Automated Workflow** (triggered on merge to main):
   - Detects version change in `pyproject.toml`
   - Runs all tests across Python 3.10-3.13
   - Creates git tag `vX.Y.Z` automatically
   - Builds and publishes to PyPI
   - Updates `server.json` with new version
   - Authenticates with MCP Registry via GitHub OIDC
   - Publishes to MCP Registry
   - Creates GitHub Release with release notes

**Note**: The workflow only triggers when `pyproject.toml` changes and the version doesn't already have a tag. This prevents duplicate publishes.

### Manual Publishing (First Time)

For the initial PyPI release, publish manually:

```powershell
# Build the package
uv build

# Publish to PyPI (will prompt for token)
uv publish
```

**Requirements**:

- PyPI account and API token
- The README includes the MCP validation line: `<!-- mcp-name: io.github.stefanstranger/avm-mcp-server -->`

**Note**: PyPI versions cannot be re-uploaded. Always bump the version number for new releases.

## 📚 References

- [Azure Verified Modules (AVM)](https://aka.ms/AVM)
- [Bicep Registry Modules](https://github.com/Azure/bicep-registry-modules)
- [Microsoft Container Registry](https://mcr.microsoft.com/)
- [Model Context Protocol](https://modelcontextprotocol.io/)
- [MCP Registry](https://registry.modelcontextprotocol.io/)
- [FastMCP](https://github.com/jlowin/fastmcp)
- [MCP Tools](https://github.com/mcptools/mcptools)

## 📄 License

MIT License

## 🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## ⚖️ Disclaimer

This tool is not officially affiliated with or endorsed by Microsoft or the Azure Verified Modules team. It provides read-only access to publicly available module information from the Microsoft Container Registry and GitHub.

<!-- mcp-name: io.github.stefanstranger/avm-mcp-server -->