Skip to main content
Glama

docker-vm-mCP

由 sundar 构建。

这是一个 MCP 服务器,为 AI 代理提供完整的虚拟机生命周期控制——创建、SSH 登录、执行命令、停止/启动/重启、删除、日志和资源统计——这些"虚拟机"由 Docker 容器提供支持。每台虚拟机都是一个真实的 Ubuntu 系统,运行着真正的 sshd,带有 sudo 和持久化磁盘,因此它的行为就像一台你可以登录的普通机器 ——无需云账户,也无需嵌套虚拟化。服务器本身已容器化并作为 Docker 镜像发布, 完全通过 Model Context Protocol 驱动。

设置完成后,你只需向 Claude 提问,例如:

  • "创建一个名为 dev-box 的虚拟机,配 2 个 CPU 和 2GB 内存"

  • "SSH 登录 dev-box" / "dev-box 的 SSH 登录信息是什么?"

  • "在 dev-box 上安装 nginx 并启动它"

  • "停止 dev-box" / "删除 dev-box"

  • "列出我所有的虚拟机"

Claude 将通过下面的工具驱动整个生命周期。

工作原理

每台"虚拟机"都是一个 Docker 容器,基于一个小型 Ubuntu 22.04 镜像 (vm-image/Dockerfile)构建,运行真正的 sshd,带有 sudo,并挂载一个 命名 Docker 卷作为其主目录(因此文件在停止/重启后仍然保留,类似于附加到 EC2 实例的 EBS 卷)。MCP 服务器本身通过 /var/run/docker.sock 与你的本地 Docker 守护进程通信——它本身不运行虚拟机,而是驱动你现有的 Docker Desktop 安装。

Claude  <--MCP/stdio-->  docker-vm-mcp container  <--docker.sock-->  Docker Desktop
                                                                          |
                                                                    vm-dev-box (Ubuntu + sshd)
                                                                    vm-staging (Ubuntu + sshd)
                                                                    ...

Related MCP server: Docker MCP Server

前置条件

  • 在 Mac 上安装并运行 Docker Desktop

  • 仅当你想在 Docker 之外运行服务器时才需要 Node.js 20+(非必需)

1. 构建

从本文件夹执行:

docker build -t docker-vm-mcp:latest .

这只会构建 MCP 服务器镜像。虚拟机基础镜像 (docker-vm-mcp/vm-base:latest)会在你第一次调用 vm_create 时自动构建 ——服务器内置了 vm-image/Dockerfile,并在首次使用时针对你的 Docker 守护 进程进行构建。你也可以自行预先构建:

docker build -t docker-vm-mcp/vm-base:latest ./vm-image

2. 运行 / 注册到 Claude Desktop

基于 stdio 的 MCP 服务器由客户端(Claude Desktop)启动,而不是独立运行。 将此配置添加到你的 Claude Desktop 配置文件中 (~/Library/Application Support/Claude/claude_desktop_config.json):

{
  "mcpServers": {
    "docker-vm-mcp": {
      "command": "docker",
      "args": [
        "run", "-i", "--rm",
        "-v", "/var/run/docker.sock:/var/run/docker.sock",
        "-v", "docker-vm-mcp-state:/data",
        "docker-vm-mcp:latest"
      ]
    }
  }
}

然后重启 Claude Desktop。两个挂载都是必需的:

  • /var/run/docker.sock —— 让服务器能在你的机器上创建/启动/停止/进入虚拟机 容器。

  • docker-vm-mcp-state(一个命名卷)—— 服务器在此记录每台虚拟机生成的 SSH 密码,以便跨重启保留。没有它,每当 MCP 服务器容器重启时,vm_ssh_info 就会丢失已保存的密码(虚拟机容器本身不受影响——它们会继续运行)。

在接入 Claude Desktop 之前,你可以先快速验证镜像能运行并能访问 Docker:

docker run -i --rm \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -v docker-vm-mcp-state:/data \
  docker-vm-mcp:latest
# should print nothing and just wait on stdin (that's correct — it's
# speaking MCP, not a REPL). Ctrl+C to exit.

此服务器暴露的工具

工具

功能

vm_create

创建并启动一台新虚拟机。参数:name、cpus、memoryMb、sshPort、sshUser、sshPublicKey。返回 SSH 命令和生成的密码。

vm_list

列出所有受管虚拟机及其状态和 SSH 端口。

vm_start

启动一台已停止的虚拟机。

vm_stop

停止一台正在运行的虚拟机(磁盘会被保留)。

vm_restart

重启一台虚拟机。

vm_delete

永久删除一台虚拟机(以及其磁盘卷,除非 removeVolume=false)。

vm_exec

直接通过 Docker 在虚拟机内运行 shell 命令(无需 SSH)。

vm_ssh_info

获取虚拟机的 SSH 命令、主机、端口、用户和密码。

vm_set_password

设置或重新生成虚拟机的 SSH 密码(在手动更改密码后也会重新同步 vm_ssh_info)。

vm_logs

跟踪虚拟机的控制台/系统日志输出。

vm_stats

查看正在运行的虚拟机的实时 CPU 百分比 / 内存使用情况。

自行登录

每台虚拟机都会将其 SSH 端口绑定到你的 Mac 上,因此一旦 Claude 创建了虚拟机, 你也可以直接从终端 SSH 登录:

ssh vmuser@localhost -p <port>   # port and password from vm_create / vm_ssh_info

向 vm_create 传入 sshPublicKey(你的 ~/.ssh/id_ed25519.pub 内容)即可 跳过密码,改用你的密钥登录。

发布此镜像

要分享它(例如让队友或其他机器直接 docker pull 而不是从源码构建):

docker tag docker-vm-mcp:latest <your-dockerhub-username>/docker-vm-mcp:latest
docker push <your-dockerhub-username>/docker-vm-mcp:latest

镜像中没有内置任何机密信息——凭据是在运行时按虚拟机生成的,并且只存储在运行 该容器的机器上的本地 docker-vm-mcp-state 卷中。可以安全发布。

安全说明(在将此工具暴露给除你自己机器以外的任何环境之前,请先阅读)

  • 挂载 Docker 套接字等同于 root 权限。 任何能访问 /var/run/docker.sock 的人都可以控制你机器上的所有容器,而不仅仅是此工具创建的虚拟机。只能在 你信任的机器上使用此镜像并挂载该套接字,切勿将 MCP 服务器本身(或其端口) 暴露给不受信任的调用方。

  • SSH 密码以明文形式存储在 docker-vm-mcp-state 卷中 (/data/credentials.json),以便 vm_ssh_info 之后能将其返回给你。这对 个人本地开发工具来说没问题;未经加固(例如改用仅密钥认证并停止持久化密码), 不要将其用于多租户或生产环境。

  • 虚拟机容器默认将 SSH 端口发布在 0.0.0.0 上(Docker 的默认行为),这意味着 如果你的防火墙允许,本地网络上的其他设备可能可以访问它。如果这对你很重要, 请传入显式的 sshPort 并设置防火墙,或仅绑定到 127.0.0.1(将 src/tools/createVm.ts 中的 PortBindings 主机 IP 改为 127.0.0.1 并重新 构建)。

真实环境验证:ServiceNow Discovery

此项目已被用作真实 ServiceNow 实例的实时 Discovery 目标,通过本地运行的 MID Server(同样已 Docker 化)——这证明了它表现得像一台真正的可通过 SSH 访问的 Linux 主机,而不仅仅是一个玩具:

  • 标准 Discovery,MID Server → 通过 Mac 的局域网 IP 和虚拟机发布的 SSH 端口访问虚拟机(例如 192.168.x.x:<port>)——成功创建了一个 cmdb_ci_linux_server CI,主机名、操作系统、内存和 CPU 详情均通过 SSH 实时获取。

  • Quick Discovery 也可以同样工作。

  • 由于 MID Server 容器和虚拟机容器都位于 Docker 默认的 bridge 网络上, 它们也可以直接通过内部容器 IP 在标准 SSH 端口(22)上互相访问——无需 发布端口,也不依赖 Mac 的局域网 IP(该 IP 会随网络变化而改变)。

  • 如果你自己尝试,有一个值得注意的小问题:发现的 CPU 制造商显示为 "Apple"。这是正确的,不是 bug——Docker Desktop for Mac 在直接启动于 主机自身 Apple Silicon 芯片上的 linuxkit 虚拟机中运行容器,因此读取 /proc/cpuinfo 的 SSH 探测会看到底层的真实硬件,就像在任何其他主机上 一样。

项目结构

docker-vm-mcp/
├── Dockerfile              # MCP server image
├── package.json
├── tsconfig.json
├── vm-image/
│   └── Dockerfile          # base "VM" image (Ubuntu + sshd), built on first vm_create
└── src/
    ├── index.ts            # MCP server entrypoint (stdio transport)
    ├── docker.ts            # Docker client, image-build, container lookup helpers
    ├── state.ts             # local credential store (/data/credentials.json)
    ├── util.ts              # exec/log demuxing helpers
    └── tools/
        ├── createVm.ts
        ├── listVms.ts
        ├── startVm.ts
        ├── stopVm.ts
        ├── restartVm.ts
        ├── deleteVm.ts
        ├── execVm.ts
        ├── sshInfo.ts
        ├── setPassword.ts
        ├── logsVm.ts
        └── statsVm.ts

关于验证方式的说明

此项目是在一个沙盒环境中构建和进行类型检查的,该环境无法访问 npm 仓库, 因此 npm install / npm run build 无法在此端到端运行。TypeScript 已针对 Node 自身的类型定义进行了检查,没有错误;唯一剩余的检查是针对 @modelcontextprotocol/sdk、dockerode 和 zod 自身的类型,这些包在 该沙盒中无法安装。将项目复制到你的 Mac 后,在首次 docker build 之前, 请运行一次以下命令:

npm install
npm run build

如果 tsc 报告了除上述已处理内容之外的任何错误,很可能是 @modelcontextprotocol/sdk 中特定版本的 API 变化(这是一个快速迭代的包) ——解决方法几乎总是对 src/index.ts 中的导入路径 (@modelcontextprotocol/sdk/server/mcp.js / .../server/stdio.js)做小幅 调整,以匹配 npm install 解析到的版本。

Related MCP Connectors

Related MCP Servers