router-ssh-mcp
Provides SSH-based service management for generic Linux systems using systemd or sysvinit, including service listing, status checks, log reading, and controlled start/stop/restart with confirmation.
Allows managing services on OpenWrt/ImmortalWrt routers over SSH, including listing services, checking status, reading logs, and performing confirmed start/stop/restart operations, with an optional high-risk shell command capability.
Click on "Install Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@router-ssh-mcp@router-ssh-mcp show the status of the dropbear SSH service and the last 20 log lines"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
router-ssh-mcp
通过 SSH 管理路由器(OpenWrt / ImmortalWrt / 通用 Linux)上服务的 MCP(Model Context Protocol)服务器。
上层模型可以列出服务、查询状态、读取日志,并在二次确认后执行启动 / 停止 / 重启,全程受命令白名单约束;此外提供一个默认关闭的高危 run_shell 能力,在显式开启并二次确认后可于远端执行任意 shell 命令,用于白名单工具覆盖不到的排障场景。
1. 能力概览
能力 | 说明 |
多 init 系统 | 自动探测 |
连接复用 | 进程内复用单条 SSH 连接,带 keepalive 与断线重连 |
只读 / 写入分离 | 4 个只读工具 + 3 个写入工具 + 1 个高危 shell 工具,通过 MCP annotations 标注 |
写入二次确认 | 写入工具必须传 |
命令白名单 | 所有命令以 argv 序列下发,不经 shell;服务名、路径、行数均做严格校验 |
可选 shell 能力 |
|
结构化输出 | 统一返回 |
结构化错误 | 连接、认证、超时、服务不存在等均映射为稳定错误码 + 修复建议 |
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 环境变量
变量 | 默认值 | 说明 |
|
| SSH 主机 |
|
| SSH 端口 |
|
| SSH 用户名 |
| — | 密码(与 |
| — | 私钥路径 |
| — | 私钥口令;未设置时会尝试用 |
|
|
|
|
| 连接超时(秒) |
|
| 单条命令超时(秒) |
|
| 保活间隔(秒) |
|
| 连续保活失败次数阈值 |
|
| 命令失败重连重试次数 |
|
| 单次日志读取上限 |
|
| 写入操作是否要求二次确认 |
| 空 | 服务白名单,逗号分隔;为空表示不限制 |
|
| 禁止写入的高危服务 |
|
| 是否校验 known_hosts(路由器重装后建议临时关闭) |
| — | known_hosts 路径(仅在严格模式下生效) |
|
| 是否启用高危的 |
|
|
|
|
| 是否拦截高危命令(rm -rf / mkfs / dd / 写 /dev/* / fork 炸弹 / 管道进 shell) |
|
| asyncssh 日志级别,排障时设 |
4.2 配置文件
复制 config.example.json 为 config.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-http5.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. 工具清单
工具 | 类型 | 参数 | 说明 |
| 只读 | — | 连接健康、init 系统、设备信息、生效的安全策略 |
| 只读 |
| 列出服务及运行状态 |
| 只读 |
| 单服务详情(PID、启动时间、自启状态) |
| 只读 |
| 日志尾部(logread / journalctl) |
| 写入 |
| 启动服务 |
| 写入 |
| 停止服务 |
| 写入 |
| 重启服务(非幂等) |
| 高危 |
| 在路由器上执行任意 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_shell以 root 身份在远端登录 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. 安全模型
无 shell 拼接:所有命令以 argv 列表经 exec 通道下发,全程不出现
sh -c。服务名白名单:
^[A-Za-z0-9][A-Za-z0-9_.@+-]{0,63}$,拒绝/、空格、;、|、&、$、反引号、换行与..。路径白名单:可读路径限定为
/proc/1/comm、/proc/uptime、/proc/stat、/etc/os-release、/etc/openwrt_release、/etc/init.d、/etc/rc.d、/run/systemd/system。写入二次确认:
confirm必须与目标服务名完全一致;可用ROUTER_MCP_REQUIRE_CONFIRM=false关闭(不推荐)。高危服务拒绝写入:
network、firewall、system、boot、done默认只可读不可写(重启这些服务会断网或重启设备)。可选服务白名单:设置
ROUTER_MCP_ALLOWED_SERVICES后,白名单外的服务读写均被拒绝。只读 / 写入标注:工具 annotations 标注
readOnlyHint/destructiveHint/idempotentHint,客户端可据此做权限提示。可选 shell 能力(高危,默认关闭):
run_shell必须显式设置ROUTER_MCP_ALLOW_SHELL=true才会出现并可调用;启用后命令仍经validate_shell_command校验,默认拦截rm -rf / mkfs / dd if= / 写入 /dev/* / fork 炸弹 / 管道进 shell等高危模式,且必须把confirm设为命令本身的完整字符串才会真正执行。shell 命令以 root 身份在远端登录 shell 中执行,绕过服务白名单——这是刻意保留的逃生通道,而非默认能力。口令不外泄:
config.redacted()用于输出快照,日志与工具返回值中不含密码。
8. 错误码
错误码 | 触发场景 | 典型修复 |
| 缺少 host / 认证方式,配置文件非法 | 设置 |
| 服务名 / 行数 / 参数非法 | 使用 |
| 路径或参数绕过白名单 | 属于实现缺陷,请提交 issue |
| TCP 不可达、连接被重置 | 检查 host/port、设备 SSH 服务与防火墙 |
| 用户名 / 密码 / 私钥错误 | 核对凭据;OpenWrt 默认用户为 |
| known_hosts 不匹配 | 更新 known_hosts 或临时关闭严格校验 |
| 命令超过 | 调大超时,或检查设备负载 |
| 命令返回非零退出码 | 查看返回中的 |
| 服务不存在 | 用 |
| 命中黑名单 / 白名单外 / polkit 拒绝 | 调整安全策略或以 root 连接 |
| 写入操作缺少正确 confirm | 传入 |
| 未开启 shell 能力却调用 | 设置 |
| 日志通道不可用(无 logread / journald) | 启用 logd 或 journald 持久化 |
| 解析 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。建议先挑选无状态影响的服务(如 dnsmasq、odhcpd),不要在远程办公时段对 network / firewall 演练。
排障小贴士
现象 | 处理 |
| OpenWrt 默认禁止空密码;确认 dropbear 允许该用户登录 |
| 设备 CPU 繁忙或网络丢包,调大 |
| 确认 |
systemd 主机 | 以 root 连接,或配置 polkit / sudo 规则 |
想看 SSH 握手细节 | 设置 |
10. 已知限制
单条 SSH 连接复用,写入操作串行执行;高并发场景建议为每个设备起独立进程。
OpenWrt 的启动时间依赖
/proc/<pid>/stat与/proc/stat的btime,容器或受限命名空间内可能拿不到。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 toolsrouter_infoARead-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": {...}}}
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_shellADestructive
在路由器上执行任意 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"}}
| Name | Required | Description | Default |
|---|---|---|---|
| command | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_listARead-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"}}
| Name | Required | Description | Default |
|---|---|---|---|
| name_filter | No | ||
| running_only | No | ||
| with_start_time | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_logsARead-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": [...] }}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| lines | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_restartADestructive
重启指定服务(写入操作,需二次确认)。
参数与返回结构同 service_start。restart 非幂等,重复调用会重复中断服务。
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_startAIdempotent
启动指定服务(写入操作,需二次确认)。
参数: name: 服务名 confirm: 必须等于服务名才真正执行;否则返回 error.code = CONFIRMATION_REQUIRED
返回结构: {"ok": true, "data": {"name", "action", "exit_status", "command", "stdout", "stderr", "duration_ms", "state_before", "state_after"}}
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_statusARead-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 中给出可用服务样例。
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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_stopADestructiveIdempotent
停止指定服务(写入操作,需二次确认)。
参数与返回结构同 service_start。注意停止 ssh/dropbear 会导致连接中断。
| Name | Required | Description | Default |
|---|---|---|---|
| name | Yes | ||
| confirm | No |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
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.
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.
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.
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.
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.
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.
8 tool updates
v0.2.0- First observed
router_info - First observed
run_shell - First observed
service_list - First observed
service_logs - First observed
service_restart - First observed
service_start - First observed
service_status - First observed
service_stop
TDQS
Scored across 8 tools
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.
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.
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.
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
- emisarOAuthdev.emisar
Let AI operate servers without SSH. Choose actions, approve risky changes, and audit every step.
Operate Linux, macOS and Windows from your LLM. Every action runs through an auditable allowlist.
Scoped, audited SSH exec, sessions, and SFTP on your saved servers without exposing credentials
Manage FadeHost game servers, Discord bots and VPS: console, stats, backups, logs, lifecycle.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables management of ASUS routers running Asuswrt-Merlin firmware via SSH/SCP. Supports system monitoring, device management, WiFi control, service restarts, NVRAM operations, file transfers, VPN management, and custom command execution.11MIT
- AlicenseAqualityFmaintenanceEnables AI agents to manage OpenWRT routers remotely via SSH, supporting system monitoring, network management, OpenThread Border Router configuration, and package management through natural language commands.1916MIT
- AlicenseBqualityDmaintenanceEnables AI assistants to monitor and securely manage AsusWRT and AsusWRT-Merlin routers via SSH with allowlisted commands, supporting read-only monitoring and controlled mutations.472MIT
- AlicenseNot gradedqualityAmaintenanceProvides full administrative control of OpenWRT routers via SSH, with a preview-confirm safety model for mutating operations.19MIT