关于 vllm-ops-mcp
vllm-ops-mcp 是面向本地 vLLM 实例的只读运维与健康检查 MCP 服务,针对由 WSL2 和 systemd 管理的环境。它通过 HTTP 探测区分存活与实际生成能力,并提供 GPU、服务状态及启动参数信息。
主要功能
- 01分层检查存活与生成能力
- 02列出可用模型
- 03执行限频的测试生成
- 04查看 GPU 显存与利用率
- 05查询 systemd 服务状态
- 06读取并脱敏启动参数
适用场景
- 01确认 vLLM 是否能实际生成
- 02检查 GPU 显存和利用率
- 03排查服务状态与启动参数
MCP 相关
向 MCP 客户端提供六个只读工具,用于健康探测、模型查询、测试生成和本地运行状态检查。深度健康检查与测试生成会调用真实推理,并受频率限制。
配置
本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。
工具
6收录的工具列表 · 更新于 2 周前
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
| deep | boolean | 否 |
详细介绍
vllm-ops-mcp
面向本地、由 WSL2/systemd 管理的 vLLM 服务的只读运维/健康 MCP 服务——提供存活状态与实际完成请求健康等级、GPU/VRAM 状态、systemd 服务状态,以及实时服务启动标志检查。它遵循与 mcp-factory、desktop-mcp 及该运维人员作品集中的其他本地工具相同的标准:独立的 pyproject、独立的 fastmcp 服务、诚实的 README、真实的测试套件,并且只有在确认规格后才编写产品代码。
这不是容器生命周期管理器。它假定 vLLM 已作为裸机 systemd 单元在 WSL2 中运行(这是该运维人员实际使用的配置——见 vllm-autostart),而非运行在 Docker/Podman 中。
快速开始
// ~/.claude.json (or any MCP-host stdio client config)
{
"mcpServers": {
"vllm-ops-mcp": {
"type": "stdio",
"command": "C:\\Users\\<you>\\projects\\vllm-ops-mcp\\.venv\\Scripts\\python.exe",
"args": ["C:\\Users\\<you>\\projects\\vllm-ops-mcp\\run_server.py"]
}
}
}
工具(阶段 1——全部为只读,除吞吐量上限外无需其他限制)
| 工具 | 功能 | 无法完成的操作 |
|---|---|---|
check_health(deep: bool = False) | deep=False:GET /v1/models 存活检查(与 llm_router.LocalLLM.is_healthy() 的信号相同)。deep=True:还会发起一次最小的真实 /v1/chat/completions 调用(与 check-vllm.cmd 的两阶段探测相对应),以确认服务确实会生成内容,而不只是报告已加载模型。 | 无法修复降级的服务——只报告实际状态。deep=True 受到速率限制(默认每分钟 20 次,见下文)。 |
list_models | 直接转发 /v1/models。 | 无法提供超出 vLLM API 本身所公开内容的详情。 |
test_completion(prompt, max_tokens=16) | 使用调用者提供的提示词,按需进行真实补全,以便手动进行健全性检查。 | 受到速率限制(与 check_health(deep=True) 使用同一个限制桶);如果存活检查未通过,则拒绝执行(服务甚至未在监听时,发起补全毫无意义)。max_tokens 会在服务端限制为 1024(config.MAX_TEST_COMPLETION_TOKENS),提示词上限为 8000 个字符(config.MAX_TEST_COMPLETION_PROMPT_CHARS;超长提示词会被拒绝,而不会截断)——速率限制只限制调用频率,不限制单次调用的成本。 |
get_gpu_status | nvidia-smi 封装:每个 GPU 的已用/总 VRAM 和利用率%,以及通过 --query-compute-apps 获取的各进程 VRAM。 | 在该运维人员实际使用的 WSL2 配置中,无法按进程归属 VRAM——即使 vLLM 进程占用 13.7GB,实时验证结果仍为空(见“限制”)。processes 仅供尽力而为,且经常为空,不应视为可靠的按 PID 细分结果。 |
get_service_status | 通过 Windows 主机上的 wsl -d <distro> 执行 systemctl show <unit> -p ...(返回结构化属性,而非解析自由文本);如果此服务本身运行在 WSL2/Linux 内,则使用原生 systemctl。返回加载/活动/子状态、重启次数、主 PID 和上次活动时间戳。 | 只读——无法启动/停止/重启单元。不计算运行时长(这是有意为之——见“限制”中的时钟同步说明)。 |
get_serve_config | 只读的启动标志检查。优先读取运行中进程的实际 argv(systemd 单元 MainPID 对应的 /proc/<pid>/cmdline——这是当前运行状态的真实依据);仅当进程未运行时,才回退到静态执行脚本(通过 VLLM_OPS_MCP_SERVE_CONFIG_PATH 指定的本地镜像,否则实时读取 WSL 侧执行脚本)。 | vLLM 不会通过 API 公开自身的启动标志,因此此工具不会查询服务本身——它始终通过 shell 命令读取。执行脚本回退解析是尽力而为的 shell 文本解析(精度低于实时 argv 路径)。 |
未来扩展:restart_service(第 2 阶段,尚未构建)
本版本中特意不实现。根据规范:vLLM 是其他机器人/工具依赖的共享基础设施(options-bot、qwen_cli.py 调用方、DeerFlow 回退机制),因此重启工具需要有自己的门控设计(默认关闭,VLLM_OPS_MCP_ENABLE_RESTART=1,除非 force=True,否则拒绝操作健康实例,并限制调用频率)之后才能发布——而不是事后改造只读 MVP。此功能仅列为 v2 的构想,并非当前能力。如果要构建,应封装 run-vllm.cmd 中的确切方案(仅执行 systemctl start vllm,绝不盲目执行 stop/restart),而非另行发明方案。
差异化优势:探测 HTTP,而非监听器
此服务中的所有健康信号都来自对 OpenAI 兼容 API 的实际 HTTP 请求(使用 urllib.request,而非套接字/连接检查)。这是刻意为之,并非偶然:Get-NetTCPConnection 等基于监听器的检查完全无法发现经 WSL2 镜像网络转发的端口——从 Windows 主机运行监听器探测时,实际健康的 127.0.0.1:8000 可能不可见。check-vllm.cmd 已经体现了这一经验;此服务则将其扩展为两层(存活状态与实际生成),而这两层是该运维人员的工具集里其他 MCP 工具都不具备的。
安全性
注册 vllm-ops-mcp 前请先阅读本节。坦诚说明影响范围正是本节的重点。
- **此服务会调用
nvidia-smi、systemctl(通过wsl -d),并读取/proc/<pid>/cmdline。**全部六个工具均为只读——这里没有任何操作会启动、停止、重启或终止进程,也没有工具会接收未经转义就传入 shell 的参数(单元/发行版名称来自服务端配置,而非调用方输入;shlex.quote会封装唯一一个与调用方相邻且确实会进入 shell 字符串的路径,即systemctl show中的单元名称)。 - **
check_health(deep=True)和test_completion会向共享 GPU 服务发送实际推理请求。**这两项操作受频率限制(默认每分钟 20 次,由VLLM_OPS_MCP_DEEP_RATE_LIMIT_PER_MIN配置),尤其因为此 vLLM 实例是其他机器人/工具依赖的共享基础设施——即使每次调用单独来看都是“只读”的,调用方反复请求此 MCP 仍可能耗尽资源或拖慢其他使用方。 get_serve_config的实时进程路径会读取/proc/<pid>/cmdline,如果曾将机密作为 CLI 标志传入,其中可能包含机密信息(在该运维人员的实际设置中并无此情况——模型路径和标志均非机密;如有身份验证信息,则通过环境变量注入执行脚本,而非作为 argv 标志传入)。作为纵深防御措施:对于前一个标志名称匹配已知敏感模式(token、key、secret、password、passwd、credential——config. SENSITIVE_ARGV_FLAG_PATTERNS)的任何 argv 条目,其值在返回前都会被替换为[REDACTED],结构化的argv/flags字段和raw_text中均如此;标志名称本身保持可见,以便仍能诊断参数结构。此规则适用于全部三个来源(live_process、exec_script、local_config_mirror)。- **此版本中的工具均不具备写入/修改能力。**没有任何环境变量可以启用此类能力——
restart_service尚不存在于此代码库中(见上文“未来扩展”),因此也就不存在误启用的可能。
能力真实性表
| 声明 | 实现 | 验证方式 |
|---|---|---|
存活健康等级(/v1/models) | vllm_ops_mcp/probes.py::_probe_models、check_health | tests/test_probes.py::TestCheckHealthLiveness;实时验证:tests/test_live_smoke.py::test_live_check_health_liveness |
| 深度/真实补全健康等级 | vllm_ops_mcp/probes.py::_probe_completion、check_health(deep=True) | tests/test_probes.py::TestCheckHealthDeep;实时验证:test_live_check_health_deep |
| 模型列表透传 | probes.py::list_models | tests/test_probes.py::TestListModels;实时验证:test_live_list_models |
| 按需补全健全性检查 | probes.py::test_completion | tests/test_probes.py::TestTestCompletion;实时验证:test_live_test_completion |
| 通过 nvidia-smi 获取 GPU/VRAM 状态 | probes.py::get_gpu_status | tests/test_probes.py::TestGetGpuStatus;实时验证:test_live_get_gpu_status |
| 按进程归属 VRAM | probes.py::get_gpu_status(--query-compute-apps) | 使用模拟的非空响应进行单元测试;实时验证确认,在此操作员的实际 WSL2 环境中返回 EMPTY——请参阅限制 |
通过结构化的 systemctl show 获取 systemd 单元状态 | probes.py::get_service_status | tests/test_probes.py::TestGetServiceStatus;实时验证:test_live_get_service_status |
通过 /proc/<pid>/cmdline 检查运行中进程的启动标志 | probes.py::get_serve_config、parse_launch_flags | tests/test_probes.py::TestGetServeConfig、TestParseLaunchFlags;实时验证:test_live_get_serve_config——实时确认其能够找回启动标志(--enable-auto-tool-choice --tool-call-parser qwen3_xml),而这些标志未出现在本仓库自身的依据规范中,证明实时 argv 方法优于信任静态文档 |
| 单元停止时回退到 Exec 脚本 | probes.py::get_serve_config、_parse_exec_script_text | tests/test_probes.py::TestGetServeConfig::test_falls_back_to_exec_script_when_service_down |
| 本地配置镜像覆盖路径 | probes.py::get_serve_config + config.serve_config_override_path | tests/test_probes.py::TestGetServeConfig::test_uses_local_override_file、test_override_file_missing_reports_error |
在 get_serve_config 中对敏感标志值进行脱敏 | probes.py::redact_argv、redact_raw_text、config.SENSITIVE_ARGV_FLAG_PATTERNS | tests/test_probes.py::TestGetServeConfig::test_live_process_redacts_sensitive_flag_values、test_exec_script_raw_text_redacts_sensitive_flag_values、test_local_override_file_redacts_sensitive_flag_values |
| 深度推理速率限制(共享基础设施保护) | config.py::TokenBucket、DeepRateLimiter、check_deep_rate_limit | tests/test_config.py::TestTokenBucket、TestDeepRateLimiter |
| WSL 与原生 shell-out 抽象 | probes.py::_shell_args、config.runs_in_wsl | tests/test_config.py::TestRunsInWsl;tests/test_probes.py::TestGetServiceStatus::test_uses_wsl_prefix_on_windows、test_no_wsl_prefix_when_native |
| 已注册全部 6 个工具,未包含 Phase-2 工具 | vllm_ops_mcp/server.py | tests/test_server.py |
局限(依赖此功能前请阅读)
- 在此运维人员实际使用的 WSL2 GPU 直通配置下,按进程归属的显存数据不可靠。
get_gpu_status的实时冒烟测试(使用真实的nvidia-smi.exe查询真实运行中的 vLLM 进程)返回了一个空的processes列表,尽管同一次调用中的gpus[0].memory_used_mib正确显示该进程占用了 13.7GB。这是部分 WSL2/直通配置下已记录的nvidia-smi --query-compute-apps局限,并非此服务的解析错误——工具如实报告空结果(ok: true, processes: []),而没有伪造归属信息。在此配置下,请勿依赖processes来排查显存超额占用的根因;gpus[].memory_used_mib才是可靠指标。 - 不计算服务运行时长。
get_service_status返回systemctl中原始的ActiveEnterTimestamp字符串(已标注时区,例如MDT),而不是在服务端计算已过时长——这是刻意设计的,遵循此运维人员自己的时钟纪律规则(绝不根据估算陈述已过时长或预计时间;产物时间戳通常为 UTC,而本地时间为 UTC-6/-7)。如果需要,请在调用处进行计算,并显式转换时区。 get_serve_config的 exec 脚本回退方案采用尽力而为的 shell 文本解析,并非精确的 argv 数组——它通过shlex.split处理\行续接和基本引号,但形式足够特殊的 exec 脚本可能会解析错误。实时进程路径(/proc/<pid>/cmdline)不受此局限(这是内核提供的精确 argv,以空字符分隔),并且只要单元处于运行状态,就始终优先使用此路径。- 默认针对 WSL2,但相关接口边界明确。
get_service_status和get_serve_config的实时进程路径假定此服务运行在 Windows 主机上,并通过wsl -d <distro>在 WSL2 中执行命令。如果此服务进程本身在 WSL2/Linux 中原生运行,请设置VLLM_OPS_MCP_RUNS_IN_WSL=1(使用原生systemctl/cat,不经wsl -d跳转)——这两种路径均经过单元测试(TestGetServiceStatus::test_uses_wsl_prefix_on_windows/test_no_wsl_prefix_when_native),但只有 Windows 主机路径已在此运维人员的实际配置中进行过实时验证。 - 适用于此运维人员的单个 vLLM 实例、单个 GPU 配置。 不支持聚合多个实例或多个 GPU;
get_gpu_status会返回nvidia-smi --query-gpu枚举到的所有 GPU,也就是进程可见的每个 GPU,而不会在存在多个 GPU 时限定为“vLLM 正在使用的 GPU”。 - 此版本完全不提供生命周期控制。 请参阅上文“未来扩展”——这是有意为之,并非疏忽。
环境变量
| 变量 | 作用 | 默认值 |
|---|---|---|
VLLM_OPS_MCP_BASE_URL | OpenAI 兼容的基础 URL | http://127.0.0.1:8000/v1(显式使用 127.0.0.1,而非 localhost——请参阅 qwen_cli.py 中关于 IPv6 挂起问题的注意事项) |
VLLM_OPS_MCP_MODEL | 服务模型名称,用于补全请求负载 | qwen3-14b |
VLLM_OPS_MCP_WSL_DISTRO | 托管 vLLM 的 WSL 发行版 | Ubuntu-22.04 |
VLLM_OPS_MCP_SERVICE_UNIT | systemd 单元名称 | vllm |
VLLM_OPS_MCP_EXEC_SCRIPT_PATH | serve exec 脚本在 WSL 中的路径(回退来源) | ~/vllm-systemd-exec.sh |
VLLM_OPS_MCP_SERVE_CONFIG_PATH | exec 脚本的本地文件副本;如果设置,get_serve_config 会直接读取此文件,而不是在回退时进入 WSL 执行命令 | 未设置 |
VLLM_OPS_MCP_NVIDIA_SMI_PATH | 覆盖 nvidia-smi 二进制文件路径 | nvidia-smi(Windows 主机)/ nvidia-smi.exe(原生 WSL2) |
VLLM_OPS_MCP_RUNS_IN_WSL | 若此服务进程本身在 WSL2/Linux 中运行,则设为 1(跳过 wsl -d 跳转) | 根据 sys.platform 自动检测 |
VLLM_OPS_MCP_DEEP_RATE_LIMIT_PER_MIN | 限制每分钟调用 check_health(deep=True) 和 test_completion 的次数 | 20 |
VLLM_OPS_MCP_LIVE | 设为 1 以运行真实基础设施冒烟测试(请参阅“测试”) | 未设置(跳过) |
使用示例
// A tool call from the MCP host, illustrative -- not a shell command.
{"tool": "check_health", "arguments": {"deep": true}}
// -> {"ok": true, "status": "up", "tier": "deep", "model_id": "qwen3-14b",
// "latency_ms": 32.0, "completion_s": 0.218, "error": ""}
{"tool": "get_serve_config", "arguments": {}}
// -> {"ok": true, "source": "live_process", "pid": 5645,
// "flags": {"model": "Qwen/Qwen3-14B-AWQ", "served_model_name": "qwen3-14b",
// "port": "8000", "max_model_len": "8192",
// "gpu_memory_utilization": "0.72", "max_num_seqs": "8",
// "enable_auto_tool_choice": true, "tool_call_parser": "qwen3_xml", ...}}
// rate limit exceeded (21st deep call within a minute):
{"tool": "test_completion", "arguments": {"prompt": "hi"}}
// -> {"ok": false, "error": {"type": "rate_limited", "group": "deep_inference",
// "tool": "test_completion", "limit_per_min": 20, "retry_after_s": 4.87}}
测试
CI(.github/workflows/ci.yml)会在每次推送和 PR 时运行此测试套件(ubuntu-latest ——
单元测试套件会模拟 HTTP/子进程,无需运行中的服务/GPU/WSL),并在 Tests 徽章与测试套件
实际报告的结果不一致时使构建失败——参见 scripts/check_readme_counts.py。
# unit suite (mocked HTTP/subprocess, no live server/GPU/WSL required)
.venv\Scripts\python.exe -m pytest -q
# -> 95 passed, 7 skipped
# handshake check -- prints every registered tool name
.venv\Scripts\python.exe scripts\list_tools.py
# real-infra smokes (real vLLM completion, real nvidia-smi, real systemctl
# via WSL, real /proc/<pid>/cmdline read) -- read-only, safe to run anytime
# vLLM is up
VLLM_OPS_MCP_LIVE=1 .venv\Scripts\python.exe -m pytest -v -m live
# -> 7 passed (all live, against the actual running qwen3-14b instance)
安装
python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
在 ~/.claude.json 中注册为 vllm-ops-mcp(stdio,使用独立的 .venv,此操作员的默认设置无需环境变量覆盖)。
商业支持
由 Jaimen Bell 维护。如需生产环境 MCP 集成、定制服务或 Agent 可靠性方面的工作,请访问 jaimenbell.dev。
正在构建自己的 MCP 服务?MCP Starter Kit 提供模板、构建指南,以及发布此服务过程中的打包经验分享。
mcp-name: io.github.jaimenbell/vllm-ops-mcp
评论
一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。