使用说明
vps-mcp
用于通过SSH管理VPS服务器的MCP(模型上下文协议)服务器。将其连接到Claude Code、Claude Desktop或Claude.ai,以执行命令、传输文件、管理Docker容器和维护每台服务器的文档——所有这些都可以在Claude中完成。
特性
- SSH执行 --在远程服务器上运行命令和shell脚本
- 文件传输 --SFTP加上三个远程友好通道:内联内容工具、流式HTTP端点和向服务器获取URL
- Docker管理 —
docker ps,docker compose,docker exec,部署应用程序 - 服务器文档 --扫描服务器并为每台服务器生成/更新Markdown文档
- 加密保管库 --使用AES-256-GCM+PBKDF2存储的服务器凭据
运作原理
Claude Code / Claude Desktop / Claude.ai
│
│ MCP protocol
▼
vps-mcp (this server)
│
│ SSH / SFTP
▼
Your VPS servers
vps-mcp将SSH密钥和密码存储在 加密保险库 (AES-256-GCM)。在每次工具调用时,它都会打开到目标服务器的SSH连接,执行操作并返回结果。
支持两种运输方式:
- 标准 --本地使用(Claude Code,同一台机器上的Claude Desktop)
- HTTP(流式HTTP) --用于远程访问(其他设备,Claude.ai网络)
安装
要求: Node.js 20+
git clone https://github.com/ereskovsky/vps-mcp
cd vps-mcp
npm install
npm run build
创建 .env 从模板中:
cp .env.example .env
编辑 .env:
# Master password for the encrypted vault. Pick any strong passphrase.
VAULT_PASSWORD=your-strong-passphrase
# Bearer token for HTTP mode (generate with: openssl rand -hex 32)
API_KEY=your-random-api-key
# HTTP port (default: 3001)
# PORT=3001
# For HTTP mode with OAuth (required for Claude.ai web)
BASE_URL=https://vps-mcp.yourdomain.com # no port — required for OAuth metadata to work
CLIENT_ID=vps-mcp # any string, needed when adding the integration in Claude.ai
CLIENT_SECRET= # defaults to API_KEY if not set
本地使用(stdio)
此模式有效 无需任何服务器部署 --vps-mcp在您的计算机上运行,并通过SSH连接到vps服务器。
克劳德代码
claude mcp add vps-mcp -s user -e VAULT_PASSWORD="your-password" -- node "/path/to/vps-mcp/dist/index.js" --stdio
克劳德桌面版
添加 claude_desktop_config.json (~/Library/Application Support/Claude/ 在Mac上, %APPDATA%\Claude\ 在Windows上):
{
"mcpServers": {
"vps-mcp": {
"command": "node",
"args": ["/absolute/path/to/vps-mcp/dist/index.js", "--stdio"],
"env": {
"VAULT_PASSWORD": "your-password"
}
}
}
}
部署到VPS(HTTP模式)
需要从其他设备或Claude.ai网站进行远程访问。
1.准备
在您的VPS上克隆仓库。编辑 Caddyfile 并替换域:
vps-mcp.yourdomain.com {
reverse_proxy vps-mcp:3001
}
确保您的域名的DNS A记录指向VPS IP。
2.开始
cp .env.example .env
# Fill in VAULT_PASSWORD and API_KEY
docker compose up -d
Caddy将通过Let's Encrypt自动获得TLS证书。
3.连接客户端
克劳德代码/克劳德桌面(远程):
claude mcp add vps-mcp -s user --transport http "https://vps-mcp.yourdomain.com/mcp" \
--header "Authorization: Bearer your-api-key"
或者在配置中手动:
{
"mcpServers": {
"vps-mcp": {
"url": "https://vps-mcp.yourdomain.com/mcp",
"headers": {
"Authorization": "Bearer your-api-key"
}
}
}
}
连接到Claude.ai(网络,OAuth)
Claude.ai使用OAuth 2.0(authorization_code +PKCE)连接到远程MCP服务器。vps-mcp实现了完整的OAuth流程。
需求
- 服务器已部署并可通过HTTPS访问
BASE_URL在.env必须是公共领域 没有非标准端口 (例如。https://vps-mcp.yourdomain.com,不https://...:4443)--否则Claude.ai无法联系到token_endpoint来自OAuth元数据
步骤
- 打开 Claude.ai→ 设置→ 集成→ 添加集成
- 输入URL:
https://vps-mcp.yourdomain.com/mcp - 进入 客户端ID (价值
CLIENT_ID从.env) - 进入 客户端密钥 (价值
CLIENT_SECRET从.env,默认为API_KEY) - Claude.ai将打开一个授权页面——确认访问
OAuth端点
| 端点 | 描述 |
|---|---|
GET /.well-known/oauth-authorization-server |
OAuth元数据(发现) |
GET /oauth/authorize |
授权页面(浏览器重定向) |
POST /oauth/token |
令牌的交换代码 |
将服务器添加到vault
通过SSH密钥(推荐)
首先用base64对私钥进行编码:
# Linux / Mac
base64 -w 0 ~/.ssh/id_ed25519
# Windows (PowerShell)
[Convert]::ToBase64String([IO.File]::ReadAllBytes("$env:USERPROFILE\.ssh\id_ed25519"))
然后打电话给 add_server 工具:
name: prod-1
host: 1.2.3.4
port: 22
username: root
authType: key
privateKey: <base64 string from above>
passphrase: <key passphrase, if any>
description: Main production server
通过密码
name: staging
host: 5.6.7.8
port: 22
username: ubuntu
authType: password
password: your-ssh-password
description: Staging environment
工具发现模型(渐进式发现)
当客户端连接时, tools/list 回报 只有4个元工具不是真正的18个。该模型使用它们来按需查找和调用实际工具,从而将LLM的“冷”上下文成本降至大致 1K代币,而不是5-10K.
| 元工具 | 它的作用 |
|---|---|
list_tool_categories |
列出5个类别(注册表、ssh、文件、部署、文档)以及工具数量和描述。 |
search_tools |
按以下方式搜索工具 query (名称/摘要/描述对应的子字符串)和/或 category.返回轻量级 {name, category, summary} --不是完整的模式。 |
get_tool_schemas |
按名称返回1-10个工具的完整描述和JSON模式输入定义。 |
invoke_tool |
执行一个真正的工具: {name, arguments}参数是严格根据工具的模式进行Zod验证的。 |
典型的LLM工作流程:
search_tools({query: "docker"}) → ["docker_ps", "docker_compose", "docker_exec", ...]
get_tool_schemas({names: ["docker_ps"]}) → full schema for docker_ps
invoke_tool({name: "docker_ps", arguments: {server: "prod"}}) → result
下面的真实工具被记录下来供人类参考——模型通过以下方式发现它们 search_tools / get_tool_schemas.
工具
注册表--服务器管理
list_servers
返回所有已注册的服务器。密码和密钥是 从未暴露.
add_server
| 参数 | 类型 | 必填 | 说明 |
|---|---|---|---|
name |
string | yes | 唯一标识符(字母、数字、, -_) |
host |
string | yes | IP地址或主机名 |
port |
number | no | SSH端口(默认值:22) |
username |
string | yes | SSH用户 |
authType |
key / password |
yes | 身份验证类型 |
privateKey |
string | 如果 key |
Base64编码的PEM私钥 |
passphrase |
string | no | 密钥短语 |
password |
string | 如果 password |
SSH密码 |
description |
string | 否 | 服务器描述 |
remove_server
| 参数 | 类型 | 说明 |
|---|---|---|
name |
string | 要删除的服务器名称 |
SSH--命令执行
execute_command
在服务器上运行单个命令。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | vault中的服务器名称 |
command |
string | Shell命令 |
→ execute_command(server="prod-1", command="df -h")
← { stdout: "...", stderr: "", exitCode: 0 }
execute_script
运行一个多行bash脚本。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
script |
string | Bash脚本(多行) |
文件--SFTP传输
重要--本地模式与远程模式
upload_file/download_file使用localPath在 MCP服务器自己的文件系统。在stdio模式下,这是您的机器(按预期工作)。在HTTP/远程模式(Claude.ai web)下,MCP服务器在VPS上运行--localPath则指VPS, 不是你的机器。对于以远程模式从计算机传输,请使用下面的内联内容工具或HTTP文件端点。
upload_file
通过SFTP将文件从MCP服务器的本地文件系统上传到目标VPS。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
localPath |
string | MCP服务器文件系统上的绝对路径 |
remotePath |
string | 目标VPS上的绝对目标路径 |
download_file
通过SFTP将文件从目标VPS下载到MCP服务器的本地文件系统。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
remotePath |
string | 目标VPS上的路径 |
localPath |
string | MCP服务器文件系统上的路径 |
upload_file_content
将内联内容写入远程文件——不需要MCP服务器端文件。在远程模式下,将此功能用于模型在对话中生成的配置、脚本和小代码文件。软天花板≈5 MB;对于较大的文件,请使用 POST /files/upload HTTP端点。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
remotePath |
string | 目标VPS上的绝对目标路径 |
content |
string | 文件内容(文本或base64) |
encoding |
utf8 / base64 |
默认值 utf8.使用 base64 对于二进制数据 |
download_file_content
读取远程文件并内联返回其内容。拒绝大于的文件 maxBytes 以保护对话上下文。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
remotePath |
string | 目标VPS上的路径 |
encoding |
utf8 / base64 |
默认值 utf8.使用 base64 对于二进制数据 |
maxBytes |
number | 要读取的最大字节数。默认1 MB,硬上限5 MB |
fetch_url_to_server
从公共URL下载文件 直接进入VPS 通过 curl.Bytes不会通过MCP主机或Claude——对于发布工件、transfer.sh链接、原始注册表、S3预签名URL来说非常方便。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
url |
string | http/https源URL |
remotePath |
string | VPS上的绝对目标 |
timeoutSec |
编号 | curl --max-time (默认值300,最大值3600) |
list_remote_files
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
remotePath |
string | 服务器上的目录路径 |
← [{ name, type, size, modifiedAt, permissions }]
HTTP文件端点(大文件,流式传输)
HTTP服务器同时暴露了两个端点 /mcp 用于传输任何大小的文件。它们通过SFTP在用户和目标VPS之间直接流式传输,因此绕过了MCP工具调用的内联内容大小限制。使用与相同的Bearer令牌 /mcp.
POST /files/upload?server=<name>&path=<absolute-remote-path>
正文:原始字节(Content-Type: application/octet-stream).答复: { ok: true, server, path, bytes }.
curl -H "Authorization: Bearer $API_KEY" \
--data-binary "@./local-archive.tar.gz" \
"https://vps-mcp.yourdomain.com/files/upload?server=prod-1&path=/tmp/local-archive.tar.gz"
PowerShell:
curl -H "Authorization: Bearer $env:API_KEY" `
--data-binary "@./local-archive.tar.gz" `
"https://vps-mcp.yourdomain.com/files/upload?server=prod-1&path=/tmp/local-archive.tar.gz"
目标目录必须已经存在(端点不会自动-mkdir).上传后,请Claude通过以下方式解压缩/移动/安装 execute_command.
GET /files/download?server=<name>&path=<absolute-remote-path>
将远程文件作为响应正文流式传输回来 Content-Disposition: attachment.
curl -H "Authorization: Bearer $API_KEY" \
"https://vps-mcp.yourdomain.com/files/download?server=prod-1&path=/var/log/app.log" \
-o app.log
Docker和部署
docker_ps
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
all |
boolean | 包含已停止的容器(默认值:true) |
docker_compose
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
path |
string | 目录的绝对路径 docker-compose.yml |
action |
enum | up / down / restart / pull / logs / ps / build |
service |
string | (可选)特定服务名称 |
flags |
string | (可选)额外标志 |
docker_exec
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
container |
string | 容器名称或ID |
command |
string | 要执行的命令 |
deploy_app
部署应用程序:git pull→ 建造→ 重新启动。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
path |
string | 应用程序目录路径 |
branch |
string | Git分支(默认值: main) |
buildCommand |
string | (可选)构建命令 |
restartCommand |
string | (可选)重新启动命令 |
文档--服务器文档
scan_server
扫描服务器并返回完整快照:
- 操作系统和内核版本
- CPU和RAM
- 磁盘使用情况
- 运行时间
- 运行Docker容器和镜像
- 主动系统服务
- 开放端口(ss/netstat)
- 时钟守护作业
get_server_docs
从以下位置读取存储的Markdown文档 data/docs/{server}.md.
update_server_docs
写入或替换服务器的Markdown文档。
| 参数 | 类型 | 说明 |
|---|---|---|
server |
string | 服务器名称 |
content |
string | 完整Markdown内容 |
常见工作流程
安装新服务器
1. add_server — register the server
2. execute_command — verify connection: "uptime"
3. scan_server — collect a state snapshot
4. update_server_docs — save documentation
部署应用程序
1. deploy_app — git pull + build + restart
2. docker_ps — check container status
3. docker_compose — check logs: action="logs"
调试服务器问题
1. execute_command — "journalctl -u nginx --since '10 minutes ago'"
2. docker_compose — action="logs", flags="--tail=200"
3. execute_command — "df -h && free -h"
安全
- 金库 (
data/servers.enc.json)用AES-256-GCM加密;密钥是通过PBKDF2(100000次迭代)从VAULT_PASSWORD - SSH密钥和密码是 从未以明文形式存储或传输 --仅通过加密的保险库
- vault文件和
data/目录位于.gitignore--从未承诺回购 - HTTP模式受承载令牌保护(
API_KEY)根据每一个请求 - 通过Claude.ai、OAuth 2.0连接时(
authorization_code+PKCE)-没有对客户端的直接API密钥暴露 - HTTPS由Caddy处理(通过Let's Encrypt自动TLS)
list_servers日志永远不会暴露密钥或密码
RAM注释: 如果您的VPS内存有限(<512 MB),请避免运行
npm install在服务器上——这可能会触发OOM杀手。在本地安装依赖项并上传node_modules/.
项目结构
src/
index.ts # Entry point — picks stdio vs HTTP mode
server.ts # createServer() — registers ONLY the 4 meta-tools
types.ts # Shared types: ServerRecord, VaultData, CommandResult
lib/
credential-store.ts # Encrypted vault (AES-256-GCM + PBKDF2)
ssh-client.ts # SSH wrapper: execCommand, execScript, SFTP upload/download/list
doc-manager.ts # Per-server Markdown docs (data/docs/{name}.md)
tools/
registry-core.ts # Central registry, search, Zod→JSON Schema util, ToolDef type
meta.ts # The 4 meta-tools (list_tool_categories, search_tools, get_tool_schemas, invoke_tool)
registry.ts # getRegistryTools() — list_servers, add_server, remove_server
ssh.ts # getSshTools() — execute_command, execute_script
files.ts # getFileTools() — upload_file, download_file, upload_file_content, download_file_content, fetch_url_to_server, list_remote_files
deploy.ts # getDeployTools() — docker_ps, docker_compose, docker_exec, deploy_app
docs.ts # getDocsTools() — scan_server, get_server_docs, update_server_docs
许可证
麻省理工学院
