Skip to main content
Glama
tigercatyxcl

Deviseur Azure

by tigercatyxcl

Deviseur Azure

GitHub repo Python 3.9+ License: MIT

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.


Related MCP server: cloudprice-mcp

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-type applies to all VMs. A sample export ships at examples/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=Consumption with "Spot" in the meter name (not type=Spot); the scripts handle this.

  • Reservation retailPrice is 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.json with a sku/family/vcpu/ram_gib row.

  • 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.md in 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

MIT

A
license - permissive license
-
quality - not tested
B
maintenance

Maintenance

Maintainers
Response time
Release cycle
Releases (12mo)
Commit activity

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/tigercatyxcl/deviseur-azure-web'

If you have feedback or need assistance with the MCP directory API, please join our Discord server