Skip to main content
Local configuration defines the full runtime behavior of the gateway: which ports to listen on, how to route traffic, which backends to proxy to, and what policies to apply. It lives in the same YAML or JSON file as static configuration, alongside or below the config key. The gateway watches the config file for changes. When you save an update, it reloads local configuration automatically — no restart required.

File structure

A complete config file has two top-level sections:
  • config — static global settings (optional; see static config)
  • binds — array of port bindings with listeners, routes, and backends
# Global static settings (optional)
config:
  logging:
    level: info
    format: json

# Runtime configuration
binds:
  - port: 3000
    listeners:
      - routes:
          - backends:
              - mcp:
                  targets:
                    - name: my-server
                      stdio:
                        cmd: npx
                        args: ["@modelcontextprotocol/server-everything"]

YAML vs JSON

Both formats are supported. Use YAML for human-authored configs — it supports comments and is less verbose. Use JSON when generating configs programmatically.
binds:
  - port: 3000
    listeners:
      - name: default
        protocol: HTTPS
        tls:
          cert: certs/cert.pem
          key: certs/key.pem
        routes:
          - backends:
              - host: localhost:8080

Top-level structure

binds
object[]
Array of port bindings. Each bind defines a port and the listeners attached to it.

Binds and listeners

A bind opens a TCP port. Each bind can have one or more listeners that match traffic by hostname and protocol. Each listener defines a set of routes that map requests to backends.
binds
└── port: 3000
    └── listeners
        └── hostname: "*.example.com", protocol: HTTPS
            └── routes
                └── path: /api → backend: api-server
                └── path: /mcp → backend: mcp-server

Listener fields

binds[].listeners[].name
string
Optional name for the listener. Used for identification in logs and metrics.
binds[].listeners[].namespace
string
Namespace for the listener resource. Used in multi-tenant and Kubernetes deployments.
binds[].listeners[].hostname
string
Hostname this listener matches. Supports wildcards, for example *.example.com. When not set, the listener matches all hostnames on the port.
binds[].listeners[].protocol
string
Protocol for this listener. Accepted values: HTTP, HTTPS. When using HTTPS, provide a tls block.
binds[].listeners[].tls
object
TLS configuration. Required when protocol is HTTPS.
binds[].listeners[].routes
object[]
Array of routes for this listener. Routes are evaluated in order; the first match wins.See Routes reference →

Routes

A route matches incoming requests and forwards them to one or more backends. Routes support matching on path, headers, method, and query parameters.
routes:
  - name: mcp-route
    matches:
      - path:
          pathPrefix: /mcp
    policies:
      cors:
        allowOrigins:
          - "*"
        allowHeaders:
          - content-type
    backends:
      - mcp:
          targets:
            - name: my-server
              stdio:
                cmd: npx
                args: ["@modelcontextprotocol/server-everything"]
See the Routes reference for full match and policy options.

Backends

Backends define where traffic is sent. The local config supports several backend types:
Routes traffic to one or more MCP servers. Each server is defined as a target with a name and transport (stdio or SSE).
backends:
  - mcp:
      targets:
        - name: filesystem
          stdio:
            cmd: npx
            args: ["@modelcontextprotocol/server-filesystem", "/data"]
        - name: github
          sse:
            host: https://mcp.github.com
Route to a plain HTTP upstream using a host shorthand. The gateway resolves this into a full backend definition.
backends:
  - host: localhost:9999
Route A2A agent traffic. Mark the route with a2a: {} to enable A2A processing and telemetry.
routes:
  - policies:
      a2a: {}
    backends:
      - host: localhost:9999
See the Backends reference for the full backend schema.

Hot reload behavior

Agentgateway uses filesystem watching to detect config file changes. When the file is saved:
  1. The new configuration is parsed and validated.
  2. If validation passes, the runtime configuration is updated atomically.
  3. Existing in-flight requests complete against the old configuration.
  4. New requests use the updated configuration immediately.
If the updated file contains a syntax error or invalid field, the gateway logs an error and continues running with the previous configuration.
Static configuration fields (under config) are not reloaded on file change. Only binds, listeners, routes, backends, and policies are hot-reloaded.

Complete examples

A minimal MCP proxy with CORS enabled for browser-based clients:
# yaml-language-server: $schema=https://agentgateway.dev/schema/config
binds:
  - port: 3000
    listeners:
      - routes:
          - policies:
              cors:
                allowOrigins:
                  - "*"
                allowHeaders:
                  - mcp-protocol-version
                  - content-type
                  - cache-control
                exposeHeaders:
                  - "Mcp-Session-Id"
            backends:
              - mcp:
                  targets:
                    - name: everything
                      stdio:
                        cmd: npx
                        args: ["@modelcontextprotocol/server-everything"]

Mapping to internal representation

Local configuration translates into an internal representation (IR) shared with XDS. Most fields map directly, but some are transformed for ergonomics:
Local config fieldIR behavior
host: localhost:9999Expanded into a full backend definition with hostname and port
mcp.targets[].sse.hostResolved to a backend + TLS configuration based on the URL scheme
tls.cert / tls.keyFile paths are read at load time and stored as PEM bytes in the IR
Route policiesMerged and applied at runtime; precedence handled by the proxy, not the control plane
This translation layer means you can use convenient shorthands in local config that would not be valid in XDS, which expects fully resolved values.