内容
# PMCP - 进步的MCP
<!-- mcp-name: io.github.ViperJuice/pmcp -->
[](https://pypi.org/project/pmcp/)
[](LICENSE)
**MCP的渐进式披露** - 尽量减少上下文膨胀,实现按需工具发现和动态服务器供应。
## 问题
当 Claude Code 直接连接到多个 MCP 服务器(GitHub、Jira、DB 等)时,它会加载**所有**工具模式到上下文中。这导致:
- **上下文膨胀**:数十个工具定义在您甚至提出问题之前就消耗了令牌
- **静态配置**:需要重启 Claude Code 才能看到新服务器
- **没有渐进式披露**:即使不需要,也会显示完整的模式
Anthropic 已经[强调了上下文膨胀](https://www.anthropic.com/news)是 MCP 工具的一个关键挑战。
## 解决方案
**PMCP** 作为一个单一的 MCP 服务器运行,Claude Code 连接到它。与其公开所有下游工具,它提供:
- **26 个稳定元工具**(不是 50+ 个底层工具)
- **默认延迟**:下游服务器按需提供,仅在 `autoStart` 中列出时才主动启动
- **动态供应**:根据包含 90+ 个服务器的清单,按需供应新服务器
- **渐进式披露**:首先是紧凑的能力卡,然后是详细模式仅在请求时提供
- **策略强制执行**:输出大小限制和可选的秘密删除
## 快速入门
### 安装
```bash
# 使用 uv(推荐)
uv pip install pmcp
# 或直接运行而无需安装
uvx pmcp
# 使用 pip
pip install pmcp
```
> **能力匹配已内置** — 无需 API 密钥。`gateway.request_capability`
> 使用纯 Python 匹配器,可以返回直接 CLI 指导,用于安装的
> 本地工具、MCP 服务器候选或注册搜索指导。
### 使用 `pmcp setup` 配置
PMCP 包括一个向导式帮助程序,可以为 Claude 和 OpenCode 渲染即用型 MCP 客户端配置。
生成的配置仅将您的客户端连接到 PMCP 网关。下游 MCP
服务器在首次使用前保持延迟状态,除非您将它们添加到 `.mcp.json` 中的 `autoStart` 中。
使用 `pmcp setup` 打印生成的配置:
```bash
pmcp setup --client claude --mode stdio # Claude 本地_stdio
pmcp setup --client claude --mode http # Claude 共享服务 HTTP
pmcp setup --client opencode --mode stdio # OpenCode 本地_stdio
pmcp setup --client opencode --mode http # OpenCode 共享服务 HTTP
```
命名配置文件涵盖常见模式:
```bash
pmcp setup --profile local-stdio
pmcp setup --profile shared-local-http
pmcp setup --profile authenticated-shared-http
pmcp setup --profile ci
```
使用 `--write` 直接写入您的客户端配置:
```bash
pmcp setup --client claude --mode http --write
```
无需 `--write`,`pmcp setup` 会打印配置,以便您可以将其粘贴到:
- Claude: `~/.mcp.json`
- OpenCode: `~/.config/opencode/opencode.json`
使用共享服务 HTTP 模式时,请为多个会话或客户端运行一个 PMCP 服务。使用单进程 stdio 模式进行本地测试。
### 共享服务模式(手动)
如果您更喜欢手动配置,请将每个客户端指向共享 HTTP 端点:
```json
{
"mcpServers": {
"pmcp": {
"type": "http",
"url": "http://127.0.0.1:3344/mcp"
}
}
}
```
为什么使用此模式:PMCP 使用单例锁(`~/.pmcp/gateway.lock`),因此多个本地启动可能会发生冲突。一个共享服务避免了锁定冲突,并保持工具状态一致。
共享网关状态:
- 所有连接到一个 PMCP HTTP 网关的客户端共享下游服务器连接、待处理请求、供应工具和生命周期状态。
- `gateway.refresh(force=true)`、`gateway.disconnect_server(force=true)` 和 `gateway.restart_server(force=true)` 可以取消或中断由使用相同网关的另一个客户端启动的下游工作。
- `gateway.health` 和实时 `pmcp status --verbose` 显示下游服务器的启动策略观察结果,而不暴露秘密值。
- `--rate-limit` / `PMCP_RATE_LIMIT` 按观察到的源 IP 地址在 `/mcp` 上应用;本地客户端和反向代理客户端可以共享一个桶,除非代理保留不同的客户端 IP 地址。
快速验证:
```bash
systemctl --user is-active pmcp
curl -sS http://127.0.0.1:3344/mcp
```
### 安全
**默认情况下,HTTP 传输未经身份验证。** 对于任何非本地主机暴露,
请选择一种 HTTP 身份验证模式,并在 PMCP 前面终止 TLS。
`shared-secret` 模式是一种向后兼容的单租户防护措施。它接受
`/mcp` 上的一个静态承载值:
```bash
# 使用环境变量启动带有承载身份验证
PMCP_AUTH_TOKEN=mysecrettoken pmcp --transport http
```
避免使用 `--auth-token` 传递生产令牌;命令行参数可以在
共享主机上的进程列表中可见。
客户端必须在 `/mcp` 请求中包含 `Authorization: Bearer mysecrettoken`。
`/health` 和 `/metrics` 按照设计保持未经身份验证;通过防火墙规则、IP 允许列表或反向代理策略在任何非本地主机暴露之前保护它们。
`resource-server` 模式使 PMCP 验证授权服务器颁发的访问
令牌作为 OAuth 2.1 资源服务器。配置 HTTP 应用程序的公共
颁发者、JWKS URL、资源受众、所需范围和确切允许的来源:
```python
create_http_app(
mcp_server,
auth_mode="resource-server",
resource_server_issuer="https://issuer.example",
resource_server_jwks_url="https://issuer.example/.well-known/jwks.json",
resource_server_audience="https://pmcp.example/mcp",
resource_server_allowed_algorithms=("RS256", "ES256"),
required_scopes=["pmcp.invoke"],
allowed_origins=["https://app.example"],
)
```
PMCP 验证令牌签名、颁发者、过期时间、不早于和受众。受众
绑定到配置的 `resource_server_audience`(服务器的规范资源 URI,按照 RFC 8707);它绝不会从请求
主机头派生。`resource-server` 模式在启动时如果颁发者、
JWKS URL 或受众缺失则关闭,如果 `resource_server_jwks_url` 是
公共主机上的 `https` URL。令牌签名仅适用于操作员配置的
`resource_server_allowed_algorithms` 允许列表(默认
`RS256`/`ES256`);永远不会信任令牌自己的 `alg` 头。JWKS 异步获取
并缓存,因此验证永远不会阻塞事件循环;不可达的 JWKS 端点返回 `503`,而无效令牌返回 `401`。
它拒绝公共身份验证元数据 URL 中的私有、链路本地、环回、多播和未指定主机。PMCP 仍然不是授权服务器,
不提供动态客户端注册、SSO、RBAC、计费或完整的
多租户身份服务。
身份验证模式和 OAuth 资源服务器参数可从 CLI 或
环境(CLI 标志优先;仅在标志未设置时读取环境值):
| 标志 | 环境变量 | 目的 |
| --- | --- | --- |
| `--auth-mode {none,shared-secret,resource-server}` | `PMCP_AUTH_MODE` | 选择 HTTP 身份验证模式。当未设置时,PMCP 推断如果存在令牌则为 `shared-secret`,否则为 `none`。 |
| `--oauth-issuer` | `PMCP_OAUTH_ISSUER` | 授权服务器颁发者(资源服务器模式)。 |
| `--oauth-jwks-url` | `PMCP_OAUTH_JWKS_URL` | 公共 `https` JWKS URL(资源服务器模式)。 |
| `--oauth-audience` | `PMCP_OAUTH_AUDIENCE` | 规范资源受众,RFC 8707(资源服务器模式)。 |
| `--required-scope` (可重复) | `PMCP_REQUIRED_SCOPES` (逗号分隔) | 每个令牌必须存在的作用域。 |
| `--allowed-origin` (可重复) | `PMCP_ALLOWED_ORIGINS` (逗号分隔) | 允许在 `/mcp` 上的浏览器来源;也启用主机头验证。 |
**来源和主机姿势(DNS 重新绑定防御)。** 默认情况下,每个身份验证模式都会运行
源检查:一个带有浏览器 `Origin` 头的请求被拒绝为 `403`,除非
源是环回、与请求 `Host` 相同源或显式允许
列出。没有 `Origin` 头的请求 — 通常的非浏览器 MCP 客户端 — 始终通过。
配置 `--allowed-origin` (或 `PMCP_ALLOWED_ORIGINS`)还会打开主机头验证:请求 `Host`
必须是环回或从配置的源和网关的规范资源主机(`--oauth-audience` /
受保护资源元数据 URL)派生的主机之一;其他主机得到 `403`。主机验证在
默认情况下保持关闭,以便反向代理部署转发任意公共
`Host` 保持工作;如果您在代理后面启用它,请确保您的
网关的公共主机名可以通过配置的源或受众可达,
因此代理的 `Host` 被接受。
**假设和信任模型:**
- PMCP 默认绑定到 `127.0.0.1` — 不安全地公开暴露而没有
`PMCP_AUTH_TOKEN`。
- 配置文件(`.mcp.json`)是受信任的输入 — 将它们视为代码;不要加载不受信任的配置文件。
- `.env` 文件中的秘密传递给子 MCP 服务器进程;使用文件系统权限保护 `.env` 文件。
**生产后台服务(Linux systemd):**
```ini
# ~/.config/systemd/user/pmcp.service
[Unit]
Description=PMCP MCP 网关
[Service]
Environment=PMCP_AUTH_TOKEN=replace-with-secret-token
ExecStart=/usr/local/bin/pmcp --transport http
Restart=on-failure
[Install]
WantedBy=default.target
```
```bash
systemctl --user enable --now pmcp
```
或使用 nohup:
```bash
PMCP_AUTH_TOKEN=replace-with-secret-token nohup pmcp --transport http >> ~/.pmcp/logs/gateway.log 2>&1 &
```
### TLS / 反向代理
PMCP 的 HTTP 传输是**纯文本的**。对于任何超出本地主机的暴露,请在反向代理处终止 TLS 并转发到 `127.0.0.1:3344`。保持 `--host 127.0.0.1`(默认),以便 PMCP
仅监听环回接口。
**Nginx** (`/etc/nginx/sites-available/pmcp`):
```nginx
server {
listen 443 ssl;
server_name pmcp.example.com;
ssl_certificate /etc/letsencrypt/live/pmcp.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/pmcp.example.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:3344;
proxy_set_header Authorization $http_authorization;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
```
**Caddy** (`Caddyfile`):
```
pmcp.example.com {
reverse_proxy 127.0.0.1:3344
}
```
Caddy 通过 Let's Encrypt 自动处理 TLS。
### 其他 MCP 客户端
PMCP 与任何 MCP 兼容的客户端配合使用。以下是热门客户端的配置示例。
#### Codex CLI
创建 `~/.codex/mcp.json`(在 Codex 文档中验证路径):
```json
{
"mcpServers": {
"gateway": {
"command": "pmcp",
"args": []
}
}
}
```
#### Gemini CLI
创建适当的配置文件(在 Gemini CLI 文档中验证路径):
```json
{
"mcpServers": {
"gateway": {
"command": "pmcp",
"args": []
}
}
}
```
> **注意**:配置路径和格式因客户端而异。请在每个客户端的官方文档中验证确切的位置和格式。
### 您的第一个交互
```
您: "截取 google.com 的屏幕截图"
Claude 使用: gateway.invoke {
tool_id: "playwright::browser_navigate",
arguments: { url: "https://google.com" }
}
// 然后: gateway.invoke { tool_id: "playwright::browser_screenshot" }
返回: google.com 的屏幕截图
```
## 架构
```
┌─────────────────────────────────────────────────────────────┐
│ Claude Code │
│ 仅连接到 PMCP(配置中的单个服务器) │
└────────────────────────────┬────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────┐
│ PMCP │
│ • 26 个元工具(目录、调用、任务、配置等) │
│ • 渐进式披露(紧凑卡 → 完整模式) │
│ • 策略强制执行(允许/拒绝列表) │
└────────────────────────────┬────────────────────────────────┘
│
┌────────────────────┼────────────────────┐
▼ ▼ ▼
┌───────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 显式 │ │ 清单 │ │ 自定义服务器 │
│ 自动启动 │ │ (90+ 服务器 │ │ (您自己的 MCP │
│ 服务器 │ │ 按需) │ │ 服务器) │
└───────────────┘ └─────────────────┘ └─────────────────┘
```
**关键原则**:用户仅配置 `pmcp` 在 Claude Code 中。
网关发现和管理所有其他服务器。
### 为什么是单网关?
1. **没有上下文膨胀** - Claude 看到 26 个工具,而不是 50+
2. **没有重启** - 无需重启 Claude Code 即可提供新服务器
3. **一致的接口** - 所有工具都通过 `gateway.invoke` 访问
4. **策略控制** - 集中式允许/拒绝规则
## 网关工具
网关公开了 **26 个元工具**,分为四个类别:
工具注释作为不受信任的提示保留;策略和安全说明
继续使用 PMCP 自己的风险模型。当工具模式省略 `$schema` 时,PMCP
报告 JSON Schema 方言为 `https://json-schema.org/draft/2020-12/schema`。
参见 [SPEC_COMPLIANCE.md](SPEC_COMPLIANCE.md) 以获取当前 MCP 规范
合规矩阵和下一修订版跟踪检查清单。
### 核心工具
| 工具 | 目的 |
|------|---------|
| `gateway.catalog_search` | 搜索可用工具,返回带有小型元数据(如标题、图标、执行提示和模式方言)的紧凑功能卡,以及附加的紧凑 CLI 提示、注册候选和(启用 `include_offline=true` 时)清单供应候选(`manifest_candidates`)携带 `provisionable`/`provision_tool`/`requires_api_key`/`api_key_available`/`env_var` 以便代理可以准确配置服务器 |
| `gateway.describe` | 获取特定工具的详细模式和更丰富的元数据,包括输出模式、注释、执行/任务支持、图标和模式方言 |
| `gateway.invoke` | 调用下游工具并进行参数验证,包括适用于具有任务增强执行功能的任务功能工具 |
| `gateway.refresh` | 重新加载后端配置并重新连接;拒绝请求或活动 MCP 任务正在进行,除非 `force=true` |
| `gateway.health` | 获取网关和服务器健康状态 |
| `gateway.config_status` | 读取有效的配置和启动/身份验证状态以及源属性 |
| `gateway.get_startup_policy` | 读取持久的 `autoStart` 和旧版 `disableAutoStart` 条目按来源 |
| `gateway.set_startup_policy` | 预览或显式应用 `autoStart` 添加/删除/设置操作针对一个选定的来源 |
### 生命周期工具
| 工具 | 目的 |
|------|---------|
| `gateway.connect_server` | 连接或启动一个已知的配置、清单/供应或注册发现的服务器 |
| `gateway.disconnect_server` | 在不编辑 `.mcp.json` 或更改 `autoStart` 的情况下运行时停止服务器 |
| `gateway.restart_server` | 在不更改持久配置的情况下运行时停止然后重新连接服务器 |
### 能力发现工具
| 工具 | 目的 |
|------|---------|
| `gateway.request_capability` | 自然语言能力匹配,可以返回直接 CLI 指导或 MCP 服务器候选 |
| `gateway.sync_environment` | 检测平台和可用 CLI |
| `gateway.provision` | 按需安装和启动 MCP 服务器 |
| `gateway.update_server` | 更新 MCP 服务器包并重新连接它 |
| `gateway.auth_connect` | 存储 API 密钥凭证或确认 URL 模式诱导并重试配置 |
| `gateway.submit_feedback` | 预览/提交技术 PMCP 反馈问题到 GitHub |
| `gateway.provision_status` | 检查安装进度 |
| `gateway.search_registry` | 从外部服务器搜索缓存的公共 MCP 注册元数据 |
| `gateway.register_discovered_server` | 注册注册结果以进行配置 |
### 监控工具
| 工具 | 目的 |
|------|---------|
| `gateway.list_pending` | 列出待处理的工具调用及其健康状态 |
| `gateway.cancel` | 取消待处理的工具调用 |
| `gateway.tasks_list` | 按不透明的任务 ID 列出已代理的下游 MCP 任务 |
| `gateway.tasks_get` | 获取下游 MCP 任务的当前状态 |
| `gateway.tasks_result` | 获取并处理下游 MCP 任务的结果 |
| `gateway.tasks_cancel` | 取消下游 MCP 任务 |
`gateway.refresh` 在共享服务模式下故意保持保守。如果下游请求或活动 MCP 任务正在进行中,刷新返回 `ok=false`,而不会断开或重新连接服务器。使用 `gateway.list_pending` 检查活动 PMCP 请求 ID,并使用 `gateway.tasks_list` 检查下游 MCP 任务 ID,然后在取消该工作可接受时使用 `force=true` 重试。
`gateway.disconnect_server` 和 `gateway.restart_server` 遵循针对目标服务器的相同共享服务中断策略:它们拒绝在服务器有待处理请求或活动 MCP 任务时执行操作,除非 `force=true`。使用 `force=true` 时,仅取消指定服务器的待处理请求和活动任务。这些控制仅在运行时有效;它们释放本地资源并更新实时网关状态,但不编辑 `.mcp.json`、删除服务器定义或更改 `autoStart`。在 HTTP 共享服务模式下,停止或重启下游服务器可能会影响使用相同 PMCP 网关的其他客户端。
MCP 任务 ID 是下游服务器标识符,与 PMCP 待处理请求 ID(如 `server::local_id`)保持不同。使用 `gateway.cancel` 仅适用于来自 `gateway.list_pending` 的 PMCP 请求 ID;使用 `gateway.tasks_cancel` 适用于 MCP 任务 ID。任务记录是瞬时的内存网关状态。PMCP 可以将可见性绑定到服务器和请求者上下文它所观察到的,但未经身份验证的本地传输无法提供跨用户授权隔离。
### 身份验证和诱导
PMCP 将下游授权报告为结构化的非秘密状态。网关输出和健康行可能包括 `auth_state` 值,如 `none`、`missing_auth`、`insufficient_scope`、`elicitation_required`、`policy_denied` 或 `unknown`,以及可选的 `next_step`、`auth_methods`、作用域名称、清理的元数据 URL 和 URL 模式诱导摘要。
支持的流程:
- 本地 API 密钥服务器继续使用环境存储凭证。当 `gateway.provision` 报告 `auth_state="missing_auth"` 和 `auth_mode="api_key"` 时,使用凭证调用 `gateway.auth_connect`,PMCP 将其存储在选定的用户或项目环境文件中。用户作用域写入 `~/.config/pmcp/pmcp.env`;项目作用域写入 `<project>/.env.pmcp`。项目作用域适用于本地开发和 CI 工作区,而用户作用域更适合于应在单个操作员跨项目的情况下使用的凭证。
- 远程持有者头部使用环境变量占位符,如 `Authorization: Bearer ${REMOTE_API_TOKEN}`。PMCP 从进程环境、项目环境存储和用户环境存储值中解析占位符,但状态、医生、健康和反馈输出仅显示必需或缺失的环境变量名称,而不显示解析的头部值。
- 租户感知远程头部解析使用解析的项目根目录下的租户作用域凭证文件。租户模式仅读取该租户的值,并报告缺失的环境变量名称,而不打印头部值。
- 远程授权发现仅用于诊断。PMCP 可以保留和报告 OAuth 受保护的资源元数据、授权服务器元数据、OpenID Connect 发现、客户端 ID 元数据文档 URL 和声明的作用域,当服务器或 `WWW-Authenticate` 挑战提供它们时。
- URL 模式诱导是带外的。PMCP 返回一个清理的 URL 和 `elicitation_id`;在 PMCP 外部完成该 URL 流程,然后使用 `gateway.auth_connect(auth_mode="url_elicitation", elicitation_id=..., consent_acknowledged=true)` 予以确认。
PMCP 不是授权服务器,不实现企业 SSO、跨应用访问、DPoP、工作负载身份联合或第三方刷新令牌存储。不要将 OAuth 代码或第三方凭证粘贴到 URL 模式网关调用中。
### 从属 MCP 更新
- `gateway.update_server` 是从属 MCP 的第一阶段更新路径。
- `pmcp update <server>` 和 `pmcp update --all` 调用相同的网关更新工作流。
- `gateway.describe`、`gateway.invoke` 和 `gateway.provision` 在检测到较新的软件包版本时可能会返回 `update_warning`。
- 基于后台的过时版本索引是活跃的 — 警告通过每小时预填充以零延迟提供。
### 反馈遥测
- PMCP 可以发出故障反馈提示并为代理生成 GitHub 问题有效载荷预览。
- 遥测仅限技术,并在使用前发出警告;有效载荷包括 PMCP/工具上下文。
- 使用 `pmcp guidance --telemetry off` 永久禁用。
## 分阶段公开工作流
PMCP 遵循分阶段公开模式 - 从自然语言开始,根据需要获取建议并深入钻取。
### 步骤 1:请求功能
```
您:“我需要查找库文档”
gateway.request_capability({ query: "库文档" })
```
对于本地工作,当安装的原生 CLI 是合适的界面时,PMCP 返回紧凑的 CLI 指导并且不执行命令:
```
gateway.request_capability({ query: "git commits", available_clis: ["git"] })
```
返回:
```json
{
"status": "use_cli",
"message": "使用 Bash/直接 CLI 与 'git'。PMCP 建议在此处使用原生命令;它不执行命令或为此路径配置 MCP 服务器。",
"cli": {
"name": "git",
"description": "Git 版本控制 CLI",
"available": true,
"help_command": ["git", "--help"],
"examples": ["git status --short", "git log --oneline -5"],
"reason": "查询与 CLI 关键字和示例匹配。"
},
"recommendation": "直接通过 Bash/直接 CLI 运行 'git'。仅当您需要 MCP 服务器时,请再次使用 gateway.request_capability。"
}
```
在 `status: "use_cli"` 后,使用 Bash/直接 CLI。PMCP 在此处停止指导;它不执行命令也不获取完整的原生帮助输出用于正常的紧凑路径。如果 PMCP 返回服务器候选人,请继续使用 MCP 配置、`gateway.describe` 和 `gateway.invoke`。
返回:
```json
{
"status": "candidates",
"candidates": [{
"name": "context7",
"candidate_type": "server",
"relevance_score": 0.95,
"is_running": true,
"reasoning": "context7 提供任何软件包的最新文档。"
}],
"recommendation": "使用 context7 - 已经运行中"
}
```
### 步骤 2:搜索可用工具
```
gateway.catalog_search({ query: "文档" })
```
CLI 建议与 MCP 工具卡分开返回:
```json
gateway.catalog_search({ "query": "git" })
```
返回:
```json
{
"results": [{
"tool_id": "github::list_issues",
"server": "github",
"tool_name": "list_issues",
"short_description": "列出仓库中的问题",
"tags": ["github", "git", "search"],
"availability": "online",
"risk_hint": "low"
}],
"total_available": 3,
"truncated": false,
"cli_hints": [{
"name": "git",
"description": "Git 版本控制 CLI",
"available": true,
"path": "/usr/bin/git",
"help_command": ["git", "--help"],
"examples": ["git status --short", "git log --oneline -5"],
"reason": "查询与 CLI 名称匹配。"
}]
}
```
将 `cli_hints` 作为 Bash/直接 CLI 命令的建议。它们不是 MCP 工具,不出现在 `results` 中,不能传递给 `gateway.describe` 或 `gateway.invoke`。从 `gateway.request_capability` 或 `gateway.catalog_search` 开始;当 PMCP 返回 `use_cli` 或匹配的 `cli_hints` 时,这足以切换到 Bash/直接 CLI。否则,请继续使用 MCP 路径。
注册支持的匹配项可以在 `gateway.catalog_search` 中作为 `registry_candidates` 或在 `gateway.request_capability` 中作为 `status="candidates"` 出现。它们是从 MCP 注册表缓存中读取的只读发现元数据,可能包括软件包标识符、传输、远程(可流式-http/sse)托管服务器的端点、服务器卡 URL、受保护的资源元数据 URL、授权服务器元数据 URL、声明的作用域和占位符头部名称。候选人被重复数据删除到最新的发布版本。在您明确注册和配置所选服务器之前,PMCP 不会安装、连接或传递凭证。
### 步骤 3:获取工具详细信息
```
gateway.describe({ tool_id: "context7::get-library-docs" })
```
### 步骤 4:调用工具
```
gateway.invoke({
tool_id: "context7::get-library-docs",
arguments: { libraryId: "/npm/react/19.0.0" }
})
```
### 离线工具发现
使用 `gateway.catalog_search` 时,您可以从尚未启动的服务器发现工具:
```json
// 搜索所有工具,包括离线/惰性服务器
gateway.catalog_search({
"query": "browser",
"include_offline": true
})
```
这使用 `.mcp-gateway/descriptions.yaml` 中预缓存的工具描述。要刷新缓存:
```bash
pmcp refresh
```
**注意**:缓存的工具仅显示元数据。完整的模式在服务器启动后可用(使用 `gateway.describe` 触发惰性启动)。
MCP 注册表缓存单独存储在 `.mcp-gateway` 下;当公共注册表不可用时,PMCP 使用该缓存。注册表候选人可以与缓存的离线工具卡共存,而不会更改 `total_available`。
#### 私有注册表(调试,启用)
默认情况下,PMCP 仅从公共 MCP 注册表发现并显示 GA 形状的最新版本条目。开发人员调试自己的**私有** MCP 服务器可以选择启用环境标志(默认为 **关闭**):
```bash
export PMCP_REGISTRY_ALLOW_PRIVATE=1
export PMCP_REGISTRY_PRIVATE_ENDPOINT=https://registry.internal.example/v0/servers
```
启用时,PMCP 从配置的私有端点获取并容忍草稿/非 GA `server.json` 架构字段,显示所有版本(包括非最新条目)以供检查。这是一个调试辅助工具,**不适用于生产发现**;关闭标志时,行为保持不变。
## 动态服务器配置
PMCP 可以根据精选的 90 多个服务器的清单按需安装和启动 MCP 服务器。
### 示例:添加 GitHub 支持
```
您:“我需要管理 GitHub 问题”
gateway.request_capability({ query: "github issues" })
```
返回(如果尚未配置):
```json
{
"status": "candidates",
"candidates": [{
"name": "github",
"candidate_type": "server",
"is_running": false,
"requires_api_key": true,
"env_var": "GITHUB_PERSONAL_ACCESS_TOKEN",
"env_instructions": "在 https://github.com/settings/tokens 创建并具有 repo 作用域"
}]
}
```
### 配置
```bash
# 1. 设置 API 密钥(如果需要)
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
# 2. 通过网关配置
gateway.provision({ server_name: "github" })
```
## 可选的急切启动
打包的清单服务器不会自动启动。它们默认情况下是惰性的;PMCP 可以从清单中发现或配置它们,然后在首次使用时连接。
要使服务器在每次 PMCP 启动时急切地启动,请在顶级 `autoStart` 中列出它:
```json
{
"autoStart": ["playwright", "context7"],
"mcpServers": {}
}
```
常见的选择:
| 服务器 | 描述 | API 密钥 |
|--------|-------------|---------|
| `playwright` | 浏览器自动化 - 导航、截图、DOM 检查 | 不需要 |
| `context7` | 库文档查找 - 任何软件包的最新文档 | 可选(对于更高的速率限制) |
启动策略决策通过 `gateway.health` 和实时 `pmcp status --verbose` 是可见的。健康行保留现有的 `name`、`status`、`tool_count` 和 `error` 字段,并且可能还包括:
| 字段 | 含义 |
|-------|---------|
| `startup_policy` | `eager`、`lazy`、`skipped` 或 `unknown` |
| `startup_source` | 解析器源,例如 `project`、`user`、`manifest`、`configured` 或 `auto_start` |
| `startup_skip_reason` | 机器可读的跳过原因,例如 `policy_denied`、`missing_auth` 或 `unknown_auto_start` |
| `startup_env_var` | 缺失身份验证跳过的所需环境变量名称 |
| `auth_state` | 机器可读的下游身份验证状态,例如 `missing_auth`、`insufficient_scope`、`elicitation_required` 或 `policy_denied` |
| `next_step` | 当身份验证状态需要操作员操作时,非秘密建议的下一步 |
对于持久管理,请使用配置工具:
```json
gateway.config_status({})
gateway.get_startup_policy({})
gateway.set_startup_policy({
"operation": "add",
"names": ["playwright"],
"source": "project"
})
```
`gateway.set_startup_policy` 默认情况下仅为预览。请选择确切的 `source` 或 `path` 并传递 `apply=true` 和 `dry_run=false` 以写入。编写者仅更新顶级 `autoStart`,保留无关的 `.mcp.json` 键和服务器定义,原子写入并返回刷新下一步而不是静默重新连接服务器。诊断报告陈旧的 `autoStart`、旧版 `disableAutoStart` 冲突、策略拒绝的行和缺失身份验证的行,而不打印机密值。
PMCP 将当前的 MCP 协议版本与下游服务器协商,并继续连接到较旧的支持服务器。当连接的服务器报告它们时,本地一致性矩阵涵盖了 `2024-11-05`、`2025-03-26`、`2025-06-18` 和 `2025-11-25` 的协商状态处理,首选 `2025-11-25` 用于新的初始化尝试。 `gateway.health` 和 `pmcp status --json` 可以包括协商的 `protocol_version` 和声明的服务器功能,当连接的服务器报告它们时。
现代 MCP 任务支持是保守的。当工具宣传 `execution.taskSupport` 且下游服务器宣传任务功能时,PMCP 仅转发任务增强的工具调用。必需任务工具如果服务器不宣传任务支持,则在调度前失败。任务记录是瞬时的网关状态,而不是持久的 PMCP 存储。
`specs/tenant-code-mode-host-contract.md` 中的租户代码模式主机合约冻结了 PMCP/伴侣服务器边界以实现未来的托管沙箱执行。PMCP 仍然是代理;伴侣租户服务器仍然是执行权限。
网关可观察性是本地化和结构化的。 `gateway.invoke` 通过 `_meta.traceparent`、`_meta.tracestate` 和 `_meta.baggage` 接受跟踪上下文,并在 PMCP 拥有的下游请求元数据上保留这些字符串值。相同的键在 HTTP 请求中被容忍。PMCP 不需要或配置 OpenTelemetry 导出器。
`gateway.health` 可能包括 `gateway_diagnostics` 和最近的 `audit_events`。诊断报告传输/头部兼容性、跟踪支持、审计缓冲区准备情况、身份验证元数据存在和速率限制配置,而不包含机密值。审计事件在内存中限定范围,包括方法/操作、服务器或工具标识、已知协议版本、任务 ID(如果存在)、结果、延迟、身份验证状态和编辑错误文本。
PMCP 的 Streamable HTTP 端点与发送没有草稿标头的现有客户端保持兼容。它还容忍 `MCP-Protocol-Version`、`Mcp-Method` 和 `Mcp-Name` 请求标头,用于客户端实验的草稿 MCP 传输约定。这些标头是兼容性输入,而不是 PMCP 实现每个草稿 MCP 扩展的承诺。
服务器使用 `gateway.disconnect_server` 停止后,在 PMCP 仍知道其配置的情况下,健康状态显示为 `offline` 或 `lazy`,并且启动策略观察字段得以保留。
缺失身份验证的健康行示例:```json
{
"name": "github",
"status": "offline",
"tool_count": 0,
"startup_policy": "skipped",
"startup_source": "manifest",
"startup_skip_reason": "missing_auth",
"startup_env_var": "GITHUB_PERSONAL_ACCESS_TOKEN"
}
```
## 可用服务器
清单包括 90 多个可以按需配置的服务器:
### 不需要 API 密钥
| 服务器 | 描述 |
|--------|-------------|
| `filesystem` | 文件操作 - 读取、写入、搜索 |
| `memory` | 持久知识图 |
| `fetch` | 带有 robots.txt 合规的 HTTP 请求 |
| `sequential-thinking` | 通过思维序列解决问题 |
| `git` | 通过 MCP 的 Git 操作 |
| `sqlite` | SQLite 数据库操作 |
| `time` | 时区操作 |
| `puppeteer` | 无头 Chrome 自动化 |
### 需要 API 密钥
| 服务器 | 描述 | 环境变量 |
|--------|-------------|---------------------|
| `github` | GitHub API - 问题、PR、仓库 | `GITHUB_PERSONAL_ACCESS_TOKEN` |
| `gitlab` | GitLab API - 项目、MRs | `GITLAB_PERSONAL_ACCESS_TOKEN` |
| `slack` | Slack 消息 - |
| `notion` | Notion 工作区 | `NOTION_TOKEN` |
| `linear` | Linear 问题跟踪 | `LINEAR_API_KEY` |
| `postgres` | PostgreSQL 数据库 | `POSTGRES_URL` |
| `brave-search` | 网络搜索 | `BRAVE_API_KEY` |
| `google-drive` | Google Drive 文件 | `GDRIVE_CREDENTIALS` |
| `sentry` | 错误跟踪 | `SENTRY_AUTH_TOKEN` |
| `stripe` | 支付和账单 | `STRIPE_SECRET_KEY` |
| `github-actions` | CI/CD 工作流 | `GITHUB_PERSONAL_ACCESS_TOKEN` |
| `datadog` | 监控和可观察性 | `DATADOG_API_KEY` |
| `cloudflare` | 边缘网络和 Workers | `CLOUDFLARE_API_TOKEN` |
| `figma` | 设计文件和组件 | `FIGMA_ACCESS_TOKEN` |
| `jira` | 问题跟踪 | `JIRA_API_TOKEN` |
| `airtable` | 电子表格数据库 | `AIRTABLE_TOKEN` |
| `hubspot` | CRM 和营销 | `HUBSPOT_ACCESS_TOKEN` |
| `twilio` | SMS 和语音 | `TWILIO_ACCOUNT_SID` |
| ...以及 80 多个 | 使用 `gateway.catalog_search` 探索 | - |
请参阅 `.env.example` 获取所有支持的环境变量。
## 代码执行指南
PMCP 包含内置的指南,鼓励模型使用代码执行模式,减少上下文膨胀,提高工作流效率。
### 指南层级
**L0(MCP 指令)**: 服务器指令中的简要理念(约 30 个标记)
- "编写代码来编排工具 - 使用循环、过滤器、条件语句"
**L1(代码提示)**: 搜索结果中的极简提示(约 8-12 个标记/卡片)
- 单词提示:"循环"、"过滤"、"尝试/捕获"、"轮询"
**L2(代码片段)**: 描述输出中的最小示例(约 40-80 个标记,可选)
- 展示实际用法的 3-4 行代码示例
**L3(方法论资源)**: 完整指南(延迟加载,0 标记)
- 可通过 `pmcp://guidance/code-execution` 资源访问
### 指南配置
创建 `~/.claude/gateway-guidance.yaml`:
```yaml
guidance:
level: "minimal" # 选项:"off"、"minimal"、"standard"
layers:
mcp_instructions: true # L0 理念
code_hints: true # L1 提示
code_snippets: false # L2 示例(默认关闭)
methodology_resource: true # L3 指南
```
**级别**:
- `minimal`(默认):L0 + L1(约 200 个标记开销)
- `standard`: L0 + L1 + L2(约 320 个标记开销)
- `off`: 无指南
### 查看指南状态
```bash
pmcp guidance # 显示配置
pmcp guidance --show-budget # 显示标记估计
```
### 标记预算
- **最小模式**: 约 200 个标记典型工作流(L0 + 搜索)
- **标准模式**: 约 320 个标记(L0 + 搜索 + 1 次描述)
- **减少 80%** 与预先加载所有工具模式相比!
## 配置
### 配置发现
PMCP 从以下位置发现 MCP 服务器:
1. **项目配置**: 项目根目录中的 `.mcp.json`(优先级最高)
2. **用户配置**: `~/.mcp.json` 或 `~/.claude/.mcp.json`
3. **自定义配置**: 通过 `--config` 标志或 `PMCP_CONFIG` 环境变量
### 私有清单叠加
如果您构建了自己的 MCP 服务器(或想要私有可配置定义),
可以添加清单条目 **而无需编辑已发布的清单**。PMCP
将这些叠加文件合并到内置清单中,以便您的服务器在 `gateway.request_capability` 关键字匹配、
`gateway.catalog_search` 离线发现、`gateway.provision` 和启动解析期间获得一流处理。
叠加位置,从低到高优先级:
1. **已发布清单**(基准)
2. **用户**: `~/.pmcp/manifest.yaml`
3. **项目**: `<project>/.pmcp/manifest.yaml`(当前工作目录的最近祖先)
4. **显式**: `PMCP_MANIFEST_PATH` 环境变量(优先级最高)
叠加使用与已发布清单相同的条目模式。示例 `~/.pmcp/manifest.yaml`:
```yaml
servers:
# 通过命令配置的本地(stdio)服务器
my-private:
description: "我的私有内部服务器"
keywords: [myprivate, internal widget]
command: "npx"
args: ["-y", "@me/my-mcp"]
requires_api_key: true
env_var: MY_TOKEN
# 通过可流式 HTTP 访问的远程服务器
my-remote:
description: "我的私有远程服务器"
keywords: [myremote, internal api]
url: "https://mcp.internal.example.com/sse"
headers:
Authorization: "Bearer ${MY_REMOTE_TOKEN}"
```
叠加加载是 **软失败** 的:缺少的文件将被静默跳过,格式错误的文件或单个错误条目将记录警告并被跳过而不会导致网关崩溃 - 已发布清单始终加载。
> **安全:** 清单条目可以指定任意 `command`/`args` 以在配置时运行 - 请将叠加文件与您自己的 `.mcp.json` 具有相同的信任度。策略仍然适用(被拒绝的服务器保持被拒绝)。
### 添加自定义服务器
对于清单中没有的 MCP 服务器,请将它们添加到 `~/.mcp.json`:
```json
{
"autoStart": ["my-custom-server"],
"mcpServers": {
"my-custom-server": {
"command": "node",
"args": ["./my-server.js"],
"env": {
"API_KEY": "..."
}
}
}
}
```
PMCP 支持本地基于命令和基于远程 URL 的下游条目,来自已发现的配置文件。`mcpServers` 中的条目使下游服务器在需要时可用;它们本身并不意味着服务器应该被热启动。
#### `index-it-mcp` 代码索引试点
对于本地优先代码索引器的舰队试点,请在 `.mcp.json` 中添加 `index-it-mcp`,并使用 **固定的** 版本及其操作环境。PMCP 通过 stdio 生成它,并将 `env` 块 **原样** 传递给子进程(`_connect_stdio` 执行 `env = os.environ.copy(); env.update(config.env)`),因此这是服务器配置的支持通道:
```json
{
"mcpServers": {
"index-it-mcp": {
"command": "uvx",
"args": ["--from", "index-it-mcp==<approved-version>", "index-it-mcp", "stdio"],
"env": {
"MCP_ALLOWED_ROOTS": "/path/to/repo",
"SEMANTIC_SEARCH_ENABLED": "true",
"SEMANTIC_DEFAULT_PROFILE": "code",
"SEMANTIC_EMBEDDING_BASE_URL": "http://localhost:8000/v1",
"QDRANT_URL": "http://localhost:6333",
"OPENAI_API_KEY": "local-vllm-placeholder"
}
}
}
}
```
注意:
- **固定版本** (`index-it-mcp==<approved-version>`) 以便 PyPI 发布行更改不会在运行时静默交换索引器。替换 `<approved-version>` 为操作员批准的固定版本。
- **`OPENAI_API_KEY`** 仅是服务器呈现给本地 OpenAI 兼容端点的令牌(例如 `SEMANTIC_EMBEDDING_BASE_URL` 中的 vLLM 嵌入服务器);它不是 api.openai.com 的秘密。
- **环境必须通过 `.mcp.json` 传递。** 已发布的清单和私有叠加条目模式 **没有** `env:` 块 - 将 `env:` 置于 `.mcp.json` 的条目中仅被 `.mcpServers` 条目所支持。
- **固定 Python 解释器** 使用 `"args": ["--python", "3.12", "--from", …]`。`index-it-mcp==1.2.0` 依赖于 `tree-sitter-languages`,后者没有 CPython 3.13 的轮;如果没有固定版本,`uvx` 可能会选择 3.13 并导致启动失败。
**仓库注册必须使用与配置相同的存储环境。** 在代理获取索引结果之前,每个仓库必须注册 *并且* 网关生成的服务器必须读取注册写入的注册表。注册表位置由 `MCP_INDEX_STORAGE_PATH` / `MCP_REPO_REGISTRY` 解析。如果您在上面的 `.mcp.json` `env` 中设置了这些环境变量,但运行 `index-it-mcp repository register` **没有** 它们,CLI 会将默认的 `~/.mcp/repository_registry.json`写入文件,而网关生成的服务器会读取 `$MCP_INDEX_STORAGE_PATH/repository_registry.json` - 因此服务器报告 `repositories: []` 并且每个查询都回退到原生搜索(`unregistered_repository`)。请使用与配置 **相同** 的环境注册:
```bash
export MCP_INDEX_STORAGE_PATH=/path/to/shared/.indexes
export MCP_REPO_REGISTRY="$MCP_INDEX_STORAGE_PATH/repository_registry.json"
for repo in /path/to/repo-a /path/to/repo-b; do
uvx --python 3.12 --from index-it-mcp==1.2.0 index-it-mcp repository register "$repo"
done
# 验证服务器端视图,然后再信任结果:
uvx --python 3.12 --from index-it-mcp==1.2.0 index-it-mcp repository list # 预期您的仓库
uvx --python 3.12 --from index-it-mcp==1.2.0 index-it-mcp preflight # 准备就绪检查
```
**在信任索引答案之前检查就绪状态。** 服务器的状态/查询工具报告就绪状态(`ready`、`unregistered_repository`、`missing_index`、`stale_commit` 等),当未就绪时,`safe_fallback: "native_search"`。代理应将任何非 `ready` 状态视为非权威,并回退到原生搜索,而不是报告过时/空索引结果。
顶级 `autoStart` 列表控制显式热启动。名称可以引用 `mcpServers` 或打包的清单条目中定义的服务器,例如 `playwright` 和 `context7`。省略服务器的 `autoStart` 以保持延迟。
遗留的顶级 `disableAutoStart` 列表仍然支持部署临时启用 `PMCP_LEGACY_MANIFEST_AUTOSTART=1`,但打包的 PMCP 默认值不再需要它。
可以在本地从 CLI 使用相同的策略:
```bash
pmcp config status --json
pmcp config startup-policy
pmcp config set-startup-policy add playwright --source project
pmcp config set-startup-policy add playwright --source project --apply
```
CLI 更改预览默认。需要 `--apply` 才能在写入之前。
延迟 Excalidraw 示例:
```json
{
"mcpServers": {
"excalidraw": {
"type": "http",
"url": "https://mcp.excalidraw.com/mcp"
}
}
}
```
热 Excalidraw 示例:
```json
{
"autoStart": ["excalidraw"],
"mcpServers": {
"excalidraw": {
"type": "http",
"url": "https://mcp.excalidraw.com/mcp"
}
}
}
```
#### 远程下游服务器
您还可以通过 `.mcp.json` 中的 HTTP/SSE 直接配置远程下游 MCP 服务器,使用 `type: "sse"` 或 `type: "http"`(或 `type: "remote"` 表示通用远程传输):
```json
{
"mcpServers": {
"acme-sse": {
"type": "sse",
"url": "https://mcp.acme.dev/sse",
"headers": {
"Authorization": "Bearer ${ACME_MCP_TOKEN}",
"X-Tenant": "${ACME_TENANT_ID}"
}
},
"acme-http": {
"type": "http",
"url": "https://mcp.acme.dev/mcp",
"headers": {
"Authorization": "Bearer ${ACME_MCP_TOKEN}"
}
}
}
}
```
- `url` 应该是该服务器的完整远程端点。
- `headers` 值支持 `${ENV_VAR}` 插值(问题 #40)。
- 从您的 shell 环境或 `~/.config/pmcp/pmcp.env` 解析这些环境变量。
**重要**: 不要将 `pmcp` 本身添加到此文件中。PMCP 在下游服务器列表中配置,而不是在网关配置中。
#### 租户代码模式服务器注册
PMCP 可以将单独的租户代码模式 MCP 服务器作为正常下游服务器进行代理。`specs/tenant-code-mode-host-contract.md` 中的合约定义了边界:PMCP 发现、调用、监控、截断并通过网关表面进行数据清洗;配套租户服务器负责沙箱执行、租户授权、日志和工件。PMCP 不会自行运行脚本。
在 `.mcp.json` 中使用配置的名称 `tenant-code-mode` 注册托管服务器:
```json
{
"mcpServers": {
"tenant-code-mode": {
"type": "streamable-http",
"url": "https://tenant.example.com/mcp",
"headers": {
"Authorization": "Bearer ${TENANT_CODE_MODE_MCP_TOKEN}",
"X-Tenant-ID": "${TENANT_CODE_MODE_TENANT_ID}"
}
}
}
}
```
对于本地配套服务器开发,请使用来自该服务器的替换 stdio 命令:
```json
{
"mcpServers": {
"tenant-code-mode": {
"command": "/path/to/tenant-code-mode-server",
"args": ["serve", "--transport", "stdio"]
}
}
}
```
注册默认延迟。仅当操作员希望 PMCP 在启动期间连接时,将 `tenant-code-mode` 添加到顶级 `autoStart`。发现和启动使用现有的 `gateway.request_capability`、`gateway.catalog_search`(`include_offline: true`)、`gateway.provision` 和 `gateway.invoke` 流。
租户运行使用现有的任务代理。提交长时间运行的工作,使用 `gateway.invoke` 和非机密 `task.metadata`、`task.ttl`、`task.poll_interval`、`task.requestor_context` 和 `_meta.traceparent` 等跟踪键;PMCP 将这些字段转发给下游服务器,仅当服务器和工具宣传任务支持时。返回的下游 MCP 任务 ID 然后用于 `gateway.tasks_list`、`gateway.tasks_get`、`gateway.tasks_result` 和 `gateway.tasks_cancel`。不要将 `gateway.list_pending` 或 `gateway.cancel` 中的 PMCP 请求 ID 用于租户任务操作。`gateway.tasks_result` 继续应用主机侧截断和可选的机密清洗,以获取沙箱状日志和诊断。
### 凭证范围管理(`pmcp secrets`)
PMCP 在作用域的环境文件中存储机密:
- **用户作用域**: `~/.config/pmcp/pmcp.env`
- **项目作用域**: `<project_root>/.env.pmcp`
您可以使用 `pmcp secrets` 管理两个作用域:
```bash
# 在用户作用域中存储机密(所有项目共享)
pmcp secrets set API_TOKEN your-token --scope user
# 在项目作用域中存储机密
pmcp secrets set API_TOKEN your-token --scope project --project /path/to/project
# 将所有用户作用域的机密复制到项目作用域
pmcp secrets sync --from-scope user --to-scope project --overwrite
# 将项目作用域的机密复制到用户作用域
pmcp secrets sync --from-scope project --to-scope user --overwrite
```
在生成的 `.env` 文件中使用作用域适当的值,例如 `API_TOKEN`;PMCP 和下游 MCP 服务器根据您的活动模式从这些文件中读取。
对于服务用户,`~/.config/pmcp/pmcp.env` 理想地存储所有会话使用的共享令牌。
### 策略文件
创建策略文件以控制访问和限制:
**~/.claude/gateway-policy.yaml**:
```yaml
servers:
allowlist: [] # 空 = 允许所有
denylist:
- dangerous-server
tools:
denylist:
- "*::delete_*"
- "*::drop_*"
limits:
max_tools_per_server: 100
max_output_bytes: 50000
max_output_tokens: 4000
redaction:
patterns:
- "(api[_-]?key)[\\s]*[:=][\\s]*[\"']?([^\\s\"']+)"
- "(password|secret)[\\s]*[:=][\\s]*[\"']?([^\\s\"']+)"
```
租户代码模式托管使用相同的策略字段。此示例仅允许租户服务器,阻止高风险提交工具,限制输出,并添加租户工件清洗模式,而不授予对无关 MCP 服务器的访问权限:
```yaml
servers:
allowlist:
- tenant-code-mode
tools:
denylist:
- "tenant-code-mode::run_script"
allowlist:
- "tenant-code-mode::get_*"
- "tenant-code-mode::cancel_*"
limits:
max_output_bytes: 50000
max_output_tokens: 4000
redaction:
patterns:
- "TENANT_CODE_MODE_[A-Z_]+=[^\\s]+"
- "artifact_token=[^\\s]+"
```
对于托管租户身份验证,请在 PMCP 环境存储或租户范围的项目存储中保留凭证,并仅从配置中引用占位符:`${TENANT_CODE_MODE_MCP_TOKEN}` 和 `${TENANT_CODE_MODE_TENANT_ID}`。使用 `pmcp secrets set ... --scope project` 或 `gateway.auth_connect` 在非租户模式下填充环境存储值;租户模式使用隔离的每个租户环境文件,这些文件源自解析的项目根目录。PMCP 诊断报告缺少字段或环境变量名称,例如 `TENANT_CODE_MODE_MCP_TOKEN`;它们不得打印令牌值。
托管操作员应要求在 `/mcp` 上进行 Bearer 身份验证,调整部署的 `--rate-limit` 或 `PMCP_RATE_LIMIT`,并将 `/health` 和 `/metrics` 保留在网络控制之下。`gateway.refresh`、`gateway.disconnect_server` 和 `gateway.restart_server` 可以在强制执行策略时中断正在进行的下游工作;使用下游任务 ID 和 `gateway.tasks_cancel` 进行租户运行取消。PMCP 任务记录是暂时的。持久的沙箱日志、工件、租户授权和工件保留仍然是配套租户服务器及其部署控制的责任。
### CLI 命令
```bash
# 启动网关服务器(默认)
pmcp
# 检查服务器状态
pmcp status
pmcp status --json # JSON 输出
pmcp status --verbose # 包括启动策略详细信息(如果可用)
pmcp status --server playwright # 按服务器过滤
# 查看日志
pmcp logs
pmcp logs --follow # 实时跟踪
pmcp logs --tail 100 # 最后 100 行
# 刷新服务器连接
pmcp refresh
pmcp refresh --server github # 刷新特定服务器
pmcp refresh --force # 强制所有服务器重新连接
# 初始化配置(交互式)
pmcp init
# 渲染客户端设置代码片段
pmcp setup
pmcp setup --client claude --mode stdio
pmcp setup --client opencode --mode http --write
# 运行锁/模式/HTTP 检查的诊断
pmcp doctor
pmcp doctor --project /path/to/project
# 管理项目/用户机密
pmcp secrets set API_TOKEN my-token --scope user
pmcp secrets sync --from-scope user --to-scope project --overwrite
```
### `pmcp doctor`(升级前后推荐使用)
使用 `pmcp doctor` 诊断常见的 PMCP 启动和连接问题。它检查:
- `lock`: 检测 `~/.pmcp/gateway.lock` 处的单一锁状态和过时锁定冲突
- `mode`: 检测共享 PMCP 系统服务运行时本地命令模式 MCP 配置冲突
- `http`: 探测从 `PMCP_GATEWAY_URL` 或 `http://127.0.0.1:3344/mcp` 派生的未经身份验证的 `/health` 端点
- `remote`: 检测未解析的远程下游头部环境引用
- `install`: 检测冲突的 `uv tool` 和 `pip --user` 安装
示例:
```bash
pmcp doctor
```
如果任何检查失败,请遵循输出中的命令,然后重新运行 `pmcp doctor`。
### 单实例锁
默认情况下,PMCP 在 `~/.pmcp/gateway.lock` 处使用全局锁,以确保每个用户只能运行一个网关。
**覆盖锁定目录:**
```bash
# CLI 标志
pmcp --lock-dir /custom/path
# 环境变量
export PMCP_LOCK_DIR=/custom/path
pmcp
```
**每个项目锁定(不推荐):**
```bash
pmcp --lock-dir ./.mcp-gateway
```
### 下游调用可调参数
```bash
# 下游 stdio 服务器的每行 stdout 读取限制(默认 10 MiB)。
# 大于此限制的单个响应行将被丢弃(仅影响该调用,
# 服务器保持连接)而不是断开服务器连接。
export PMCP_STDIO_READ_LIMIT=$((20 * 1024 * 1024))
# 单个下游工具调用的绝对后备时间(默认 600000ms / 10 分钟)。
# `timeout_ms` 是不活动超时 - 只要服务器
# 继续产生输出,调用将持续;此上限限制工具调用的总时钟时间
# 以便聊天但永远不会完成的调用不会无限期挂起。
export PMCP_REQUEST_CEILING_MS=600000
```
## 废弃功能
- `mcp-gateway` 命令命名在文档和示例中已废弃。
- 从现在起,请使用 `pmcp` 进行所有 CLI 命令。
- 迁移示例:
- `mcp-gateway refresh --force` -> `pmcp refresh --force`
- `mcp-gateway status --json` -> `pmcp status --json`
## Docker
```bash
# 使用 Docker
docker run -it --rm \
-v ~/.mcp.json:/home/appuser/.mcp.json:ro \
-v ~/.env:/app/.env:ro \
ghcr.io/viperjuice/pmcp:latest
# 使用 Docker Compose
docker-compose up -d
```
## 开发
```bash
# 克隆仓库
git clone https://github.com/ViperJuice/pmcp
cd pmcp
# 使用 uv 安装(推荐)
uv sync --all-extras
# 运行测试
uv run pytest
# 运行带有调试日志
uv run pmcp --debug
```
### 运行测试
```bash
# 运行所有测试
uv run pytest
# 运行带有覆盖率测试
uv run pytest --cov=pmcp
# 运行特定测试文件
uv run pytest tests/test_policy.py -v
```
### 项目结构
```
pmcp/
├── src/pmcp/
│ ├── __init__.py
│ ├── __main__.py # python -m pmcp 入口
│ ├── cli.py # CLI 命令(status, logs, init, refresh)
│ ├── server.py # MCP 服务器实现
│ ├── config/
│ │ └── loader.py # 配置发现(.mcp.json)
│ ├── client/
│ │ └── manager.py # 下游服务器连接
│ ├── policy/
│ │ └── policy.py # 允许/拒绝列表
│ ├── tools/
│ │ └── handlers.py # 网关工具实现
│ ├── manifest/
│ │ ├── manifest.yaml # 服务器清单(90+ 服务器)
│ │ ├── loader.py # 清单加载
│ │ ├── installer.py # 服务器配置
│ │ └── environment.py # 平台/CLI 检测
│ └── baml_client/ # BAML 生成的客户端(用于结构化解析;自 v1.8.0 起无外部 LLM 调用)
├── tests/ # 310+ 测试
├── Dockerfile
├── docker-compose.yml
├── .env.example
├── pyproject.toml
└── README.md
```
## 故障排除
### 服务器无法连接
```bash
pmcp status
pmcp logs --level debug
pmcp refresh --force
```
### 缺失 API 密钥
```bash
# 检查需要哪个密钥
pmcp status --server github
# 设置密钥
export GITHUB_PERSONAL_ACCESS_TOKEN=ghp_...
```
### 工具调用失败
```
gateway.catalog_search({ query: "tool-name" })
gateway.describe({ tool_id: "server::tool-name" })
gateway.list_pending()
```
如果 `gateway.refresh` 报告待处理请求或活跃的 MCP 任务,请使用 `gateway.list_pending()` 和 `gateway.tasks_list()` 检查它们,或重试刷新并使用 `force=true` 取消它们,然后重新加载服务器配置。
如果 `gateway.disconnect_server` 或 `gateway.restart_server` 报告待处理请求或活跃的 MCP 任务,请检查 `gateway.list_pending(server="<name>")` 和 `gateway.tasks_list(server_name="<name>")`,或重试并使用 `force=true` 仅取消该服务器的待处理工作。
## 许可证
MIT
连接信息
猜你喜欢
暂无推荐服务器