Skip to main content

Hot Reload

Open MCP Gateway supports hot reload of the server catalog without restarting the gateway.

How It Works

catalog.yaml modified

File watcher detects change

500ms debounce (handles rapid saves)

Parse and validate new catalog

Atomic registry swap

New servers available immediately

Automatic Reload

Hot reload is enabled by default. When you save changes to catalog.yaml:

  1. The file watcher detects the modification
  2. After a 500ms debounce period, the new catalog is loaded
  3. The server registry is atomically updated
  4. Changes are immediately available

Example log output:

INFO catalog_watcher: Catalog file changed, scheduling reload...
INFO catalog_watcher: Reloading catalog from: /path/to/catalog.yaml
INFO catalog_watcher: Loaded 5 servers (added: 1, removed: 0, modified: 1, unchanged: 3)

Manual Reload

Trigger a reload via the admin API:

curl -X POST http://localhost:4444/admin/reload

Response:

{
"status": "ok",
"message": "Catalog reloaded",
"servers_loaded": 5
}

This is useful when:

  • File watcher is not detecting changes
  • You want to force a reload
  • Automated deployment scripts need to trigger reload

What Happens During Reload

New Servers

  • Immediately available in the registry
  • Start on first request (on-demand)
  • No impact on existing servers

Modified Servers

  • Configuration change detected by ID
  • Running servers continue with old config
  • New config takes effect on next restart
  • Use stop/start to apply changes to running servers
# Apply changes to a modified running server
curl -X POST http://localhost:4444/servers/postgres/stop
curl -X POST http://localhost:4444/servers/postgres/start

Removed Servers

  • Gracefully stopped if running
  • Removed from registry
  • Existing connections completed before shutdown
  • Subsequent requests return "not found"

Unchanged Servers

  • No impact whatsoever
  • Running servers continue running
  • Connections maintained

Debouncing

The file watcher uses a 500ms debounce to handle:

  • Multiple rapid saves (IDE auto-save)
  • Partial writes during file sync
  • Network file system delays

During the debounce period:

  • Additional changes reset the timer
  • Only the final state is loaded
  • No intermediate states are applied

Error Handling

Invalid YAML

If the new catalog has syntax errors:

ERROR catalog_watcher: Failed to parse catalog: expected ':' at line 5
WARN catalog_watcher: Keeping previous catalog due to parse error

The existing configuration continues to work.

Missing Required Fields

ERROR catalog_watcher: Server at index 2 missing required field: runtime
WARN catalog_watcher: Keeping previous catalog due to validation error

Unknown Runtime Type

ERROR catalog_watcher: Server 'my-server' has unknown runtime type: unknown
WARN catalog_watcher: Keeping previous catalog due to validation error

Best Practices

1. Validate Before Deploy

# Validate catalog syntax
gateway-http --config config.yaml --validate

# Or use a YAML linter
yamllint catalog.yaml

2. Use Version Control

# Track changes to catalog
git add catalog.yaml
git commit -m "Add new postgres server"
git push

3. Staged Rollouts

# catalog.yaml - add one server at a time
servers:
- id: existing-server
# ... existing config

# New server - add and save
- id: new-server
runtime:
type: local-process
command: new-mcp

4. Monitor Reload Events

Watch the gateway logs during changes:

# Terminal 1: Watch logs
RUST_LOG=info gateway-http --config config.yaml

# Terminal 2: Edit catalog
vim catalog.yaml

5. Automate with CI/CD

# .github/workflows/deploy-catalog.yml
- name: Update catalog
run: |
scp catalog.yaml server:/etc/mcp-gateway/
curl -X POST http://server:4444/admin/reload

Monitoring Reload Status

Gateway Stats

Check when the last reload occurred:

curl http://localhost:4444/stats | jq '.last_reload'

Server Count

Verify expected number of servers:

curl http://localhost:4444/servers | jq 'length'

Specific Server

Check if a specific server was loaded:

curl http://localhost:4444/servers/new-server

Disabling Hot Reload

If you need to disable automatic hot reload:

# config.yaml
catalog_path: "catalog.yaml"
hot_reload: false # Disable file watching

With hot reload disabled:

  • Changes require gateway restart
  • Manual reload via API still works
  • File watcher is not started

Troubleshooting

Changes Not Detected

  1. Check file permissions
  2. Ensure catalog path is correct
  3. Try manual reload: POST /admin/reload
  4. Check for file system event limitations (NFS, Docker volumes)

Reload Failing Silently

Enable debug logging:

RUST_LOG=debug gateway-http --config config.yaml

Container/Docker Issues

If using Docker with mounted volumes:

# docker-compose.yml
volumes:
- ./catalog.yaml:/app/catalog.yaml:ro

# Note: Some Docker setups don't propagate file events
# Use manual reload via API in these cases