MCP代理网关
通过模式验证观察和门控MCP工具调用,并记录/回放确定性测试。
它的作用
- HTTP JSON-RPC代理(
POST /rpc,与POST /mcp兼容性别名),转发到上游MCP服务器 - 验证
tools/callJSON模式参数 - 记录对NDJSON的请求/响应
- 在没有上游服务器的情况下回放录制的通话
- 当客户端请求时,流式传输上游SSE响应(
Accept: text/event-stream) - 状态检查的健康端点(
GET /healthz) - 本地运行时计数器的度量端点(
GET /metricsz) - 可选的Prometheus公开端点(
GET /metrics)启用时(标志/策略) - 支持JSON-RPC批处理请求(按项目顺序处理)
- 实现JSON-RPC通知语义(
204 No Content当请求省略时id) - 将重放的响应ID重写为传入请求ID,以确保相关性安全
快速入门
make setup
make build
./bin/mcp-proxy-gateway \
--listen :8080 \
--upstream http://localhost:8090/rpc \
--policy ./policy.example.yaml \
--record ./records.ndjson将JSON-RPC请求发送到 http://localhost:8080/rpc (或 http://localhost:8080/mcp). 检查健康状况 http://localhost:8080/healthz. 检查以下指标 http://localhost:8080/metricsz. 启用Prometheus指标 http://localhost:8080/metrics 随着 --prometheus-metrics (或 policy.http.prometheus_metrics: true).
演示(重播)
make build
./bin/mcp-proxy-gateway --listen :8080 --replay ./records.example.ndjson --replay-strict
curl -sS -X POST http://localhost:8080/rpc \
-H 'Content-Type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"tool":"web.search","arguments":{"query":"hello","max_results":3}}}'回放模式
./bin/mcp-proxy-gateway \
--listen :8080 \
--replay ./records.example.ndjson \
--replay-strict重播查找匹配可在策略中配置:
replay:
match: signature # signature (default), method, or tool流媒体/SSE直通
如果上游工具响应长时间运行,并且上游服务器支持SSE,则客户端可以通过以下方式请求:
curl -sS -N -X POST http://localhost:8080/rpc \
-H 'Content-Type: application/json' \
-H 'Accept: text/event-stream' \
-d '{"jsonrpc":"2.0","id":1,"method":"tools/call","params":{"tool":"web.search","arguments":{"query":"hello"}}}'笔记:
- 仅当客户端请求SSE时,网关才按原样流式传输上游响应字节(
Accept: text/event-stream)上游以Content-Type: text/event-stream. - 如果上游返回SSE,但客户端没有请求SSE,则网关返回JSON-RPC上游错误。
- 流式响应不会被记录(记录/回放仅为JSON)。
- 流式回复仍受
--max-body(提高它以获得更长的流量)。 - 流式处理仅支持单个JSON-RPC请求(不支持批处理)。
- 回放模式从不流式传输;它只提供记录的JSON响应。
- 对于批处理请求,网关不转发
Accept: text/event-stream上游;如果上游仍然响应text/event-stream,网关将其视为该批处理项的上游错误。
政策示例
version: 1
mode: enforce
allow_tools:
- web.search
- fs.read
http:
# Optional CSRF-style hardening for browser-initiated requests: if a request
# includes an `Origin` header not in this list, it is rejected (403). Requests
# without an Origin header are allowed.
origin_allowlist: ["http://localhost:3000"]
# Optional explicit allowlist of headers to forward upstream. This is
# intentionally narrow to avoid becoming a generic HTTP proxy.
# Notes:
# - `Authorization` is forwarded regardless to support authenticated upstreams.
# - `Accept` is forwarded only for SSE requests (`Accept: text/event-stream`).
forward_headers: ["Traceparent", "Tracestate", "Baggage", "X-Request-Id"]
# Optional Prometheus text exposition endpoint at GET /metrics.
prometheus_metrics: false
record:
# Redaction is applied before writing NDJSON recordings.
redact_keys: ["token", "access_token", "api_key", "authorization"]
redact_key_regex: ["(?i)secret|password"]
# Optional recorder lifecycle controls:
# - max_bytes rotates the active file when the next append would exceed this size.
# - max_files retains up to N rotated backups as `records.ndjson.1..N`.
max_bytes: 10485760 # 10 MiB
max_files: 3
tools:
web.search:
schema:
type: object
properties:
query:
type: string
max_results:
type: integer
minimum: 1
maximum: 10
required: [query]
additionalProperties: false上游报头转发
- 网关转发
Authorization如果存在,则向上游请求发送。 - 对于其他标头(例如分布式跟踪),请配置
policy.http.forward_headers. - 网关故意不转发传输/逐跳报头(例如
Host,Connection,Content-Length).
示例文件
policy.example.yamlrecords.example.ndjson
烟雾测试
make smoke文档
看 docs/ 有关架构、命令和贡献的详细信息。
许可证
麻省理工学院
