这是一个可部署到 Prefect Horizon 的通用单上游 MCP 认证代理。它将原本需要 固定 HTTP 请求头的远程 Streamable HTTP MCP,包装为由 Horizon OAuth 保护的 MCP 地址。
MCP 客户端 -- Horizon OAuth --> 本代理 -- 固定认证请求头 --> 远程 MCP
上游 MCP 不需要在本地或本仓库中运行。本仓库中的 main.py:mcp 本身就是
Horizon 所要求的 FastMCP 服务实例。
代理只需要三个环境变量:
| 变量 | 说明 | 示例 |
|---|---|---|
MCP_UPSTREAM_URL |
完整的远程 Streamable HTTP MCP 地址 | https://example.com/mcp |
MCP_AUTH_HEADER_NAME |
上游认证请求头名称 | Authorization |
MCP_AUTH_HEADER_VALUE |
完整请求头值 | Bearer your-token |
MCP_AUTH_HEADER_VALUE 应在 Horizon 中作为 Secret 保存,不要提交到 GitHub。
MCP_UPSTREAM_URL=https://example.com/mcp
MCP_AUTH_HEADER_NAME=Authorization
MCP_AUTH_HEADER_VALUE=Bearer your-upstream-token
MCP_UPSTREAM_URL=https://stitch.googleapis.com/mcp
MCP_AUTH_HEADER_NAME=X-Goog-Api-Key
MCP_AUTH_HEADER_VALUE=your-google-api-key
- 将本仓库推送到 GitHub,并在 Horizon Deploy 中选择它。
- Entrypoint 填写
main.py:mcp。 - 开启 Horizon Authentication。Horizon 将负责客户端侧 OAuth。
- 可以先不填写上游环境变量并完成第一次部署。此时服务是一个合法但没有工具的
Horizon MCP Auth Proxy (Unconfigured)。 - 在部署设置中添加上述三个环境变量。
- 重新部署或重启服务。环境变量在进程启动时读取,不会热更新。
- 在 Horizon Inspector 中连接服务并确认上游工具已经出现。
部署后的客户端只连接:
https://<server-name>.fastmcp.app/mcp
客户端不需要、也不应该携带上游 API Key。代码会禁用下游请求头转发,因此
Horizon OAuth 的 Authorization Bearer Token 不会发送到上游。
如果只配置了部分环境变量,服务会启动失败并明确列出缺失的变量。这可以避免 代理在错误凭据状态下运行。要恢复“待配置”状态,需要同时删除三个变量并重新部署。
- 一个远程 Streamable HTTP MCP 上游
- 一个固定认证请求头
Authorization: Bearer ...、API Key 和其他自定义认证头- Horizon 管理的下游 OAuth
当前不支持 SSE-only、stdio、多上游、上游 OAuth 登录流程或配置热更新。
安装依赖:
python -m pip install -r requirements.txt未配置状态可以直接启动:
fastmcp run main.py:mcp --transport http --port 8000完整配置可以复制 .env.example 为 .env,填写真实值后启动。FastMCP 默认加载
项目目录中的 .env,但真实 .env 已被 .gitignore 排除。
python -m pip install -r requirements-dev.txt
ruff check main.py tests
mypy --strict main.py
python -m pytest -q
python -m compileall main.py tests
fastmcp inspect main.py:mcpfastmcp inspect 在未配置状态下应成功,并显示一个没有上游工具的有效 MCP 服务。