Skip to main content
Glama
README.md
# netops-mcp

网络运维 MCP 工具包:**Node.js + Python 双栈实现**,把「设备巡检 → 日志诊断 → 配置草稿 → 工单建单/流转」沉淀成 5 个
结构化 MCP 工具,供 LLM / Agent 通过 [Model Context Protocol](https://modelcontextprotocol.io) 调用。

配套 Skill 说明见 [`skill/SKILL.md`](skill/SKILL.md)。

## 一键演示

```powershell
.\demo.ps1
```

依次跑 Node 13 用例、Python 13 用例、跨实现一致性比对(输出示例存档在 [`docs/demo-output.txt`](docs/demo-output.txt))。

## 为什么做这个

运维场景里模型最容易出两类错:一是**编造设备状态**("CPU 大概 60% 吧"),二是**凭印象写配置命令**。
本项目用工具把这些事实固定下来——设备台账、端口状态、配置模板、工单状态机都在代码里,模型只能查询和提交,
不能凭空生成。同时提供 Node.js 与 Python 两套同构实现,用来验证「同一套工具契约在不同运行时下行为一致」。

## 特性

- **5 个工具**:`net_inspect_device`、`net_cfg_draft`、`net_log_analyze`、`net_ticket_create`、`net_ticket_update`
- **手写 JSON-RPC 2.0 over stdio**:零运行时依赖(Node ≥ 18 / Python ≥ 3.10 标准库即可),协议版本 `2024-11-05`
- **结构化错误码**:`DEVICE_NOT_FOUND` / `INVALID_ARGS` / `INVALID_TRANSITION` / `TICKET_NOT_FOUND` / `TOOL_NOT_FOUND`
- **工单状态机**:`OPEN → ACK → FIXED → CLOSED`,非法跳转直接拒绝(`INVALID_TRANSITION`)
- **双栈一致性对拍**:13 条用例在两套实现上全部通过、字段与错误码一致,自动生成 `compat-report.json`
- **可测**:分发逻辑与 stdio 解耦(`createMcpServer` / `process_line`),测试不依赖子进程管道

## 目录结构

```
netops-mcp/
├── node/
│   ├── tools.mjs          # 设备台账 + 5 个工具实现 + 工具 schema
│   ├── server.mjs         # MCP 服务器:JSON-RPC over stdio,导出 createMcpServer 便于测试
│   └── test-client.mjs    # 13 条用例(内存流驱动)
├── python/
│   ├── tools.py           # 与 Node 侧同构的工具实现
│   ├── server.py          # JSON-RPC 分发,导出 process_line 便于测试
│   └── test_client.py     # 同一套 13 条用例
├── skill/
│   └── SKILL.md           # Skill 描述:何时用、怎么调、错误码、Token 控制
├── compat_check.py        # 双栈报告对拍 → compat-report.json
├── test-report.json       # Node 侧测试报告
├── test-report-python.json# Python 侧测试报告
└── compat-report.json     # 一致性报告
```

## 快速开始

### Node.js

```bash
node node/server.mjs            # 启动 stdio 服务
node node/test-client.mjs       # 跑测试(13 条)
```

### Python

```bash
python python/server.py         # 启动 stdio 服务
python python/test_client.py    # 跑测试(13 条)
python compat_check.py          # 对拍两份报告,生成兼容性结论
```

### 手动发一条 JSON-RPC

```bash
echo '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"curl","version":"0"}}}' | node node/server.mjs
```

## 工具契约

| 工具 | 必填参数 | 成功返回(要点) |
| --- | --- | --- |
| `net_inspect_device` | `device` | `cpuPercent` `memPercent` `temperatureC` `optical{rxDbm}` `ports[]` `health` `warnings[]` |
| `net_cfg_draft` | `platform` `task` `spec` | `config`(配置文本) `warnings[]` |
| `net_log_analyze` | `log` | `categories[{category,evidence,suggestion}]` `summary` |
| `net_ticket_create` | `title` `severity` | `ticket{id,status,slaHours,history[]}` |
| `net_ticket_update` | `ticketId` `to` | 更新后的 `ticket` |

规则细节:

- 巡检:光模块收光功率 `< -15 dBm` 触发告警;存在 `down` 端口时 `health = WARN`
- 配置草稿:`vlanId` 限 1–4094;ACL 编号限 2000–3999;华为/思科语法分别生成;只产出文本,不下发
- 日志分析:5 条规则(链路断链 / 光模块光衰 / 通讯超时 / 弱口令与高危端口 / 物理层错包)
- 工单:`P1/P2/P3 → SLA 2/8/24 小时`,工单号 `WO-YYYYMMDD-NNN`

## 测试结果

Node.js 侧(`test-report.json`):

```
结果:13/13 通过
```

Python 侧(`test-report-python.json`):

```
结果:13/13 通过
```

双栈一致性(`compat-report.json`):

```
一致性:13/13(100.0%)
```

| # | 用例 | Node.js | Python | 一致 |
|---|------|---------|--------|------|
| 1 | initialize 握手 | PASS | PASS | ✅ |
| 2 | ping 保活 | PASS | PASS | ✅ |
| 3 | tools/list 返回 5 个工具且 schema 完整 | PASS | PASS | ✅ |
| 4 | net_inspect_device 正常设备 | PASS | PASS | ✅ |
| 5 | net_inspect_device 未知设备返回 DEVICE_NOT_FOUND | PASS | PASS | ✅ |
| 6 | net_cfg_draft 生成 VLAN 配置 | PASS | PASS | ✅ |
| 7 | 非法 vlanId 返回 INVALID_ARGS | PASS | PASS | ✅ |
| 8 | net_log_analyze 识别断链与光衰 | PASS | PASS | ✅ |
| 9 | net_ticket_create 创建 P1 工单(SLA 2h) | PASS | PASS | ✅ |
| 10 | 工单 OPEN→ACK 流转 | PASS | PASS | ✅ |
| 11 | 工单非法流转 ACK→CLOSED 被拒绝 | PASS | PASS | ✅ |
| 12 | 未知工具返回 TOOL_NOT_FOUND | PASS | PASS | ✅ |
| 13 | 非法 JSON 返回 -32700 Parse error | PASS | PASS | ✅ |

## 接入 MCP 客户端

Claude Desktop / Cursor 等客户端的 `mcpServers` 配置(Node 侧):

```json
{
  "mcpServers": {
    "netops-mcp": {
      "command": "node",
      "args": ["A:/path/to/netops-mcp/node/server.mjs"]
    }
  }
}
```

Python 侧:

```json
{
  "mcpServers": {
    "netops-mcp": {
      "command": "python",
      "args": ["A:/path/to/netops-mcp/python/server.py"]
    }
  }
}
```

## 设计说明

**为什么手写 JSON-RPC 而不引入官方 SDK?** MCP 的 stdio 传输就是「一行一个 JSON」,`initialize` / `ping` /
`tools/list` / `tools/call` 四个方法足够覆盖工具型服务。手写让协议细节(版本协商、错误码、通知不回包)透明可见,
也便于在同样 200 行内实现两套同构代码做对照。

**为什么把分发逻辑和 stdio 解耦?** 测试时不需要 spawn 子进程、不需要管道与超时控制,直接把字符串喂给
`createMcpServer` / `process_line` 就能断言返回,测试稳定且秒级完成。

**为什么设备数据是模拟的?** 这是作品集项目,不接触真实生产网络。台账结构参照华为/华三设备实际输出字段设计,
真实接入时只需替换 `tools.mjs` / `tools.py` 里 `DEVICES` 的取数来源(SSH/SNMP/Syslog),工具契约与上层 Agent 无需改动。

## 边界

- 不做真实设备连接与配置下发(`net_cfg_draft` 只产出文本)
- 工单存内存,进程结束即丢失;真实场景应接数据库与工单系统
- 未实现 `resources` / `prompts` 能力,仅 `tools`
- 未实现流式进度通知(`notifications/progress`)

## 后续计划

- 接 SQLite/PostgreSQL 持久化工单与巡检历史
- 增加 `net_scan_subnet`(批量巡检)与 `net_config_diff`(配置变更比对)
- 用官方 SDK 再实现一版,与本实现做协议层对拍

## License

MIT