diagnosis-service
by CarlosYonng
README.md
# Diagnosis Service
独立故障诊断 MCP 服务,作为可被任意业务服务接入的异常诊断中心:
- 业务服务通过 HTTP 推送异常日志。
- 诊断服务使用独立 MySQL 库 `diagnosis_db` 保存日志、服务注册、静态代码索引、历史工单和诊断报告。
- Codex、Claude Desktop 或其他 MCP 客户端可通过 `/mcp` 查询日志并生成诊断报告。
- `demo-service/` 是随项目携带的外接测试服务,会随机制造 timeout 和空指针异常,用于验证接入链路。
## Project Map
- `app/`: 诊断服务 FastAPI 应用。
- `main.py`: HTTP API 和 MCP JSON-RPC 入口。
- `log_store.py`: 日志写入、查询、统计和报告生成。
- `mcp_tools.py`: MCP 工具定义和工具调用分发。
- `db.py`: MySQL 访问层。
- `schemas.py`: API DTO。
- `demo-service/`: 外部服务接入测试用例。
- `infra/mysql/diagnosis_init.sql`: 独立诊断库初始化脚本。
- `scripts/`: 本地链路冒烟测试和诊断静态数据导入脚本。
- `docker-compose.yml`: diagnosis-service、demo-service 一键运行,MySQL 连接外部 infra-stack。
## APIs
| Endpoint | Description |
| --- | --- |
| `POST /api/logs` | 业务服务推送异常日志 |
| `GET /api/logs?service=&level=&trace_id=` | 查询异常日志 |
| `GET /api/logs/stats?hours=24` | 查询日志聚合统计 |
| `GET /api/services` | 查询已接入服务 |
| `POST /api/reports` | 生成诊断报告 |
| `GET /api/reports/{report_id}` | 查询诊断报告 |
| `POST /mcp` | MCP JSON-RPC 工具入口 |
| `GET /.well-known/oauth-protected-resource/mcp` | MCP OAuth protected resource metadata |
| `GET /.well-known/oauth-authorization-server/mcp` | MCP OAuth authorization server metadata |
| `POST /mcp/oauth/token` | 可选 client_credentials token 端点 |
| `GET /health` | 健康检查 |
## MCP Tools
- `search_logs`: 按服务、级别、traceId 和时间窗口查日志。
- `search_code`: 查询静态导入的代码符号。
- `search_tickets`: 查询相似历史故障工单。
- `generate_report`: 聚合日志、代码和工单证据生成诊断报告。
- `get_report`: 按报告 ID 查询报告。
## Quick Start
```bash
cp .env.example .env
# 先启动外部 ai-agent-infra-stack,再启动诊断服务
docker compose up -d diagnosis-service demo-service
curl http://localhost:8200/health
```
推送一条异常:
```bash
curl -X POST http://localhost:8200/api/logs \
-H 'Content-Type: application/json' \
-d '{"service":"demo-service","level":"ERROR","trace_id":"tr_001","endpoint":"/api/order/1","exception_type":"TimeoutError","message":"order query timeout"}'
```
生成诊断报告:
```bash
curl -X POST http://localhost:8200/mcp \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"name":"generate_report","arguments":{"service":"demo-service","trace_id":"tr_001"}}}'
```
运行 demo-service 外部接入验证:
```bash
for i in 1 2 3 4 5; do curl -s http://localhost:8300/api/order/$i || true; done
curl 'http://localhost:8200/api/logs?service=demo-service&page_size=10'
```
## Local Development
```bash
python3 -m venv .venv
. .venv/bin/activate
pip install -r requirements.txt
DIAGNOSIS_MYSQL_DSN=mysql://agent:agent123@localhost:3306/diagnosis_db \
uvicorn app.main:app --host 127.0.0.1 --port 8200 --reload
```
demo-service 本地启动:
```bash
cd demo-service
pip install -r requirements.txt
DIAGNOSIS_URL=http://localhost:8200 uvicorn app.main:app --host 127.0.0.1 --port 8300 --reload
```
## Codex MCP Usage
把 MCP HTTP 入口配置到本地 Codex/其他 MCP 客户端时,服务地址使用:
```text
http://localhost:8200/mcp
```
默认本地开发不启用 MCP 鉴权。部署到外部网络时建议配置 MCP 专用 Bearer token:
```bash
export MCP_AUTH_TOKEN='replace-with-a-long-random-token'
uvicorn app.main:app --host 127.0.0.1 --port 8200 --reload
```
客户端连接 `/mcp` 时带上:
```http
Authorization: Bearer replace-with-a-long-random-token
```
启用 token 后,未带或带错 token 的 `/mcp`、`/api/tools` 和 `/api/tools/{tool_name}` 会返回 `401`,并通过 `WWW-Authenticate` 指向 MCP/OAuth protected resource metadata。Codex、Claude Code 等客户端探测这些地址时不会再遇到 well-known 404:
```text
/.well-known/oauth-protected-resource/mcp
/.well-known/oauth-authorization-server/mcp
/mcp/.well-known/oauth-authorization-server
/.well-known/oauth-authorization-server
/.well-known/openid-configuration/mcp
/mcp/.well-known/openid-configuration
/.well-known/openid-configuration
```
如果客户端支持 MCP OAuth Client Credentials 扩展,也可以额外配置:
```bash
export MCP_AUTH_TOKEN='replace-with-a-long-random-token'
export MCP_OAUTH_CLIENT_ID='diagnosis-client'
export MCP_OAUTH_CLIENT_SECRET='replace-with-a-long-random-secret'
```
然后用 `client_credentials` 从 `/mcp/oauth/token` 换取 Bearer token。这个端点同时支持 `client_secret_basic` 和 `client_secret_post`。
工具发现请求:
```bash
curl -X POST http://localhost:8200/mcp \
-H 'Authorization: Bearer replace-with-a-long-random-token' \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}'
```
## Environment
- `DIAGNOSIS_MYSQL_DSN`: 诊断库连接串,默认 `mysql://agent:agent123@localhost:3306/diagnosis_db`。
- `MCP_AUTH_TOKEN`: MCP 专用 Bearer token;为空时 `/mcp` 保持免鉴权,便于本地开发。
- `MCP_AUTH_SCOPE`: MCP OAuth scope,默认 `diagnosis:mcp`。
- `MCP_AUTH_ISSUER`: OAuth issuer;默认按请求 host 自动生成。
- `MCP_OAUTH_CLIENT_ID`: 可选 OAuth client credentials 客户端 ID。
- `MCP_OAUTH_CLIENT_SECRET`: 可选 OAuth client credentials 客户端密钥。
- `DIAGNOSIS_URL`: demo-service 推送诊断服务地址,默认 `http://localhost:8200`。
- `SERVICE_NAME`: demo-service 上报服务名,默认 `demo-service`。
## Verification
```bash
python3 -m compileall app demo-service/app
bash scripts/smoke_test.sh
```
导入诊断静态数据:
```bash
python3 scripts/ingest_code.py --repo-dir demo-service --service demo-service
python3 scripts/ingest_tickets.py --ticket-dir datasets/tickets --service demo-service
python3 scripts/ingest_logs.py --log-dir datasets/logs --service demo-service
```
This server cannot be deployed
Maintenance
ActivityStale
ResponsivenessNo issues