okedeji/mcpvessel

GitHub: okedeji/mcpvessel

mcpvessel 将不受信任的 MCP 服务器隔离在独立容器中运行,支持安全组合、编排和通过 OCI registry 分发 MCP agent。

Stars: 1 | Forks: 0

# mcpvessel **将不受信任的 MCP 服务器隔离起来,继续使用它们,将其组合成 agent,并进行分享。** [![CI](https://static.pigsec.cn/wp-content/uploads/repos/cas/ad/ad5834178f7599af9fdda11629d49cae07f2997beec49821b2920eff5bfd50e7.svg)](https://github.com/okedeji/mcpvessel/actions/workflows/ci.yml) [![Release](https://img.shields.io/github/v/release/okedeji/mcpvessel?include_prereleases&sort=semver)](https://github.com/okedeji/mcpvessel/releases) [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE) MCP 服务器作为子进程运行,拥有您的完整用户权限。该协议并未对其进行沙箱处理,因此已安装的服务器可以: - 读取您的 SSH 密钥、云凭据和 `.env` 文件 - 在您的机器上运行任意命令 - 将上述任何内容发送到任何地方 这并非理论上的威胁。[CVE-2025-6514](https://nvd.nist.gov/vuln/detail/CVE-2025-6514)(评级为严重)就是由于连接到不受信任的服务器而导致的宿主机远程代码执行,而且审计不断发现数以千计存在漏洞的公共服务器。今天安全并不意味着下一次更新后依然安全。 mcpvessel 将每个 MCP 服务器运行在一个独立的容器中: - 无法访问您的宿主机或文件 - 除非您允许,否则没有出站网络 - 沙箱内没有任何提供商密钥 它自带运行时,因此无需安装 Docker 或容器引擎。它还可以将多个被隔离的服务器组合成一个单一的 LLM agent,并通过 OCI registry 进行分发,这两点将在下文介绍。 ![Claude Code 通过一个被隔离的笔记服务器保存了一条普通笔记,而 mcpvessel 的审计日志捕获并阻止了该服务器试图将 Stripe 密钥泄露给攻击者主机的尝试。](https://raw.githubusercontent.com/okedeji/mcpvessel/main/docs/demo.gif)

让 Claude 保存一条普通笔记。被隔离的服务器悄悄地尝试将您的 STRIPE_SECRET_KEY 发送到 exfil.attacker.net,而 mcpvessel 拦截了它。Claude 看到的是一个刚刚运行成功的工具;而您看到的是它试图掩盖的窃取行为在审计日志中被拒绝。

## 目录 - [隔离它](#cage-it) - [赋予它大脑](#give-it-a-brain) - [发布它](#ship-it) - [隔离环境究竟做了什么](#what-the-cage-actually-does) - [它不能防范什么](#what-it-does-not-protect-against) - [简述工作原理](#how-it-works-briefly) - [安装说明](#install) - [环境要求](#requirements) - [卸载说明](#uninstall) - [命令](#commands) - [贡献与支持](#contributing-and-support) - [许可证](#license) ## 隔离它 在 macOS 或 Linux 上: ``` # 安装已签名的 cask(这也会配置 shell 补全)。 brew install --cask okedeji/tap/mcpvessel # 一次性运行时设置;在 macOS 上这会获取一个小型 Linux VM。 mcpvessel init ``` 隔离您自己的服务器的工作方式也是一样的,无论它是哪个服务器。下面的示例使用 GitHub 的服务器,因为它带有一个真实的 token,隔离环境必须防止其泄露: ``` # 存储 token。mcpvessel 会提示输入该值并隐藏你的输入。 # (或者在脚本中通过管道传入:mcpvessel secrets set NAME < token.txt) mcpvessel secrets set GITHUB_PERSONAL_ACCESS_TOKEN # Cage GitHub 的 MCP server,命名为 @me/github:0.1。 mcpvessel import io.github.github/github-mcp-server -t @me/github:0.1 --secret GITHUB_PERSONAL_ACCESS_TOKEN # 在一个 URL 上提供它,且 api.github.com 是它唯一能访问的 host。 mcpvessel serve @me/github:0.1 --listen 127.0.0.1:7000 --secret GITHUB_PERSONAL_ACCESS_TOKEN --egress api.github.com ``` 这会输出一个 URL。将 Claude 或任何 MCP 客户端指向它: ``` http://127.0.0.1:7000/mcp ``` GitHub 的所有工具都会出现在该 URL 上,您的客户端可以完全像以前一样调用它们。服务器在其自己的容器中运行,除了 `api.github.com` 之外互联网连接被切断,并且其 token 保留在隔离区内:它只能连接到 GitHub,无法触达其他任何地方,也永远无法离开。 `-t @me/github:0.1` 是被隔离服务器的标识符:您通过它来进行服务、推送和拉取。`import` 还会将可编辑的源码写入 `./github-mcp-server/`,您可以随时对其进行调整和重新构建。 不确定服务器需要访问哪些主机?您不必事先知道。每次运行默认采取拒绝策略:当服务器首次尝试连接新主机时,连接会被挂起,mcpvessel 会询问您是否允许。批准一次后就会被记住: ``` # 在未设置 egress 的情况下提供服务,第一个发起外联的调用会被挂起,而不是失败。 mcpvessel serve @me/github:0.1 --listen 127.0.0.1:7000 --secret GITHUB_PERSONAL_ACCESS_TOKEN # mcpvessel egress ls 显示被挂起的 host;批准它,它就会被记住以供下次使用: mcpvessel egress allow @me/github:0.1 api.github.com ``` 通过导入更多服务器并将它们一起提供服务,将多个服务器放在同一个 endpoint 后面,每个服务器都在自己的容器中,且相互之间没有路由: ``` # Cage 第二个 server,一个时钟,命名为 @me/time:0.1。 mcpvessel import pypi:mcp-server-time -t @me/time:0.1 # 在一个 URL 上提供两者;--egress me-github:... 仅向 GitHub server 授予 host。 mcpvessel serve @me/github:0.1 @me/time:0.1 \ --listen 127.0.0.1:7000 --secret GITHUB_PERSONAL_ACCESS_TOKEN \ --egress me-github:api.github.com ``` 每个服务器的工具都会一起出现在那个单一的 URL 上,但每个工具仍处于自己的隔离区中。`--egress me-github:api.github.com` 仅向 GitHub 服务器授予对该主机的访问权限;`me-github` 是它的地址,由 `serve` 命令打印输出。时间服务器没有获得网络权限,因为它不需要网络。 mcpvessel 接受来自 npm、PyPI 或容器镜像的任何 MCP 服务器,无论它是否在 registry 中。只要它能作为 MCP 服务器运行,就可以被隔离。 ## 赋予它大脑 被隔离的服务器负责暴露工具,而像 Claude 这样的 MCP 客户端负责思考。加上 `--reasoning`,思考过程就会移入隔离区内。相同的服务器将变成一个 agent,它可以接受一个目标,并自行决定按何种顺序调用哪些工具。只需一个标志,无需编写 agent 代码。 组合一个可以跨 Sentry 和 Brave Search 进行推理的值班助手: ``` # 存储每个 server 的 key(会提示输入该值;输入将被隐藏)。 mcpvessel secrets set SENTRY_ACCESS_TOKEN mcpvessel secrets set BRAVE_API_KEY # 在一个名为 @me/oncall:0.1 的 reasoning agent 下组合这两个 server。 mcpvessel import io.github.getsentry/sentry-mcp io.github.brave/brave-search-mcp-server \ --reasoning -t @me/oncall:0.1 --secret SENTRY_ACCESS_TOKEN --secret BRAVE_API_KEY ``` 它需要一个已配置的 LLM 提供商(`mcpvessel config provider set`),以及与之前相同的密钥和出站规则: ``` # 给它一个任务,它会通过两个 server 的工具进行推理来回答。 mcpvessel run @me/oncall:0.1 "what is causing our top Sentry error this week, and how do I fix it?" \ --secret SENTRY_ACCESS_TOKEN --secret BRAVE_API_KEY \ --egress sentry.io --egress api.search.brave.com ``` 这会在两个服务器上运行一个 LLM 工具使用循环,该循环与它们一起被隔离,并设有单次运行的花费上限。结果就是您可以像调用其他工具一样调用的 agent,而服务器依然像以前一样保持在沙箱中。密钥只会触达声明了它的服务器,并且与 `--egress` 类似,`--secret` 可以将密钥的作用域限定在多个服务器中的某一个。 它不一定要驻留在您的终端中。通过 serve 运行后,它就是一个您只需使用 `curl` 即可访问的 HTTP endpoint: ``` # 在一个 URL 上提供该 agent。 mcpvessel serve @me/oncall:0.1 \ --listen 127.0.0.1:7000 --secret SENTRY_ACCESS_TOKEN --secret BRAVE_API_KEY \ --egress sentry.io --egress api.search.brave.com # 使用 curl 提示它;结果以 JSON 返回。 curl -sX POST 127.0.0.1:7000/agents/oncall -d '{"prompt":"what is causing our top Sentry error, and how do I fix it?"}' # {"result": "..."} ``` 无需 MCP 客户端或 SDK,只需输入 JSON 并输出 JSON。相同的 agent 可以驻留在服务器上、在 CI 作业中运行,或者隐藏在您自己的 API 背后。它在该端口上仍然为偏好使用它的客户端使用 MCP 协议进行通信,并且任何单个工具都可以通过 `POST /agents//tools/` 直接调用。 ## 发布它 被隔离的服务器或 agent 是一个内容寻址的 bundle。将其推送到您已登录的任何 OCI registry(`mcpvessel login`): ``` mcpvessel push @me/oncall:0.1 ``` 队友可以通过相同的引用拉取并运行它,并以相同的方式进行沙箱化,而无需自己导入或构建: ``` mcpvessel run @me/oncall:0.1 "what is causing our top Sentry error?" ``` 它在推送时签名,在拉取时验证,因此他们运行的正是您构建的内容,并以相同的方式被隔离。发布者密钥指纹以及如何验证拉取的内容在 [SECURITY.md](SECURITY.md#signing-and-trust) 中。 ## 简述工作原理 每次运行都是一组位于私有、仅限内部访问的网络上的小型容器。您隔离的服务器独自位于其专有的网络上,没有向外路由的路径。唯一的出口是 mcpvessel 为您运行的小型代理容器:一个根据您设置的允许列表过滤每个出站网络请求,一个代理服务器之间的调用,当服务器结合 LLM 进行推理时,还有一个容器负责持有您的模型密钥,确保 agent 永远看不到它。在 macOS 上,所有这些都运行在 mcpvessel 首次运行时设置的轻量级 Linux VM 内,因此没有任何东西会直接触及您的宿主机。在 Linux 上,它使用宿主机自带的容器运行时。 ## 安装说明 **Homebrew(推荐)。** 安装已签名的 cask 并配置 shell 自动补全: ``` brew install --cask okedeji/tap/mcpvessel ``` **直接下载。** 从[发布页面](https://github.com/okedeji/mcpvessel/releases)获取适用于您的操作系统和架构的压缩包,根据 `checksums.txt` 进行校验,然后将二进制文件放到您的 `PATH` 路径下。这是在 Windows 上的正确操作方式(在 WSL2 内运行)。 **从源码构建。** 适用于贡献者和任何想要自行构建的人: ``` git clone https://github.com/okedeji/mcpvessel cd mcpvessel make build ``` 注意:在 macOS 上,发布的压缩包捆绑了运行时所需的 Linux VM 镜像,因此优先选择 Homebrew 或直接下载,而不是 `go install`。 ## 环境要求 - macOS(Apple Silicon 或 Intel)或 Linux。在 Windows 上,它在 WSL2 内运行。 - 使用上面的推荐安装方式需要 Homebrew。 - 在首次运行时,`mcpvessel init` 会设置运行时。在 macOS 上,这是一次性步骤:它会下载一个小型 Linux VM 镜像并启动一个无根(rootless)的容器守护进程,根据您的网络连接情况,这大概需要两到五分钟。之后每次运行只需几秒钟。在 Linux 上,这是一个空操作,直接使用宿主机的容器运行时。 ## 卸载说明 停止运行时,移除二进制文件,然后删除状态目录(这将删除 macOS VM、缓存的镜像、您的签名密钥和配置): ``` mcpvessel daemon stop brew uninstall --cask mcpvessel # or delete the binary you installed rm -rf ~/.mcpvessel ``` ## 命令 `mcpvessel --help` 会列出所有命令,而 `mcpvessel --help` 会详细介绍其中任何一个命令,包括其标志和示例。您只需要 `import` 和 `serve` 即可入门;其余的命令会随着您的深入使用而派上用场。 每个命令的深度指南位于 [docs](docs/) 目录中。 ## 贡献与支持 - Bug 和功能请求:[提交 issue](https://github.com/okedeji/mcpvessel/issues)。 - 贡献代码:请参阅 [CONTRIBUTING.md](CONTRIBUTING.md)。 - 发现安全问题?请私下报告。请参阅 [SECURITY.md](SECURITY.md)。 ## 许可证 Apache 2.0。请参阅 [LICENSE](LICENSE)。
标签:AI代理, EVTX分析, MCP协议, NIDS, StruQ, 子域名枚举, 容器化, 日志审计, 沙箱隔离, 系统安全, 运维工具