关于 Azure FinOps MCP Server
Azure FinOps MCP Server 让 LLM 客户端查询多个 Azure 订阅的成本、预算、预测和资源优化数据。它提供专用查询工具,并支持跨订阅汇总及订阅 ID 白名单限制。
主要功能
- 01按日期、服务、资源组、区域或标签分析成本
- 02跟踪单个订阅及整体预算
- 03预测跨订阅的月末支出
- 04查找闲置资源并查看 Advisor 建议
- 05查看 VM CPU 使用率以辅助规格调整
适用场景
- 01查看多个订阅的本月支出
- 02按服务或标签拆分成本
- 03查找闲置资源和潜在节省空间
- 04比较月末支出预测与预算
MCP 相关
通过 stdio 或 HTTP 向 MCP 客户端提供 15 个 Azure FinOps 专用查询工具。可查询的订阅仅限配置的 ID 白名单。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
uvx azure-finops-mcpAZURE_ALLOWED_SUBSCRIPTIONSComma-separated list of Azure subscription IDs this server may queryAZURE_DEFAULT_SUBSCRIPTIONDefault subscription ID used when none is specified in a query (must be in AZURE_ALLOWED_SUBSCRIPTIONS)FINOPS_CACHE_TTL_SECONDSTTL for cost query cache in seconds (default: 900)本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。
工具
本地服务需要在你的电脑上运行后才能读取工具,维护者暂未提供工具列表。
详细介绍
Azure FinOps MCP 服务
一个 MCP 服务,可让大模型客户端(Claude Desktop、Claude Code、VS Code、Cursor) 以对话方式访问 Azure 成本分析、预算跟踪、成本预测和资源优化,覆盖多个订阅。
工具
发现
| 工具 | 用途 |
|---|---|
list_subscriptions | 列出获准访问的订阅及其易识别名称 |
成本分析
| 工具 | 用途 |
|---|---|
get_cost_summary | 指定日期范围内的总成本(单个订阅) |
get_cost_by_dimension | 按服务 / RG / 位置 / 计量项划分的成本明细 |
get_cost_by_tag | 按标记值分组的成本(分摊 / 计费分摊) |
get_month_to_date_cost | 本月迄今的支出(单个订阅) |
get_portfolio_month_to_date_cost | 所有订阅本月迄今的支出 |
预算
| 工具 | 用途 |
|---|---|
get_budget_status | 单个订阅的预算使用情况 |
get_portfolio_budget_status | 所有订阅的预算状态 |
优化
| 工具 | 用途 |
|---|---|
find_idle_resources | 未附加的磁盘、闲置的 IP / NIC、已停止的 VM |
find_idle_resources_portfolio | 所有订阅中的闲置资源 |
get_advisor_recommendations | Azure Advisor 成本优化建议及年度节省金额 |
get_vm_utilization | 用于验证规格调整是否合理的 CPU 统计数据 |
成本预测
| 工具 | 用途 |
|---|---|
forecast_month_end_spend | 预测月末成本(单个订阅) |
forecast_portfolio_month_end_spend | 预测所有订阅的月末成本 |
快速安装
pip install azure-finops-mcp
然后使用安装后的命令将其添加到 MCP 客户端配置中,无需克隆:
{
"mcpServers": {
"azure-finops": {
"command": "azure-finops-mcp",
"env": {
"AZURE_ALLOWED_SUBSCRIPTIONS": "sub-id-1,sub-id-2",
"AZURE_DEFAULT_SUBSCRIPTION": "sub-id-1"
}
}
}
}
请参阅下方的客户端配置部分,了解各客户端的配置文件位置。
前提条件
- Python 3.11+
- 已安装 Azure CLI 并完成登录(
az login)
Azure RBAC 权限
运行此服务的身份(你的用户、服务主体或托管身份) 需要在你想查询的每个订阅上分配以下三个角色:
| 角色 | 用途 |
|---|---|
| Cost Management Reader | 成本分析、成本预测、预算查询 |
| Reader | 通过 Resource Graph 获取资源清单 |
| Monitoring Reader | 通过 Azure Monitor 获取 VM 利用率指标 |
通过 Azure CLI 分配
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
对 AZURE_ALLOWED_SUBSCRIPTIONS 中列出的每个订阅重复执行。
本地开发(你自己的用户)
az login
az account set --subscription "<your-subscription-id>"
# Check your object ID
az ad signed-in-user show --query id -o tsv
如果你是订阅所有者或参与者,你的用户已拥有这些角色。 否则,请让 Azure 管理员为你分配这些角色。
托管身份(Container Apps 部署)
使用 deploy.sh 部署后,脚本会自动在每个允许的订阅上,
为 Container App 的系统分配托管身份分配这三个角色。
无需凭据或机密——DefaultAzureCredential 会在运行时自动获取
托管身份。
安装
git clone <your-repo-url> azure-finops-mcp
cd azure-finops-mcp
python3 -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e .
cp .env.example .env
# Edit .env: set your subscription IDs
配置 .env
# Required: comma-separated subscription IDs the server may query
AZURE_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
使用 MCP Inspector 测试
Inspector 是一个 Web UI,可让你交互式调用工具并查看 原始 JSON-RPC 消息。连接 Claude Desktop 之前,请务必先在此处测试。
# 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
在 Inspector UI 中:
- 确认传输类型为 STDIO
- 点击 Connect——应成功连接,并显示服务器名称“azure-finops”
- 转到 Tools,点击 List Tools——应能看到全部 15 个工具
- 先试用
list_subscriptions(无需参数) - 再试用
get_month_to_date_cost(无需参数——使用默认订阅)
客户端配置
先找到虚拟环境中 Python 的绝对路径——以下每份配置都需要用到:
# With your venv activated:
which python3
# e.g. /Users/yourname/azure-finops-mcp/.venv/bin/python3
Claude Desktop
编辑 claude_desktop_config.json:
| 操作系统 | 路径 |
|---|---|
| macOS | ~/Library/Application Support/Claude/claude_desktop_config.json |
| Windows | %APPDATA%\Claude\claude_desktop_config.json |
| Linux | ~/.config/Claude/claude_desktop_config.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"
}
}
}
}
重启 Claude Desktop。聊天输入框中出现工具图标,即表示服务已连接。
VS Code(GitHub Copilot / Agent 模式)
在工作区中创建 .vscode/mcp.json(或在用户 settings.json 的 "mcp" 下添加):
{
"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"
}
}
}
}
需要 VS Code 1.99+ 和 GitHub Copilot 扩展。打开聊天面板,切换到 Agent 模式,azure-finops 工具便会自动显示。
Cursor
创建或编辑 ~/.cursor/mcp.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"
}
}
}
}
或者通过 Cursor Settings → MCP → Add new global MCP server 添加。 重启 Cursor。工具会显示在 Cursor 的 Agent/Composer 面板中。
Claude Code(CLI)
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
远程 HTTP(部署到 Azure Container Apps 后)
所有客户端都支持通过 HTTP 连接到已部署的服务 — 无需本地安装 Python:
Claude Desktop / Cursor — 添加到上述相同的配置文件中:
{
"mcpServers": {
"azure-finops": {
"type": "http",
"url": "https://<your-container-app-fqdn>/mcp"
}
}
}
VS Code — 在 .vscode/mcp.json 中:
{
"servers": {
"azure-finops": {
"type": "http",
"url": "https://<your-container-app-fqdn>/mcp"
}
}
}
Claude Web — Settings → Integrations → Add → https://<your-container-app-fqdn>/mcp
示例提示词
连接后,试试这些提示词:
- “我们允许使用哪些订阅?”
- “我们所有订阅本月至今的总支出是多少?”
- “上个月,我们 prod 订阅中成本最高的 10 项服务是哪些?”
- “按
costcenter标签细分上季度的支出。” - “有哪些预算即将超支?”
- “显示我们所有订阅中的闲置资源。”
- “Azure Advisor 推荐了哪些节省成本的方法?”
- “VM
my-analytics-vm实际上有人在用吗?检查其过去 14 天的 CPU 使用情况。” - “比较本月的支出预测与预算。”
架构
Claude Desktop ◄─┐
VS Code ◄─┤
Cursor ◄─┼──stdio / HTTP──► Azure FinOps MCP Server ◄──REST──► Azure APIs
Claude 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
关键设计决策
使用范围明确的工具,而非灵活的工具。 与构造复杂的查询对象相比,大模型更擅长从命名清晰的工具中进行选择。15 个专用工具胜过 3 个可配置工具。
订阅允许列表。 从环境变量加载一个 frozenset。每个工具都会调用 resolve_subscription(),拒绝任何不在列表中的 ID。这可以防止大模型查询未经授权的订阅 — 对防御提示词注入至关重要。
组合工具逐个捕获订阅错误。 查询 5 个以上订阅时,其中某个订阅可能有不同的 RBAC 配置,或处于异常状态。组合工具(get_portfolio_*)会用 try/except 包装每个订阅,因此即使只获取到部分结果,也会返回结果,并单独列出错误。
仅缓存 Cost Management。 成本查询耗时较长且受速率限制(每个租户约 30 个请求/分钟)。成本数据最多每小时更新一次。默认的 15 分钟 TTL 几乎不影响数据新鲜度,却能显著缓解速率限制压力。 Resource Graph 和 Advisor 速度快、成本低 — 无需缓存。
返回结构化数据,而非散文。 工具返回包含列、行和元数据的字典。大模型会自然地将其转述。这样可以避免将英文编码到工具响应中(否则提示词变更时容易出错)。
部署到 Azure(远程模式)
如需团队共同访问,请将其部署为远程 HTTP 服务:
-
切换
server.py中的传输方式:mcp.run(transport="streamable-http", host="0.0.0.0", port=8000) -
Dockerfile:
FROM python:3.12-slim WORKDIR /app COPY . . RUN pip install --no-cache-dir -e . CMD ["azure-finops-mcp"] -
使用用户分配的托管标识部署到 Azure Container Apps。
-
为托管标识授予 RBAC 权限(相同的 3 个角色:Cost Management Reader、 Reader、Monitoring Reader),并应用到每个订阅。
-
通过 APIM 或 Azure Front Door + Entra ID 添加身份验证。 MCP 支持远程服务使用 OAuth。
-
DefaultAzureCredential会自动获取托管标识 — 无需更改代码。
故障排除
| 问题 | 解决方法 |
|---|---|
DefaultAzureCredential 身份验证错误 | 运行 az login,并通过 az account show 验证 |
| Cost Management 返回 429 限流错误 | 增大 FINOPS_CACHE_TTL_SECONDS |
| 预算列表为空 | 门户中必须已存在预算 — API 不会创建预算 |
find_idle_resources 错误 | 你需要订阅范围的 Reader RBAC 权限 |
| Inspector 显示“Connection Error” | 在 Command 字段中使用 venv 的 python3 的绝对路径 |
print() 导致服务出错 | 切勿在 MCP 工具中使用 print() — 它会破坏 stdio JSON 流。请改用 logging |
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。