Files
awoooi/docs/adr/ADR-015-mcp-modular-architecture.md
OG T 8a163609bf docs(adr): 更新 ADR-006/009/015 狀態
ADR-015: 標記為「已實作」 (Phase 16 R1 完成)
ADR-009: 標記為「已實作」 (Phase 9.1-9.5 全部完成)
ADR-006: 新增智能路由整合章節 (Phase 13.3)

首席架構師 ADR 審計 P0/P1 完成

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-03-26 10:45:29 +08:00

157 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ADR-015: MCP 模組化架構重構
| 欄位 | 值 |
|------|-----|
| **狀態** | **已實作** ✅ |
| **決策日期** | 2026-03-26 |
| **實作完成** | 2026-03-26 (Phase 16 R1) |
| **決策者** | 統帥 + 首席架構師 |
| **觸發原因** | Code Review 發現嚴重模組化違規 |
---
## 背景
Phase 13.2 實作 MCP Tool 整合時,為了快速交付,在 `mcp_bridge.py` 直接 import services 層,違反了 leWOOOgo 積木化原則。
### 違規清單
| 位置 | 違規 |
|------|------|
| mcp_bridge.py:570 | `from src.services.executor import get_executor` |
| mcp_bridge.py:655 | `from src.services.signoz_client import get_signoz_client` |
| mcp_bridge.py:734 | `from src.services.approval_db import ...` |
| mcp_bridge.py:738 | `from src.services.incident_service import get_incident_service` |
### 違反的鐵律
1. **Interface 先行** - 無 ABC 定義
2. **禁止跨模組非法引用** - plugins → services 直接 import
3. **模組間透過 Public API 溝通** - 直接呼叫具體實作
---
## 決策
### 架構重構
```
apps/api/src/plugins/mcp/
├── __init__.py
├── interfaces.py # MCPToolProvider ABC (新增)
├── mcp_bridge.py # 透過 DI 注入 providers (重構)
├── registry.py # Provider 註冊中心 (新增)
└── providers/ # 具體實作 (新增)
├── __init__.py
├── k8s_provider.py
├── signoz_provider.py
└── database_provider.py
```
### Interface 定義
```python
from abc import ABC, abstractmethod
from typing import Any
class MCPToolProvider(ABC):
"""MCP Tool Provider 抽象介面"""
@property
@abstractmethod
def name(self) -> str:
"""Provider 名稱 (如 'kubernetes', 'signoz')"""
pass
@abstractmethod
async def list_tools(self) -> list[dict]:
"""列出可用工具"""
pass
@abstractmethod
async def execute(self, tool_name: str, parameters: dict) -> Any:
"""執行工具"""
pass
```
### DI 注入模式
```python
# registry.py
class ProviderRegistry:
_providers: dict[str, MCPToolProvider] = {}
@classmethod
def register(cls, provider: MCPToolProvider) -> None:
cls._providers[provider.name] = provider
@classmethod
def get(cls, name: str) -> MCPToolProvider | None:
return cls._providers.get(name)
# mcp_bridge.py (重構後)
async def call_tool(self, server_name: str, tool_name: str, parameters: dict):
provider = ProviderRegistry.get(server_name)
if not provider:
raise ValueError(f"Unknown provider: {server_name}")
return await provider.execute(tool_name, parameters)
```
---
## 優點
1. **符合 leWOOOgo 積木化** - Interface 先行DI 注入
2. **可測試性** - 可輕鬆 Mock Provider
3. **可擴展性** - 新增 Provider 無需修改 mcp_bridge.py
4. **單一職責** - 每個 Provider 只負責一個領域
---
## 缺點
1. **重構工時** - 需要 2-3 天
2. **檔案數增加** - 從 1 個變 6+ 個
3. **學習曲線** - 新成員需了解 DI 模式
---
## 實作計畫
| 步驟 | 內容 | 工時 |
|------|------|------|
| 1 | 建立 interfaces.py | 30min |
| 2 | 建立 registry.py | 30min |
| 3 | 建立 providers/ 目錄 | 15min |
| 4 | 實作 k8s_provider.py | 1h |
| 5 | 實作 signoz_provider.py | 1h |
| 6 | 實作 database_provider.py | 1h |
| 7 | 重構 mcp_bridge.py | 2h |
| 8 | 更新測試 | 1h |
| 9 | Code Review | 1h |
| **總計** | | **8-9h** |
---
## 實作驗收 (2026-03-26)
| 項目 | 狀態 |
|------|------|
| interfaces.py | ✅ 已建立 MCPToolProvider ABC |
| registry.py | ✅ 已建立 ProviderRegistry |
| k8s_provider.py | ✅ 已實作 |
| signoz_provider.py | ✅ 已實作 |
| database_provider.py | ✅ 已實作 |
| mcp_bridge.py 重構 | ✅ 透過 DI 注入 |
| 測試驗證 | ✅ 28/28 通過 |
**驗收人**: 首席架構師 (Phase 16 R1.3 審查)
---
## 相關文件
- [feedback_modular_architecture.md](../../memory/feedback_modular_architecture.md)
- [feedback_modular_core_spirit.md](../../memory/feedback_modular_core_spirit.md)
- [ADR-003: leWOOOgo 模組化架構](ADR-003-lewooogo-module-architecture.md)