内容
# Azure MCP via `azd` 扩展
[查看仓库 POC](https://github.com/wbreza/azd-azure-mcp)
该仓库展示了一种模块化、可扩展的 Azure 自动化和资源管理方法,使用 Azure Developer CLI (`azd`) 和模型上下文协议 (MCP)。根 `mcp.azure` 扩展提供了一个统一的 MCP 服务器,能够动态发现、安装并将请求委派给特定提供者的 MCP 扩展(如存储、密钥保管库、资源和 azd)。这种架构使得对 Azure 资源和服务的实时、程序化访问成为可能,支持 LLMs/agents 的迭代学习和工具发现,并允许团队独立构建、发布和更新扩展,而无需对根服务器进行更改。扩展可以用任何语言实现,并按需加载,确保在自动化和 AI 场景中提供最小且相关的工具表面。
## 扩展示例
| 扩展 | 描述 |
|---------------------|---------------------------------------------------------------------------------------------------|
| `mcp.account` | 用于 Azure 账户管理的扩展 MCP 服务器 |
| `mcp.azd` | 用于 `azd` CLI 的扩展 MCP 服务器 |
| `mcp.azure` | 托管 Azure MCP 服务器的根扩展,支持动态发现 |
| `mcp.azure.csharp` | 托管 Azure MCP 服务器的根扩展,支持动态发现(C# 版本,带有 MCP 采样) |
| `mcp.cosmos` | 用于 Azure Cosmos DB 资源的扩展 MCP 服务器 |
| `mcp.keyvault` | 用于 Azure KeyVault 资源的扩展 MCP 服务器 |
| `mcp.resource` | 用于通用 Azure 资源的扩展 MCP 服务器 |
| `mcp.roles` | 用于 Azure 角色分配和 RBAC 的扩展 MCP 服务器 |
| `mcp.servicebus` | 用于 Azure Service Bus 资源的扩展 MCP 服务器 |
| `mcp.storage` | 用于 Azure 存储账户的扩展 MCP 服务器(建模为远程 MCP 服务器) |
## 亮点
- 在 VS Code 中进行单一服务器注册
- 服务器中的单一工具 "azure"
- 根工具通过 `azd` 扩展发现功能
- 扩展由根服务器动态安装和调用
- 每个 `azd` 扩展(如 "storage"、"keyvault" 等)都托管其自己的 MCP 服务器
- 根服务器充当 MCP 服务器和客户端,并动态分发调用到子服务器
- Azure 团队可以在不需要对根扩展进行任何发布或更改的情况下构建、发布和迭代
- 扩展可以用任何语言构建
## Azure Developer CLI (`azd`)
- 单一二进制可执行文件
- 解压后约 30MB
- 支持 Windows、MacOS 和 Linux,支持 AMD64 和 ARM64
- 可轻松嵌入容器中(例如 Azure Cloud Shell、vscode.dev/azure)
- 可通过流行的包管理器安装,包括 Choco、Winget、Homebrew、cURL
- 可以轻松添加 `npx` 支持。
- **安全性与认证:** 使用 Azure 认证(例如 Azure CLI 登录、服务主体、托管身份);扩展继承此上下文。
- **可扩展性:** 支持官方和自定义扩展,通过公共或私有源分发。
- **版本兼容性:** 扩展应针对兼容版本的 `azd`;根服务器可以检查版本不匹配。
### 性能
目前没有针对 MCP 场景的深入性能指标。
- 单一 `azure` 工具,无需工具过载以消耗 LLMs/agents
- `azd` MCP 扩展按需懒加载,无启动开销
- 仅加载所需的扩展,最小化内存和 CPU 使用
- 安装新扩展仅需几秒钟
- 扩展小至 5MB(解压后 7MB)
- 根服务器可以检查扩展更新并自动更新客户端
- 随着更多扩展的添加,架构能够良好扩展,因为未使用的扩展不会影响基线性能
- 根服务器启动迅速;仅在首次使用新扩展时会有额外延迟
### 部署
MCP 贡献者可以利用 [`azd` 扩展框架](https://github.com/Azure/azure-dev/blob/main/cli/azd/docs/extension-framework.md) 来构建、打包和发布扩展到 `azd` 扩展源。
- **CI/CD 集成:** MCP 扩展可以作为 CI/CD 管道的一部分构建和发布;建议进行自动化测试。
- **更新策略:** 根服务器和扩展可以独立更新;根服务器可以检查并提示扩展更新。
- **多平台支持:** `azd` 和扩展支持 Windows、MacOS 和 Linux;部署工件应为所有目标平台构建。
MCP 扩展可以托管在官方 `azd` 扩展源上,或可以驻留在本地文件或公开可访问的 HTTPS 端点中的自定义扩展源。
## 动态发现与 "学习" 模式
根 `mcp.azure` 服务器使用动态发现机制在运行时枚举并暴露所有可用的 Azure MCP 扩展。当服务器启动时,或者当代理或用户请求 "学习" 可用工具时,服务器:
- 调用 `azd ext list --tags azure,mcp` 以发现所有已安装和可用的 MCP 扩展。
- 按需动态安装任何缺失的扩展。
- 仅在需要时启动每个提供者扩展的 MCP 服务器。
- 维护正在运行的工具客户端的缓存,以避免冗余启动。
### "学习" 模式与 Azure 工具参数
"学习" 模式是 LLMs/agents 和用户探索可用功能的核心特性。单一的 `azure` 工具暴露了一组灵活的参数,使得动态发现和调用所有可用 Azure MCP 扩展功能成为可能:
- `intent` (字符串):代理/用户想要执行的高层操作或场景(例如 "deploy"、"list"、"delete")。
- `tool` (字符串):要调用的提供者扩展或子工具的名称(例如 "storage"、"keyvault"、"resource"、"azd")。
- `command` (字符串):在所选工具内要执行的具体命令或操作(例如 "list-containers"、"delete-blob")。
- `parameters` (对象):命令特定参数的字典(例如存储账户名称、容器名称、Blob 名称等)。
- `learn` (布尔值):如果设置为 `true`,则触发 "学习" 模式,返回可用工具及其模式的列表。可以递归使用以深入到子工具和命令中。
#### 预期使用周期
1. **发现:** 代理或用户可以始终调用相同的 `azure` 工具,使用 `learn` 参数实时发现可用的子工具和命令。例如:
- `learn: true`,未指定工具,返回可用工具的顶层列表(例如 storage、keyvault、resource、azd 等)。
- `learn: true, tool: "storage"` 返回存储扩展支持的命令和参数列表,使用相同的 MCP 工具模式。
2. **选择:** 代理可以推理可用的工具和命令,并选择适当的 `tool`、`command` 和 `parameters` 以执行所需操作。
3. **调用:** 代理通过调用 `azure` 工具并传入所选参数来执行所选操作。
4. **迭代:** 在任何时候,代理都可以重新调用 `learn` 以进一步探索或适应新功能,支持强大、迭代和友好的自动化。
该响应使用与 MCP 协议本身相同的 **MCP 工具列表模式**,确保:
- 一致性:工具列表和模式始终是最新的且可机器读取。
- 迭代探索:代理可以递归调用 `learn`,指定工具名称以深入其支持的命令和参数。
- 自描述:系统完全自描述,使代理能够以编程方式推理和选择工具。
这种方法最大化了可发现性、灵活性和代理推理,使其非常适合 LLM 驱动的自动化和交互场景。
### 采样
采样是一个强大的 MCP 特性,允许服务器通过客户端请求 LLM 完成,从而实现复杂的代理行为,同时保持安全性和隐私。
采样的工作原理:
1. 服务器向客户端发送 `sampling/createMessage` 请求。
2. 客户端审核请求并可以修改它。
3. 客户端从 LLM 中进行采样。
4. 客户端审核完成结果。
5. 客户端将结果返回给服务器。
这种人机协作设计确保用户对 LLM 看到和生成的内容保持控制。(注意:此功能尚未在所有 MCP 客户端中支持。)
目前,采样在 MCP 实现中尚未广泛采用,但随着支持的增加,"学习" 模式和其他代理工作流可能会演变为利用采样以实现更强大、安全和交互的自动化场景。
这种方法使系统高度可发现且友好,支持强大、实时和迭代的自动化场景。
## 架构与流程(时序图)
以下时序图展示了动态、按需扩展管理和调用调度模型中的三个主要流程:
```mermaid
sequenceDiagram
participant User as LLM/Agent or User
participant AzureMCP as azd mcp azure (根 MCP 服务器)
participant azd as azd CLI
participant Provider as azd mcp 扩展 (例如 mcp.storage)
participant LLM as LLM (例如 OpenAI GPT)
%% 1. 根学习
Note over User,AzureMCP: 1. 根学习(发现顶层工具)
User->>AzureMCP: 调用 (learn: true)
AzureMCP->>azd: azd ext list --tags azure,mcp
azd-->>AzureMCP: 扩展元数据(提供者列表)
AzureMCP->>User: 工具列表(顶层工具)
%% 2. 工具学习
Note over User,AzureMCP: 2. 工具学习(发现工具命令/参数)
User->>AzureMCP: 调用 (learn: true, tool: "storage")
AzureMCP->>AzureMCP: 检查工具客户端缓存
alt 未缓存
AzureMCP->>azd: azd ext install <provider>
azd-->>AzureMCP: 安装结果
AzureMCP->>azd: <provider> 服务器启动
azd-->>AzureMCP: 提供者 MCP 服务器已启动
AzureMCP->>AzureMCP: 创建 MCP 客户端
end
AzureMCP->>Provider: 调用 (learn: true)
Provider-->>AzureMCP: 工具模式(命令/参数)
AzureMCP->>User: 工具模式(命令/参数)
%% 3. 工具调用
Note over User,AzureMCP: 3. 工具调用(执行命令)
User->>AzureMCP: 调用 (tool: "storage", command: "delete-blob", parameters)
AzureMCP->>AzureMCP: 检查工具客户端缓存
alt 未缓存
AzureMCP->>azd: azd ext install <provider>
azd-->>AzureMCP: 安装结果
AzureMCP->>azd: <provider> 服务器启动
azd-->>AzureMCP: 提供者 MCP 服务器已启动
AzureMCP->>AzureMCP: 创建 MCP 客户端
end
AzureMCP->>Provider: 调用 (command: "delete-blob", parameters)
Provider-->>AzureMCP: 结果
AzureMCP-->>User: 结果
%% 4. 工具/命令选择的内部采样
Note over AzureMCP: 4. 内部采样(AzureTool 利用采样从意图中选择工具/命令)
User->>AzureMCP: 调用 (intent: "delete a blob", learn: false)
AzureMCP->>AzureMCP: 检测意图,未指定工具/命令
AzureMCP->>LLM: 采样请求("哪个工具与此意图匹配?")
LLM-->>AzureMCP: 工具名称(例如 "storage")
AzureMCP->>LLM: 采样请求("哪个命令和参数与此意图匹配?")
LLM-->>AzureMCP: 命令名称和参数(例如 "delete-blob",{ ... })
AzureMCP->>Provider: 调用 (command: "delete-blob", parameters)
Provider-->>AzureMCP: 结果
AzureMCP-->>User: 结果(单次往返)
```
## 设计权衡:动态扩展与单体服务器
该项目使用 **动态扩展模型**:根 `mcp.azure` 服务器按需发现、安装和启动提供者 MCP 扩展。这与 **单体模型** 相对立,后者将所有 MCP 工具编码、打包并加载到根服务器中。
**动态扩展模型(当前):**
- 扩展独立开发、发布和更新。
- 新工具/扩展无需对根服务器进行更改。
- 仅加载所需的扩展,减少资源使用和启动时间。
- 允许团队使用任何语言或技术栈。
- 由于额外的往返:发现、可能的安装和服务器启动,首次使用延迟略高。后续调用由于缓存而快速。
- 保持工具表面最小且与 LLMs/agents 相关,降低工具膨胀、混淆或在初始工具选择时的延迟风险。
**单体模型(所有工具在根中):**
- 所有工具始终可用,无需安装/启动延迟。
- 架构更简单,但所有工具必须用根服务器的语言编码。
- 任何更新或新工具都需要完整的根服务器发布。
- 二进制文件更大,资源使用更高。
- 可能一次暴露大量工具,这可能在初始工具选择时导致 LLMs 或 agents 膨胀/混淆/延迟,尤其是随着工具数量的增加。
这种动态方法最大化了灵活性、可扩展性和团队自主性,代价是稍微增加的复杂性和首次使用延迟,同时也帮助 LLMs/agents 专注于相关且可管理的工具集。
## 比较:动态工具通知与单一 "Azure" 工具与学习
[查看 GitHub 上的动态代理方法分支](https://github.com/wbreza/azd-azure-mcp/tree/proxy)
当前架构的另一种替代方法是在运行时动态将工具添加到 MCP 服务器,并向 LLM/agent 发送 `tools/list_changed` 通知。该通知告知代理新工具可用,允许其根据需要调用这些工具。
**然而,在实践中,这种方法并未按预期工作:**
- 尽管发送了 `tools/list_changed` 通知,但代理在当前任务或推理周期内并未利用任何新工具。
- 代理仅在当前请求完成后才意识到并使用新工具,并在发起新的类似请求时使用。
- 这导致体验不够流畅和不够代理化,因为代理无法立即在工作流中利用新功能。
**相比之下,单一的 `azure` 工具与动态学习能力证明更为有效:**
- 代理始终可以调用相同的 `azure` 工具,使用 "学习" 模式实时发现可用的子工具和命令。
- 代理能够构建对同一 `azure` 工具的额外调用,使用适当的 `tool`、`command` 和 `parameters`,然后由根服务器正确处理和代理。
- 该模型支持强大、迭代和友好的自动化,因为代理可以以编程方式推理和选择工具,而无需等待新的推理周期或外部通知。
连接信息
猜你喜欢
文件系统操作
Node.js MCP服务器,用于文件系统操作,支持动态访问控制。
Git
一个用于Git自动化和交互的模型上下文协议服务器。
Everything
模型上下文协议服务器
OpenInsider-MCP
将openinsider.com暴露给任何MCP兼容客户端的MCP服务器。
SharpClawCode
C# coding-agent harness (.NET 10, Microsoft Agent Framework) — sessions,...
tmux-bridge-mcp
用于跨面板 AI 代理通信的独立 MCP 服务器,通过 tmux 实现。让 Claude Code、Gemini CLI、Codex 和 Kimi...