MCP Servers

A collection of Model Context Protocol servers, templates, tools and more.

ssh-mcp 支持连接远程节点,支持维持会话

Created 6/5/2026
Updated about 18 hours ago
Repository documentation and setup instructions

SSH MCP

一个不依赖 Xshell 的 Python SSH MCP Server。它由 MCP Server 自己建立交互式 SSH PTY 会话,适合 CMSM/堡垒机菜单、进入 master、进入 pod 后复用当前 shell 状态的排障流程。

能力概览

  • open_session(profile, owner_label=None):按配置打开持久 SSH 会话,并返回对应的浏览器 viewer_url
  • list_sessions():查看当前 MCP Server 实例内的活动会话和运行时信息。
  • send_text(session_id, text, enter=True, wait_for="", timeout=30):向菜单或 shell 发送文本。
  • execute_command(session_id, command, wait_for_prompt=True, timeout=30):在当前 shell 状态下执行命令。
  • get_screen(session_id, lines=100):查看内存中最近的终端输出。
  • get_transcript(session_id, tail=200):读取 JSONL 审计记录。
  • interrupt(session_id):发送 Ctrl+C
  • search_logs(...):在当前远端 shell 中执行 find + grep 日志搜索。

架构

Claude / Codex / MCP Client
  -> ssh-mcp FastMCP Server
  -> Paramiko SSH interactive shell channel
  -> remote CMSM / master / pod shell

ssh-mcp Server
  -> runtime/instances/<server_instance_id>/logs/ssh_mcp.log
  -> runtime/instances/<server_instance_id>/transcripts/<session_id>.jsonl
  -> local browser viewer

每个 MCP Server 进程都会生成独立的 server_instance_id。多个 LLM 窗口同时启动 MCP Server 时,默认写入不同的实例目录,避免日志和 transcript 混在一起。

安装

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

开发测试可直接使用:

.\.venv\Scripts\python.exe -m unittest discover -s tests -v

SSH 配置

复制配置模板:

Copy-Item .\config\profiles.example.json .\config\profiles.json

示例:

{
  "profiles": {
    "dev": {
      "host": "10.0.0.10",
      "port": 22,
      "username": "your-user",
      "key_filename": "C:/Users/you/.ssh/id_rsa",
      "passphrase_env": "SSH_MCP_KEY_PASSPHRASE",
      "allow_agent": true,
      "look_for_keys": true,
      "auto_add_host_key": true,
      "term": "xterm-256color",
      "width": 120,
      "height": 40,
      "keepalive_interval": 30
    }
  }
}

keepalive_interval 使用 Paramiko transport keepalive,只做 SSH 探活,不会向远端 shell 注入命令。

运行

直接启动:

.\.venv\Scripts\python.exe -m ssh_mcp.server --viewer-host 127.0.0.1 --viewer-port auto

常用环境变量:

  • SSH_MCP_CONFIG:profile 配置路径,默认 config/profiles.json
  • SSH_MCP_RUNTIME_DIR:运行产物根目录,默认 runtime
  • SSH_MCP_CLIENT_LABEL:当前 MCP Server 来源标签,例如 claude-order-debugcodex-local
  • SSH_MCP_KEY_PASSPHRASE:私钥口令。
  • SSH_MCP_KEEPALIVE_INTERVAL:默认 SSH keepalive 秒数,可被 profile 覆盖。

兼容旧配置:

  • 显式设置 SSH_MCP_LOG_PATH 时,运行日志写到该路径。
  • 显式设置 SSH_MCP_TRANSCRIPTS_DIR 时,transcript 写到该目录。

Claude / Codex 接入

仓库提供 .mcp.json.codex/config.toml 示例。默认建议只设置:

  • SSH_MCP_CONFIG
  • SSH_MCP_RUNTIME_DIR
  • SSH_MCP_CLIENT_LABEL
  • SSH_MCP_KEY_PASSPHRASE

不要让多个 MCP Server 固定写同一个 logs/ssh_mcp.logtranscripts/,否则排查时很难区分不同 LLM 窗口。

启动 Claude Code 前可设置:

$env:SSH_MCP_KEY_PASSPHRASE = "<your-private-key-passphrase>"
$env:SSH_MCP_CLIENT_LABEL = "claude-payment-debug"
claude

open_session 时建议传入 owner_label

{"profile": "lab", "owner_label": "payment-log-check"}

SSH_MCP_CLIENT_LABEL 标记 MCP Server 来源,owner_label 标记具体 SSH session 的用途。

浏览器 Viewer

MCP Server 启动时会同时启动本地 viewer。默认从 8765 附近自动选择可用端口。

  • /:按 server_instance_id 分组展示 sessions。
  • /sessions/<session_id>:单个 session 的终端式页面。
  • /api/sessions:返回 session 列表和 server 元数据。
  • /api/sessions/<session_id>/events:长轮询读取 transcript 增量。

open_session 会返回准确的 viewer_url,不要手动猜 session URL。

也可以只启动历史 viewer:

.\.venv\Scripts\python.exe -m ssh_mcp.viewer --port 8765 --transcripts-dir transcripts

Runtime 目录

默认结构:

runtime/
  instances/
    <server_instance_id>/
      server_meta.json
      logs/
        ssh_mcp.log
      transcripts/
        <session_id>.jsonl

server_meta.json 记录:

  • server_instance_id
  • pid
  • cwd
  • started_at
  • client_label
  • viewer_base_url
  • log_path
  • transcripts_dir
  • config_path

旧的 transcripts/*.jsonl 仍可被 viewer 读取,并标记为 legacy

Transcript 与安全

每个 SSH session 都有独立 JSONL 文件。首行是 session_meta,包含 profile、host、username、owner_label、server_instance_id、client_label、viewer_url 等信息。

示例事件:

{"dir":"session_meta","session_id":"lab-...","owner_label":"payment-log-check","server_instance_id":"ssh-mcp-..."}
{"dir":"send","tool":"send_text","text":"2\n"}
{"dir":"recv","text":"Logged in to master...\n"}
{"dir":"session_health","health_status":"unhealthy","health_error":"SSH transport is inactive"}

重要:send_text(..., sensitive=true) 不会脱敏,text 仍按原文写入 transcript。请保护 runtime/logs/transcripts/ 的文件权限。

SSH 心跳与断线处理

当前策略是“只探活,不自动重连”:

  • 使用 Paramiko transport keepalive 保持 SSH 连接活跃。
  • 后台 health monitor 定期检查 transport/channel。
  • 断开后 session 会标记为 unhealthyclosed
  • 后续 send_text / execute_command 返回可读错误。
  • 不自动重放 CMSM -> master -> pod 路径,避免误以为恢复了原始 shell 状态。

本地 CMSM 测试环境

仓库内置 CMSM simulator:

lab/cmsm_simulator/

它模拟:

CMSM 菜单 -> master shell -> kubectl exec -> pod shell

部署和测试步骤见 lab/cmsm_simulator/README.md

常见问题

为什么 viewer 端口不是 8765?

如果端口被占用,viewer 会自动选择后续可用端口。以 open_session 返回的 viewer_url 为准。

多个 Claude/Codex 窗口如何区分?

设置不同的 SSH_MCP_CLIENT_LABEL,并在 open_session 传入 owner_label。运行日志、server_meta 和 transcript 都会记录这些字段。

MCP 重启后 SSH session 还在吗?

不在。当前实现使用 Paramiko interactive shell channel,MCP Server 进程退出后 SSH 连接也会关闭。历史 transcript 会保留在 runtime 目录。

什么时候考虑 tmux?

如果需要 MCP 重启后仍能 attach 原 SSH 会话,可以在后续版本评估 tmux 底座。但 Windows 原生部署会更复杂,本项目当前优先保持 Python/Paramiko 的轻量实现。

Quick Setup
Installation guide for this server

Install Package (if required)

uvx ssh-mcp

Cursor configuration (mcp.json)

{ "mcpServers": { "sc-ml-cmd-ssh-mcp": { "command": "uvx", "args": [ "ssh-mcp" ] } } }