Skip to main content
Glama
LianXia233

router-ssh-mcp

by LianXia233

router-ssh-mcp

通过 SSH 管理路由器(OpenWrt / ImmortalWrt / 通用 Linux)上服务的 MCP(Model Context Protocol)服务器。 上层模型可以列出服务、查询状态、读取日志,并在二次确认后执行启动 / 停止 / 重启,全程受命令白名单约束;此外提供一个默认关闭的高危 run_shell 能力,在显式开启并二次确认后可于远端执行任意 shell 命令,用于白名单工具覆盖不到的排障场景。


1. 能力概览

能力

说明

多 init 系统

自动探测 procd(OpenWrt)、systemdsysvinit,也可手动指定

连接复用

进程内复用单条 SSH 连接,带 keepalive 与断线重连

只读 / 写入分离

4 个只读工具 + 3 个写入工具 + 1 个高危 shell 工具,通过 MCP annotations 标注

写入二次确认

写入工具必须传 confirm=<服务名>,否则返回 CONFIRMATION_REQUIRED

命令白名单

所有命令以 argv 序列下发,不经 shell;服务名、路径、行数均做严格校验

可选 shell 能力

run_shell 默认关闭;开启后需二次确认,并默认拦截 rm -rf / mkfs / dd 等高危命令

结构化输出

统一返回 ok/tool/host/duration_ms/data/error,并附带 MCP structuredContent

结构化错误

连接、认证、超时、服务不存在等均映射为稳定错误码 + 修复建议


Related MCP server: OpenWRT SSH MCP Server

2. 目录结构

router-ssh-mcp/
├── pyproject.toml               # 依赖与 console script 入口
├── config.example.json          # 配置文件示例(不含真实口令)
├── .env.example                 # 环境变量示例
├── src/router_mcp/
│   ├── config.py                # 配置加载(默认值 < 配置文件 < 环境变量)
│   ├── errors.py                # 错误码与结构化异常
│   ├── commands.py              # 命令白名单与 argv 模板(安全核心)
│   ├── ssh_pool.py              # SSH 连接复用 / 保活 / 超时重连 / 错误归类
│   ├── controller.py            # 编排层:安全策略、二次确认、工具语义
│   ├── models.py                # pydantic 返回模型
│   ├── server.py                # MCP 服务器与工具注册
│   ├── _compat.py               # mcp 1.x / 2.x 兼容层
│   └── backends/
│       ├── base.py              # 后端抽象与公共能力(启动时间推算)
│       ├── initd.py             # /etc/init.d 通用实现(sysvinit)
│       ├── procd.py             # OpenWrt ubus + procd
│       └── systemd.py           # systemctl + journalctl
├── scripts/
│   ├── selftest.py              # 真实设备自测(只读 + 可选写入演练)
│   └── mcp_smoke.py             # stdio 协议级冒烟测试
└── tests/                       # 离线单元测试 + MCP 层端到端测试

调用链:MCP 工具 → controller(安全策略/确认) → backends(init 适配) → commands(白名单 argv) → ssh_pool(连接复用) → asyncssh


3. 环境要求与依赖

项目

要求

Python

>= 3.10(CI 验证 3.11 / 3.12 / 3.13)

mcp

>= 2.0, < 3(SDK,代码内含 1.x 兼容路径)

asyncssh

>= 2.14(纯 Python SSH,自带 crypto,不需要系统 ssh 客户端)

pydantic

>= 2.7(结构化输出模型)

Linux / macOS

python3 -m venv .venv
source .venv/bin/activate
pip install -e .          # 开发模式
# 或:pip install .

Windows(PowerShell 7)

python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -e .

开发额外依赖:pip install -e ".[dev]"(pytest、pytest-asyncio)。


4. 配置

优先级:默认值 < JSON 配置文件 < 环境变量 < 命令行参数

连接参数完全可自定义:目标路由器 IP、登录账号、密码或私钥均由你按实际设备填写,三种方式任意组合。本仓库所有示例中的 192.168.1.1 仅为占位默认地址,请替换为你自己的路由器地址。密码与令牌切勿提交进仓库config.json / .env 已在 .gitignore 中忽略)。

配置文件查找顺序:--config$ROUTER_MCP_CONFIG./router-mcp.json./config.json~/.config/router-mcp/config.json

4.1 环境变量

变量

默认值

说明

ROUTER_MCP_HOST

192.168.1.1

SSH 主机

ROUTER_MCP_PORT

22

SSH 端口

ROUTER_MCP_USER

root

SSH 用户名

ROUTER_MCP_PASSWORD

密码(与 KEY_PATH 至少提供一个)

ROUTER_MCP_KEY_PATH

私钥路径

ROUTER_MCP_KEY_PASSPHRASE

私钥口令;未设置时会尝试用 PASSWORD 解密私钥

ROUTER_MCP_INIT_SYSTEM

auto

auto / procd / systemd / sysvinit

ROUTER_MCP_CONNECT_TIMEOUT

8

连接超时(秒)

ROUTER_MCP_COMMAND_TIMEOUT

12

单条命令超时(秒)

ROUTER_MCP_KEEPALIVE_INTERVAL

15

保活间隔(秒)

ROUTER_MCP_KEEPALIVE_COUNT

3

连续保活失败次数阈值

ROUTER_MCP_MAX_RECONNECT_ATTEMPTS

2

命令失败重连重试次数

ROUTER_MCP_MAX_LOG_LINES

500

单次日志读取上限

ROUTER_MCP_REQUIRE_CONFIRM

true

写入操作是否要求二次确认

ROUTER_MCP_ALLOWED_SERVICES

服务白名单,逗号分隔;为空表示不限制

ROUTER_MCP_DENIED_SERVICES

network,firewall,system,boot,done

禁止写入的高危服务

ROUTER_MCP_STRICT_HOST_KEY

false

是否校验 known_hosts(路由器重装后建议临时关闭)

ROUTER_MCP_KNOWN_HOSTS

known_hosts 路径(仅在严格模式下生效)

ROUTER_MCP_ALLOW_SHELL

false

是否启用高危的 run_shell 任意命令能力

ROUTER_MCP_SHELL_REQUIRE_CONFIRM

true

run_shell 是否要求二次确认(confirm 须等于命令本身)

ROUTER_MCP_SHELL_DENY_UNSAFE

true

是否拦截高危命令(rm -rf / mkfs / dd / 写 /dev/* / fork 炸弹 / 管道进 shell)

ROUTER_MCP_LOG_LEVEL

WARNING

asyncssh 日志级别,排障时设 DEBUG

4.2 配置文件

复制 config.example.jsonconfig.json(已在 .gitignore 中忽略,避免口令入库):

{
  "host": "192.168.1.1",
  "username": "root",
  "password": "",
  "init_system": "auto",
  "security": {
    "require_confirmation": true,
    "allowed_services": [],
    "denied_services": ["network", "firewall"]
  }
}

5. 启动

5.1 直接运行

# stdio(默认,供 MCP 客户端拉起)
ROUTER_MCP_HOST=192.168.1.1 ROUTER_MCP_PASSWORD=xxx python -m router_mcp

# 等价的 console script
ROUTER_MCP_HOST=192.168.1.1 ROUTER_MCP_PASSWORD=xxx router-ssh-mcp

# 命令行覆盖参数
router-ssh-mcp --host 192.168.1.1 --user root --key-path ~/.ssh/id_ed25519

# SSE / Streamable HTTP(远程部署时使用)
router-ssh-mcp --transport streamable-http

5.2 接入 MCP 客户端

WorkBuddy(~/.workbuddy/mcp.json):

{
  "mcpServers": {
    "router-ssh": {
      "description": "通过 SSH 管理路由器(OpenWrt/ImmortalWrt/systemd)服务的 MCP 连接器;只读工具可直接调用,写入操作需二次确认,run_shell 高危能力默认关闭。",
      "command": "python",
      "args": ["-m", "router_mcp"],
      "env": {
        "ROUTER_MCP_HOST": "192.168.1.1",
        "ROUTER_MCP_USER": "root",
        "ROUTER_MCP_PASSWORD": "你的密码"
      }
    }
  }
}

新增服务器后需在 WorkBuddy 的连接器管理页点击「信任」才会启用。

Claude Desktop / 其他支持 MCP 的客户端:claude_desktop_config.json 使用同样的 mcpServers 结构。


6. 工具清单

工具

类型

参数

说明

router_info

只读

连接健康、init 系统、设备信息、生效的安全策略

service_list

只读

name_filter?, running_only?, with_start_time?

列出服务及运行状态

service_status

只读

name

单服务详情(PID、启动时间、自启状态)

service_logs

只读

name, lines=50

日志尾部(logread / journalctl)

service_start

写入

name, confirm?

启动服务

service_stop

写入

name, confirm?

停止服务

service_restart

写入

name, confirm?

重启服务(非幂等)

run_shell

高危

command, confirm?

在路由器上执行任意 shell 命令(默认关闭,需二次确认)

6.1 成功返回示例

{
  "ok": true,
  "tool": "service_status",
  "host": "192.168.1.1",
  "duration_ms": 412,
  "data": {
    "service": {
      "name": "dnsmasq",
      "running": true,
      "enabled": true,
      "pid": 2814,
      "started_at": "2026-09-10 09:00:12",
      "description": "/usr/sbin/dnsmasq -C /var/etc/dnsmasq.conf",
      "source": "procd"
    },
    "checked_at": "2026-09-10T09:21:03+08:00"
  },
  "error": null
}

6.2 需要二次确认时

{
  "ok": false,
  "tool": "service_restart",
  "host": "192.168.1.1",
  "error": {
    "code": "CONFIRMATION_REQUIRED",
    "message": "写入操作 restart 需要二次确认",
    "hint": "确认无误后再次调用,并传入 confirm=\"dnsmasq\"",
    "details": {"service": "dnsmasq", "expected_confirm": "dnsmasq"}
  }
}

6.3 常见用法(场景示例)

识别连接器本质(capability)

router_info 的返回中包含机器可读的 capability 字段(固定为 ssh-router-management),上层软件可据此确认本连接器是「可通过 SSH 操作路由器」的 MCP 连接器,而非普通工具:

{
  "ok": true,
  "tool": "router_info",
  "data": {
    "capability": "ssh-router-management",
    "init_system": "procd",
    "host": "192.168.1.1",
    "security": {
      "require_confirmation": true,
      "allow_shell": false,
      "denied_services": ["network", "firewall", "system", "boot", "done"]
    }
  }
}

通过 run_shell 安装插件(OpenWrt / ImmortalWrt)

服务管理类工具只覆盖已注册 init 脚本的服务,安装插件这类操作需走 run_shell 高危通道。先确保已设置 ROUTER_MCP_ALLOW_SHELL=true 启用该能力,再按「命令本身」做二次确认:

# 1) 刷新软件源并安装插件(OpenWrt 包管理器 opkg)
run_shell(
  command="opkg update && opkg install luci-app-sqm",
  confirm="opkg update && opkg install luci-app-sqm"
)

# 2) 安装后启用并随系统自启
run_shell(
  command="/etc/init.d/sqm enable && /etc/init.d/sqm start",
  confirm="/etc/init.d/sqm enable && /etc/init.d/sqm start"
)

经验证,opkg update / opkg install <包名> / 带 && 的连写均不会被高危拦截列表误拦;被拦的只有 rm -rf / mkfs / dd if= / 写 /dev/* / fork 炸弹 / curl ... | sh 等模式。 run_shellroot 身份在远端登录 shell 中执行,绕过服务白名单,仅应在可信网络内启用;每次执行都会写入审计日志(仅含命令本身,不含任何凭据)。

run_shell 返回示例

{
  "ok": true,
  "tool": "run_shell",
  "data": {
    "raw_command": "opkg update && opkg install luci-app-sqm",
    "exit_status": 0,
    "stdout": "Installing luci-app-sqm (...)",
    "stderr": "",
    "host": "192.168.1.1",
    "reused_connection": true,
    "confirmed": true,
    "warning": "命令以 root 身份在路由器上执行,已绕过服务白名单;请确认输出不含敏感信息"
  }
}

7. 安全模型

  1. 无 shell 拼接:所有命令以 argv 列表经 exec 通道下发,全程不出现 sh -c

  2. 服务名白名单^[A-Za-z0-9][A-Za-z0-9_.@+-]{0,63}$,拒绝 /、空格、;|&$、反引号、换行与 ..

  3. 路径白名单:可读路径限定为 /proc/1/comm/proc/uptime/proc/stat/etc/os-release/etc/openwrt_release/etc/init.d/etc/rc.d/run/systemd/system

  4. 写入二次确认confirm 必须与目标服务名完全一致;可用 ROUTER_MCP_REQUIRE_CONFIRM=false 关闭(不推荐)。

  5. 高危服务拒绝写入networkfirewallsystembootdone 默认只可读不可写(重启这些服务会断网或重启设备)。

  6. 可选服务白名单:设置 ROUTER_MCP_ALLOWED_SERVICES 后,白名单外的服务读写均被拒绝。

  7. 只读 / 写入标注:工具 annotations 标注 readOnlyHint / destructiveHint / idempotentHint,客户端可据此做权限提示。

  8. 可选 shell 能力(高危,默认关闭)run_shell 必须显式设置 ROUTER_MCP_ALLOW_SHELL=true 才会出现并可调用;启用后命令仍经 validate_shell_command 校验,默认拦截 rm -rf / mkfs / dd if= / 写入 /dev/* / fork 炸弹 / 管道进 shell 等高危模式,且必须把 confirm 设为命令本身的完整字符串才会真正执行。shell 命令以 root 身份在远端登录 shell 中执行,绕过服务白名单——这是刻意保留的逃生通道,而非默认能力。

  9. 口令不外泄config.redacted() 用于输出快照,日志与工具返回值中不含密码。


8. 错误码

错误码

触发场景

典型修复

CONFIG_ERROR

缺少 host / 认证方式,配置文件非法

设置 ROUTER_MCP_HOST 与口令或私钥

INVALID_INPUT

服务名 / 行数 / 参数非法

使用 service_list 获取合法服务名

BLOCKED_COMMAND

路径或参数绕过白名单

属于实现缺陷,请提交 issue

CONNECTION_FAILED

TCP 不可达、连接被重置

检查 host/port、设备 SSH 服务与防火墙

AUTH_FAILED

用户名 / 密码 / 私钥错误

核对凭据;OpenWrt 默认用户为 root

HOST_KEY_UNVERIFIED

known_hosts 不匹配

更新 known_hosts 或临时关闭严格校验

COMMAND_TIMEOUT

命令超过 COMMAND_TIMEOUT

调大超时,或检查设备负载

COMMAND_FAILED

命令返回非零退出码

查看返回中的 stderr 字段

SERVICE_NOT_FOUND

服务不存在

service_list 确认名称(注意大小写)

PERMISSION_DENIED

命中黑名单 / 白名单外 / polkit 拒绝

调整安全策略或以 root 连接

CONFIRMATION_REQUIRED

写入操作缺少正确 confirm

传入 confirm="<服务名>";shell 则需 confirm="<命令本身>"

SHELL_DISABLED

未开启 shell 能力却调用 run_shell

设置 ROUTER_MCP_ALLOW_SHELL=true 启用(谨慎)

UNSUPPORTED_ACTION

日志通道不可用(无 logread / journald)

启用 logd 或 journald 持久化

BACKEND_ERROR

解析 ubus / systemctl 输出失败

检查系统版本兼容性


9. 本地自测步骤

共四层,从无依赖到真实设备逐级验证。

第 1 层:离线单元测试(无需设备、无需网络)

pip install -e ".[dev]"
python -m pytest -q

覆盖:命令白名单、配置优先级、procd/systemd 解析、确认机制、黑名单、超时映射、错误结构。

第 2 层:MCP 协议冒烟(验证客户端视角)

# 仅握手 + 列工具,不需要设备
python scripts/mcp_smoke.py

# 真实调用一次只读工具
ROUTER_MCP_HOST=192.168.1.1 ROUTER_MCP_USER=root ROUTER_MCP_PASSWORD=xxx \
  python scripts/mcp_smoke.py --call router_info

# 带参数调用
python scripts/mcp_smoke.py --call service_status --args '{"name": "dnsmasq"}'

预期输出:握手成功、8 个工具、读写标注正确;调用失败时返回 ok=false 与错误码。

第 3 层:真实设备自测(只读)

ROUTER_MCP_HOST=192.168.1.1 ROUTER_MCP_USER=root ROUTER_MCP_PASSWORD=xxx \
  python scripts/selftest.py

依次验证:SSH 连接与 init 探测 → 服务列表 → 单服务状态 → 日志读取 → 错误路径(服务不存在)→ 写入二次确认拦截,并输出表格化结果。加 --json 可查看原始返回。

第 4 层:写入演练(谨慎)

python scripts/selftest.py --host 192.168.1.1 --password xxx \
  --service dnsmasq --do-write

会真正执行一次 restart。建议先挑选无状态影响的服务(如 dnsmasqodhcpd),不要在远程办公时段对 network / firewall 演练。

排障小贴士

现象

处理

AUTH_FAILED

OpenWrt 默认禁止空密码;确认 dropbear 允许该用户登录

COMMAND_TIMEOUT 频繁

设备 CPU 繁忙或网络丢包,调大 ROUTER_MCP_COMMAND_TIMEOUT

logread 无输出

确认 logd 在运行:service_status(name="log")

systemd 主机 PERMISSION_DENIED

以 root 连接,或配置 polkit / sudo 规则

想看 SSH 握手细节

设置 ROUTER_MCP_LOG_LEVEL=DEBUG(日志仅写 stderr,不影响 stdio 协议)


10. 已知限制

  • 单条 SSH 连接复用,写入操作串行执行;高并发场景建议为每个设备起独立进程。

  • OpenWrt 的启动时间依赖 /proc/<pid>/stat/proc/statbtime,容器或受限命名空间内可能拿不到。

  • service_list 默认不填充 started_at(避免对每个服务额外发起命令),需要时传 with_start_time=true 或调用 service_status

  • systemd 主机上 enabled 判定包含 static 状态(视为自启)。

  • 默认 run_shell 不可用(刻意的安全设计);仅当用户显式设置 ROUTER_MCP_ALLOW_SHELL=true 后才提供任意命令执行能力。该通道仍受高危拦截列表与强制二次确认约束,但本质上以 root 身份运行,请仅在可信网络内启用。


11. 许可证

MIT

Available Tools

8 tools
router_infoA
Read-onlyIdempotent

查询 SSH 连接健康状态、探测到的 init 系统、设备系统与生效的安全策略。

返回结构: {"ok": true, "tool": "router_info", "host": "...", "data": { "host", "port", "username", "backend", "ssh": {"connected", "reuse_count", "reconnect_count", "server_version", ...}, "device": {"uname", "release", "release_source"}, "security": {...}, "limits": {...}}}

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.7/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description reinforces this by using the read-only verb '查询' and disclosing the return structure, which adds context about the sort of diagnostic data provided. It does not go deeper into operational behavior beyond what annotations already state, so a 3 is appropriate.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is efficient: one line states the purpose, then a compact return structure is provided. The return structure is helpful and well organized, though the scattered fields inside the 'data' object could be slightly more compact. Overall every sentence earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description adequately covers what an agent needs to know to call this parameterless, read-only diagnostic tool. It explains the key data sections and the availability of an output schema means result documentation is already present. It could mention how this information supports other actions, but that is not essential for correct invocation.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool has zero parameters and schema description coverage is 100%, so there is nothing for the description to add. Baseline for 0 params is 4; the description simply confirms no inputs are needed.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool queries SSH connection health, detected init system, device system, and effective security policy. It uses a specific verb (查询/'query') with a concrete resource (router information), which is distinct from the sibling service_* and run_shell tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No explicit guidance is given on when to use this tool versus alternatives. The description only lists what it returns; it doesn't say that it is diagnostic, that it should be used before service operations, or when another tool would be a better choice. Usage must be inferred.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

run_shellA
Destructive

在路由器上执行任意 shell 命令(高危能力,默认关闭,需二次确认)。

安全约束(任意一条不满足都会返回错误而非执行): * 必须设置 ROUTER_MCP_ALLOW_SHELL=true 才会启用,否则返回 error.code = SHELL_DISABLED; * 默认拦截高危命令(rm -rf / mkfs / dd if= / 写入 /dev/* / fork 炸弹 / 管道进 shell 等), 命中时返回 error.code = BLOCKED_COMMAND; * 需把 confirm 设为命令本身的完整字符串进行二次确认,否则返回 CONFIRMATION_REQUIRED; * 命令以 root 身份在远端登录 shell 中执行,会绕过服务白名单,请谨慎使用。

参数: command: 要执行的 shell 命令字符串 confirm: 必须等于 command 的完整内容(含空格与引号)才真正执行

返回结构: {"ok": true, "data": {"raw_command", "exit_status", "stdout", "stderr", "duration_ms", "host", "reused_connection", "denied", "confirmed", "warning"}}

ParametersJSON Schema
NameRequiredDescriptionDefault
commandYes
confirmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.8/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description goes far beyond the annotations, detailing exact error codes (SHELL_DISABLED, BLOCKED_COMMAND, CONFIRMATION_REQUIRED), command-blocking rules, root execution, bypass of the service whitelist, and the required confirm mechanism. This is exemplary behavioral disclosure.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured with a high-level warning, bullet-pointed safety constraints, parameter explanations, and return structure. Each sentence carries necessary operational information, and the risk warning is front-loaded.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a complex, destructive, gated tool, this description covers enablement, blocked commands, confirmation requirements, execution identity, error codes, parameters, and return fields. An agent has everything it needs to invoke the tool safely and interpret results.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The input schema only provides types and nullability, with no description. The tool description fully compensates by explaining the command parameter and, crucially, that confirm must exactly equal the command string including spaces and quotes. This is essential semantic information the schema lacks.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific verb and resource: execute arbitrary shell commands on the router. It also immediately flags this as a high-risk capability, distinguishing it from the sibling service-management and read-only tools.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description provides strong context: it is for arbitrary shell commands and is high-risk, default-disabled, and requires confirmation. It does not explicitly name sibling tools as alternatives, but the scope is clear enough for an agent to know when this tool is intended.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_listA
Read-onlyIdempotent

列出路由器上的服务及其运行状态。

参数: name_filter: 按名称子串过滤(大小写不敏感),可选 running_only: 仅返回运行中的服务 with_start_time: 额外读取每个服务的启动时间(命令数随服务数增加,默认关闭)

返回结构: {"ok": true, "data": {"services": [{"name", "running", "enabled", "pid", "started_at", "description", "source"}], "count", "running_count", "init_system", "host", "warnings"}}

ParametersJSON Schema
NameRequiredDescriptionDefault
name_filterNo
running_onlyNo
with_start_timeNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already mark the tool as readOnly, idempotent, and non-destructive, lowering the burden on the description. The description adds valuable behavioral context: with_start_time grows the number of commands with service count and is off by default, and the output includes warnings. This meaningfully exceeds what annotations and schema alone provide.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: a one-sentence purpose, then a short parameter list with defaults/costs, then the return structure. Every section earns its place and there is no padding or redundant schema repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a read-only listing tool with three optional parameters, the description covers purpose, all parameter semantics, performance implications, and output shape. An agent has everything needed to invoke it correctly.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so parameter semantics depend entirely on the description. It fully explains all three parameters: case-insensitive substring filtering, running-only filtering, and with_start_time including its performance cost and default behavior. This adds real meaning beyond the bare schema types and defaults.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The opening sentence states '列出路由器上的服务及其运行状态' (list services and their running status on the router), a clear verb+resource description. The plural 'services' separates it from the more specific service_status sibling, though it does not explicitly name the alternative.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explains options such as name_filter, running_only, and with_start_time, and even warns about the command-count cost of with_start_time, giving some invocation guidance. It does not explicitly advise when to choose service_list over service_status or service_logs, so usage context is only implied.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_logsA
Read-onlyIdempotent

读取服务日志尾部内容(OpenWrt 走 logread,systemd 走 journalctl)。

参数: name: 服务名 lines: 返回行数,1 <= lines <= ROUTER_MCP_MAX_LOG_LINES(默认 500)

返回结构: {"ok": true, "data": {"name", "requested_lines", "returned_lines", "source", "command", "truncated", "lines": [...] }}

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
linesNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

注释已声明 readOnlyHint=true、idempotentHint=true、destructiveHint=false,安全概况清楚。描述在此基础上补充了执行细节(具体命令 logread/journalctl)和返回结构,包括 'truncated' 字段暗示可能截断,增强了行为透明度。没有与注释矛盾,且为只读工具提供了有用的上下文。

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

描述简洁且结构清晰:首句概括功能,随后分列参数,最后给出返回结构。无冗余信息,关键约束前置,便于快速理解。

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

对于简单的只读工具,描述涵盖了调用所需的核心信息:参数意义、返回结构、实现方式。虽有输出模式的定义在描述中而非独立 schema,但足够指导调用。未提及错误情况(如服务不存在)或平台差异的细节,略微不完整,但基于工具复杂度此描述已基本充足。

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema 覆盖率为 0%,描述完全承担参数解释:为 name 提供含义(服务名),为 lines 提供范围约束和上限说明(1 <= lines <= ROUTER_MCP_MAX_LOG_LINES,默认500)。这远超 Schema 中仅有类型和默认值的信息,有效补偿了 schema 的空白。不过默认值措辞存在一定模糊性(可能指上限默认值而非 lines 默认值),小有扣分。

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

描述明确说'读取服务日志尾部内容',具体动词+资源,并指出底层实现(OpenWrt logread / systemd journalctl),与兄弟工具(service_status 查看状态、service_start 控制服务)明显区分。这比简单的'查看日志'更为具体,界定了范围。

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

描述暗示这是获取服务日志的专用工具,但没有明确说明何时使用它而非兄弟工具(如 run_shell 直接执行命令,或 service_status 查看状态)。没有提供使用场景的排除条件或替代说明,因此仅靠隐含语境,未给出明确指引。

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_restartA
Destructive

重启指定服务(写入操作,需二次确认)。

参数与返回结构同 service_start。restart 非幂等,重复调用会重复中断服务。

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
confirmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.6/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

描述披露了写入操作、非幂等性和重复调用会中断服务,这些信息在annotations中未提及(annotations仅有destructiveHint),补充了关键行为。但没有说明权限要求或返回格式等,不过仍有实质增量。

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

两句话简洁明了,第一句说明功能和写入性质,第二句补充参数和幂等性,没有冗余,信息密度高。结构合理,关键信息前置。

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

有输出schema但内容未知,描述中通过引用service_start的返回结构提供间接说明。但confirm参数如何填写(如需要什么值)未说明,依赖外部定义,整体完整性一般。

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

schema覆盖率为0%,描述指出'参数与返回结构同service_start',提供了参考路径但未直接解释每个参数。对于已知service_start的用户有帮助,但独立使用仍显不足,因此评分中等。

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

描述以'重启指定服务'开头,明确动词和对象,并注明是写入操作。但未直接说明与service_start、service_stop的区别,如重启与先停再起的差别,因此未完全区分开兄弟工具,但基本清晰。

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

提到'需二次确认'暗示应谨慎使用,且强调非幂等和重复中断,提供了使用时的注意事项。但未明确说明何时应该用restart而不是start或stop,也没有排除场景。

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_startA
Idempotent

启动指定服务(写入操作,需二次确认)。

参数: name: 服务名 confirm: 必须等于服务名才真正执行;否则返回 error.code = CONFIRMATION_REQUIRED

返回结构: {"ok": true, "data": {"name", "action", "exit_status", "command", "stdout", "stderr", "duration_ms", "state_before", "state_after"}}

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
confirmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.2/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The description adds substantial behavioral context beyond the annotations: it warns that this is a write operation needing secondary confirmation, states that confirm must equal the service name, and documents the exact error code CONFIRMATION_REQUIRED. It also previews state_before/state_after and output fields, which helps the agent anticipate side effects and return behavior.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-organized and front-loaded, opening with the operation type and confirmation requirement before listing parameters. The return-structure block is useful but somewhat redundant given that an output schema exists, which prevents a perfect conciseness score.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the core invocation contract, confirmation logic, error behavior, and return shape, so an agent can call the tool correctly. It is slightly incomplete in not mentioning prerequisites such as service existence or permissions, and it does not route the agent to related service tools for discovery.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 0% schema description coverage, the description fully compensates by explaining both parameters: name is the service name, and confirm must match the service name to execute. This is essential semantic information that the bare input schema does not provide.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states a specific action and resource: '启动指定服务' (start the specified service), and further marks it as a write operation requiring confirmation. This makes the tool's purpose unmistakable, though it does not explicitly differentiate itself from sibling tools like service_stop or service_restart.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The intended use is implied: use this tool to start a service and provide confirmation. However, the description gives no explicit guidance about when to prefer this over siblings such as service_restart or service_status, and no exclusions are mentioned.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_statusA
Read-onlyIdempotent

查询单个服务的运行状态、PID、启动时间与开机自启状态。

参数: name: 服务名(OpenWrt 为 /etc/init.d 脚本名,systemd 为 unit 名,如 sshd.service)

返回结构: {"ok": true, "data": {"service": {"name", "running", "enabled", "pid", "started_at", "description", "source"}, "checked_at", "init_system"}}

服务不存在时返回 ok=false,error.code = SERVICE_NOT_FOUND,并在 details 中给出可用服务样例。

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the description need not labor the safety profile. It adds value by disclosing the exact return structure (fields like running, enabled, pid, started_at, source, init_system) and error behavior (ok=false with error.code=SERVICE_NOT_FOUND and details with examples). This informs the agent about response shape and failure mode beyond the schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is well-structured: purpose statement first, then parameter explanation, return structure, and error handling. Each section is concise and earns its place. It is not overly verbose, though it could be slightly tightened; the parameter and return details are essential. The front-loaded purpose immediately clarifies the tool's role.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple, single-parameter read-only query, the description is complete: it covers the parameter format (for both init systems), the exact return structure, and the error case with a specific error code and guidance. Since an output schema exists (as per context signals), the description correctly focuses on the naming semantics and error behavior rather than repeating the schema. Nothing an agent needs to call it correctly is missing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description carries the full burden. It explains that 'name' is the service name, with concrete naming conventions: OpenWrt uses /etc/init.d script names, systemd uses unit names like 'sshd.service'. It also gives an example. This goes well beyond the bare schema property and compensates completely for the lack of schema documentation.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states it queries the running status, PID, start time, and auto-start state of a single service. The phrase '单个服务' (single service) explicitly distinguishes it from sibling tools like service_list (which would enumerate services) and service_start/service_stop (which mutate state). The verb '查询' (query) is specific and matches the read-only intent.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage for checking a single service, but does not explicitly state when to use this over service_list (e.g., 'use service_list to enumerate services; use this to check a specific one'). It provides no exclusions or alternative routing. The 'service not found' error handling hints at expected input, but there's no direct guidance on when to choose this tool versus siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

service_stopA
DestructiveIdempotent

停止指定服务(写入操作,需二次确认)。

参数与返回结构同 service_start。注意停止 ssh/dropbear 会导致连接中断。

ParametersJSON Schema
NameRequiredDescriptionDefault
nameYes
confirmNo

Output Schema

ParametersJSON Schema
NameRequiredDescription
resultYes

TDQS

A3.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already provide destructiveHint=true, readOnlyHint=false, and idempotentHint=true, so the bar is lower. The description adds meaningful behavioral context: '需二次确认' (requires second confirmation) and the warning that stopping ssh/dropbear will interrupt the connection, both of which are absent from the annotations and schema.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is compact and front-loaded: the first clause states the operation, followed by confirmation and connection-risk warnings. Every sentence contributes useful information with no filler or repetition.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The description covers the key safety context and confirms the return-structure relationship to service_start, and an output schema exists. However, it relies on sibling service_start for parameter semantics and does not specify how the confirm parameter should be set, leaving a real gap for a destructive tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, and the description only says parameters mirror service_start without explaining 'name' or the expected value/format of 'confirm'. Even though the confirmation requirement is implied, the agent is left with insufficient information about how to satisfy the confirm parameter.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the action '停止指定服务' (stop specified service), naming both the verb and the target resource. This distinguishes it from siblings like service_start and service_restart, and it additionally flags that this is a write operation.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The usage is implied by the verb 'stop', but there is no explicit when-to-use versus alternatives guidance. The description does add a valuable warning about stopping ssh/dropbear causing disconnection and mentions the confirmation requirement, which helps the agent execute correctly but not select the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 8 tool updatesv0.2.0
    • First observedrouter_info
    • First observedrun_shell
    • First observedservice_list
    • First observedservice_logs
    • First observedservice_restart
    • First observedservice_start
    • First observedservice_status
    • First observedservice_stop

TDQS

A4.1/5.0

Scored across 8 tools

Disambiguation5/5

Each tool has a clearly distinct role: router-level info, service list/status/logs, three explicit service actions, and shell execution. The service_list/service_status pair is well-differentiated as bulk listing vs single-service lookup.

Naming Consistency4/5

The service_* family follows a predictable and readable pattern, and all names use snake_case. Minor deviations exist: router_info is noun-style rather than verb_noun, and service_logs uses a noun instead of a verb like service_log.

Tool Count5/5

Eight tools is well-scoped for an SSH-based router management server. The set covers inspection, logs, and service lifecycle operations without bloating the surface.

Completeness4/5

Core service operations—list, status, logs, start, stop, restart—are covered, plus router health info and shell fallback. A notable minor gap is the lack of first-class service enable/disable operations, since the enabled state is reported but cannot be changed through the main tools.

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers