内容
<p align="center">
```
████████ ██████ ████████ ████████ ████████ ████████
██ ██ ██ ██ ██ ██ ██ ██ ██ ██
████████ ██ ██ ████████ ██ ██████ ████████
██ ██ ██ ██ ██ ██ ██ ██ ██
██ ██████ ██ ██ ██ ████████ ██ ██
```
</p>
<h3 align="center">独立MCP网关</h3>
<p align="center"><em>尼布斯生态系统的一部分</em></p>
---
Porter 将多个MCP服务器聚合到一个统一的MCP端点。你可以使用 `porter serve` 或 `porter stdio` 独立使用它,也可以作为 [尼布斯](https://github.com/Layer-Prime-Solutions/nimbus) 平台的一部分。
## 什么是Porter?
Porter 是一个库和二进制文件,它在单个MCP接口后面聚合了多个MCP服务器:
- **MCP服务器**:通过STDIO或流式HTTP传输管理外部MCP服务器,命名空间隔离它们的工具以防止名称冲突
无需任何尼布斯基础设施即可独立运行。直接连接任何MCP客户端。
## 安装
```bash
cargo install nimbus-porter-cli
```
从源代码构建:
```bash
git clone https://github.com/Layer-Prime-Solutions/porter
cd porter
cargo build --release
# 二进制文件位于 ./target/release/porter
```
## 快速入门
**1. 创建一个 `porter.toml` 配置文件** (或复制示例: `cp porter.example.toml porter.toml` ):
```toml
# MCP服务器(STDIO或HTTP传输)
[servers.github-mcp]
slug = "gh-mcp"
transport = "stdio"
command = "gh-mcp"
[servers.context7]
slug = "c7"
transport = "http"
url = "https://mcp.context7.com/mcp"
```
**2. 启动Porter:**
```bash
porter serve
```
输出:
```
Porter HTTP服务器监听 host=127.0.0.1 port=3000
将你的MCP客户端连接到 http://127.0.0.1:3000/mcp
```
**3. 将你的MCP客户端连接到 `http://127.0.0.1:3000/mcp`**
所有已配置服务器上的所有工具都可在该单个端点上使用。
## 配置
Porter 配置使用 `porter.toml` (或通过 `--config` 使用自定义路径)。
### 监听
为 `porter serve` 设置默认绑定地址和端口。命令行标志 `--host` 和 `--port` 在提供时覆盖这些。
```toml
[listen]
host = "127.0.0.1" # 默认: "127.0.0.1"
port = 3000 # 默认: 3000
```
### MCP 服务器
```toml
[servers.<name>]
slug = "unique-id" # 必需:用作工具命名空间前缀的标识符
transport = "stdio" # "stdio" 或 "http"
enabled = true # 可选:默认 true
# 对于stdio传输:
command = "my-mcp-server" # stdio所需
args = ["--verbose"] # 可选额外参数
env.MY_VAR = "${MY_VAR}" # 可选环境变量(必须使用 ${VAR} 语法)
cwd = "/path/to/dir" # 可选工作目录
# 对于http传输:
url = "https://mcp.example.com/mcp" # http所需
# 工具访问门控(可选,适用于任何传输):
allow = ["get_*", "search_*"] # 如果存在,只允许匹配的工具
deny = ["*delete*", "merge_*"] # 匹配的工具始终被阻止
```
### 工具访问门控
每个服务器都接受可选的 `allow` 和 `deny` 列表,以控制Porter公开哪些工具。门控在 **两个** 方向上强制执行:被拒绝的工具从聚合工具列表中隐藏 **并且** 在转发到下游服务器之前被拒绝(Porter从不代理然后过滤)。
匹配应用于下游(非命名空间)工具名称。每个条目都是确切的名称或简单的通配符:
| 模式 | 匹配 | 示例 |
|------------|--------------------|----------------------|
| `name` | 完全匹配 | `merge_pull_request` |
| `prefix*` | 前缀匹配 | `jira_get_*` |
| `*suffix` | 后缀匹配 | `*_issue` |
| `*inner*` | 子字符串匹配 | `*delete*` |
`*` 通配符仅在单个前导和/或尾随字符中受尊敬(上述四种形式)。`*` 在其他任何地方 — 内部星号,如 `delete*confirm` 或双 `**abc` — 都被视为字面意义并静默匹配,因此Porter **在启动时拒绝此类模式** 而不是开放失败。
如果工具 **同时** 允许(`allow` 被省略 **或** 它与 `allow` 条目匹配) **并且** 它不与任何 `deny` 条目匹配,则该工具被允许。**拒绝始终优先于允许** — 同时列出的工具被阻止(Porter在启动时记录警告)。如果未配置 `allow`/`deny`,则代理所有后端工具。显式空列表(`allow = []`)阻止所有工具。 裸 `*` 匹配所有内容。
被阻止的工具永远不会到达后端:对一个被阻止的工具的调用被Porter本身以访问策略错误拒绝,该错误会指定工具、服务器和原因。
> **通用执行器**:一些服务器在单个工具后面提供整个API(例如 `awslabs.aws-api-mcp-server` 的 `call_aws`)。Porter's gate 匹配工具 **名称**,因此它无法区分读取和写入操作,当两者都在一个工具内部时 — 对于这些服务器,请使用服务器自己的开关强制只读(例如 `READ_OPERATIONS_ONLY=true`)。
### 完整示例
```toml
[servers.filesystem]
slug = "fs"
transport = "stdio"
command = "mcp-server-filesystem"
args = ["/home/user/projects"]
[servers.github-mcp]
slug = "gh-mcp"
transport = "stdio"
command = "gh-mcp"
env.GITHUB_TOKEN = "${GITHUB_TOKEN}"
```
## 用法
### porter serve
启动一个可流式的HTTP MCP服务器:
```bash
# 默认:localhost:3000,porter.toml中的配置
porter serve
# 自定义配置、端口和主机
porter serve --config my-tools.toml --port 8080 --host 0.0.0.0
```
选项:
- `--config` / `-c`:配置文件路径(默认: `./porter.toml` 或 `~/.config/porter/porter.toml`)
- `--port` / `-p`:HTTP端口(覆盖配置中的 `[listen].port`;默认: `3000`)
- `--host`:绑定地址(覆盖配置中的 `[listen].host`;默认: `127.0.0.1`)
**热重载**:Porter 监视配置文件中的更改。当你编辑 `porter.toml` 时,Porter 会自动重新加载工具表面并向所有连接的MCP客户端发送 `tools/list_changed` 通知 — 无需重启。
MCP端点: `http://<host>:<port>/mcp`
### porter stdio
通过STDIO桥接所有已配置的工具,适用于Claude Desktop和其他基于STDIO的MCP客户端:
```bash
porter stdio
porter stdio --config /path/to/porter.toml
```
选项:
- `--config` / `-c`:配置文件路径(默认: `./porter.toml` 或 `~/.config/porter/porter.toml`)
**热重载**:与 `porter serve` 相同 — Porter 监视配置文件中的更改并自动向连接的客户端发送 `tools/list_changed` 通知。无需重启。
## 客户端配置
Porter 按顺序搜索配置文件: `./porter.toml` 然后 `~/.config/porter/porter.toml`。如果你将配置文件放在 `~/.config/porter/porter.toml`,下面的示例在不带 `--config` 的情况下直接工作。
### Claude 代码
```bash
claude mcp add porter -- porter stdio
```
或使用显式配置文件路径:
```bash
claude mcp add porter -- porter stdio --config ~/.config/porter/porter.toml
```
### Claude 桌面版
添加到 `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS)或 `%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"porter": {
"command": "porter",
"args": ["stdio"]
}
}
}
```
### 光标
添加到光标MCP设置( `.cursor/mcp.json` ):
```json
{
"mcpServers": {
"porter": {
"command": "porter",
"args": ["stdio"]
}
}
}
```
### VS 代码 / Copilot
添加到 `.vscode/mcp.json`:
```json
{
"servers": {
"porter": {
"type": "stdio",
"command": "porter",
"args": ["stdio"]
}
}
}
```
### 风云
添加到 `~/.codeium/windsurf/mcp_config.json`:
```json
{
"mcpServers": {
"porter": {
"command": "porter",
"args": ["stdio"]
}
}
}
```
### 任何流式HTTP客户端
启动 `porter serve` 并连接到端点:
```
http://127.0.0.1:3000/mcp
```
## 用例配方
`porter.example.toml` 包含可直接使用的配置块,用于通过MCP服务器将AI代理连接到流行的项目管理、代码审查和云基础设施平台。每个配方都按照访问层记录了每个公开的工具,并附带一个默认只读的 `deny` 列表,您可以放松此限制。
### 访问层
| 层级 | 默认 | 描述 | 示例 |
|------|---------|-------------|----------|
| **读取** | 已启用 | 被动观察 — 无副作用 | 搜索,列出,获取,查看,差异 |
| **反馈** | 已启用 | 参与工作流而无破坏性副作用 | 创建问题,添加评论,更新标签/状态 |
| **破坏性** | 已拒绝 | 不可逆或高影响操作 | 删除,合并,关闭,存档 |
| **代码写入** | 已拒绝 | 源代码的重要修改 | 推送文件,创建分支,复刻仓库 |
每个配方都附带一个 `deny` 列表(参见 [工具访问门控](#tool-access-gate)),默认阻止其 **破坏性** 和 **代码写入** 工具,因此 **读取** 和 **反馈** 工具默认是唯一公开的工具。要选择一个被阻止的工具,请在审查影响后,从该服务器的 `deny` 列表中删除其行。
### 可用配方
| 平台 | 包 | 传输 | 认证 |
|----------|---------|-----------|------|
| GitHub | `@modelcontextprotocol/server-github` | STDIO | `GITHUB_TOKEN` |
| GitLab | `@modelcontextprotocol/server-gitlab` | STDIO | `GITLAB_TOKEN` (+ 可选 `GITLAB_API_URL`) |
| Linear | `mcp-remote` → `https://mcp.linear.app/sse` | STDIO(远程桥) | OAuth(浏览器流程) |
| Jira | `mcp-atlassian` (通过 `uvx`) | STDIO | `JIRA_URL` + `JIRA_USERNAME` + `JIRA_API_TOKEN` |
| ClickUp | `clickup-mcp-server` | STDIO | `CLICKUP_API_KEY` + `CLICKUP_TEAM_ID` |
| AWS | `awslabs.aws-api-mcp-server` (通过 `uvx`) | STDIO | `AWS_PROFILE` (+ `READ_OPERATIONS_ONLY=true` 表示只读) |
要使用配方:打开 `porter.example.toml`,找到平台块,取消注释,设置所需环境变量,并将其复制到 `porter.toml` 中。
> **注意**:这些是由其各自社区维护的第三方MCP服务器。在将它们公开给生产环境中的AI代理之前,请查看每个服务器的文档和安全状况。
## 安全
- **工具命名空间**:每个服务器的工具都带有其slug前缀,以防止名称冲突
- **工具访问门控**:每个服务器的 `allow`/`deny` 列表隐藏被阻止的工具,并拒绝它们在到达下游服务器之前([详细信息](#tool-access-gate))
- **环境隔离**:子STDIO服务器 **不** 继承Porter的环境。每个子进程都从清空的环境启动,只带有最小的基准(`PATH`,`HOME`,`LANG`)加上其 `env` 块中声明的变量 — Porter自己的秘密永远不会泄露到下游
- **健康跟踪**:不健康的服务器自动从工具列表和调用中排除
- **热重载**:配置更改被自动拾取,无需重启
## 许可证
根据MIT或Apache-2.0许可证授权,由您选择。