SSH MCP Server

chính thức

Chạy lệnh, di chuyển tệp, tìm kiếm nhật ký và kiểm tra máy chủ qua SSH từ agent của bạn.

GitHub
2
Dùng thử MCP nàyĐược tài trợ

Bạn có thể làm gì với SSH MCP?

  • Chạy lệnh với rào chắn an toàn — Yêu cầu trợ lý của bạn thực thi các lệnh đơn lẻ hoặc theo lô qua ssh_exec, với tính năng bảo vệ lệnh nguy hiểm chặn các thao tác không thể hoàn tác trước khi chúng đến máy chủ.
  • Đọc, ghi và liệt kê tệp từ xa — Sử dụng ssh_file_read, ssh_file_writessh_file_list để kiểm tra hoặc sửa đổi tệp, với ghi nguyên tử và xác minh SHA-256 tùy chọn.
  • Tìm kiếm nhật ký và kiểm tra tình trạng máy chủ — Truy vấn ssh_log_search hoặc ssh_log_tail trên các tệp và container, hoặc lấy ảnh chụp nhanh tình trạng có cấu trúc bằng ssh_snapshotssh_audit_baseline.
  • Truyền tệp với kiểm tra tính toàn vẹn — Tải lên hoặc tải xuống tệp và thư mục qua ssh_uploadssh_download, với cơ chế dự phòng scp cũ tự động cho các thiết bị đời cũ.
  • Quản lý tác vụ nền chạy lâu — Tách các thao tác chậm bằng ssh_exec và theo dõi chúng qua ssh_job_status, ssh_job_outputssh_job_kill, vẫn hoạt động khi mất kết nối.

Tài liệu

SSH MCP Server — Công cụ máy chủ từ xa cho tác nhân AI

SSH MCP Server

Một máy chủ MCP SSH — một công cụ đa năng giúp bạn và tác nhân AI tiết kiệm thời gian và token cho việc gỡ lỗi, phát triển và bảo trì máy chủ.

Chạy lệnh, di chuyển tệp, đọc nhật ký và kiểm tra máy qua SSH — một VPS đám mây, một máy chủ vật lý, hoặc bộ định tuyến BusyBox đặt trong tủ của bạn.

Nó sử dụng ứng dụng khách OpenSSH đã có trên máy của bạn: khóa của bạn, ~/.ssh/config của bạn, máy chủ nhảy của bạn, chuyển tiếp tác nhân của bạn. Không có gì được đóng gói, không có gì để biên dịch, không có ràng buộc gốc.

Hoạt động với Claude Code, Codex CLI, Cline, opencode, Gemini CLI, Qwen Code, Hermes và các ứng dụng khách MCP khác.

MCP Registry Glama Smithery npm downloads tests

Cài đặt · Công cụ · Thiết lập · Bảo mật · Lộ trình · Tài liệu · Nhật ký thay đổi


Cài đặt trong 30 giây

Không cần cài đặt toàn cục. npx tải xuống gói khi sử dụng lần đầu:

npx -y @hypnosis/ssh-mcp-server

Thêm nó vào ứng dụng khách MCP của bạn — Claude Code, ví dụ — cho mọi dự án:

claude mcp add ssh -s user \
  -e SSH_PROFILES_FILE="$HOME/.claude/ssh-profiles.json" \
  -- npx -y @hypnosis/ssh-mcp-server

Hoặc viết tay — cùng một máy chủ ở dạng cấu hình mà hầu hết các ứng dụng khách chia sẻ:

{
  "mcpServers": {
    "ssh": {
      "command": "npx",
      "args": ["-y", "@hypnosis/ssh-mcp-server"],
      "env": {
        "SSH_PROFILES_FILE": "~/.claude/ssh-profiles.json"
      }
    }
  }
}

Sau đó tạo ~/.claude/ssh-profiles.json với ít nhất một máy:

{
  "profiles": {
    "production": {
      "host": "server.example.com",
      "username": "admin",
      "privateKeyPath": "~/.ssh/your_private_key"
    }
  }
}

Như vậy là đủ để kết nối.

Codex, opencode, Qwen Code và các ứng dụng khách khác được trình bày trong Thiết lập máy chủ MCP SSH.

Cài đặt như một plugin

Một số ứng dụng khách — Claude Code, ví dụ — có thể nhận toàn bộ như một plugin thay thế:

/plugin marketplace add hypnosis/ssh-mcp-server
/plugin install ssh-mcp-server@ssh-mcp-server

Plugin đọc ~/.claude/ssh-profiles.json trừ khi SSH_PROFILES_FILE quy định khác, vì vậy hãy tạo tệp đó trước và máy chủ sẽ khởi động với các máy của bạn đã được tải sẵn.

Yêu cầu

npm version Node.js TypeScript MCP SDK

Node.js 18+ và một ứng dụng khách ssh hệ thống trên PATH. Trên Windows, hãy sử dụng hồ sơ dựa trên khóa; hồ sơ mật khẩu và cụm mật khẩu hiện không khả dụng.

Thích phiên bản cố định, làm việc ngoại tuyến, hoặc ít kiểm tra registry hơn mỗi lần khởi chạy: npm install -g @hypnosis/ssh-mcp-server, sau đó sử dụng ssh-mcp-server làm lệnh thay vì npx.

Dành cho ai

  • DevOps và SRE muốn kiểm tra nhanh hơn, kiểm tra sự cố và công việc máy chủ định kỳ.
  • Người viết mã theo cảm hứng và nhà xây dựng độc lập giao hàng với trợ lý AI và chạy những gì họ xây dựng trên máy chủ của riêng họ.
  • Quản trị viên hệ thống và kỹ sư nền tảng muốn các công cụ có cấu trúc thay vì shell thô không giới hạn.
  • Nhà phát triển và nhóm nhỏ tự chạy VPS mà không có đội vận hành chuyên trách.
  • Chủ sở hữu homelab, NAS và bộ định tuyến có phần cứng hữu ích đã vượt qua các giao thức hiện đại.

Tại sao máy chủ MCP SSH thay vì shell thô

Ít token hơn, chi phí AI thấp hơn

Shell thô cho tác nhân AI một luồng dữ liệu khổng lồ: các lệnh lặp lại, bảng ASCII và kết xuất nhật ký. Nó đốt token để chuyển đổi tiếng ồn đó thành bức tranh về máy chủ — tiền của bạn.

Gỡ lỗi máy chủ nhanh hơn

Các công cụ chuyên dụng gộp các kiểm tra định kỳ, giới hạn đầu ra ồn ào và trả về phần quan trọng. Tác nhân dành ít thời gian hơn để dịch đầu ra thiết bị đầu cuối và đến được giải pháp nhanh hơn.

Ít phỏng đoán hơn, ít lỗi AI hơn

Câu trả lời có cấu trúc cho biết những gì đã tìm thấy, những gì không thể đo lường và những gì đã bị cắt bớt. Điều đó để lại cho tác nhân ít chỗ hơn để lấp đầy khoảng trống bằng ảo giác — và cho bạn ít bản sửa lỗi tệ hơn, triển khai bình tĩnh hơn và mã đáng tin cậy hơn.

Tương thích SSH: máy chủ hiện đại, thiết bị cũ và Windows

Sử dụng thiết lập OpenSSH hiện có của bạn

Không có triển khai SSH đóng gói, không có ràng buộc gốc, không cần biên dịch lại cho từng nền tảng. Các lệnh sử dụng ứng dụng khách ssh hệ thống, vì vậy khóa của bạn, ~/.ssh/config của bạn, máy chủ nhảy của bạn và chuyển tiếp tác nhân của bạn tiếp tục hoạt động chính xác như trong thiết bị đầu cuối. Khi được hỗ trợ, một kết nối đa kênh dùng chung cho mỗi đích đến có nghĩa là bạn xác thực một lần, không phải mỗi lệnh một lần.

Hỗ trợ SSH cho máy chủ cũ, bộ định tuyến và thiết bị NAS

Gửi một tệp đến bộ định tuyến với scp hiện đại và bạn nhận được điều này:

scp app.conf router:/etc/
# scp: subsystem request failed on channel 0

Không có gì bị hỏng — một scp hiện tại nói giao thức mới, và bộ định tuyến không biết điều đó. Trong thiết bị đầu cuối, bạn bây giờ đi đọc một chủ đề diễn đàn và quay lại với một cờ bổ sung. Ở đây bạn không làm gì: việc truyền được thử, sự từ chối được nhận ra, giao thức cũ được sử dụng thay thế, và máy đó được ghi nhớ để tệp tiếp theo đi thẳng đến đó.

Dự phòng cho ứng dụng khách SSH cũ và công cụ bị thiếu

Thiết bị cũ nhận được dự phòng, không phải ngõ cụt. Khi một tính năng hiện đại bị thiếu, máy chủ đi con đường cũ hơn nơi có thể:

Máy của bạnNhững gì bạn nhận được
Bộ định tuyến hoặc NAS quá nhỏ cho truyền tệp hiện đạiTệp vẫn đến — giao thức cũ được sử dụng tự động
Máy chủ từ mười năm trướcQuy trình làm việc vẫn hoạt động; nó chỉ mở kết nối mới mỗi lệnh thay vì tái sử dụng
Hình ảnh bị cắt bớt không có cách băm tệpTải lên nói "không thể xác minh" thay vì tuyên bố khớp mà không ai kiểm tra
Một máy nơi một công cụ đơn giản không được cài đặtCâu trả lời nói "không được đo" — không bao giờ là số không đọc là "không có gì ở đó"

Được xây dựng cho Giao thức Ngữ cảnh Mô hình

Được xây dựng trên SDK MCP chính thức, TypeScript toàn bộ, hơn 2500 bài kiểm tra đơn vị cộng với bộ kiểm tra trực tiếp chạy trên các container thực thay vì mô phỏng.


SSH thô so với máy chủ MCP SSH: cùng công việc, cả hai cách

Kiểm tra sức khỏe máy chủ SSH

Tình huống: Một bản triển khai vừa được phát hành. Máy chủ có vẻ chậm, và bạn không biết liệu đĩa, bộ nhớ, dịch vụ, container hay lỗi là nguyên nhân.

Câu hỏi: "Máy này có khỏe không?"

SSH thô

$ uptime
 10:42:17 up 18 days,  3:21,  2 users,  load average: 0.42, 0.31, 0.28
$ df -hT
Filesystem     Type   Size  Used Avail Use% Mounted on
/dev/sda1      ext4    40G   35G  5.0G  87% /
overlay        overlay  40G   35G  5.0G  87% /var/lib/docker/overlay2/...
$ free -h
               total        used        free      shared  buff/cache   available
Mem:           7.7Gi       4.9Gi       612Mi       121Mi       2.2Gi       2.5Gi
$ systemctl --failed
  UNIT              LOAD   ACTIVE SUB    DESCRIPTION
● api-worker.service loaded failed failed API background worker
$ docker ps -a
CONTAINER ID   IMAGE          STATUS                     PORTS
8e14d0b41c2a   api:latest     Up 3 minutes               0.0.0.0:8080->8080/tcp
65b894af2430   worker:latest  Exited (1) 2 minutes ago
$ ss -tulpn
Netid  State   Local Address:Port   Process
tcp    LISTEN  0.0.0.0:22          users:(("sshd",pid=842,fd=3))
tcp    LISTEN  0.0.0.0:8080        users:(("docker-proxy",pid=1942,fd=4))
$ journalctl -p err --since -1h | tail -50
Aug 20 10:39:14 prod api-worker[22104]: database connection timed out
Aug 20 10:39:14 prod systemd[1]: api-worker.service: Failed with result 'exit-code'.

Đó vẫn là kết quả rút gọn. Một kiểm tra đầy đủ cần nhiều lệnh hơn cho CPU, trạng thái dịch vụ, số lượng container và lỗi gần đây, mỗi lệnh có định dạng đầu ra riêng. Tệ hơn, một máy không có ss có thể trông như có không người nghe khi kiểm tra cổng không bao giờ chạy.

Kết quả MCP có cấu trúc

ssh_snapshot({ "profile": "production" })
{
  "disk_pct": 87,
  "mem_pct": 64,
  "cpu_pct": 12,
  "load": "0.42 0.31 0.28",
  "containers": 7,
  "ports": 14,
  "services_running": 3,
  "recent_errors": 21,
  "unavailable": []
}

Những gì tác nhân đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Nhiều lệnh và bảng ASCIICác trường được đặt tên trong một kết quảMột lệnh gọi, trường được đặt tên và ít vòng lặp hơn
Công cụ bị thiếu có thể trông như đầu ra trốngunavailable đặt tên những gì không được đoÍt phỏng đoán hơn và ít bản sửa lỗi tệ hơn
Bạn sắp xếp qua đĩa, dịch vụ và lỗiCác tín hiệu vấn đề đã được làm nổi bậtGỡ lỗi nhanh hơn

Một kết quả ssh_audit_baseline đầy đủ có thể dài hơn một số đầu ra lệnh thô — khoảng 1.077 token so với 765 trong phép đo phòng thí nghiệm của chúng tôi. Sự tiết kiệm đến từ quy trình làm việc hoàn chỉnh, không phải từ việc làm cho một phản hồi ngắn hơn.

Trong một phiên khắc phục sự cố thực tế, các công cụ chuyên dụng đã giảm 49 lệnh gọi riêng biệt xuống 4 lệnh gọi MCP. Mỗi lệnh gọi bổ sung bắt đầu một lượt mô hình khác với cuộc trò chuyện tích lũy. Bộ nhớ đệm lời nhắc có thể giảm chi phí đầu vào lặp lại, nhưng các lệnh mới và đầu ra của chúng vẫn tiêu thụ ngữ cảnh. Ít vòng lặp hơn có nghĩa là ít token hơn trong suốt phiên, ít phân tích lặp lại hơn và con đường nhanh hơn đến câu trả lời.

Cần bức tranh toàn cảnh thay vì chỉ nhịp đập? ssh_audit_baseline gộp hệ thống, đĩa, bộ nhớ, cổng, sshd, các đơn vị lỗi, Docker, tường lửa và cập nhật. Các phát hiện đến dưới dạng NGHIÊM TRỌNG / CẢNH BÁO / OK; các phần không được đo được đặt tên thay vì âm thầm đọc là số không.

Tìm kiếm nhật ký máy chủ Linux

Tình huống: API đang hết thời gian chờ, nhưng cùng một thông báo có thể nằm trong nginx, syslog, journald hoặc nhật ký ứng dụng mà bạn không thể đọc với người dùng bình thường của mình.

Câu hỏi: "Lỗi đó đến từ đâu?"

SSH thô

$ grep -i "timeout" /var/log/nginx/error.log
2026/08/20 10:38:54 [error] upstream timed out while reading response header
$ grep -i "timeout" /var/log/syslog
Aug 20 10:39:14 prod api-worker[22104]: database connection timed out
$ grep -i "timeout" /var/log/app/*.log 2>/dev/null
$ journalctl -u api --since "1 hour ago" | grep -i timeout
Aug 20 10:39:14 prod api[22104]: database connection timed out after 30000ms

Lệnh thứ ba trông sạch sẽ, nhưng 2>/dev/null cũng đã ẩn lỗi quyền. "Không có gì khớp" và "không có gì được đọc" bây giờ trông giống hệt nhau. Một nhật ký bận rộn cũng có thể trả về hàng nghìn dòng và đẩy phần còn lại của sự cố ra khỏi ngữ cảnh của tác nhân.

Kết quả MCP có cấu trúc

ssh_log_search({ "profile": "production",
                 "path": ["/var/log/nginx/error.log", "/var/log/syslog", "/var/log/app/*.log"],
                 "query": "timeout", "context": 2, "since": "1h" })
{
  "matches": 34,
  "lines": [
    { "file": "/var/log/nginx/error.log", "line": 4821,
      "text": "upstream timed out while reading response header", "context": false },
    { "file": "/var/log/nginx/error.log", "line": 4822,
      "text": "client closed connection", "context": true }
  ],
  "files_searched": 6,
  "files_unreadable": ["/var/log/app/private"],
  "files_skipped": 12,
  "files_undated": [],
  "limited": false,
  "truncated": false
}

Những gì tác nhân đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Bốn tìm kiếm và bốn đầu raMột tìm kiếm qua các tệp và globÍt token và vòng lặp hơn
Lỗi quyền có thể biến mấtfiles_unreadable đặt tên mọi đường dẫn bị bỏ lỡKhông có kết luận sai "nhật ký sạch"
Đầu ra có thể phát triển không có giới hạn hữu íchlimitedtruncated phơi bày mọi điểm cắtQuyết định an toàn hơn từ kết quả một phần

since sử dụng đồng hồ của máy chủ, namesOnly: true chỉ trả về các đường dẫn khớp, và ssh_log_tail đọc N dòng cuối từ nhiều nhật ký trong một lệnh gọi.

Chỉnh sửa cấu hình từ xa an toàn

Tình huống: Bạn cần thay thế cấu hình nginx trên một máy chủ trực tiếp. Một kết nối bị rơi, chế độ sai hoặc bản sao không được kiểm tra có thể để lại dịch vụ với một tệp bị hỏng.

Câu hỏi: "Tôi có thể thay thế cấu hình này mà không để lại tệp một phần không?"

SSH thô

$ sudo sh -c 'cat > /etc/nginx/conf.d/api.conf' <<'EOF'
server {
    listen 80;
    location / { proxy_pass http://127.0.0.1:8080; }
}
EOF
$ echo $?
0

Mã thoát bằng không nói shell đã hoàn thành. Nó không chứng minh byte nào đã đến, và > đã cắt bớt tệp cũ trước khi byte đầu tiên của tệp mới đến. Nếu kết nối rơi giữa chừng ghi, dịch vụ bị để lại với cấu hình một phần.

Kết quả MCP có cấu trúc

ssh_file_write({ "profile": "production",
                 "files": [{ "path": "/etc/nginx/conf.d/api.conf",
                             "content": "server {\n    listen 80;\n    location / { proxy_pass http://127.0.0.1:8080; }\n}\n",
                             "mode": "644", "sudo": true, "verify": true }] })
{
  "files": [{ "path": "/etc/nginx/conf.d/api.conf", "written": true,
              "verified": "verified", "reason": null, "bytes": 79 }]
}

Những gì tác nhân đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Mục tiêu bị cắt bớt trước khi bản sao hoàn thànhMột tệp tạm thời hoàn chỉnh thay thế nó bằng một lần đổi tênKhông có cấu hình viết dở
Chỉ mã thoátByte và kết quả xác minh được đặt tênBạn biết những gì thực sự đã đến
Quyền nằm bên trong văn bản shellsudo, modeverify là các trường theo tệpQuyền sở hữu có thể dự đoán và ít lỗi trích dẫn hơn

verified có ba kết quả trung thực: verified, unavailable khi máy chủ không có công cụ băm, và skipped khi xác minh không được yêu cầu. Cho việc đọc, ssh_file_read chấp nhận một danh sách đường dẫn; ssh_file_list xử lý glob, đệ quy, kích thước và chế độ.

Chạy lệnh SSH hàng loạt với sudo

Tình huống: Một bản triển khai đã sẵn sàng, nhưng cú pháp nginx, trạng thái dịch vụ và lỗi gần đây phải được kiểm tra trước khi lưu lượng di chuyển. Một kiểm tra thất bại không nên biến mất bên trong một kết xuất kết hợp.

Câu hỏi: "Mọi kiểm tra trước khi triển khai có vượt qua không?"

SSH thô

$ ssh admin@server.example.com 'sudo nginx -t'
nginx: configuration file /etc/nginx/nginx.conf test is successful
$ ssh admin@server.example.com 'sudo systemctl is-active nginx'
active
$ ssh admin@server.example.com 'sudo tail -5 /var/log/nginx/error.log'
2026/08/20 10:38:54 [error] upstream timed out while reading response header

Ba kết nối trả về ba đầu ra không liên quan. Nếu các lệnh được nối với ;, shell chỉ báo cáo mã thoát cuối cùng; nếu chúng được nối với &&, các kiểm tra sau biến mất sau lần thất bại đầu tiên.

Kết quả MCP có cấu trúc

ssh_exec({ "profile": "production",
           "command": ["nginx -t", "systemctl is-active nginx",
                       "tail -5 /var/log/nginx/error.log"],
           "sudo": true })
{
  "commands": [
    { "command": "nginx -t", "exit_code": 0, "truncated": false, "clipped_bytes": 0,
      "stdout": "", "stderr": "nginx: configuration file /etc/nginx/nginx.conf test is successful\n" },
    { "command": "systemctl is-active nginx", "exit_code": 0, "truncated": false,
      "clipped_bytes": 0, "stdout": "active\n", "stderr": "" },
    { "command": "tail -5 /var/log/nginx/error.log", "exit_code": 0, "truncated": false,
      "clipped_bytes": 0, "stdout": "2026/08/21 09:14:02 [error] upstream timed out\n", "stderr": "" }
  ],
  "job_id": null
}

Những gì tác nhân đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Ba lệnh gọi và đầu ra không liên quanMột danh sách lệnh có thứ tựÍt vòng lặp hơn
Một shell kết hợp có thể ẩn trạng thái trung gianMỗi lệnh giữ exit_code riêng của nóKhông bỏ lỡ kiểm tra thất bại
sudo và trích dẫn được lặp lại trong văn bản lệnhsudo áp dụng cho toàn bộ lôÍt lỗi trích dẫn hơn

Bộ bảo vệ lệnh phá hủy kiểm tra toàn bộ danh sách trước khi lệnh đầu tiên chạy. Nếu một mục bị từ chối, mọi mục khác được đánh dấu là không chạy và không có gì được gửi đến máy chủ. Mỗi lệnh mang theo stdoutstderr riêng của nó. Một lệnh đã chạy và không in ra gì có chuỗi rỗng; một lệnh chưa bao giờ chạy thì không có trường nào như vậy, vì vậy hai trường hợp không thể bị nhầm lẫn. Đầu ra trên 128 KB cho mỗi lệnh giữ cả hai đầu — phần đầu cho bảng, phần đuôi cho nhật ký — với một điểm nối ở giữa nêu rõ dung lượng, và clipped_bytes cho biết bao nhiêu đã bị cắt. Việc cắt xảy ra trên ranh giới byte và lùi lại đến mép của một ký tự, vì vậy một câu trả lời bị cắt không bao giờ mang dấu thay thế.

sudo đến máy chủ mà không có terminal: câu trả lời của hồ sơ được chuyển cho sudo trên đầu vào chuẩn. Bí mật đó là gì đến từ sudoPassword khi hồ sơ chỉ định một bí mật và từ password nếu không — một hồ sơ đăng nhập bằng khóa không có mật khẩu đăng nhập nào cả, và ở nơi máy tách biệt hai loại, mật khẩu đăng nhập là câu trả lời sai. Khi không có gì để trả lời, phản hồi nói rõ điều đó và nêu tên các cách thoát, thay vì để lại lời khuyên của chính sudo về -S và các trình trợ giúp askpass. Một lệnh đọc đầu vào chuẩn của chính nó không bao giờ được cấp mật khẩu, vì nếu không mật khẩu sẽ bị trộn vào dữ liệu.

Chạy các tác vụ SSH dài hạn

Tình huống: Một bản sao lưu hoặc di chuyển sẽ chạy lâu hơn phiên làm việc của agent. Kết nối có thể đóng, nhưng bạn vẫn cần trạng thái, đầu ra và mã thoát của nó sau đó.

Câu hỏi: "Tác vụ này có sống sót qua cuộc trò chuyện không?"

SSH thô

$ ssh admin@server.example.com 'pg_dump app | gzip > /srv/backups/app.sql.gz'
client_loop: send disconnect: Broken pipe

Terminal đã biến mất. Bạn giờ phải kết nối lại, tìm tiến trình, kiểm tra tệp đích và đoán xem bản sao lưu đã hoàn tất hay dừng giữa chừng.

Kết quả MCP có cấu trúc

ssh_exec({ "profile": "production",
           "command": "pg_dump app | gzip > /srv/backups/app.sql.gz",
           "detach": true })
{
  "commands": [{
    "command": "pg_dump app | gzip > /srv/backups/app.sql.gz",
    "exit_code": null,
    "truncated": false,
    "timed_out": false,
    "blocked": false,
    "blocked_reason": null,
    "not_run": false,
    "warning": null
  }],
  "job_id": "mst0f2q1-9ab3c4d5"
}

Điều agent đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Tác vụ gắn với một phiên SSHTác vụ từ xa có id bền vữngNgắt kết nối và khởi động lại an toàn
Kết nối lại nghĩa là tìm kiếm tiến trình và tệpTrạng thái và mã thoát có trạng thái được đặt tênKhông phải đoán xem nó đã hoàn tất chưa
Đọc lại đầu ra lặp lại văn bản cũĐầu ra tiếp tục từ một offset byteGiảm token sử dụng cho tác vụ dài

Trạng thái tác vụ nằm trên đĩa từ xa, không nằm trong bộ nhớ của máy chủ này. ssh_job_status phân biệt running, finishedlost; ssh_job_output tiếp tục từ offset byte cuối cùng; và ssh_job_kill gửi tín hiệu đến toàn bộ nhóm tiến trình thay vì chỉ shell của nó.

Chuyển tệp đến router và NAS cũ

Tình huống: Một máy khách OpenSSH hiện tại thử SFTP, nhưng router hoặc NAS chỉ hiểu giao thức scp cổ điển. Tệp vẫn phải đến nguyên vẹn và thay thế đích một cách an toàn.

Câu hỏi: "Thiết bị cũ này có thể vẫn nhận được một tệp đã xác minh không?"

SSH thô

$ scp app.conf operator@router:/etc/app.conf
subsystem request failed on channel 0
scp: Connection closed

Bước tiếp theo thông thường là nhớ cờ kế thừa, thử lại bản sao và sau đó chạy một lệnh hash riêng — nếu thiết bị có công cụ hash nào cả.

Kết quả MCP có cấu trúc

ssh_upload({ "profile": "router", "local_path": "./app.conf",
             "remote_path": "/etc/app.conf", "sudo": true,
             "mode": "644", "owner": "root:root", "verify": true })
{
  "files": [{
    "path": "/etc/app.conf",
    "written": true,
    "verified": "verified",
    "reason": null,
    "bytes": 1284
  }]
}

Điều agent đạt được

SSH thôMCP có cấu trúcLợi ích của bạn
Chế độ SFTP hiện đại dừng ở lỗi đầu tiênDự phòng scp cổ điển tự động và được ghi nhớThiết bị cũ vẫn hoạt động
Bản sao thành công không chứng minh tính toàn vẹnXác minh SHA-256 có kết quả được đặt tênHỏng hóc không bị nhầm là thành công
Thay thế trực tiếp có thể để lại đích một phầnMột tệp tạm được di chuyển vào vị trí sau khi chuyểnTệp đang hoạt động sống sót qua gián đoạn

Nếu thiết bị không có sha256sum cũng như openssl, kết quả nói unavailable và nêu lý do thay vì báo cáo khớp sai. Toàn bộ thư mục sử dụng recursive: true và xác minh hash của chúng trong một lô.

Bảo vệ lệnh phá hủy cho agent AI

Lớp bảo vệ chạy cục bộ, trước khi lệnh đến SSH. Nó tách các thao tác có thể khôi phục khỏi những thao tác phá hủy vùng chứa giữ dữ liệu, và nó kiểm tra thứ tự lệnh bên trong chuỗi và lô.

Dừng một chuỗi phá hủy trước khi nó bắt đầu

Một chuỗi sao lưu và thay thế an toàn:

cp -r /srv/app /srv/app.bak && mv /srv/app /srv/app-old && rm -rf /srv/app

Các thao tác tương tự theo thứ tự sai:

rm -rf /srv/app && cp -r /srv/app /srv/app.bak && mv /srv/app /srv/app-old
# REFUSED before the first command runs

Shell sẽ xóa thư mục và chỉ sau đó mới phát hiện ra rằng nguồn sao lưu đã biến mất. Lớp bảo vệ thấy rằng các bước sau đọc một đích đã bị phá hủy bởi một bước trước, vì vậy toàn bộ lệnh gọi vẫn nằm trên máy của bạn. Kiểm tra tương tự cũng bắt dropdb app && pg_dump app > backup.sql.

Từ chối mất mát không thể đảo ngược, cảnh báo về thay đổi có thể khôi phục

Bị từ chối — chính vùng chứaChỉ cảnh báo — nội dung của nó
DROP DATABASE, dropdbDROP TABLE, TRUNCATE, DELETE FROM
docker volume rm, docker compose down -vdocker rm -f <name>
crontab -rchỉnh sửa một tác vụ
mkfs, wipefs -a, lvremove, zfs destroychmod 777
reboot, shutdown, haltgit reset --hard

docker compose down -v bị từ chối vì -v xóa các volume Docker được đặt tên, bao gồm một volume cơ sở dữ liệu. Không có -v, việc dừng các dịch vụ không được coi là hành động không thể đảo ngược tương tự.

Xóa đệ quy gốc hệ thống tệp, thư mục chính hoặc cây hệ thống như /etc, /var/usr cũng bị từ chối, bao gồm khi một symlink dẫn đến đó. Một đích chưa được giải quyết như rm -rf "$DIR"/* cũng bị từ chối: "không thể kiểm tra" không được coi là "an toàn".

Đặt tên cho thứ bạn dừng

Một lệnh tìm đích của nó thay vì đặt tên cho nó sẽ không được gửi. Máy chủ mở rộng nó và trả lời với những gì đứng sau đích:

docker kill $(docker ps -q --filter ancestor=web)
# BLOCKED — would stop:
#   edge — web:latest, Up 34 days, 0.0.0.0:8443->8443/tcp

Đối với một tiến trình, câu trả lời thêm các dấu hiệu cho thấy nó đang được sử dụng: nó đã chạy bao lâu, nó chấp nhận kết nối trên cổng nào, nó đang mang bao nhiêu kết nối. Các đích được đặt tên không tốn thêm gì và đi qua trong im lặng — docker kill web-1, kill 4871, systemctl stop app.

Để tiếp tục, hãy đặt tên cho thứ đang được dừng. Các tên được kiểm tra với những gì lệnh thực sự chạm tới, vì vậy một mặt nạ đã trôi sang thứ khác bị từ chối thay vì xác nhận:

docker kill $(docker ps -q --filter ancestor=web) # CONFIRMED-KILL: edge

Một mẫu trên các dòng lệnh là một trường hợp riêng. Nó khớp chính lệnh mang nó, vì vậy shell chạy nó bị báo hiệu trước đích và câu trả lời bị cắt giữa chừng. Một cú đánh như vậy không được xác nhận mà được viết lại — bằng số, hoặc với một ký tự được viết dưới dạng một lớp để mẫu ngừng khớp chính nó:

pkill -f relay
# BLOCKED — two ways through:
#   kill 4871
#   pkill -f '[r]elay' # CONFIRMED-KILL: 4871

Ba kết quả tách biệt: đích được tìm thấy, việc mở rộng không chạm tới gì, và không có gì để hỏi — không có engine trên máy, một câu trả lời bị cắt, một kết nối thất bại. Hai trường hợp cuối cũng là từ chối: không biết không phải là lý do để tiếp tục.

Xác nhận một lệnh phá hủy có chủ đích

Không có gì bị cấm vĩnh viễn. Thêm # CONFIRMED-DESTRUCTIVE vào một lệnh đã được xem xét và nó được cho phép đi qua. Khi lớp bảo vệ từ chối một mục trong một lô, toàn bộ lô dừng trước khi thực thi, vì vậy máy chủ không bao giờ bị bỏ lại sau một thao tác chạy nửa chừng.

Lớp bảo vệ hoạt động trong một lệnh gọi duy nhất. Nó không thể kết nối một lệnh xóa trong một lần gọi với một lần đọc trong lần tiếp theo, hoặc suy luận về các công cụ nó không nhận ra. Nó là một dây an toàn, không phải một engine chính sách: các thao tác có thể khôi phục vẫn là quyết định của bạn. Các hạn chế đường dẫn và quy tắc trích dẫn được ghi trong docs/security.md.

Công cụ

18 công cụ MCP SSH cho các thao tác máy chủ. Tham số đầy đủ và ví dụ nằm trong docs/tools.md.

Công cụChức năng
ssh_execChạy một lệnh hoặc một lô, với lớp bảo vệ lệnh phá hủy và tùy chọn tách rời
ssh_file_readĐọc một hoặc nhiều tệp, văn bản hoặc nhị phân
ssh_file_writeGhi tệp với đổi tên nguyên tử và xác minh SHA-256 tùy chọn
ssh_file_listLiệt kê một thư mục, với glob và đệ quy tùy chọn
ssh_uploadTải lên một tệp hoặc thư mục qua SSH, an toàn nhị phân với kiểm tra toàn vẹn; một thư mục thay thế đích hoặc hợp nhất vào đó
ssh_downloadTải xuống một tệp hoặc thư mục qua SSH, an toàn nhị phân với kiểm tra toàn vẹn
ssh_job_statusTrạng thái của một tác vụ nền: đang chạy, đã hoàn tất, hoặc bị mất
ssh_job_outputĐọc đầu ra tích lũy từ một offset byte
ssh_job_listLiệt kê các tác vụ, quét sạch các tác vụ đã hoàn tất quá TTL
ssh_job_killGửi tín hiệu đến toàn bộ nhóm tiến trình của một tác vụ
ssh_log_tailN dòng cuối của một hoặc nhiều nhật ký, hỗ trợ glob; một vùng chứa theo tên
ssh_log_searchTìm kiếm mẫu trong nhật ký, hoặc qua nhật ký của một vùng chứa
ssh_snapshotẢnh chụp sức khỏe một lần: dịch vụ, tài nguyên, Docker, mạng, lỗi
ssh_monitorKiểm soát vận chuyển: thống kê, tải lại, kiểm tra, liệt kê, đóng
ssh_audit_baselineHệ thống, đĩa, bộ nhớ, mạng, ssh, dịch vụ, Docker, tường lửa, cập nhật
ssh_tls_checkHết hạn chứng chỉ, SAN, chuỗi và hook gia hạn cho một tên miền
ssh_disk_breakdownNơi đĩa đã đi: du top-N, Docker, journald, bộ nhớ cache
ssh_service_statussystemctl status cộng với một đuôi journalctl cho một đơn vị

Chú thích an toàn công cụ MCP

Các chú thích MCP tiêu chuẩn cho máy khách biết công cụ nào là chỉ đọc, phá hủy, idempotent hoặc thế giới mở. Xem bảng đầy đủ.

Chạy lệnh SSH và quản lý tệp từ xa

Lệnh, đọc và ghi tệp, liệt kê thư mục — công việc thông thường trên một máy, mỗi câu trả lời đã được phân tích.

Giám sát các tác vụ SSH dài hạn

Công việc chậm được tách rời và theo dõi thay vì chờ đợi: mỗi lần nhìn cho biết nó đã đi được bao xa.

Tìm kiếm nhật ký và kiểm tra sức khỏe máy chủ

Nhật ký của tệp và vùng chứa, và một bức tranh một lần của máy, với đầu ra được giới hạn để một đuôi không nuốt chửng cửa sổ ngữ cảnh.

Tải lên và tải xuống tệp qua SSH

Chuyển an toàn nhị phân với kiểm tra toàn vẹn. Chi tiết trong docs/transfer.md.

Đối với tệp nhị phân và tệp lớn, hãy sử dụng ssh_upload / ssh_download — các khối base64 và heredoc không an toàn nhị phân hoặc nguyên tử.

Kiểm toán máy chủ Linux qua SSH

Chỉ đọc và được gộp thành một chuyến đi khứ hồi. Chi tiết trong docs/audit.md.

Chế độ tương thích SSH Windows

Windows sử dụng chế độ tương thích tự động. Khi ghép kênh kết nối không khả dụng, máy chủ chuyển sang một kết nối cho mỗi lệnh. Các công cụ tương tự vẫn khả dụng qua SSH dựa trên khóa — không cần thiết lập riêng hoặc triển khai dành riêng cho Windows.

Lớp bảo vệ lệnh phá hủy được trình bày trong Bảo vệ lệnh phá hủy cho agent AI.

Thiết lập máy chủ SSH MCP

Chạy gói từ Cài đặt trong 30 giây trước, sau đó tạo một tệp hồ sơ.

Tạo hồ sơ kết nối SSH

Đặt nó ở bất cứ đâu bạn muốn — bên cạnh cấu hình riêng của agent là lựa chọn thông thường. Các ví dụ dưới đây sử dụng ~/.claude/ssh-profiles.json; cho các agent khác, hãy đổi thư mục (~/.codex/, ~/.qwen/, ~/.config/opencode/):

{
  "profiles": {
    "production": {
      "host": "server.example.com",
      "username": "admin",
      "port": 22,
      "privateKeyPath": "~/.ssh/your_private_key"
    }
  }
}

Chọn một hồ sơ SSH một cách rõ ràng

Không có hồ sơ nào máy chủ dự phòng: mỗi hồ sơ là một máy khác nhau, và một lệnh gửi đến máy sai không phải là điều một thông báo lỗi có thể hoàn tác sau đó. Hỏi mà không có tên và câu trả lời liệt kê các tên để chọn:

ssh_exec({ command: "uptime" })
→ No profile specified. Name one explicitly: production

Một hồ sơ máy chủ không thể sử dụng cho SSH — không có host, không có username, hoặc mode: "local" — bị bỏ qua mà không phàn nàn, và các trường nó không nhận ra được để nguyên, vì vậy tệp có thể được chia sẻ với các công cụ khác. Một hồ sơ có trường hỏng là một trường hợp khác: nó được nêu tên cùng với trường và giá trị, và các hồ sơ khỏe mạnh lân cận vẫn hoạt động.

Mỗi hồ sơ tùy chọn nhận một khối pathSecurity cho phép hoặc chặn các đường dẫn mà công cụ tệp có thể chạm tới — xem docs/security.md.

Một hồ sơ đăng nhập bằng khóa nhưng cần sudo ở phía xa nhận một sudoPassword — bí mật sudo được trả lời bằng, mà trên nhiều máy không phải là mật khẩu đăng nhập. Giữ nó trong tệp bí mật thay vì ở đây.

Giữ mật khẩu SSH và cụm mật khẩu ngoài hồ sơ

Ưu tiên dùng khóa. Nếu không thể tránh được mật khẩu hoặc cụm mật khẩu cho khóa đã mã hóa, hãy giữ nó trong một tệp bí mật riêng, không bao giờ đặt trong chính hồ sơ:

{
  "secretsFile": "~/.config/ssh-mcp/secrets.json",
  "profiles": {
    "production": {
      "host": "server.example.com",
      "username": "admin"
    }
  }
}

Tệp bí mật được khóa theo tên hồ sơ — xem secrets.json.example:

{
  "production": { "password": "..." },
  "buildbox": { "sudoPassword": "..." }
}

sudoPassword là câu trả lời cho sudo trên máy đó. Một hồ sơ đăng nhập bằng khóa không có mật khẩu đăng nhập để cung cấp, và khi hai giá trị khác nhau, giá trị đăng nhập là câu trả lời sai; nếu không có nó, password sẽ được sử dụng.

Tệp bí mật chỉ bạn mới có thể đọc được (chmod 600). Các đường dẫn tương đối được phân giải từ tệp hồ sơ; bí mật nằm ngoài argv và được che trong nhật ký. Xem bảo mật thông tin xác thực.

Cấu hình Claude Code, Codex và các MCP client khác

Chọn client bạn sử dụng và trỏ nó đến cùng tệp hồ sơ.

Claude Code

Một lệnh; -s user giúp máy chủ khả dụng trong mọi dự án:

claude mcp add ssh -s user \
  -e SSH_PROFILES_FILE="$HOME/.claude/ssh-profiles.json" \
  -- npx -y @hypnosis/ssh-mcp-server

Codex CLI

codex mcp add ssh \
  --env SSH_PROFILES_FILE="$HOME/.codex/ssh-profiles.json" \
  -- npx -y @hypnosis/ssh-mcp-server

opencode

Đặt nó trong ~/.config/opencode/opencode.json:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "ssh": {
      "type": "local",
      "command": ["npx", "-y", "@hypnosis/ssh-mcp-server"],
      "enabled": true,
      "environment": {
        "SSH_PROFILES_FILE": "~/.config/opencode/ssh-profiles.json"
      }
    }
  }
}

Qwen Code

Một lệnh, giống như các lệnh khác:

qwen mcp add ssh \
  -e SSH_PROFILES_FILE="$HOME/.qwen/ssh-profiles.json" \
  npx -y @hypnosis/ssh-mcp-server

Các MCP client khác

Gemini CLI, Hermes, Cline, plugin trình soạn thảo hoặc agent của riêng bạn hoạt động theo cùng cách. Tất cả những gì chúng cần là một lệnh để chạy và một biến môi trường.

Khởi động lại MCP client của bạn

Khởi động lại client, sau đó chạy ssh_monitor({ action: "list" }) để xác nhận hồ sơ đã được tải.

Cấu hình SSH MCP server

BiếnChức năngMặc định
SSH_PROFILES_FILEĐường dẫn đến tệp JSON hồ sơ — bắt buộc
SSH_MCP_LOG_LEVELdebug, info, warn, errorinfo
LOG_LEVELDự phòng, chỉ dùng khi SSH_MCP_LOG_LEVEL chưa được đặtinfo
SSH_MCP_LOG_TIMESTAMPDấu thời gian trong dòng nhật kýtrue
SSH_MCP_CONTROL_PERSISTSố giây kết nối dùng chung duy trì sau lệnh cuối; 0 đóng ngay lập tức600
SSH_MCP_CONTROL_DIRNơi lưu socket điều khiển~/.ssh/ssh-mcp
SSH_MCP_PROFILES_CACHE_TTLTTL bộ nhớ đệm hồ sơ, ms60000
SSH_MCP_PROFILES_WATCHTải lại tệp hồ sơ khi nó thay đổitrue

Kết nối dùng chung cố tình tồn tại lâu hơn tiến trình này: đóng nó khi thoát sẽ cắt kênh mà một cửa sổ khác trên cùng máy đang sử dụng.

Giới hạn của SSH MCP server

Mỗi giới hạn đều chỉ cho bạn cách vượt qua. Một công cụ không thể làm điều gì đó sẽ nói rõ và nêu tên ssh_exec, công cụ chạy lệnh trực tiếp trên máy — một trình điều khiển nhật ký không được hỗ trợ, một tiện ích máy không có, một engine máy chủ này không hỗ trợ. Bạn không cần biết trước ranh giới của các công cụ: lời từ chối sẽ nói rõ, vào đúng thời điểm quan trọng.

Ba lời từ chối cố tình giữ im lặng về shell, vì ở đó đó là câu trả lời sai: một đường dẫn mà hồ sơ của bạn cấm (đi vòng qua quy tắc của chính bạn không phải là cách khắc phục), một lệnh gọi sai định dạng (cách khắc phục nằm trong lệnh gọi), và một lời từ chối từ chính ssh_exec.

  • Hủy bỏ: một lệnh gọi bị hủy giờ cũng dừng lệnh trên máy chủ, được gửi dưới dạng lệnh gọi thứ hai qua cùng kết nối. Nơi máy chủ không có /proc, lệnh được tìm qua ps thay thế. FreeBSD chưa được xác minh: hành vi chính xác ở đó không được đảm bảo. Truyền tệp và ssh_snapshot hoàn toàn không hỗ trợ hủy bỏ.
  • Ghi nguyên tử: BSD và macOS không thể kiểm tra trước các thao tác đổi tên giữa các hệ thống tệp.

Lộ trình phát triển SSH MCP server

  • Chạy thử nghiệm đầy đủ trên máy chủ SSH macOS

  • Chạy kiểm tra tương thích đầu cuối trên Windows

  • Kiểm tra nhiều máy chủ — so sánh tình trạng sức khỏe trên nhiều hồ sơ SSH trong một lệnh gọi

  • Nhập hồ sơ từ ~/.ssh/config hiện có

  • Truyền tệp có thể tiếp tục cho tệp lớn và kết nối không ổn định

  • Dòng thời gian thao tác từ xa — lệnh, truyền tệp và quyết định bảo vệ trong một dấu vết kiểm toán

  • Sổ tay xử lý sự cố SSH có sẵn

  • Nhật ký container mà không cần truy cập shellHOÀN THÀNH: ssh_log_tailssh_log_search nhận tên container, hỏi docker nơi nó ghi và đọc tệp đó bằng cùng cơ chế như mọi nhật ký khác

  • Lời từ chối khiến bạn bế tắcHOÀN THÀNH: mọi giới hạn giờ đều nêu tên ssh_exec như cách vượt qua, vì vậy chạm ranh giới của một công cụ chỉ tốn một câu thay vì một trò đoán

  • Câu trả lời đến được mô hìnhHOÀN THÀNH: đầu ra lệnh, dòng nhật ký khớp, tên máy và phần ảnh chụp di chuyển trong các trường, không chỉ trong văn bản

  • Lược đồ công cụ MCP nhỏ hơnHOÀN THÀNH: danh sách công cụ nhẹ hơn 10%, và một công việc tách rời giờ hiển thị các dòng cuối nó ghi thay vì bị thăm dò mù

  • Công việc dài dưới quyền rootHOÀN THÀNH: một công việc tách rời chạy với sudo và được theo dõi dưới quyền root, và một hồ sơ chỉ dùng khóa trả lời sudo bằng sudoPassword của chính nó

Phát triển và kiểm thử SSH MCP server

npm install
npm run build           # tsc
npx tsc --noEmit        # types, plus dead declarations
npm run test:unit       # unit tests
npm run lab:up          # start the two test containers
npm run test:live       # live suite against those containers

Bộ kiểm thử trực tiếp chạy trên các container thực — một BusyBox, một coreutils — vì hai loại này âm thầm bất đồng, và một mô hình giả lập đồng ý với bất kỳ ai viết ra nó. Xem docs/architecture.md để biết cấu trúc.

Thích SSH MCP Server? ⭐

Nếu bạn thích công cụ này, hãy tặng nó một sao trên GitHub — điều đó giúp nhiều người khám phá dự án hơn.

Đóng góp cho SSH MCP server

Các vấn đề và yêu cầu kéo đều được hoan nghênh tại github.com/hypnosis/ssh-mcp-server.

Giấy phép

MIT — xem LICENSE.