Azure FinOps MCP Server

io.github.raviteja-pegata由 GitHub 账号 raviteja-pegata 发布v0.1.1更新于 Nov 3, 2026

Azure FinOps MCP: cost, budgets, forecasting and optimization for Claude, VS Code and Cursor.

已验证STDIO仅桌面云端与基础设施金融

概览

AI 生成的概览

本地运行的 MCP 服务器,让助手在允许的订阅范围内进行 Azure 成本分析、预算跟踪、支出预测和闲置资源优化。

可以做什么
  • 列出允许访问的订阅及其友好名称
  • 查询成本总额、本月至今支出,以及按服务、资源组、位置、计量或标签的明细,并支持跨订阅汇总
  • 查看单个订阅或全部订阅的预算消耗情况
  • 查找闲置资源、获取 Azure Advisor 成本优化建议、查看虚拟机 CPU 使用率
  • 预测单个订阅或整个订阅组合的月末支出
适用场景
适合希望用自然语言向助手询问 Azure 支出、预算余量、节省空间或月末预测的场景,尤其是需要跨多个订阅查看时,无需手写查询。
运行要求
以 Python 包形式本地运行(需 Python 3.11+),通过 stdio 启动;需安装 Azure CLI 并已执行 az login,远程部署时可用托管标识。必须设置 AZURE_ALLOWED_SUBSCRIPTIONS 和 AZURE_DEFAULT_SUBSCRIPTION,可选 FINOPS_CACHE_TTL_SECONDS。所用身份需在每个被查询的订阅上具备 Cost Management Reader、Reader 和 Monitoring Reader 角色。
安装前请注意
它会读取 Azure 租户中真实的账单和资源数据,订阅白名单与 RBAC 范围决定了助手能看到什么,请只对确实需要开放的订阅授予这三个只读角色。Cost Management 有速率限制,频繁查询可能被限流。README 中的远程 HTTP 部署方式默认没有身份验证,需自行添加。

安装

在 SourceWeft 中

  1. 打开 控制台中的 Azure FinOps MCP Server,将其添加到工作区。
  2. 为需要使用其工具的对话启用该服务。

Desktop only,通过 STDIO。 STDIO 服务会启动本地进程,因此需要 SourceWeft 桌面宿主。

其他 MCP 客户端

参照 仓库 中的启动说明。

README

Azure FinOps MCP Server

An MCP server that gives LLM clients (Claude Desktop, Claude Code, VS Code, Cursor) conversational access to Azure cost analysis, budget tracking, forecasting, and resource optimization — across multiple subscriptions.

Tools

Discovery

ToolPurpose
list_subscriptionsList allowed subscriptions with friendly names

Cost Analysis

ToolPurpose
get_cost_summaryTotal cost for a date range (single sub)
get_cost_by_dimensionCost breakdown by service / RG / location / meter
get_cost_by_tagCost grouped by tag value (showback/chargeback)
get_month_to_date_costCurrent-month spend (single sub)
get_portfolio_month_to_date_costCurrent-month spend across ALL subs

Budgets

ToolPurpose
get_budget_statusBudget consumption for a single sub
get_portfolio_budget_statusBudget status across ALL subs

Optimization

ToolPurpose
find_idle_resourcesUnattached disks, stranded IPs/NICs, stopped VMs
find_idle_resources_portfolioIdle resources across ALL subs
get_advisor_recommendationsAzure Advisor cost recs with annual savings
get_vm_utilizationCPU stats to validate rightsizing

Forecasting

ToolPurpose
forecast_month_end_spendPredicted month-end cost (single sub)
forecast_portfolio_month_end_spendPredicted month-end cost across ALL subs

Quick Install

bash
pip install azure-finops-mcp

Then add it to your MCP client config using the installed command — no cloning needed:

json
{  "mcpServers": {    "azure-finops": {      "command": "azure-finops-mcp",      "env": {        "AZURE_ALLOWED_SUBSCRIPTIONS": "sub-id-1,sub-id-2",        "AZURE_DEFAULT_SUBSCRIPTION": "sub-id-1"      }    }  }}

See the Client Configuration section below for per-client config file locations.


Prerequisites

  • Python 3.11+
  • Azure CLI installed and logged in (az login)

Azure RBAC Permissions

The identity running this server (your user, a service principal, or a managed identity) needs three roles assigned on each subscription you want to query:

RolePurpose
Cost Management ReaderCost analysis, forecasting, budget queries
ReaderResource inventory via Resource Graph
Monitoring ReaderVM utilization metrics via Azure Monitor

Assign via Azure CLI

bash
SUBSCRIPTION_ID="<your-subscription-id>"PRINCIPAL_ID="<object-id-of-user-sp-or-managed-identity>"
for ROLE in "Cost Management Reader" "Reader" "Monitoring Reader"; do  az role assignment create \    --assignee "$PRINCIPAL_ID" \    --role "$ROLE" \    --scope "/subscriptions/$SUBSCRIPTION_ID"done

Repeat for each subscription listed in AZURE_ALLOWED_SUBSCRIPTIONS.

Local development (your own user)

bash
az loginaz account set --subscription "<your-subscription-id>"
# Check your object IDaz ad signed-in-user show --query id -o tsv

Your user already has these roles if you're a subscription Owner or Contributor. If not, ask your Azure admin to assign them.

Managed Identity (Container Apps deployment)

After deploying with deploy.sh, the script automatically assigns these three roles to the Container App's system-assigned managed identity on each allowed subscription. No credentials or secrets are needed — DefaultAzureCredential picks up the managed identity automatically at runtime.

Install

bash
git clone <your-repo-url> azure-finops-mcpcd azure-finops-mcp
python3 -m venv .venvsource .venv/bin/activate      # Windows: .venv\Scripts\activatepip install -e .
cp .env.example .env# Edit .env: set your subscription IDs

Configure .env

bash
# Required: comma-separated subscription IDs the server may queryAZURE_ALLOWED_SUBSCRIPTIONS=sub-id-1,sub-id-2,sub-id-3
# Required: default subscription (must be in the list above)AZURE_DEFAULT_SUBSCRIPTION=sub-id-1

Test with MCP Inspector

The Inspector is a web UI that lets you call tools interactively and see raw JSON-RPC messages. Always test here before connecting to Claude Desktop.

bash
# Use the venv's python3 explicitly — the Inspector launches a subprocess# and needs the binary that has mcp + azure SDKs installed.npx @modelcontextprotocol/inspector $(which python3) -m azure_finops_mcp.server

In the Inspector UI:

  1. Verify Transport Type is STDIO
  2. Click Connect — should succeed and show "azure-finops" as the server name
  3. Navigate to Tools, click List Tools — you should see all 15 tools
  4. Try list_subscriptions first (no arguments needed)
  5. Try get_month_to_date_cost (no arguments needed — uses default sub)

Client Configuration

Find the absolute path to your venv's Python first — you'll need it in every config below:

bash
# With your venv activated:which python3# e.g. /Users/yourname/azure-finops-mcp/.venv/bin/python3

Claude Desktop

Edit claude_desktop_config.json:

OSPath
macOS~/Library/Application Support/Claude/claude_desktop_config.json
Windows%APPDATA%\Claude\claude_desktop_config.json
Linux~/.config/Claude/claude_desktop_config.json
json
{  "mcpServers": {    "azure-finops": {      "command": "/absolute/path/to/.venv/bin/python3",      "args": ["-m", "azure_finops_mcp.server"],      "env": {        "AZURE_ALLOWED_SUBSCRIPTIONS": "sub-1,sub-2,sub-3",        "AZURE_DEFAULT_SUBSCRIPTION": "sub-1",        "FINOPS_CACHE_TTL_SECONDS": "900"      }    }  }}

Restart Claude Desktop. A tool icon in the chat input confirms the server connected.


VS Code (GitHub Copilot / Agent mode)

Create .vscode/mcp.json in your workspace (or add to user settings.json under "mcp"):

json
{  "servers": {    "azure-finops": {      "type": "stdio",      "command": "/absolute/path/to/.venv/bin/python3",      "args": ["-m", "azure_finops_mcp.server"],      "env": {        "AZURE_ALLOWED_SUBSCRIPTIONS": "sub-1,sub-2,sub-3",        "AZURE_DEFAULT_SUBSCRIPTION": "sub-1",        "FINOPS_CACHE_TTL_SECONDS": "900"      }    }  }}

Requires VS Code 1.99+ with the GitHub Copilot extension. Open the Chat panel, switch to Agent mode, and the azure-finops tools will appear automatically.


Cursor

Create or edit ~/.cursor/mcp.json:

json
{  "mcpServers": {    "azure-finops": {      "command": "/absolute/path/to/.venv/bin/python3",      "args": ["-m", "azure_finops_mcp.server"],      "env": {        "AZURE_ALLOWED_SUBSCRIPTIONS": "sub-1,sub-2,sub-3",        "AZURE_DEFAULT_SUBSCRIPTION": "sub-1",        "FINOPS_CACHE_TTL_SECONDS": "900"      }    }  }}

Or add it via Cursor Settings → MCP → Add new global MCP server. Restart Cursor. The tools appear in Cursor's Agent/Composer panel.


Claude Code (CLI)

bash
claude mcp add azure-finops \  /absolute/path/to/.venv/bin/python3 \  -m azure_finops_mcp.server \  -e AZURE_ALLOWED_SUBSCRIPTIONS=sub-1,sub-2,sub-3 \  -e AZURE_DEFAULT_SUBSCRIPTION=sub-1

Remote HTTP (after deploying to Azure Container Apps)

All clients support connecting to the deployed server over HTTP — no local Python needed:

Claude Desktop / Cursor — add to the same config files above:

json
{  "mcpServers": {    "azure-finops": {      "type": "http",      "url": "https://<your-container-app-fqdn>/mcp"    }  }}

VS Code — in .vscode/mcp.json:

json
{  "servers": {    "azure-finops": {      "type": "http",      "url": "https://<your-container-app-fqdn>/mcp"    }  }}

Claude Web — Settings → Integrations → Add → https://<your-container-app-fqdn>/mcp

Example Prompts

Try these once connected:

  • "What are our allowed subscriptions?"
  • "What's our total month-to-date spend across all subscriptions?"
  • "Which 10 services cost the most on our prod subscription last month?"
  • "Break down last quarter's spend by the costcenter tag."
  • "Are any budgets close to breaching?"
  • "Show me idle resources across all our subscriptions."
  • "What does Azure Advisor recommend for cost savings?"
  • "Is VM my-analytics-vm actually being used? Check its CPU over 14 days."
  • "Compare our forecast for this month against our budgets."

Architecture

Claude Desktop ◄─┐VS Code        ◄─┤Cursor         ◄─┼──stdio / HTTP──► Azure FinOps MCP Server ◄──REST──► Azure APIsClaude Code    ◄─┤                        │Claude Web     ◄─┘                        ├── config.py          ← env + allowlist                                          ├── azure_clients.py   ← shared credential                                          ├── cache.py           ← TTL cache                                          ├── server.py          ← FastMCP + registration                                          └── tools/                                              ├── subscriptions  ← discovery                                              ├── cost           ← queries + portfolio                                              ├── budgets        ← budget status                                              ├── optimization   ← idle + advisor + metrics                                              └── forecast       ← predictions

Key design decisions

Narrow tools over flexible tools. The LLM picks among well-named tools far better than it constructs complex query objects. 15 purpose-built tools beats 3 configurable ones.

Subscription allowlist. A frozenset loaded from env. Every tool calls resolve_subscription() which refuses any ID not in the list. Prevents the LLM from querying unauthorized subscriptions — important for prompt injection defense.

Portfolio tools catch per-sub errors. When querying 5+ subscriptions, one might have different RBAC or be in a weird state. Portfolio tools (get_portfolio_*) wrap each sub in try/except so partial results are returned with errors listed separately.

Cache on Cost Management only. Cost queries are expensive and rate-limited (~30 req/min per tenant). Cost data updates hourly at best. Default 15-minute TTL trades almost nothing in freshness for significant rate-limit headroom. Resource Graph and Advisor are fast and cheap — no caching needed.

Structured returns, not prose. Tools return dicts with columns/rows/metadata. The LLM narrates them naturally. This avoids encoding English into tool responses (which makes them brittle to prompt changes).

Deploying to Azure (Remote Mode)

For team-wide access, deploy as a remote HTTP server:

  1. Transport swap in server.py:

    python
    mcp.run(transport="streamable-http", host="0.0.0.0", port=8000)
  2. Dockerfile:

    dockerfile
    FROM python:3.12-slimWORKDIR /appCOPY . .RUN pip install --no-cache-dir -e .CMD ["azure-finops-mcp"]
  3. Deploy to Azure Container Apps with a user-assigned managed identity.

  4. Grant RBAC to the managed identity (same 3 roles: Cost Management Reader, Reader, Monitoring Reader) on each subscription.

  5. Add auth via APIM or Azure Front Door + Entra ID. MCP supports OAuth for remote servers.

  6. DefaultAzureCredential picks up the managed identity automatically — no code changes needed.

Troubleshooting

ProblemFix
DefaultAzureCredential auth errorsRun az login and verify with az account show
429 throttling on Cost ManagementIncrease FINOPS_CACHE_TTL_SECONDS
Empty budget listBudgets must exist in the portal — the API doesn't create them
find_idle_resources errorsYou need Reader RBAC at subscription scope
Inspector "Connection Error"Use absolute path to venv's python3 in Command field
print() breaks the serverNever use print() in MCP tools — it corrupts the stdio JSON stream. Use logging instead

来源:README.md,提交 ef5b83b

工具

0
SourceWeft 尚未在沙箱中启动过该软件包,因此其工具未知。

版本历史

1
  1. v0.1.1最新Sep 16, 2026

评分

已满足适用检查项的 50%

该评分衡量此收录条目的完整程度,依据注册中心条目、端点与公开来源计算得出。它不是对服务器本身的评价,也不表示服务器安全或当前可用:可连通性是带日期的检查结果,评分也不包含安装量或用户评价。

  • 近 30 天内可连通25 分

    请保持端点能够响应 MCP 握手;SourceWeft 每 30 天探测一次。

  • 已声明认证方式10 分

    请在注册中心条目中声明凭据请求头,或保持端点能够响应探测,以便判定其认证方式。

  • 已列出工具15 分

    请让服务器在无凭据时响应 tools/list,或发布可在沙箱中无凭据启动的软件包。

  • 描述必需15 分
  • 图标10 分
  • 文档15 分
  • 许可证10 分