netmiko-mcp
# netmiko-mcp
一个极简的 MCP 服务器,为编码智能体(Claude / DSH / Codex)提供对**华三 Comware 网络设备**与**Linux 服务器**的 SSH/telnet 命令执行能力。
- 两个工具:`list_devices`(枚举设备)与 `run_command`(执行命令)。
- 完全读写委托,无确认门禁、无命令白名单。
- 每次调用独立连接,无跨调用会话状态。
- 唯一的护栏是本地审计日志(事后复盘,非事前拦截)。
## 依赖管理
本项目使用 [uv](https://docs.astral.sh/uv/) 管理依赖,`.python-version` 固定 Python 3.12。
```bash
uv sync # 安装依赖到 .venv
uv run pytest # 运行测试
uv run python main.py # 以 stdio 启动 MCP 服务器
```
## 清单文件
默认读取当前目录下的 `hosts.yaml`(可用环境变量 `NETMKO_MCP_INVENTORY` 覆盖)。参见 `hosts.example.yaml` 的完整示例:
```yaml
- id: core-switch # 唯一标识,run_command 用它对目标寻址
description: 核心交换机,负责办公网络汇聚 # 可选的设备描述
platform: network # network | linux
host: 192.168.1.1
protocol: ssh # ssh | telnet
port: 22 # 可选
device_type: hp_comware # netmiko 类型;telnet 会自动补 _telnet 后缀
username: admin
password: "CHANGE_ME"
secret: "CHANGE_ME" # 特权(super)密码,可选
- id: jump-host
platform: linux
host: 192.168.1.10
username: ops
password: "CHANGE_ME"
sudo_password: "CHANGE_ME" # linux 必填,经 sudo -S 使用
```
## 工具
### `list_devices`
返回清单中所有设备的公开元数据(id、description、platform、host、port、protocol、device_type、username),**不返回** `password`、`secret`、`sudo_password`。
`description` 是可选的字符串,用于说明设备用途、位置等信息;未配置或设为 `null` 时返回 `null`,空字符串原样返回。现有清单无需修改。
### `run_command(target, mode, command)`
- `target`:清单中的 `id`。
- `mode`:`read`(只读命令)或 `config`(配置下发)。
- `command`:命令字符串;`config` 模式按换行拆分为多条配置命令。
行为:
- 网络设备:`read` 走 `send_command`,`config` 走 `send_config_set`(自动进/出系统视图);连接后自动关闭分页,连接时自动进入特权视图(`secret`)。
- Linux:命令以 `sudo -S` 执行,使用清单中的 `sudo_password`。
- 每次调用独立连接,执行后断开。
- 输出**完整返回**,不截断。
- 配置下发**不自动保存**:持久化需由智能体显式执行 `save`(华三)等命令。
## 环境变量
| 变量 | 默认值 | 说明 |
|------|--------|------|
| `NETMKO_MCP_INVENTORY` | `hosts.yaml` | 清单文件路径 |
| `NETMKO_MCP_AUDIT_LOG` | `audit.log` | 审计日志路径 |
## 审计日志
每次 `run_command` 都会向审计日志追加一行 JSON,字段含时间戳、目标、模式、命令、成功与否与输出:
```json
{"timestamp":"...","target":"core-switch","mode":"read","command":"display version","success":true,"output":"..."}
```
## 客户端接入示例
以 stdio 方式接入 MCP 客户端时,启动命令为:
```json
{ "command": "uv", "args": ["run", "python", "main.py"], "cwd": "/path/to/netmiko-mcp" }
```
## 安全警告(必读)
本工具默认**完全委托、不做拦截**,叠加以下设计后风险很高,请务必知悉:
1. **凭证明文内联**:`hosts.yaml` 直接存放所有设备的密码、特权密码与 sudo 密码,且已加入 `.gitignore`。一旦该文件泄露,攻击者即获得所有设备的完全控制权。**切勿提交到版本库,并严格控制文件权限。**
2. **支持 telnet**:telnet 为明文传输,登录凭证会在链路上明文暴露。仅应在隔离网络中使用。
3. **完全读写、无确认**:智能体可直接下发真实配置,无二次确认、无命令白名单、无干跑。
4. **无提示注入防护**:若智能体被不可信内容(网页、邮件、设备回显)诱导,命令会以完全权限执行。
5. **不自动保存**:配置下发后不会自动持久化,重启可能丢失,需智能体显式保存。
6. 审计日志只能**事后复盘**,不能**事前拦截**。
请在完全理解并接受上述风险后再部署到生产环境。
TDQS
Scored across 2 tools
list_devices and run_command have clearly distinct purposes: one enumerates available devices, the other executes commands on a target device. There is no overlap or ambiguity between them.
Both tool names follow the same verb_noun pattern: list_devices and run_command. The naming is consistent, predictable, and easy for an agent to reason about.
With only two tools, the server feels minimal and is at the thin end of the scale. The tools are essential and earn their place, but the surface is quite sparse for a network automation MCP.
The combination of listing devices and running arbitrary read/config commands covers the core Netmiko workflow well. Minor gaps exist, such as no dedicated multi-device execution or explicit save/commit operation, but agents can work around these via run_command.