A flexible and extensible proxy gateway for MCP (Model Context Protocol) servers, providing enterprise-grade middleware capabilities including authentication, authorization, rate limiting, and observability.
- Multiple Auth Providers: Okta OAuth2/JWT
- Role-Based Permissions: Fine-grained tool access control
- attribute-to-Role Mapping: Flexible user permission assignment
- JWT Token Verification: Secure token validation
- Multiple Storage Backends: Memory (dev), PostgreSQL
- RESTful Admin API: Dynamic configuration management
- Prometheus Metrics: Built-in observability
- Structured Logging: JSON and text output formats
- Health Endpoints: Container orchestration support
- YAML Configuration: Environment variable substitution
- CLI Flags: Override any configuration option
- Hot Configuration: Runtime proxy/role management via API
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ β AI Client βββββΆβ MCP Gateway βββββΆβ MCP Server β β (Claude, etc.) β β β β (n8n, etc.) β βββββββββββββββββββ β βββββββββββββ β βββββββββββββββββββ β β β β β βOkta Auth β β βββββββββββββββββββ β β Roles β βββββΆβ Another Server β β β Metrics β β βββββββββββββββββββ β βββββββββββββ β βββββββββββββββββββ
# Clone and run without authentication git clone https://github.com/matthisholleville/mcp-gateway.git cd mcp-gateway # Run without authentication go run main.go serve \ --log-format=text \ --log-level=debug
# Pull the latest image docker pull ghcr.io/matthisholleville/mcp-gateway:latest # Run with environment variables docker run -p 8082:8082 \ ghcr.io/matthisholleville/mcp-gateway:latest serve
# Start PostgreSQL docker-compose up -d postgres # Run migrations go run main.go migrate up \ --backend-engine=postgres \ --backend-uri='postgresql://mcp-gateway:changeme@localhost:5439/mcp-gateway?sslmode=disable' # Start server with PostgreSQL backend go run main.go serve \ --log-format=text \ --log-level=debug \ --backend-engine=postgres \ --backend-uri='postgresql://mcp-gateway:changeme@localhost:5439/mcp-gateway?sslmode=disable' \ --backend-encryption-key=0123456789abcdeffedcba9876543210cafebabefacefeeddeadbeef00112233
helm repo add mcp-gateway https://matthisholleville.github.io/mcp-gateway helm install mcp-gateway mcp-gateway/mcp-gateway
- CLI Flags (highest priority)
- Environment Variables (
MCP_GATEWAY_*
) - YAML Configuration File (
config/config.yaml
) - Default Values (lowest priority)
# config/config.yaml server: url: "http://localhost:8082" # Authentication authProvider: enabled: true name: "okta" okta: issuer: "https://custom-xxx.okta.com/oauth2/default" orgUrl: "https://custom-xxx.okta.com" clientId: "xxx" privateKey: "-----BEGIN PRIVATE KEY-----xxx-----END PRIVATE KEY-----" privateKeyId: "xxx" oauth: enabled: true provider: "okta" authorizationServers: - "https://custom-xxx.okta.com/oauth2/default" bearerMethodsSupported: ["Bearer"] scopesSupported: ["openid", "email", "profile"] # Storage backend backendConfig: engine: "memory" # "postgres" coming soon # uri: "postgres://user:pass@localhost/mcp_gateway" # Proxy configuration proxy: cacheTTL: 300s heartbeat: enabled: true intervalSeconds: 10s
All configuration options can be set via environment variables with MCP_GATEWAY_
prefix:
export MCP_GATEWAY_AUTH_PROVIDER_ENABLED=true export MCP_GATEWAY_OAUTH_ENABLED=true
go run main.go serve \ --auth-provider-name=okta \ --okta-issuer=https://your-domain.okta.com/oauth2/default \ --okta-org-url=https://your-domain.okta.com \ --okta-client-id=your-client-id --okta-private-key="-----BEGIN RSA PRIVATE KEY-----\n..." --okta-private-key-id="akXpH7Ha5VKCe2kNT3eCPn_YRaJ0..."
- Usage: Development and testing
- Persistence: None (data lost on restart)
- Configuration:
--backend-engine=memory
- Usage: Production environments
- Persistence: Full durability
- Configuration:
--backend-engine=postgres --backend-uri=postgres://...
You can update the admin API Key with --http-admin-api-key
flag
The gateway provides RESTful APIs for runtime configuration management:
Swagger is available at http://localhost:8082/swagger/index.html
# List all proxies curl -H "X-API-Key: your-api-key" http://localhost:8082/v1/admin/proxies # Add/Update proxy curl -X PUT -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"name":"n8n","type":"streamable-http","connection":{"url":"http://n8n:5678"}}' \ http://localhost:8082/v1/admin/proxies/n8n
objectType
can be*
ortools
objectName
is the tool name ifobjectType
istools
. Can be*
or your object nameproxy
is the proxy name. Can be*
or your proxy name
# Create role curl -X PUT -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"name":"admin","permissions":[{"objectType":"*","proxy":"*","objectName":"*"}]}' \ http://localhost:8082/v1/admin/roles
attributeKey
is the key in your JWTattributes
attributeValue
is the attribute valueroles
is the list of roles. You must create the roles before creating the attribute-to-role mapping
# Map user attributes to roles curl -X PUT -H "X-API-Key: your-api-key" \ -H "Content-Type: application/json" \ -d '{"attributeKey":"groups","attributeValue":"admins","roles":["admin"]}' \ http://localhost:8082/v1/admin/attribute-to-roles
Endpoint | Method | Description |
---|---|---|
/mcp | POST | MCP protocol endpoint |
/live | GET | Liveness probe |
/ready | GET | Readiness probe |
/metrics | GET | Prometheus metrics |
/swagger/* | GET | API Documentation |
/v1/admin/proxies | GET, PUT, DELETE | Proxy management |
/v1/admin/roles | GET, PUT, DELETE | Role management |
/v1/admin/attribute-to-roles | GET, PUT, DELETE | attribute mapping |
- Go 1.24.3+
- Docker (optional)
- Make
# Install dependencies make deps # Run in development make dev # Build binary make build # Run tests make test # Generate coverage make test-cover # Build Docker image make docker-build
The gateway searches for config.yaml
in:
/etc/mcp-gateway/
$HOME/.mcp-gateway/
./config/
--log-format # text, json --log-level # debug, info, warn, error --log-timestamp-format # Format for logging timestamps --auth-provider-enabled # Enable authentication --auth-provider-name # okta --oauth-enabled # Enable OAuth2 --backend-engine # memory, postgres --http-addr # Server address (default: :8082) --http-admin-api-key # Admin API key for MCP Gateway configuration
--proxy-cache-ttl # TTL for the proxy cache --proxy-heartbeat-interval # Interval for the proxy heartbeat
--backend-uri # URI for the auth backend --backend-username # The username to use for the auth backend. It will override the username in the URI if provided. --backend-password # The password to use for the auth backend. It will override the password in the URI if provided. --backend-max-open-conns # Maximum number of open database connections --backend-max-idle-conns # Maximum number of idle connections in pool --backend-conn-max-idle-time # Maximum time a connection may be idle --backend-conn-max-lifetime # Maximum time a connection may be reused
--oauth-authorization-servers # OAuth authorization servers --oauth-resource # OAuth resource (e.g. http://localhost:8082) --oauth-bearer-methods-supported # Bearer methods supported for OAuth --oauth-scopes-supported # OAuth scopes supported (e.g. openid,email,profile)
--okta-issuer # Okta authorization server --okta-org-url # Okta organization URL --okta-client-id # Okta client ID --okta-private-key # Private key for client auth --okta-private-key-id # Private key ID
We welcome contributions! Please see CONTRIBUTING.md for guidelines.
Licensed under the Apache License 2.0 - see LICENSE for details.
Made with β€οΈ by Matthis Holleville