HTTP Service Proxy Configuration

The following is a specific configuration example for HTTP service proxy, including routing, tools and other configurations:

name: "mock-server"              # Proxy service name, globally unique
tenant: "default"                # Tenant identifier for multi-tenant scenarios

# Routing configuration
routers:
  - server: "mock-server"       # Service name
    prefix: "/gateway/user"         # Route prefix, globally unique, non-repeatable, recommended to distinguish prefixes by service or domain+module

    # CORS configuration
    cors:
      allowOrigins:             # Development and test environments can be fully open, production should be opened as needed. (Most MCP Clients do not need to open cross-origin)
        - "*"
      allowMethods:             # Allowed request methods, open as needed, for MCP (SSE and Streamable) usually only these 3 methods are needed
        - "GET"
        - "POST"
        - "PUT"
        - "OPTIONS"
      allowHeaders:
        - "Content-Type"        # Must be allowed
        - "Authorization"       # Required for authentication needs to support carrying this key in requests
        - "Mcp-Session-Id"      # For MCP, must support carrying this key in requests, otherwise Streamable HTTP cannot be used normally
        - "mcp-protocol-version" # MCP protocol version header for protocol version negotiation
      exposeHeaders:
        - "Mcp-Session-Id"      # For MCP, when cross-origin is enabled, this key must be exposed, otherwise Streamable HTTP cannot be used normally
        - "mcp-protocol-version" # MCP protocol version header
      allowCredentials: true    # Whether to add Access-Control-Allow-Credentials: true header

# Service configuration
servers:
  - name: "mock-server"               # Service name, must match server in routers
    description: "Mock User Service"  # Service description
    allowedTools:                     # List of allowed tools (subset of tools)
      - "register_user"
      - "get_user_by_email"
      - "update_user_preferences"
      - "update_user_avatar"
    config:                                           # Service-level configuration, can be referenced in tools via {{.Config}}
      Cookie: 123                                     # Hardcoded configuration
      Authorization: 'Bearer {{ env "AUTH_TOKEN" }}'  # Configuration from environment variables, usage is '{{ env "ENV_VAR_NAME" }}'

# Tool configuration
tools:
  - name: "register_user"                                   # Tool name
    description: "Register a new user"                      # Tool description
    method: "POST"                                          # HTTP method for requesting target (upstream, backend) service
    endpoint: "http://localhost:5236/users"                 # Target service address
    headers:                                                # Request header configuration for carrying headers when requesting target service
      Content-Type: "application/json"                      # Hardcoded request header
      Authorization: "{{.Config.Authorization}}"            # Use value from service configuration
      Cookie: "{{.Config.Cookie}}"                          # Use value from service configuration
    args:                         # Parameter configuration
      - name: "username"          # Parameter name
        position: "body"          # Parameter position: header, query, path, body, form-data
        required: true            # Whether parameter is required
        type: "string"            # Parameter type
        description: "Username"   # Parameter description
        default: ""               # Default value
      - name: "email"
        position: "body"
        required: true
        type: "string"
        description: "Email"
        default: ""
    requestBody: |-                       # Request body template for dynamically generating request body, e.g., values extracted from parameters (MCP request arguments)
      {
        "username": "{{.Args.username}}",
        "email": "{{.Args.email}}"
      }
    responseBody: |-                      # Response body template for dynamically generating response body, e.g., values extracted from response
      {
        "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}}"
      }

Configuration Explanation

1. Basic Configuration

A configuration can be treated as a namespace, recommended to distinguish by service or domain. A service contains many API interfaces, each API interface corresponds to a Tool.

  • name: Proxy service name, globally unique, used to identify different proxy services
  • tenant: Tenant identifier for data isolation and permission management in multi-tenant scenarios

2. Routing Configuration

Routing configuration is used to define request forwarding rules:

routers:
  - server: "mock-server"       # Service name, must match name in servers
    prefix: "/gateway/user"         # Route prefix, globally unique, non-repeatable

Currently, by default, 3 endpoints are derived based on prefix:

  • SSE: ${prefix}/sse, e.g., /gateway/user/sse
  • SSE: ${prefix}/message, e.g., /gateway/user/message
  • StreamableHTTP: ${prefix}/mcp, e.g., /gateway/user/mcp

3. CORS Configuration

Cross-Origin Resource Sharing (CORS) configuration is used to control access permissions for cross-origin requests:

cors:
  allowOrigins:             # Development and test environments can be fully open, production should be opened as needed. (Most MCP Clients do not need to open cross-origin)
    - "*"
  allowMethods:             # Allowed request methods, open as needed, for MCP (SSE and Streamable) usually only these 3 methods are needed
    - "GET"
    - "POST"
    - "OPTIONS"
  allowHeaders:
    - "Content-Type"        # Must be allowed
    - "Authorization"       # Required for authentication needs to support carrying this key in requests
    - "Mcp-Session-Id"      # For MCP, must support carrying this key in requests, otherwise Streamable HTTP cannot be used normally
  exposeHeaders:
    - "Mcp-Session-Id"      # For MCP, when cross-origin is enabled, this key must be exposed, otherwise Streamable HTTP cannot be used normally
  allowCredentials: true    # Whether to add Access-Control-Allow-Credentials: true header

Usually, MCP Clients do not need to open cross-origin

4. Service Configuration

Service configuration is used to define service metadata, associated tool lists, and service-level configuration:

servers:
  - name: "mock-server"               # Service name, must match server in routers
    namespace: "user-service"         # Service namespace for service grouping
    description: "Mock User Service"  # Service description
    allowedTools:                     # List of allowed tools (subset of tools)
      - "register_user"
      - "get_user_by_email"
      - "update_user_preferences"
    config:                                           # Service-level configuration, can be referenced in tools via {{.Config}}
      Cookie: 123                                     # Hardcoded configuration
      Authorization: 'Bearer {{ env "AUTH_TOKEN" }}'  # Configuration from environment variables, usage is '{{ env "ENV_VAR_NAME" }}'

Service-level configuration can be referenced in tools via {{.Config}}. This can be hardcoded in the configuration file or obtained from environment variables. For environment variable injection, reference using {{ env "ENV_VAR_NAME" }}.

5. Tool Configuration

Tool configuration is used to define specific API call rules. Each parameter can set a default value (default), which will be automatically used when the parameter is not provided in the MCP request.

5.1 Request Parameter Assembly

When requesting the target service, parameter assembly is involved. Currently there are several sources:

  1. .Config: Extract values from service-level configuration
  2. .Args: Extract values directly from request parameters
  3. .Request: Values extracted from the request, including request headers .Request.Headers, request body .Request.Body, etc.

Parameter position (position) supports the following types:

  • header: Parameter will be placed in request headers
  • query: Parameter will be placed in URL query string
  • path: Parameter will be placed in URL path
  • body: Parameter will be placed in JSON format request body
  • form-data: Parameter will be placed in multipart/form-data format request body, for file upload scenarios

Parameter type (type) supports the following types:

  • string: String type
  • number: Number type
  • boolean: Boolean type
  • array: Array type, needs to be used with items to define array element types
  • object: Object type, can use properties to define object structure

For complex array type parameters, detailed element structures can be defined:

- 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: "[]"

When using form-data as parameter position, no need to specify requestBody, the system will automatically assemble parameters into multipart/form-data format.

For JSON format request body, assembly is needed in requestBody, for example:

    requestBody: |-
      {
        "isPublic": {{.Args.isPublic}},
        "showEmail": {{.Args.showEmail}},
        "theme": "{{.Args.theme}}",
        "tags": {{.Args.tags}}
      }

Including endpoint (target address) can also use the above sources to extract values, such as http://localhost:5236/users/{{.Args.email}}/preferences which extracts values from request parameters.

5.2 Response Parameter Assembly

Response body assembly is similar to request body assembly:

  1. .Response.Data: Values extracted from response, response must be in JSON format to be extractable
  2. .Response.Body: Directly pass through the entire response body, ignoring response content format and directly passing to client

Both extract values via .Response, for example:

    responseBody: |-
      {
        "id": "{{.Response.Data.id}}",
        "username": "{{.Response.Data.username}}",
        "email": "{{.Response.Data.email}}",
        "createdAt": "{{.Response.Data.createdAt}}"
      }

Configuration Storage

Gateway proxy configuration can be stored in the following two ways:

Database Storage (Recommended)

  • Supports SQLite3, PostgreSQL, MySQL
  • Each configuration stored as a record
  • Supports dynamic updates and hot reloading

File Storage

  • Each configuration stored separately as a YAML file
  • Similar to Nginx vhost configuration method
  • File name recommended to use service name, such as mock-server.yaml

MCP Service Proxy Configuration

In addition to proxying HTTP services, MCP Gateway also supports proxying MCP services. Currently, stdio, SSE, and streamable-http three transport protocols are all supported.

Configuration Example

The following is a complete MCP service proxy configuration example:

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"

Configuration Explanation

1. MCP Service Types

MCP Gateway supports the following three types of MCP service proxies:

2. stdio Type Configuration

stdio type MCP service configuration example:

mcpServers:
  - type: "stdio"
    name: "amap-maps"                                   # Service name
    command: "npx"                                      # Command to execute
    args:                                               # Command arguments
      - "-y"
      - "@amap/amap-maps-mcp-server"
    env:                                                # Environment variables
      AMAP_MAPS_API_KEY: "{{.Request.Headers.Apikey}}"  # Extract value from request headers

Environment variables can be set via the env field, supporting value extraction from requests, for example {{.Request.Headers.Apikey}} means extract the Apikey value from request headers.

3. SSE Type Configuration

SSE type MCP service configuration example:

mcpServers:
  - type: "sse"
    name: "mock-user-sse"                           # Service name
    url: "http://localhost:3000/gateway/user/sse"   # Upstream SSE service address, usually ends with /sse, actual depends on upstream service

4. streamable-http Type Configuration

streamable-http type MCP service configuration example:

mcpServers:
  - type: "streamable-http"
    name: "mock-user-mcp"                           # Service name
    url: "http://localhost:3000/gateway/user/mcp"   # Upstream MCP service address, usually ends with /mcp, actual depends on upstream service

5. Routing Configuration

For MCP service proxy, routing configuration is similar to HTTP service proxy. CORS should be configured according to actual situation (usually production environments generally do not enable cross-origin):

routers:
  - server: "amap-maps"               # Service name, must match name in mcpServers
    prefix: "/gateway/stdio-proxy"    # Route prefix, globally unique
    cors:
      allowOrigins:
        - "*"
      allowMethods:
        - "GET"
        - "POST"
        - "OPTIONS"
      allowHeaders:
        - "Content-Type"
        - "Authorization"
        - "Mcp-Session-Id"        # MCP service must include this header
      exposeHeaders:
        - "Mcp-Session-Id"        # MCP service must expose this header
      allowCredentials: true

For MCP services, Mcp-Session-Id in request and response headers must be supported, otherwise clients cannot use it normally.

Advanced Configuration

Notifier Configuration

Notifier is used to configure reload notifications, supporting multiple methods:

Environment Variable Injection

Environment variables can be used in configuration, supporting default values:

# Basic syntax
port: ${MCP_GATEWAY_PORT:5235}  # Use environment variable, default value 5235

# String format
logger:
  level: "${LOGGER_LEVEL:info}"  # Use environment variable, default value info

# Use in service configuration
config:
  ApiKey: '{{ env "API_KEY" }}'
  BaseUrl: '{{ env "API_BASE_URL" "http://localhost:8080" }}'  # With default value

Template Functions

In request and response body templates, template functions can be used to handle complex data:

Using the toJSON function ensures complex objects and arrays are correctly serialized to JSON format, especially suitable for nested structures and data containing special characters.

Complex Parameter Processing Example

The following is a complete example of handling complex parameters, showing how to define and use object and array type parameters:

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 }}
  }

File Upload Processing

Supports file upload scenarios:

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"

Best Practices

Configuration Validation

Before applying configuration, it is recommended to perform the following validations:

1

Syntax Check

Ensure YAML syntax is correct with no indentation errors

2

Environment Variable Verification

Check if all required environment variables are set

3

Storage Connection Test

Verify database or Redis connection configuration is correct

4

Reference Verification

Check if all reference relationships are correct, such as server name matching

5

Template Verification

Verify Go Template syntax and variable references

6

Endpoint Testing

Ensure all endpoints are accessible

7

Permission Verification

Ensure PID file path has write permissions

For more information on Go Template usage, please refer to Template Usage Guide.