内容
# DevOps MCP 服务器
一个生产就绪的 **模型上下文协议(MCP)** 服务器,为 DevOps 知识库提供服务——技能、说明、提示和适用于 Python、Ansible、Terraform、Docker、Kubernetes、CI/CD 和一般工程的策略,适用于任何与 MCP 兼容的 AI 客户端(Claude Desktop、VS Code、Cursor 等)。
---
## 1. 概述
服务器从 `content/` 读取版本化的 Markdown 文件(带有 YAML 前言),并通过 4 个 MCP 工具将它们暴露给 AI 助手,使用 **可流式传输的 HTTP** 进行传输,并作为 Docker 容器部署。
为什么使用 MCP?它为 AI 助手提供了一个受控、可审计的只读窗口,以便访问您的 DevOps 标准,这样生成的代码、管道和基础设施始终与内部策略保持一致——无需将文档复制到提示中。
---
## 2. 架构
```
┌─────────────────────┐ HTTPS / X-API-Key ┌─────────────────────────────┐
│ MCP 客户端 │ ───────────────────────────▶ │ Starlette ASGI 应用 │
│ (Claude / VS Code) │ │ ├─ /health │
└─────────────────────┘ │ └─ /mcp (FastMCP 挂载) │
│ APIKeyMiddleware │
└──────────────┬───────────────┘
│
▼
┌─────────────────────────────┐
│ mcp_server.tools (FastMCP) │
│ @tool fetch_devops_content│
│ @tool list_devops_* │
│ @tool get_devops_*_by_id │
└──────────────┬───────────────┘
│
▼
┌─────────────────────────────┐
│ src/services │
│ └─ ContentService │
│ ├─ ContentLoader (fs) │
│ └─ ContentFilter │
└──────────────┬───────────────┘
│
▼
┌────────────────────────┐
│ content/*.md │
│ (前言 + 正文) │
└────────────────────────┘
```
---
## 3. 先决条件
- Python **3.11+**
- Poetry **1.7+** (或 pip)
- Docker Engine **24+** 和 Docker Compose v2(用于容器化部署)
- 您选择的 API 密钥值(任意非空字符串)用于 `MCP_API_KEY`
---
## 4. 本地设置
```bash
# 1. 克隆
git clone <仓库网址> hbiz-devops-mcp
cd hbiz-devops-mcp
# 2. 环境
cp .env.example .env
# 编辑 .env — 至少设置 MCP_API_KEY 为非空密钥
# 3. 安装依赖
poetry install
# 或
python -m venv .venv && source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
# 4. 运行
poetry run python main.py
# 或
python main.py
```
服务器默认监听 `http://localhost:8000`。
- 健康检查:`GET http://localhost:8000/health`
- MCP:`POST http://localhost:8000/mcp` (带有 `X-API-Key: <您的密钥>`)
---
## 5. Docker
```bash
cp .env.example .env
# 编辑 .env — 设置 MCP_API_KEY 并根据需要调整 MCP_PORT
# 构建镜像
docker build -t hbiz-devops-mcp:latest .
# 启动容器
docker compose up -d
# 验证
curl http://localhost:8001/health
# {"status":"healthy","server":"hBiz-DevOps MCP Server","version":"1.0.0"}
# 查看实时日志
docker logs hbiz-devops-mcp -f
```
服务器在由 `MCP_PORT` 定义的端口(默认为 `8001`)上暴露;MCP 端点是 `http://localhost:8001/mcp`。
停止:
```bash
docker compose down
```
---
## 6. VS Code MCP 配置
在任何使用者工作区中创建 `.vscode/mcp.json` (此文件故意提交 - 它不包含秘密,只有服务器网址):
```json
{
"servers": {
"hbiz-devops": {
"type": "http",
"url": "http://localhost:8000/mcp",
"headers": {
"X-API-Key": "${env:HBIZ_MCP_API_KEY}"
}
}
}
}
```
然后在您的 shell 中导出密钥(或 VS Code 用户环境):
```bash
export HBIZ_MCP_API_KEY="<您的密钥>"
```
对于生产部署,请将 `http://localhost:8000/mcp` 替换为 `https://<您的主机>/mcp`。
---
## 7. 环境变量
### 服务器
| 变量 | 默认值 | 描述 |
|--------------------|--------------------------|--------------------------------------------------|
| `DOCKER_IMAGE` | `hbiz-devops-mcp:latest` | Docker 镜像名称,用于 `docker-compose.yml` |
| `ENVIRONMENT` | `local` | `local` / `staging` / `production` |
| `MCP_API_KEY` | *(必填)* | 客户端必须发送的 API 密钥作为 `X-API-Key` |
| `MCP_SERVER_NAME` | `hBiz-DevOps MCP 服务器` | 显示给 MCP 客户端的名称 |
| `MCP_HOST` | `0.0.0.0` | 绑定地址 |
| `MCP_PORT` | `8000` | 绑定端口(主机上暴露) |
| `CONTENT_DIR` | `content` | 内容根目录的路径(相对或绝对) |
### 日志记录
| 变量 | 默认值 | 描述 |
|-------------------------|------------------------------------------------------|--------------------------------------------------|
| `LOG_LEVEL` | `INFO` | `DEBUG` / `INFO` / `WARNING` / `ERROR` |
| `LOG_FORMAT` | `%(asctime)s - %(name)s - %(levelname)s - %(message)s` | Python `logging` 格式字符串 |
| `LOG_FILE_ENABLED` | `false` | 设置为 `true` 以将日志写入文件 |
| `LOG_FILE_PATH` | `logs/mcp_logs.log` | 日志文件路径(自动创建) |
| `LOG_FILE_MAX_BYTES` | `10485760` | 文件大小上限(默认 10 MB) |
| `LOG_FILE_BACKUP_COUNT` | `5` | 保留的旋转备份文件数量 |
所有变量都可以通过 `.env` 或进程环境覆盖。
---
## 8. MCP 工具
| 工具 | 参数 | 返回 |
|---------------------------------|-------------------------------------------------------|----------------------------------------|
| `fetch_devops_content` | `query: str, content_type?: str, tags?: list[str]` | 匹配的项目以 Markdown 渲染 |
| `list_devops_categories` | *(无)* | 分类列表 |
| `list_devops_content` | `category?: str, content_type?: str` | 元数据 Markdown 表格 |
| `get_devops_content_by_id` | `content_id: str` | 单个项目以 Markdown 渲染 |
所有工具都是只读的(`readOnlyHint: true`, `destructiveHint: false`)。
---
## 9. 添加新内容
1. 在 `content/<category>/<type>/<id>.md` 下创建 Markdown 文件,其中:
- `<category>` ∈ `python | ansible | terraform | docker | kubernetes | cicd | general`
- `<type>` ∈ `skills | instructions | prompts | policies | rules`
2. 添加所需的前言:
```markdown
---
id: kebab-case-unique-id
title: 人类可读的标题
type: skill # 技能 | 说明 | 提示 | 策略 | 规则
category: python # 必须与文件夹名称匹配
tags:
- python # 第一个标签应为类别
- clean-arch
version: "1.0" # 引号字符串
---
# 标题
正文 Markdown 内容...
```
3. 重启服务器(内容在启动时加载一次)。
`id` 值在整个树中必须 **全局唯一** —— 重复项将导致加载失败,出现 `ContentLoadError`。
---
## 10. 项目结构
```
hbiz-devops-mcp/
├── main.py # Uvicorn 入口点
├── pyproject.toml # Poetry 依赖项
├── requirements.txt # pip-installable 镜像
├── Dockerfile
├── .dockerignore
├── docker-compose.yml
├── .env.example # 模板 — 复制到 .env
├── config/
│ └── settings.py # Pydantic 设置
├── src/
│ ├── core/
│ │ ├── content_loader.py # 文件系统 → ContentItem[]
│ │ ├── content_filter.py # 纯过滤逻辑
│ │ └── exceptions.py
│ ├── models/
│ │ └── content.py # ContentMeta, ContentItem, ContentType
│ ├── services/
│ │ └── content_service.py # 缓存 + 暴露内容
│ └── utils/
│ ├── auth.py # APIKeyMiddleware
│ └── logger.py # stdout + 可选的旋转文件处理程序
├── mcp_server/
│ ├── app.py # Starlette + FastMCP 接线
│ └── tools.py # @mcp.tool 定义
├── content/ # DevOps 知识库
│ ├── python/ ansible/ terraform/ docker/ kubernetes/ cicd/ general/
├── logs/ # 运行时创建(gitignored)
│ └── mcp_logs.log # 仅在 LOG_FILE_ENABLED=true 时存在
└── tests/
├── conftest.py
├── core/
└── services/
```
---
## 11. 依赖管理
- **真实来源:** `pyproject.toml` (Poetry)。
- `requirements.txt` 为无 Poetry 环境而生成:
```bash
poetry export -f requirements.txt -o requirements.txt --without-hashes
```
- 锁定主版本号和次版本号(`^1.0`)。使用 `poetry update` 更新并运行完整的测试套件,然后再提交新的锁定文件。
- 安全:每次 PR 都运行 `poetry run pip-audit` (或 `safety check`)。
---
## 12. 日志记录
默认情况下,日志仅写入 **stdout**,并可以通过以下方式查看:
```bash
# 本地运行
python main.py
# Docker
docker logs hbiz-devops-mcp
docker logs hbiz-devops-mcp -f # 实时跟随
```
### 启用文件日志记录
在 `.env` 中设置以下内容并重启服务器:
```env
LOG_FILE_ENABLED=true
LOG_FILE_PATH=logs/mcp_logs.log
LOG_FILE_MAX_BYTES=10485760 # 10 MB 每文件
LOG_FILE_BACKUP_COUNT=5 # 保留最后 5 个旋转文件
```
`logs/` 目录会自动创建。文件会在达到 `LOG_FILE_MAX_BYTES` 时旋转,最多保留 `LOG_FILE_BACKUP_COUNT` 个备份文件(`mcp_logs.log`, `mcp_logs.log.1`, … `mcp_logs.log.5`)。启用文件日志记录时,stdout 和文件日志记录同时激活。
> `logs/` 被 gitignore — 日志文件永远不会提交到源代码控制。
---
## 13. 使用 Postman 测试
MCP 服务器通过 **HTTP POST 以 JSON-RPC 2.0 协议** 进行通信。每个请求都发送到 `http://localhost:8001/mcp`,并设置 `X-API-Key` 头。
### 必需头信息(所有请求)
| 头信息 | 值 |
|--------|-------|
| `Content-Type` | `application/json` |
| `Accept` | `application/json, text/event-stream` |
| `X-API-Key` | 您的 `MCP_API_KEY` 值 |
---
### 步骤 1 — 验证服务器是否启动
**GET** `http://localhost:8001/health`
预期响应:
```json
{"status": "healthy", "server": "hBiz-DevOps MCP 服务器", "version": "1.0.0"}
```
---
### 步骤 2 — 初始化 MCP 会话
**POST** `http://localhost:8001/mcp`
正文:
```json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2024-11-05",
"capabilities": {},
"clientInfo": { "name": "postman", "version": "1.0" }
}
}
```
> 从 **响应头** 中复制 `mcp-session-id` 值 — 您必须在所有后续请求中将其作为 `mcp-session-id: <值>` 包含在内。
---
### 步骤 3 — 列出可用工具
**POST** `http://localhost:8001/mcp`
添加头信息:`mcp-session-id: <步骤 2 中的值>`
正文:
```json
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/list",
"params": {}
}
```
---
### 步骤 4 — 调用工具
#### 列出所有类别
```json
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "list_devops_categories",
"arguments": {}
}
}
```
#### 搜索内容
```json
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "fetch_devops_content",
"arguments": {
"query": "docker",
"content_type": "skill"
}
}
}
```
#### 按类别列出内容
```json
{
"jsonrpc": "2.0",
"id": 5,
"method": "tools/call",
"params": {
"name": "list_devops_content",
"arguments": {
"category": "python"
}
}
}
```
#### 获取特定 ID 的项目
```json
{
"jsonrpc": "2.0",
"id": 6,
"method": "tools/call",
"params": {
"name": "get_devops_content_by_id",
"arguments": {
"content_id": "python-clean-architecture"
}
}
}
```
---
### 步骤 5 — 验证身份拒绝
发送任何请求 **不带** `X-API-Key` 头(或使用错误的值)。
预期响应:**HTTP 401**
```json
{"detail": "Unauthorized"}
```
---
## 14. 单元测试
```bash
# 运行所有测试
poetry run pytest -v
# 带有覆盖率
poetry run pytest --cov=src --cov-report=term-missing
# 单个文件
poetry run pytest tests/core/test_content_loader.py -v
```
测试使用在 `tmp_path` 中创建的示例 Markdown 夹层 — 它们不会读取生产 `content/` 树。
MCP 配置
以下是此 MCP Server 的配置信息,可直接复制到 Cursor 或其他 MCP 客户端中使用。
mcp.json
连接信息
猜你喜欢
暂无推荐服务器