使用说明
MCP网关
描述
MCP网关是一个反向代理服务器,它将客户端的请求转发到MCP服务器,或者通过统一的门户使用网关下的所有MCP服务器。
支持两种传输协议(启动时可切换):
- 上海证券交易所 (默认,传统MCP传输)
- 可流式传输的HTTP (MCP规范
2025-03-26)
特性
- 部署多个MCP服务器
- 连接到MCP服务器
- 使用网关呼叫MCP服务器
- 获取所有MCP服务器的SSE流
- 获取所有MCP服务器的工具
- 可流式HTTP聚合端点,通过会话管理
Mcp-Session-Id头球 - 动态能力聚合(网关仅通告至少一个下游MCP支持的能力)
- MCP OAuth 2.1资源服务器身份验证与受保护资源元数据发现
安装
- 拉取github包
docker pull ghcr.io/lucky-aeon/mcp-gateway:latest
- 自建docker镜像
docker build -t mcp-gateway .
用法
运行github docker容器
docker run -d --name mcp-gateway -p 8080:8080 ghcr.io/lucky-aeon/mcp-gateway
运行自建docker容器
docker run -d --name mcp-gateway -p 8080:8080 mcp-gateway
配置
网关读取 config.json 从配置目录(默认为 ./vm 如果存在,否则 .).一个最小的例子:
{
"LogLevel": 0,
"Bind": "[::]:8080",
"Auth": {
"Enabled": true,
"AuthorizationServers": ["https://auth.example.com"],
"TokenIssuer": "https://auth.example.com",
"TokenJWKSURI": "https://auth.example.com/.well-known/jwks.json",
"TokenAudience": "http://localhost:8080/stream",
"RequiredScopes": ["mcp:read"],
"ScopesSupported": ["mcp:read"]
},
"GatewayProtocol": "all",
"McpServiceMgrConfig": {
"McpServiceRetryCount": 3
}
}
关键字段:
| 字段 | 默认值 | 描述 |
|---|---|---|
Bind |
[::]:8080 |
服务器侦听地址。 |
GatewayProtocol |
all |
暴露的网关协议: all, sse,或 streamhttp.也可通过 --protocol 旗帜。 |
Auth.Enabled |
true |
是否强制执行身份验证。集 false 用于本地未经身份验证的MCP使用。 |
Auth.ApiKey |
123456 |
传统的单密钥管理API登录令牌;未用作MCP身份验证。 |
Auth.Mode |
single-key |
single-key 或 saasSaaS模式使用MCP网关帐户和密码登录。 |
Auth.AuthorizationServers |
empty | 可选的外部OAuth颁发者URL。在SaaS模式下为空意味着网关将自己宣传为授权服务器。 |
Auth.TokenIssuer |
第一个授权服务器 | 需要 iss MCP OAuth访问令牌的索赔。 |
Auth.TokenJWKSURI |
从发行者处发现 | 用于验证JWT访问令牌的JWKS URL。 |
Auth.TokenIntrospectionURL |
空 | 不透明访问令牌的RFC 7662自检端点。如果设置,则使用内省而不是JWKS。 |
Auth.TokenAudience |
请求资源URL | 需要 aud 索赔。配置到授权服务器使用的MCP资源指示器。 |
Auth.RequiredScopes |
空 | MCP请求所需的范围,并在 WWW-Authenticate. |
Auth.ScopesSupported |
空 | 受保护资源元数据中通告的作用域。 |
SessionGCInterval |
10s |
垃圾收集空闲代理会话的间隔。 |
ProxySessionTimeout |
1m |
GC前空闲代理会话超时。 |
McpServiceMgrConfig.McpServiceRetryCount |
3 |
标记失败的MCP服务之前的最大重试次数 failed. |
选择网关协议
任一组 GatewayProtocol 在 config.json:
{ "GatewayProtocol": "all" }
或者传递CLI标志(优先):
./mcp-gateway --protocol=streamhttp
有效值: all (默认), sse,或 streamhttp.
认证
当 Auth.Enabled 是 true,每个MCP协议请求都必须提供一个承载令牌:
Authorization: Bearer <access-token>
网关不再处理 api_key, sessionId, Mcp-Session-Id,或 X-Session-Id 作为身份验证凭证。 Mcp-Session-Id 仍然是传输会话标识符,必须在经过身份验证的Streamable HTTP请求上与Bearer令牌一起发送。
对于MCP OAuth发现,网关公开OAuth受保护的资源元数据:
GET /.well-known/oauth-protected-resource
GET /.well-known/oauth-protected-resource/stream
未经授权的MCP请求返回 401 带着一个 WWW-Authenticate: Bearer ... resource_metadata="..." OAuth发现可用时的挑战。对于本地未经身份验证的开发,设置 Auth.Enabled 到 false.
在 Auth.Mode = "saas" 无外部 Auth.AuthorizationServers,网关使用自己的帐户系统登录MCP。Discovery将网关源作为授权服务器进行公告,并公开:
GET /.well-known/oauth-authorization-server
POST /oauth/token
POST /oauth/register
/oauth/token 接受已编码的表单 grant_type=password 随着 username/password 并返回与所使用的网关JWT相同的网关 /api/v1/auth/login.配置 Auth.AuthorizationServers 仅当您需要Keycloak、Auth0或其他外部OAuth提供程序时。
基于浏览器的MCP客户端还可以使用公告的授权端点:
GET /oauth/authorize
内置的授权端点呈现网关帐户登录表单,并完成OAuth授权代码流,包括PKCE。
/oauth/register 为MCP Inspector等客户端实现了最小的动态客户端注册。
API
部署
支持:uvx、npx。或sse url
POST /deploy HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"mcpServers": {
"time": {
"url": "http://mcp-server:8080", // url 和 command 二选一
"command": "uvx", // url 和 command 二选一
"args": ["mcp-server-time", "--local-timezone=America/New_York"], // 可选,command 的参数
"env": { // 可选,环境变量
"KEY1": "VALUE1",
"KEY2": "VALUE2"
}
}
}
}
使用MCP(SSE模式)
可用时间:
GatewayProtocol是all(默认)或sse.
得到SSE
GET /{mcp-server-name}/sse HTTP/1.1
Host: localhost:8080
发布消息
POST /{mcp-server-name}/message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/call",
"params": {
"name": "get_current_time",
"arguments": {
"timezone": "Asia/Seoul"
}
},
"jsonrpc": "2.0",
"id": 2
}
使用网关(SSE模式)
可用时间:
GatewayProtocol是all(默认)或sse.
网关和直连MCP的区别在于,只需要与网关交互,网关会自动将请求转发到对应的MCP服务器。在call 时,需要在method前面添加 mcpServerName 内容,标识该请求来自哪个 MCP 服务器。
得到SSE
GET /sse HTTP/1.1
Host: localhost:8080
这里 sse 是整个网关下所有的 MCP 服务器的 SSE 流。
当客户端订阅 sse 时,网关会为每个 MCP 服务器创建一个 SSE 连接,并将所有 MCP 服务器的 SSE 流合并到一起。
在响应的所有tools/call 的结果中,会在method前面添加 mcpServerName 内容,标识该结果来自哪个 MCP 服务器。
发布消息
POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/call",
"params": {
"name": "{mcp-server-name}-get_current_time",
"arguments": {
"timezone": "Asia/Seoul"
}
},
"jsonrpc": "2.0",
"id": 2
}
获取网关下所有工具
POST /message HTTP/1.1
Host: localhost:8080
Content-Type: application/json
{
"method": "tools/list",
"jsonrpc": "2.0",
"id": 1
}
# SSE 响应 message event
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"tools": [
{
"name": "{mcpServerName}-get_current_time",
"description": "Get current time in a specific timezones",
"inputSchema": {
"type": "object",
"properties": {
"timezone": {
"type": "string",
"description": "IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no timezone provided by the user."
}
},
"required": [
"timezone"
]
}
},
{
"name": "{mcpServerName}-convert_time",
"description": "Convert time between timezones",
"inputSchema": {
"type": "object",
"properties": {
"source_timezone": {
"type": "string",
"description": "Source IANA timezone name (e.g., 'America/New_York', 'Europe/London'). Use 'America/New_York' as local timezone if no source timezone provided by the user."
},
"time": {
"type": "string",
"description": "Time to convert in 24-hour format (HH:MM)"
},
"target_timezone": {
"type": "string",
"description": "Target IANA timezone name (e.g., 'Asia/Tokyo', 'America/San_Francisco'). Use 'America/New_York' as local timezone if no target timezone provided by the user."
}
},
"required": [
"source_timezone",
"time",
"target_timezone"
]
}
}
]
}
}
使用网关(流式HTTP模式)
可用时间:
GatewayProtocol是all(默认)或streamhttp.实现规范中定义的MCP流式HTTP传输
2025-03-26网关公开单个聚合端点/stream接受POST,GET和DELETE会话标识符在Mcp-Session-IdHTTP标头。
1.建立会话(初始化)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json
{
"jsonrpc": "2.0",
"id": 1,
"method": "initialize",
"params": {
"protocolVersion": "2025-03-26",
"capabilities": {},
"clientInfo": {"name": "my-client", "version": "1.0.0"}
}
}
答复:
HTTP/1.1 200 OK
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"protocolVersion": "2025-03-26",
"serverInfo": {"name": "mcp-gateway", "version": "1.0.0"},
"capabilities": { /* OR-merged from all downstream MCP servers */ },
"instructions": "MCP Gateway aggregates multiple MCP servers. Tools are namespaced as <serverName>_<toolName>."
}
}
保留退回的 Mcp-Session-Id 并在每次后续请求时发送它。
2.完成握手(通知)
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{"jsonrpc": "2.0", "method": "notifications/initialized"}
答复: 202 Accepted (空的身体)。
3.调用工具或列出资源
POST /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: application/json, text/event-stream
Content-Type: application/json
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "{mcp-server-name}_get_current_time",
"arguments": {"timezone": "Asia/Seoul"}
}
}
聚合工具名称遵循以下模式 <serverName>_<toolName>,规则与SSE网关模式相同。
响应同步到达HTTP响应体:
{"jsonrpc": "2.0", "id": 2, "result": { /* ... */ }}
通知(JSON-RPC消息,无 id)答案是 202 Accepted 并异步转发。
4.订阅服务器发起的事件(可选)
GET /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Accept: text/event-stream
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
网关保持连接打开并发出 event: message 服务器框架→ 客户端JSON-RPC 请求: 和 通知 (例如进度更新、日志消息)。JSON-RPC 回应 永远不会被推送到这里——它们会在发起的HTTP响应中返回 POST /stream 请求。
以开头的行 : 是SSE保持活动的评论,可以忽略。
5.结束会议
DELETE /stream HTTP/1.1
Host: localhost:8080
Authorization: Bearer <access-token>
Mcp-Session-Id: 7782f2f9-563c-4379-b961-df06e49e54c0
答复: 200 OK.
单服务器直通
在Streamable HTTP模式下,您还可以直接访问单个MCP服务器:
POST /{mcp-server-name} HTTP/1.1
GET /{mcp-server-name} HTTP/1.1
网关将请求转发给目标MCP message 终点。此模式下的会话管理由下游服务器负责。
与MCP检查员联系
- 在检查器中选择 传输类型:
Streamable HTTP. - 网址:
http://localhost:8080/stream. - 在您的授权服务器中完成OAuth流程,并提供
Authorization: Bearer <access-token>. - 点击 连接.检查员负责处理
Mcp-Session-Id自动交换。