事件知識圖譜 MCP Server
by ianchu32123
README.md
# 事件知識圖譜 MCP Server(Incident Knowledge Graph)
以 **MCP(stdio)** 對外提供的、以事件(incident)為中心的知識圖譜,可供任何相容
MCP 的 client 使用(本專案以 **Codex CLI** 與 **OpenCode** 為目標)。它是整個
SRE × MCP 架構中「可寫入、可完整測試」的核心:負責保存那些 beever-atlas MCP 介面
本身無法保存的觀測訊號與 **Atlas 永久座標**,讓上層 agent 在查詢時能把事件與對話
內容關聯起來。
> 設計原則:**不把 Atlas 內容複製進來。** 我們只存**指標(pointer)**
> (`channel_id` + 永久 `message_id` + `url`),避免產生重複的真實來源。
本 repo **只**實作 KG server(見 spec 第 0 節)。真實的 Atlas / Prometheus / DB2
client、signature 的內容(門檻)、JSON 以外的儲存後端、MCP gateway 等,皆為整合
擴充點(spec 第 10 節),不在此實作。
## 文件導覽
| 文件 | 內容 |
| ---- | ---- |
| [SPEC_knowledge_graph_mcp.md](SPEC_knowledge_graph_mcp.md) | **需求規格**:資料模型、工具規格、驗證規則、驗收標準 |
| [NEXT_STEPS.md](NEXT_STEPS.md) | 安裝說明、後續待確認事項、注意事項 |
| [skills/mmdb-troubleshooting/SKILL.md](skills/mmdb-troubleshooting/SKILL.md) | MMDB activelog / busy-ratio 排障手冊(規則) |
| 本檔 README | 安裝、設定、工具清單、專案結構 |
## 環境需求
- Python 3.11+
## 安裝
```bash
# 於專案根目錄
python -m venv .venv
# Windows PowerShell: .venv\Scripts\Activate.ps1
# macOS/Linux: source .venv/bin/activate
pip install -e ".[dev]"
```
## 設定
所有設定皆由環境變數驅動(見 `.env.example`),程式碼與 repo 內不寫死任何真實環境資訊。
| 變數 | 預設值 | 意義 |
| -------------- | -------------------- | ------------------------ |
| `KG_DATA_PATH` | `./data/graph.json` | JSON 圖譜的持久化路徑 |
資料檔於首次寫入時建立,採用原子寫入(temp 檔 + rename),寫入中途崩潰也不會毀損
既有資料。
## 執行
```bash
kg-mcp-server # console 進入點(以 stdio 提供服務)
# 或
python -m kg_server.server
```
此 server 走 stdio,設計上由 MCP host 啟動,而非互動式使用。
## 註冊到 MCP client
本 server 走標準 MCP stdio 協定,任何相容 client 都能啟動它。建議直接指定 venv 的
Python(當 `kg-mcp-server` 不在 `PATH` 時最穩)。
### Codex CLI
加入 `~/.codex/config.toml`:
```toml
[mcp_servers.incident-knowledge-graph]
command = "C:\\path\\to\\tsmc\\.venv\\Scripts\\python.exe"
args = ["-m", "kg_server.server"]
env = { KG_DATA_PATH = "C:\\path\\to\\tsmc\\data\\graph.json" }
```
(若 `kg-mcp-server` 已在 `PATH`,也可用 `command = "kg-mcp-server"`、`args = []`。)
### OpenCode
加入 OpenCode 設定檔(專案根目錄的 `opencode.json`,或全域的
`~/.config/opencode/opencode.json`):
```json
{
"$schema": "https://opencode.ai/config.json",
"mcp": {
"incident-knowledge-graph": {
"type": "local",
"command": [
"C:\\path\\to\\tsmc\\.venv\\Scripts\\python.exe",
"-m",
"kg_server.server"
],
"environment": { "KG_DATA_PATH": "C:\\path\\to\\tsmc\\data\\graph.json" },
"enabled": true
}
}
}
```
重啟 client 後,KG 工具就會出現在其 MCP 工具清單中。
## 多 MCP server 協作(方案 A)
本 server 是 MCP **server**,不會主動去呼叫別的 server。要整合 Grafana / MariaDB
等資料源,標準做法是**在 client 層並列掛載多個 server**,由 agent 自己編排跨源查詢:
```
Codex CLI / OpenCode(agent = MCP client)
├── incident-knowledge-graph(本專案) 寫入事件、查因果鏈、存 Teams 座標
├── grafana(官方 mcp-grafana) 跑 PromQL、查 Loki logs、dashboard
└── mariadb(官方 MariaDB/mcp) 唯讀 SQL、查 schema
```
**分工原則:讀在別人,寫在我們。** Grafana / MariaDB 負責讀取現場資料;本 server 負責
把「判讀後的結論」沉澱成可累積、可回溯的知識圖譜。
可直接套用的設定範例:
- Codex CLI → [`examples/codex-config.toml`](examples/codex-config.toml)
- OpenCode → [`examples/opencode.json`](examples/opencode.json)
外部 server 安裝方式:
| Server | 安裝 | 需要的認證 |
| ------ | ---- | ---------- |
| [mcp-grafana](https://github.com/grafana/mcp-grafana) | `go install github.com/grafana/mcp-grafana/cmd/mcp-grafana@latest` 或 `docker pull grafana/mcp-grafana` | `GRAFANA_URL` + service account token |
| [MariaDB/mcp](https://github.com/mariadb/mcp) | 見其 README | 連線資訊(**請用唯讀帳號**) |
### 典型的跨 server 排障流程
agent 在一次對話中會這樣串接(括號內是它呼叫的 server):
1. 「正式機昨天下午怪怪的」→ `resolve_alias("正式機")` **(KG)**
→ 得知 canonical 是 `MMDB`、Prometheus instance 是 `mmdb-prod-01:9104`
2. `query_prometheus("mmdb_busy_ratio{...}")` **(Grafana)** → 撈出指標曲線
3. 判讀出異常區段 → `create_incident(system="MMDB", slug_hint="busy_ratio", ...)` **(KG)**
→ 自動建立 `AFFECTS` 關係
4. `record_signature_match(...)` **(KG)** → 掛上 `mmdb.busy_ratio.sustained`
5. `incident_time_window(...)` **(KG)** → 取得時間窗
6. 用該時間窗查 Teams/Atlas → `attach_atlas_reference(...)` **(KG)** 存永久座標
7. 需要細看資料庫狀態時 → 唯讀 SQL **(MariaDB)** → 結論寫回 `add_observation(...)` **(KG)**
下次再遇到類似狀況,`find_incidents` / `trace_incident_chain` 就能直接調出歷史情境,
不必再人工翻聊天紀錄。
## 工具(Tools)
寫入類:
- `upsert_system(name, aliases=[], labels={})` — 建立/合併 System(合併、去重)。
- `create_incident(system, occurred_at, ...)` — 建立事件,自動建立 `AFFECTS` 關係。
- `add_observation(entity_name, observation)` — 對實體追加自由備註。
- `link(from_entity, to_entity, relation_type)` — 建立關係,強制型別紀律。
- `record_signature_match(incident_id, signature_name)` — 建立/連結 Signature(`MATCHES`)。
- `attach_atlas_reference(incident_id, channel_id, message_id, url, fact_id=None)` — 附上 Atlas 永久座標。
查詢類:
- `get_incident(incident_id)` — 事件完整視圖 + 關係。
- `find_incidents(system=, signature=, severity=, since=, until=)` — 條件篩選摘要。
- `resolve_alias(term)` — canonical / alias / label → System。
- `incident_time_window(incident_id, pad_minutes=15)` — `{start_utc, end_utc}`。
- `trace_incident_chain(incident_id, direction="downstream")` — 沿 `CAUSED` 追鏈。
## 重要慣例
- **時間戳**一律為 ISO-8601 **UTC**(例:`2026-06-12T03:14:00Z`)。無時區或非 UTC
的值會被拒絕——請先轉成 UTC 再送。這是對齊 Prometheus(UTC)與 Teams(本地時間)
的前提。
- **incident_id** 格式為 `INC-YYYY-MM-DD-<slug>`;未指定時由 server 依 system slug
自動產生。
- **System 的 canonical 名稱**採用團隊口語慣用的短名(以便與 Atlas 實體對齊);精確的
ops 標籤(如 `prometheus_instance`)放進 `labels`。
- **Atlas 永久鍵**是 `message_id`;`fact_id` 僅為快取(Atlas 重新同步後可能改變)。
## 關係契約(強制)
| RelationType | from | to |
| ------------ | ----------- | ----------- |
| AFFECTS | Incident | System |
| MATCHES | Incident | Signature |
| BASED_ON | Signature | Metric |
| HANDLED_BY | Incident | Person |
| RESOLVED_BY | Incident | Remediation |
| CAUSED | Incident | Incident |
連結端點型別錯誤時,會回傳明確錯誤。
## 測試
```bash
pytest
```
測試全程離線(mock Atlas client + 暫存檔儲存),不依賴任何外部服務或網路。
## 專案結構
```
src/kg_server/
models.py # pydantic 模型 + enums + 關係契約
storage.py # Storage protocol + JsonStorage(原子寫入) + MemoryStorage
validation.py # server 端驗證規則 + 型別化錯誤
graph.py # entity/relation CRUD、查詢、alias、追鏈、Atlas 配對
atlas.py # AtlasClient protocol + MockAtlasClient
tools.py # MCP 工具定義(薄封裝、結構化錯誤)
server.py # FastMCP 組裝 + stdio 進入點
sources/ # 監控 / 資料庫來源整合(擴充點)
prometheus.py # 功能完整:偵測門檻突破 -> 自動 create_incident
db2.py # 骨架 + mock:DB2 insight 報告增補
mariadb.py # 骨架 + mock:MariaDB(MMDB)狀態增補
skills/
mmdb-troubleshooting/SKILL.md # MMDB activelog / busy-ratio 排障手冊(規則)
tests/ # pytest 測試 + 合成 fixtures
```
## 來源整合(`sources/`)
每個來源都比照 `AtlasClient` 的樣式——一個 `Protocol` 介面加上離線的 `Mock*`——
讓偵測/增補流程無需真實基礎設施即可完整測試。換成真實 client 時,圖譜與工具邏輯
完全不需更動。
- **`prometheus.py`(功能完整):** `record_threshold_anomalies(graph, prom,
system, rule, start, end)` 會查詢序列、偵測「持續超過門檻」的突破(`ThresholdRule`),
並自動建立事件 + signature 連結。具冪等性(同一 system+start 不會重複建立)。這就是
目標 (1)+(2) 的示範:一個指標來源自動餵入圖譜。
- **`db2.py` / `mariadb.py`(骨架):** `enrich_incident_with_*` 把報告 / 狀態快照
併入既有事件(合併 metrics、findings 轉為 observation)。報告格式為待與團隊確認的
起始形狀。
上述流程引用的 MMDB signatures(如 `mmdb.busy_ratio.sustained`)記錄於
[`skills/mmdb-troubleshooting/SKILL.md`](skills/mmdb-troubleshooting/SKILL.md)
——規則歸 Skill,事件實例歸圖譜。
## 擴充點(仍待處理)
- 真實 `AtlasClient`,由 Atlas MCP 支撐(接回 Teams 對話)。
- 真實 `PrometheusClient` / `Db2InsightClient` / `MariaDbClient`(替換 mock)。
- 截圖辨識(vision/OCR)——屬於上層另一層處理。
- `Signature` 門檻——與 ops 確認 SKILL.md 中的 placeholder 數值。
- TKMSAPI 研究(spec 凍結,待其文件釋出)。
- 額外 `Storage` 後端(`SqliteStorage`、`Neo4jStorage`)——protocol 已抽象化,工具
邏輯不變。
This server cannot be deployed
Maintenance
ActivitySlowing
ResponsivenessNo issues