HTTP 服务代理配置
以下是HTTP服务代理的具体配置示例,包含了路由、工具等配置:
name: "mock-server" # 代理服务名称,全局唯一
tenant: "default" # 租户标识,用于多租户场景
# 路由配置
routers:
- server: "mock-server" # 服务名称
prefix: "/gateway/user" # 路由前缀,全局唯一,不可重复,建议按照服务或者领域+模块来区分前缀
# CORS 配置
cors:
allowOrigins: # 开发测试环境可全部开放,线上最好按需开放。(大部分MCP Client是不需要开放跨域的)
- "*"
allowMethods: # 允许的请求方法,按需开放,对于MCP(SSE和Streamable)来说通常只需要这3个方法即可
- "GET"
- "POST"
- "PUT"
- "OPTIONS"
allowHeaders:
- "Content-Type" # 必须允许的
- "Authorization" # 有鉴权需求的需要支持请求里携带此Key
- "Mcp-Session-Id" # 对于MCP来说,必须支持请求里携带这个Key,否则Streamable HTTP无法正常使用
- "mcp-protocol-version" # MCP协议版本头,用于协议版本协商
exposeHeaders:
- "Mcp-Session-Id" # 对于MCP来说,开启跨域的时候必须要暴露这个Key,否则Streamable HTTP无法正常使用
- "mcp-protocol-version" # MCP协议版本头
allowCredentials: true # 是否增加 Access-Control-Allow-Credentials: true 这个Header
# 服务配置
servers:
- name: "mock-server" # 服务名称,需要与routers中的server保持一致
description: "Mock User Service" # 服务描述
allowedTools: # 允许使用的工具列表(为tools的子集)
- "register_user"
- "get_user_by_email"
- "update_user_preferences"
- "update_user_avatar"
config: # 服务级别的配置,可以在tools中通过{{.Config}}引用
Cookie: 123 # 写死的配置
Authorization: 'Bearer {{ env "AUTH_TOKEN" }}' # 从环境变量中获取的配置,用法是'{{ env "ENV_VAR_NAME" }}'
# 工具配置
tools:
- name: "register_user" # 工具名称
description: "Register a new user" # 工具描述
method: "POST" # 请求目标(上游、后端)服务的HTTP方法
endpoint: "http://localhost:5236/users" # 目标服务地址
headers: # 请求头配置,用于在请求目标服务时携带的请求头
Content-Type: "application/json" # 写死的请求头
Authorization: "{{.Config.Authorization}}" # 使用服务配置中的值
Cookie: "{{.Config.Cookie}}" # 使用服务配置中的值
args: # 参数配置
- name: "username" # 参数名称
position: "body" # 参数位置:header, query, path, body, form-data
required: true # 参数是否必填
type: "string" # 参数类型
description: "Username" # 参数描述
default: "" # 默认值
- name: "email"
position: "body"
required: true
type: "string"
description: "Email"
default: ""
requestBody: |- # 请求体模板,用于动态生成请求体,如:从参数(MCP的请求arguments)中提取的值
{
"username": "{{.Args.username}}",
"email": "{{.Args.email}}"
}
responseBody: |- # 响应体模板,用于动态生成响应体,如:从响应中提取的值
{
"id": "{{.Response.Data.id}}",
"username": "{{.Response.Data.username}}",
"email": "{{.Response.Data.email}}",
"createdAt": "{{.Response.Data.createdAt}}"
}
- name: "get_user_by_email"
description: "Get user by email"
method: "GET"
endpoint: "http://localhost:5236/users/email/{{.Args.email}}"
args:
- name: "email"
position: "path"
required: true
type: "string"
description: "Email"
default: ""
responseBody: |-
{
"id": "{{.Response.Data.id}}",
"username": "{{.Response.Data.username}}",
"email": "{{.Response.Data.email}}",
"createdAt": "{{.Response.Data.createdAt}}"
}
- name: "update_user_preferences"
description: "Update user preferences"
method: "PUT"
endpoint: "http://localhost:5236/users/{{.Args.email}}/preferences"
headers:
Content-Type: "application/json"
Authorization: "{{.Request.Headers.Authorization}}"
Cookie: "{{.Config.Cookie}}"
args:
- name: "email"
position: "path"
required: true
type: "string"
description: "Email"
default: ""
- name: "isPublic"
position: "body"
required: true
type: "boolean"
description: "Whether the user profile is public"
default: "false"
- name: "showEmail"
position: "body"
required: true
type: "boolean"
description: "Whether to show email in profile"
default: "true"
- name: "theme"
position: "body"
required: true
type: "string"
description: "User interface theme"
default: "light"
- name: "tags"
position: "body"
required: true
type: "array"
items:
type: "string"
enum: ["developer", "designer", "manager", "tester"]
description: "User role tags"
default: "[]"
- name: "settings"
position: "body"
required: false
type: "object"
description: "User custom settings as key-value pairs"
default: "{}"
- name: "notifications"
position: "body"
required: false
type: "array"
description: "User notification preferences"
items:
type: "object"
properties:
type:
type: "string"
description: "Notification type (email, push, sms)"
channel:
type: "string"
description: "Notification channel (marketing, system, security)"
enabled:
type: "boolean"
description: "Whether this notification is enabled"
frequency:
type: "number"
description: "Notification frequency (0: realtime, 1: daily, 2: weekly, 3: monthly)"
default: "[]"
requestBody: |-
{
"isPublic": {{.Args.isPublic}},
"showEmail": {{.Args.showEmail}},
"theme": "{{.Args.theme}}",
"tags": {{.Args.tags}},
"settings": {{ toJSON .Args.settings }},
"notifications": {{ .Args.notifications }}
}
responseBody: |-
{
"id": "{{.Response.Data.id}}",
"username": "{{.Response.Data.username}}",
"email": "{{.Response.Data.email}}",
"createdAt": "{{.Response.Data.createdAt}}",
"preferences": {
"isPublic": {{.Response.Data.preferences.isPublic}},
"showEmail": {{.Response.Data.preferences.showEmail}},
"theme": "{{.Response.Data.preferences.theme}}",
"tags": {{.Response.Data.preferences.tags}},
"settings": {{ toJSON .Response.Data.preferences.settings }},
"notifications": {{ toJSON .Response.Data.preferences.notifications }}
}
}
- name: "update_user_avatar"
description: "Update user avatar using a URL via multipart form"
method: "POST"
endpoint: "http://localhost:5236/users/{{.Args.email}}/avatar"
headers:
Authorization: "{{.Request.Headers.Authorization}}"
Cookie: "{{.Config.Cookie}}"
args:
- name: "email"
position: "path"
required: true
type: "string"
description: "Email of the user"
default: ""
- name: "url"
position: "form-data"
required: true
type: "string"
description: "The avatar image URL"
default: ""
responseBody: |-
{
"message": "{{.Response.Data.message}}",
"avatarUrl": "{{.Response.Data.avatarUrl}}"
}
配置说明
1. 基础配置
MCP Gateway 服务监听端口,默认 5235
可以把一份配置当作一个命名空间,建议按照服务或者领域来区分,某个服务里包含很多API接口,每个API接口对应一个Tool
name
: 代理服务名称,全局唯一,用于标识不同的代理服务
tenant
: 租户标识,用于多租户场景的数据隔离和权限管理
2. 路由配置
路由配置用于定义请求的转发规则:
routers:
- server: "mock-server" # 服务名称,需要与servers中的name保持一致
prefix: "/gateway/user" # 路由前缀,全局唯一,不可重复
目前默认情况下会在prefix
的基础之上衍生出3个接入点:
- SSE:
${prefix}/sse
,如:/gateway/user/sse
- SSE:
${prefix}/message
,如:/gateway/user/message
- StreamableHTTP:
${prefix}/mcp
,如:/gateway/user/mcp
3. CORS配置
跨域资源共享(CORS)配置用于控制跨域请求的访问权限:
cors:
allowOrigins: # 开发测试环境可全部开放,线上最好按需开放。(大部分MCP Client是不需要开放跨域的)
- "*"
allowMethods: # 允许的请求方法,按需开放,对于MCP(SSE和Streamable)来说通常只需要这3个方法即可
- "GET"
- "POST"
- "OPTIONS"
allowHeaders:
- "Content-Type" # 必须允许的
- "Authorization" # 有鉴权需求的需要支持请求里携带此Key
- "Mcp-Session-Id" # 对于MCP来说,必须支持请求里携带这个Key,否则Streamable HTTP无法正常使用
exposeHeaders:
- "Mcp-Session-Id" # 对于MCP来说,开启跨域的时候必须要暴露这个Key,否则Streamable HTTP无法正常使用
allowCredentials: true # 是否增加 Access-Control-Allow-Credentials: true 这个Header
通常情况下,MCP Client是不需要开放跨域的
4. 服务配置
服务配置用于定义服务元信息、关联的工具列表,以及服务级别的配置
servers:
- name: "mock-server" # 服务名称,需要与routers中的server保持一致
namespace: "user-service" # 服务命名空间,用于服务分组
description: "Mock User Service" # 服务描述
allowedTools: # 允许使用的工具列表(为tools的子集)
- "register_user"
- "get_user_by_email"
- "update_user_preferences"
config: # 服务级别的配置,可以在tools中通过{{.Config}}引用
Cookie: 123 # 写死的配置
Authorization: 'Bearer {{ env "AUTH_TOKEN" }}' # 从环境变量中获取的配置,用法是'{{ env "ENV_VAR_NAME" }}'
服务级别的配置,可以在tools中通过 {{.Config}}
引用。此处可以通过写死在配置文件里的方式,也可以通过从环境变量中获取的方式。通过环境变量注入的话,需要通过{{ env "ENV_VAR_NAME" }}
的方式引用
5. 工具配置
工具配置用于定义具体的API调用规则,每个参数都可以设置默认值(default),当MCP请求中没有提供该参数时,将自动使用默认值。
5.1 请求参数组装
请求目标服务的时候会涉及组装参数的动作,目前有几个来源:
.Config
: 从服务级别的配置中提取值
.Args
: 直接从请求参数中提取值
.Request
: 从请求中提取的值,包括请求头.Request.Headers
、请求体.Request.Body
等
参数位置(position)支持以下几种:
header
: 参数将被放置在请求头中
query
: 参数将被放置在URL查询字符串中
path
: 参数将被放置在URL路径中
body
: 参数将被放置在JSON格式的请求体中
form-data
: 参数将被放置在multipart/form-data格式的请求体中,用于文件上传等场景
参数类型(type)支持以下几种:
string
: 字符串类型
number
: 数字类型
boolean
: 布尔类型
array
: 数组类型,需要配合 items
定义数组元素类型
object
: 对象类型,可以使用 properties
定义对象结构
对于复杂的 array
类型参数,可以定义详细的元素结构:
- name: "notifications"
position: "body"
required: false
type: "array"
description: "User notification preferences"
items:
type: "object"
properties:
type:
type: "string"
description: "Notification type (email, push, sms)"
enabled:
type: "boolean"
description: "Whether this notification is enabled"
default: "[]"
当使用 form-data
作为参数位置时,不需要指定 requestBody
,系统会自动将参数组装成 multipart/form-data 格式。
对于JSON格式的请求体,需要在 requestBody
中组装,比如:
requestBody: |-
{
"isPublic": {{.Args.isPublic}},
"showEmail": {{.Args.showEmail}},
"theme": "{{.Args.theme}}",
"tags": {{.Args.tags}}
}
包括 endpoint
即目标地址也可以使用以上的来源去提取值,比如 http://localhost:5236/users/{{.Args.email}}/preferences
就是从请求参数中提取的值
5.2 响应参数组装
响应体的组装和请求体的组装类似:
.Response.Data
: 从响应中提取的值,响应必须是JSON的格式才可以提取
.Response.Body
: 直接透传整个响应体,会忽略响应内容格式,直接传递给客户端
都是通过 .Response
来提取值,比如:
responseBody: |-
{
"id": "{{.Response.Data.id}}",
"username": "{{.Response.Data.username}}",
"email": "{{.Response.Data.email}}",
"createdAt": "{{.Response.Data.createdAt}}"
}
配置存储
网关代理配置可以通过以下两种方式存储:
数据库存储(推荐)
- 支持 SQLite3、PostgreSQL、MySQL
- 每个配置作为一条记录存储
- 支持动态更新和热重载
文件存储
- 每个配置单独存储为一个 YAML 文件
- 类似 Nginx 的 vhost 配置方式
- 文件名建议使用服务名称,如
mock-server.yaml
MCP 服务代理配置
除了代理 HTTP 服务外,MCP Gateway 还支持代理 MCP 服务,目前 stdio、SSE 和 streamable-http 三种传输协议都已支持
配置示例
以下是一个完整的 MCP 服务代理配置示例:
name: "proxy-mcp-exp"
tenant: "default"
routers:
- server: "amap-maps"
prefix: "/gateway/stdio-proxy"
cors:
allowOrigins:
- "*"
allowMethods:
- "GET"
- "POST"
- "OPTIONS"
allowHeaders:
- "Content-Type"
- "Authorization"
- "Mcp-Session-Id"
exposeHeaders:
- "Mcp-Session-Id"
allowCredentials: true
- server: "mock-user-sse"
prefix: "/gateway/sse-proxy"
cors:
allowOrigins:
- "*"
allowMethods:
- "GET"
- "POST"
- "OPTIONS"
allowHeaders:
- "Content-Type"
- "Authorization"
- "Mcp-Session-Id"
exposeHeaders:
- "Mcp-Session-Id"
allowCredentials: true
- server: "mock-user-mcp"
prefix: "/gateway/streamable-http-proxy"
cors:
allowOrigins:
- "*"
allowMethods:
- "GET"
- "POST"
- "OPTIONS"
allowHeaders:
- "Content-Type"
- "Authorization"
- "Mcp-Session-Id"
exposeHeaders:
- "Mcp-Session-Id"
allowCredentials: true
mcpServers:
- type: "stdio"
name: "amap-maps"
command: "npx"
args:
- "-y"
- "@amap/amap-maps-mcp-server"
env:
AMAP_MAPS_API_KEY: "{{.Request.Headers.Apikey}}"
- type: "sse"
name: "mock-user-sse"
url: "http://localhost:3000/gateway/user/sse"
- type: "streamable-http"
name: "mock-user-mcp"
url: "http://localhost:3000/gateway/user/mcp"
配置说明
1. MCP 服务类型
MCP Gateway 支持以下三种类型的 MCP 服务代理:
- 通过标准输入输出与 MCP 服务进程通信
- 适用于需要本地启动的 MCP 服务,如第三方 SDK
- 配置参数包括
command
、args
和 env
- 将 MCP 客户端的请求转发到支持 SSE 的上游服务
- 适用于已有的支持 SSE 协议的 MCP 服务
- 仅需配置
url
参数指向上游 SSE 服务地址
- 将 MCP 客户端的请求转发到支持可流式 HTTP 的上游服务
- 适用于已有的支持 MCP 协议的上游服务
- 仅需配置
url
参数指向上游 MCP 服务地址
2. stdio 类型配置
stdio 类型的 MCP 服务配置示例:
mcpServers:
- type: "stdio"
name: "amap-maps" # 服务名称
command: "npx" # 要执行的命令
args: # 命令参数
- "-y"
- "@amap/amap-maps-mcp-server"
env: # 环境变量
AMAP_MAPS_API_KEY: "{{.Request.Headers.Apikey}}" # 从请求头中提取值
通过 env
字段可以设置环境变量,支持从请求中提取值,例如 {{.Request.Headers.Apikey}}
表示从请求头中提取 Apikey 的值
3. SSE 类型配置
SSE 类型的 MCP 服务配置示例:
mcpServers:
- type: "sse"
name: "mock-user-sse" # 服务名称
url: "http://localhost:3000/gateway/user/sse" # 上游 SSE 服务地址,通常以/sse结尾,实际根据上游服务而定
4. streamable-http 类型配置
streamable-http 类型的 MCP 服务配置示例:
mcpServers:
- type: "streamable-http"
name: "mock-user-mcp" # 服务名称
url: "http://localhost:3000/gateway/user/mcp" # 上游 MCP 服务地址,通常以/mcp结尾,实际根据上游服务而定
5. 路由配置
对于 MCP 服务代理,路由配置与 HTTP 服务代理类似,CORS 则根据实际情况配置(通常生产环境一般是不会开启跨域的):
routers:
- server: "amap-maps" # 服务名称,需要与 mcpServers 中的 name 保持一致
prefix: "/gateway/stdio-proxy" # 路由前缀,全局唯一
cors:
allowOrigins:
- "*"
allowMethods:
- "GET"
- "POST"
- "OPTIONS"
allowHeaders:
- "Content-Type"
- "Authorization"
- "Mcp-Session-Id" # MCP 服务必须包含此头
exposeHeaders:
- "Mcp-Session-Id" # MCP 服务必须暴露此头
allowCredentials: true
对于 MCP 服务,请求头和响应头中的 Mcp-Session-Id
是必须要支持的,否则客户端无法正常使用。
高级配置
通知器配置
通知器用于配置重载通知,支持多种方式:
通过系统信号进行通知,适用于单机部署
notifier:
type: "signal"
signal:
signal: "SIGHUP"
pid: "/var/run/mcp-gateway.pid"
通过HTTP API进行通知,适用于远程管理
notifier:
type: "api"
api:
port: 5235
target_url: "http://localhost:5235/_reload"
通过Redis发布订阅进行通知,适用于集群部署
notifier:
type: "redis"
redis:
cluster_type: "single"
addr: "localhost:6379"
topic: "mcp-gateway:reload"
环境变量注入
在配置中可以使用环境变量,支持默认值:
# 基础语法
port: ${MCP_GATEWAY_PORT:5235} # 使用环境变量,默认值 5235
# 字符串格式
logger:
level: "${LOGGER_LEVEL:info}" # 使用环境变量,默认值 info
# 服务配置中使用
config:
ApiKey: '{{ env "API_KEY" }}'
BaseUrl: '{{ env "API_BASE_URL" "http://localhost:8080" }}' # 带默认值
模板函数
在请求体和响应体模板中,可以使用模板函数来处理复杂数据:
将对象或数组转换为 JSON 字符串,用于处理复杂数据结构
requestBody: |-
{
"settings": {{ toJSON .Args.settings }},
"notifications": {{ toJSON .Args.notifications }}
}
对于简单的数组和对象,可以直接使用变量
requestBody: |-
{
"tags": {{.Args.tags}},
"preferences": {{ .Args.preferences }}
}
使用 toJSON
函数可以确保复杂的对象和数组被正确序列化为 JSON 格式,特别适用于嵌套结构和包含特殊字符的数据。
复杂参数处理示例
以下是一个处理复杂参数的完整示例,展示了如何定义和使用 object 和 array 类型的参数:
args:
- name: "settings"
position: "body"
required: false
type: "object"
description: "User custom settings as key-value pairs"
default: "{}"
- name: "notifications"
position: "body"
required: false
type: "array"
description: "User notification preferences"
items:
type: "object"
properties:
type:
type: "string"
description: "Notification type (email, push, sms)"
channel:
type: "string"
description: "Notification channel (marketing, system, security)"
enabled:
type: "boolean"
description: "Whether this notification is enabled"
frequency:
type: "number"
description: "Notification frequency (0: realtime, 1: daily, 2: weekly, 3: monthly)"
default: "[]"
requestBody: |-
{
"settings": {{ toJSON .Args.settings }},
"notifications": {{ .Args.notifications }}
}
responseBody: |-
{
"settings": {{ toJSON .Response.Data.preferences.settings }},
"notifications": {{ toJSON .Response.Data.preferences.notifications }}
}
文件上传处理
支持文件上传场景:
args:
- name: "file"
position: "form-data"
required: true
type: "string"
description: "File to upload"
- name: "description"
position: "form-data"
required: false
type: "string"
description: "File description"
最佳实践
- 使用环境变量存储敏感信息(如数据库密码、API密钥)
- 在生产环境中限制CORS Origins,避免使用 ”*”
- 启用OAuth2认证和适当的授权机制
- 定期轮换API密钥和令牌
- 使用加密的Redis连接存储会话数据
- 合理设置超时时间和重载间隔
- 使用Redis集群提高会话存储性能
- 选择合适的日志级别,避免过多debug日志
- 使用连接池减少连接开销
- 对频繁调用的API进行缓存
- 避免在模板中进行复杂计算
- 使用有意义的工具和服务名称
- 添加详细的描述信息
- 保持配置文件的整洁和可读性
- 配置日志轮转,避免磁盘空间不足
- 监控PID文件和进程状态
- 设置合适的通知器类型便于配置管理
- 定期检查和更新配置
- 在开发环境中充分测试配置
- 使用mock服务进行集成测试
- 验证所有参数和响应格式
- 测试错误处理和边界情况
配置验证
在应用配置之前,建议进行以下验证:
更多关于Go Template的使用方法,请参考模板使用指南。
Responses are generated using AI and may contain mistakes.