Deviseur Azure
MCP server that converts hardware specs into Azure price quotes using live Azure Retail Prices API. Provides tools to propose VM flavors, get full quotes with disk and reservation options, and batch-analyze RVTools exports.
README
Deviseur Azure
English | 中文
Turn a one-line hardware spec (e.g. 4U8G, 25G SSD) into an Azure price quote.
Live prices come from the
Azure Retail Prices API (no key
required); the spec→flavor mapping uses the local catalog in
references/vm-catalog.json.
One set of scripts/ + references/ is reusable by four AI coding tools:
| Tool | Entry file |
|---|---|
| Claude Code | SKILL.md |
| Hermes Agent | SKILL.md (same file — Hermes reads the Claude skill format) |
| OpenAI Codex | AGENTS.md |
| GitHub Copilot | .github/copilot-instructions.md |
1. Requirements
- Python 3.9+
- Dependency:
requests - Network access to
prices.azure.com(no Azure account / API key needed)
pip install -r requirements.txt
# or: pip install requests
Verify:
python3 scripts/propose_flavors.py --vcpu 2 --ram 8
If it prints a candidate-flavor table, your environment is ready.
2. Installation
2.1 As a Claude Code skill (auto-trigger + /deviseur-azure)
Copy the whole skill into your global skills directory:
mkdir -p ~/.claude/skills/deviseur-azure
cp -R SKILL.md scripts references ~/.claude/skills/deviseur-azure/
Open a new Claude Code session and just say "quote a 4U8G, 25G SSD Azure VM" —
it triggers automatically. You can also invoke /deviseur-azure.
Note: the global copy is separate from this repo. After changing scripts, re-copy them, or run the scripts directly from the repo.
2.2 As a Hermes Agent skill (no copy needed)
Hermes Agent reads the same Claude SKILL.md
format, so this repo is already a Hermes skill. Register it without copying the
code by adding the repo path to skills.external_dirs in your Hermes
config.yaml. Hermes uses one config per active profile, so edit the profile(s)
you run — ~/.hermes/profiles/<name>/config.yaml — and/or the default
~/.hermes/config.yaml:
skills:
external_dirs:
- /path/to/deviseur-azure
Hermes then discovers SKILL.md, injects the absolute [Skill directory: …],
and runs the same scripts/ via its shell — so edits to the repo take effect
immediately, no re-copy. Make sure requests is installed in the Python env
Hermes shells into.
2.3 As a Codex project (AGENTS.md)
No extra install: Codex (CLI or cloud agent) reads AGENTS.md at the repo root.
Describe a spec quote in this repo and it runs the scripts under scripts/.
2.4 As a GitHub Copilot project (.github/copilot-instructions.md)
No extra install: open this repo in VS Code with Copilot Chat agent mode
(which can run terminal commands) and .github/copilot-instructions.md is
injected automatically. Plain inline completion only reads the guidance; it does
not run scripts.
3. Usage — two-step workflow
Quoting is always two interactive steps: pick a flavor first, then quote.
Step 1 — Propose flavors
Split the spec into vCPU and RAM (GiB): 4U8G → --vcpu 4 --ram 8.
python3 scripts/propose_flavors.py --vcpu 4 --ram 8 --region francecentral
Outputs candidates across families (Burstable / General / Memory / Compute), the recommended D-series (RAM meets-or-exceeds, vCPU floored to the nearest size just below) first, with Linux €/hr, €/month, and 1yr reserved €/month. Pick one flavor.
Step 2 — Full quote
Add the disk requirement (25G SSD → --disk-size 25 --disk-type premium-ssd):
python3 scripts/query_quote.py --sku Standard_D4as_v5 --region francecentral \
--disk-size 25 --disk-type premium-ssd --os linux --qty 1
Outputs: VM compute table + managed disk + total across all commitment options (PAYG / Spot / 1yr Reserved / 3yr Reserved).
Export to a Markdown file
# auto-named under quotes/quote-<sku>-<region>-<date>.md
python3 scripts/query_quote.py --sku D4as_v5 --disk-size 25 --output
# specific path
python3 scripts/query_quote.py --sku D4as_v5 --disk-size 25 --output /tmp/quote.md
Batch mode — size a whole estate from RVTools
Already have a VMware RVTools export? Skip the
interactive flow and size every VM at once. The analyzer reads the vInfo sheet
and maps each VM's allocated vCPU/RAM/disk to a D-preferred Azure flavor under
the sizing rule — RAM meets-or-exceeds the source while vCPU floors to
the nearest Azure size just below it — then prints a per-VM mapping plus
rollup totals (PAYG + 1yr Reserved). Needs openpyxl (already in
requirements.txt).
python3 scripts/analyze_rvtools.py inventory.xlsx --region francecentral
# include powered-off VMs and write a Markdown report under quotes/
python3 scripts/analyze_rvtools.py inventory.xlsx --include-poweredoff --output
# try it now with the bundled sample export
python3 scripts/analyze_rvtools.py examples/rvtools-sample.xlsx
OS is auto-detected per VM from the sheet's OS column — Windows VMs are
priced with the Windows rate (licence included; the reserved column keeps the
licence at PAYG, i.e. assume Azure Hybrid Benefit to drop it), Linux with the
base rate. --os is only the fallback when the sheet has no OS column.
Heads-up: RVTools contains no Azure region — region is a target you choose (default
francecentral). It's also a point-in-time allocation snapshot, not performance data, so this is an allocation-based estimate; for performance-based right-sizing use Azure Migrate. Powered-off VMs and templates are excluded by default; one--disk-typeapplies to all VMs. A sample export ships atexamples/rvtools-sample.xlsx.
4. Options reference
propose_flavors.py
| Option | Default | Notes |
|---|---|---|
--vcpu / -v |
required | vCPU count |
--ram / -m |
required | RAM in GiB |
--region / -r |
francecentral | Azure region |
--currency / -c |
EUR | Currency code |
--max |
6 | Max candidates |
query_quote.py
| Option | Default | Notes |
|---|---|---|
--sku / -s |
required | Chosen flavor (Standard_ prefix auto-added) |
--region / -r |
francecentral | Azure region |
--currency / -c |
EUR | Currency code |
--os |
linux | linux or windows (which OS the total row uses) |
--qty / -q |
1 | Number of identical VMs |
--disk-size |
none | Disk size in GiB (rounded up to next tier) |
--disk-type |
premium-ssd | premium-ssd / standard-ssd / standard-hdd |
--output / -o |
none | Export Markdown; bare flag auto-names, or pass a PATH. Still echoes to screen |
analyze_rvtools.py
| Option | Default | Notes |
|---|---|---|
file |
required | Path to the RVTools .xlsx export |
--region / -r |
francecentral | Target Azure region |
--currency / -c |
EUR | Currency code |
--os |
linux | Fallback OS when the sheet has no OS column (OS is auto-detected per VM otherwise) |
--disk-type |
premium-ssd | Disk type applied to every VM |
--sheet |
auto | Worksheet name (auto-detects vInfo) |
--include-poweredoff |
off | Include powered-off VMs |
--include-templates |
off | Include VM templates |
--output / -o |
none | Export Markdown report; bare flag auto-names under quotes/, or pass a PATH |
5. Pricing model (key to reading a quote)
- Spot is returned by the API as
type=Consumptionwith "Spot" in the meter name (nottype=Spot); the scripts handle this. - Reservation
retailPriceis the TOTAL for the whole term; the scripts amortize it to an effective hourly/monthly rate. - Linux and Windows+AHB share the same compute price.
- Disk bills at the next tier up (25 GiB → P4 = 32 GiB), with no reservation discount.
- Monthly = hourly × 730; annual = hourly × 8760.
6. Extending
- Add flavors (GPU N-series, constrained-core sizes, etc.): edit
references/vm-catalog.jsonwith asku/family/vcpu/ram_gibrow. - Add disk tiers: edit
references/disk-tiers.json. - Non-VM/disk service-name mapping: see
references/service-mapping.md.
When you change behavior, keep
SKILL.md(shared by Claude Code and Hermes),AGENTS.md, and.github/copilot-instructions.mdin sync.
7. MCP server (use it inside Claude Desktop / Cursor)
The same quoting engine is exposed as an MCP
server (mcp_server/server.py, stdio transport) so any MCP-capable IDE can call
it directly. It exposes three tools — propose_flavors, query_quote,
analyze_rvtools (plus a parse_spec helper) — the vm-catalog/disk-tiers
reference data as resources, and the two-step workflow as a prompt.
7.1 Install (own environment)
The mcp package pulls a newer starlette than the FastAPI backend tolerates,
so install the server in its own virtualenv:
python -m venv .venv-mcp && . .venv-mcp/bin/activate
pip install -r requirements-mcp.txt
7.2 Add to Claude Desktop
Edit claude_desktop_config.json (Claude → Settings → Developer → Edit Config):
{
"mcpServers": {
"deviseur-azure": {
"command": "/absolute/path/to/deviseur-azure-web/.venv-mcp/bin/python",
"args": ["-m", "mcp_server.server"],
"cwd": "/absolute/path/to/deviseur-azure-web"
}
}
}
Restart Claude Desktop; the three tools appear under the 🔌 tools menu. (Cursor
uses the same command/args/cwd triple in its MCP settings.)
7.3 Verify without an IDE
mcp_server/verify_client.py drives the server over the same stdio protocol
the IDE uses — handshake, list tools/resources/prompts, then call all three
tools live:
python -m mcp_server.verify_client
# ✅ handshake … ✅ propose_flavors … ✅ query_quote … ✅ analyze_rvtools
If this passes, the identical config above works in Claude Desktop / Cursor.
Running it offline
The verifier is offline-tolerant: a tool call that returns a structured
no_pricing error (no network, or a SKU absent in the region) still counts as a
success — it prints ⚠️ query_quote → no pricing rather than failing, because
S1.4 verifies the tool invocation, not the presence of live prices.
To exercise that path you must force the spawned server offline. Note the MCP
stdio SDK only forwards a fixed env allowlist to the child
(HOME/LOGNAME/PATH/SHELL/TERM/USER), so a parent HTTPS_PROXY does not
reach it. Patch the SDK's child-env builder to inject a dead proxy, then call
main() unchanged:
import os, mcp.client.stdio as stdio
os.environ["HTTPS_PROXY"] = os.environ["HTTP_PROXY"] = "http://127.0.0.1:9" # closed port
_orig = stdio.get_default_environment
stdio.get_default_environment = lambda: {**_orig(),
"HTTPS_PROXY": "http://127.0.0.1:9", "HTTP_PROXY": "http://127.0.0.1:9"}
import mcp_server.verify_client as v
raise SystemExit(v.main())
# → propose_flavors (price_hr=None) ✅ · query_quote ⚠️ no_pricing · analyze_rvtools (payg 0.0) ✅ · exit 0
8. Troubleshooting
| Symptom | Fix |
|---|---|
ModuleNotFoundError: requests |
pip install -r requirements.txt |
ModuleNotFoundError: openpyxl (RVTools mode) |
pip install openpyxl (or -r requirements.txt) |
| RVTools: "Could not find CPU/Memory columns" | Point --sheet vInfo, or confirm the export has CPUs + Memory columns |
| All prices show N/A | SKU not available in that region; change region or check the SKU name |
| Connection timeout | Check access to prices.azure.com (corporate proxy/firewall) |
| Copilot doesn't run scripts | Use agent mode; inline completion does not execute commands |
| Claude Code doesn't trigger the skill | Ensure it's copied to ~/.claude/skills/deviseur-azure/ and start a new session |
MCP: The 'mcp' package is required |
Install into the dedicated env: pip install -r requirements-mcp.txt (see §7.1) |
| MCP: tools don't appear in Claude Desktop | Use absolute paths for command/cwd, then fully restart Claude Desktop; verify with python -m mcp_server.verify_client |
License
Recommended Servers
playwright-mcp
A Model Context Protocol server that enables LLMs to interact with web pages through structured accessibility snapshots without requiring vision models or screenshots.
Magic Component Platform (MCP)
An AI-powered tool that generates modern UI components from natural language descriptions, integrating with popular IDEs to streamline UI development workflow.
Audiense Insights MCP Server
Enables interaction with Audiense Insights accounts via the Model Context Protocol, facilitating the extraction and analysis of marketing insights and audience data including demographics, behavior, and influencer engagement.
VeyraX MCP
Single MCP tool to connect all your favorite tools: Gmail, Calendar and 40 more.
graphlit-mcp-server
The Model Context Protocol (MCP) Server enables integration between MCP clients and the Graphlit service. Ingest anything from Slack to Gmail to podcast feeds, in addition to web crawling, into a Graphlit project - and then retrieve relevant contents from the MCP client.
Kagi MCP Server
An MCP server that integrates Kagi search capabilities with Claude AI, enabling Claude to perform real-time web searches when answering questions that require up-to-date information.
E2B
Using MCP to run code via e2b.
Neon Database
MCP server for interacting with Neon Management API and databases
Exa Search
A Model Context Protocol (MCP) server lets AI assistants like Claude use the Exa AI Search API for web searches. This setup allows AI models to get real-time web information in a safe and controlled way.
Qdrant Server
This repository is an example of how to create a MCP server for Qdrant, a vector search engine.