This page provides a complete reference for configuring Model Context Protocol (MCP) servers in Nexus. All MCP servers are configured in the [mcp.servers]
section of your nexus.toml
file.
[mcp]
enabled = true # Enable/disable MCP functionality (default: true)
path = "/mcp" # Endpoint path for MCP connections (default: "/mcp")
enabled
: Enable/disable MCP functionality (default:true
)path
: The endpoint path for MCP (default:"/mcp"
)
HTTP-based MCP servers implementing the latest protocol.
[mcp.servers.example]
protocol = "streamable-http" # Optional - auto-detected for HTTP URLs
url = "https://api.example.com/mcp"
# Optional authentication
[mcp.servers.example.auth]
token = "{{ env.API_TOKEN }}"
# Optional TLS configuration
[mcp.servers.example.tls]
verify_certs = true
Local processes that communicate via standard input/output.
[mcp.servers.local_tool]
cmd = ["executable", "arg1", "arg2"] # Command array (required)
env = { KEY = "value" } # Environment variables (optional)
cwd = "/path/to/directory" # Working directory (optional)
stderr = "null" # Error handling (optional)
cmd
: Command array with executable and arguments (required)env
: Environment variables to set (optional, default:{}
)cwd
: Working directory for the subprocess (optional, default: current directory)stderr
: Where to send stderr output (optional, default:"null"
)"null"
: Discard stderr output"inherit"
: Show in console{ file = "/path/to/log" }
: Write to file
Server-Sent Events protocol. Use Streamable HTTP instead in the backstream if you can.
[mcp.servers.legacy]
protocol = "sse"
url = "https://api.example.com/sse"
message_url = "https://api.example.com/messages" # Optional
[mcp.servers.api]
url = "https://api.example.com/mcp"
[mcp.servers.api.auth]
token = "bearer_token_here"
# Or use environment variables
token = "{{ env.API_TOKEN }}"
Forward the incoming OAuth2 token to downstream servers:
[mcp.servers.internal]
url = "https://internal.company.com/mcp"
[mcp.servers.internal.auth]
type = "forward"
Requirements:
- OAuth2 must be enabled on the Nexus server
- Downstream server must accept the same OAuth2 tokens
- Both must use the same authorization server
[mcp.servers.secure]
url = "https://api.secure.com/mcp"
[mcp.servers.secure.tls]
verify_certs = true # Verify server certificates
accept_invalid_hostnames = false # Reject hostname mismatches
root_ca_cert_path = "/etc/ssl/certs/ca.pem" # Custom CA certificate
# Client certificates for mutual TLS
client_cert_path = "/etc/ssl/certs/client.pem"
client_key_path = "/etc/ssl/private/client.key"
verify_certs
: Whether to verify server certificates (default:true
)accept_invalid_hostnames
: Accept certificates with hostname mismatches (default:false
)root_ca_cert_path
: Path to custom root CA certificate (optional, default: system CA)client_cert_path
: Path to client certificate for mTLS (optional)client_key_path
: Path to client private key for mTLS (optional)
Use {{ env.VARIABLE_NAME }}
for environment variable substitution:
[mcp.servers.database]
cmd = ["psql-mcp"]
env = {
PGHOST = "{{ env.DB_HOST }}",
PGUSER = "{{ env.DB_USER }}",
PGPASSWORD = "{{ env.DB_PASSWORD }}",
PGDATABASE = "{{ env.DB_NAME }}"
}
cwd = "{{ env.HOME }}/workspace"
[mcp.servers.api]
url = "{{ env.API_URL }}"
[mcp.servers.api.auth]
token = "{{ env.API_TOKEN }}"
[mcp.servers.filesystem]
cmd = ["npx", "-y", "@modelcontextprotocol/server-filesystem", "/home/user/documents"]
[mcp.servers.python_tools]
cmd = ["python", "-m", "my_mcp_server"]
env = {
PYTHONPATH = "/opt/mcp/modules",
PYTHONUNBUFFERED = "1"
}
cwd = "/workspace"
stderr = "inherit" # See errors during development
[mcp.servers.node_analyzer]
cmd = ["/opt/node/bin/node", "dist/server.js"]
env = {
NODE_ENV = "production",
NODE_PATH = "/opt/node/lib/node_modules"
}
cwd = "/opt/mcp/analyzer"
[mcp.servers.github]
url = "https://api.github.com/mcp"
[mcp.servers.github.auth]
token = "{{ env.GITHUB_TOKEN }}"
[mcp.servers.company_api]
url = "https://api.internal.company.com/mcp"
[mcp.servers.company_api.auth]
type = "forward"
[mcp.servers.company_api.tls]
verify_certs = true
root_ca_cert_path = "/etc/ssl/company-ca.pem"
[mcp.servers.postgres]
cmd = ["python", "-m", "mcp_postgres"]
env = {
PGHOST = "{{ env.DB_HOST }}",
PGPORT = "{{ env.DB_PORT }}",
PGUSER = "{{ env.DB_USER }}",
PGPASSWORD = "{{ env.DB_PASSWORD }}",
PGDATABASE = "{{ env.DB_NAME }}"
}
Nexus optimizes performance through connection caching for downstream MCP servers. This cache significantly reduces latency and resource usage by reusing established connections.
[mcp.downstream_cache]
max_size = 1000 # Max cached connections for auth forwarding (default: 1000)
idle_timeout = "10m" # Connection idle timeout (default: 600s or 10 minutes)
max_size
: Maximum number of cached downstream connections (default:1000
)- Only applies to servers with
auth.type = "forward"
- Each entry represents connections for a unique OAuth2 token
- Only applies to servers with
idle_timeout
: How long connections stay cached when idle (default:"600s"
or 10 minutes)- Connections are automatically evicted after this timeout
- Only affects dynamic connections; static connections persist until shutdown
Static Connections (initialized once at startup):
- Servers with no authentication
- Servers with static token authentication (
token = "..."
) - All STDIO servers
- Shared across all requests
Dynamic Connections (cached per OAuth2 token):
- Only servers with
auth.type = "forward"
- Cached using SHA-256 hash of the token
- Created on-demand when a new token is seen
- Automatically evicted after idle timeout
- Each cache entry includes connections to all dynamic servers for that token
Development Environment:
max_size
: 100-500 (sufficient for local testing)idle_timeout
: "5m" to "10m" (quick iteration)
Production Environment:
max_size
: Based on concurrent usersidle_timeout
: "20m" to "60m" (match typical session duration)
Monitor these metrics to optimize cache configuration:
- Cache hit rate (should be >80% in production)
- Eviction rate (high rate indicates
max_size
too small) - Connection creation time (spikes indicate cache misses)
- Memory usage per connection
In addition to server-level rate limiting, Nexus supports fine-grained rate limits for individual MCP servers and their tools. This allows you to protect expensive operations while maintaining high throughput for lightweight queries.
Configure rate limits for individual MCP servers:
[mcp.servers.my_api]
url = "https://api.example.com/mcp"
[mcp.servers.my_api.rate_limits]
limit = 50
interval = "60s"
For even finer control, set rate limits on individual tools within an MCP server:
[mcp.servers.my_api.rate_limits.tools]
expensive_operation = { limit = 10, interval = "60s" }
bulk_process = { limit = 5, interval = "300s" }
standard_query = { limit = 100, interval = "60s" }
Rate limits are evaluated in the following order (most to least restrictive):
- Tool-specific limits
- MCP server limits
- Per-IP limits (configured at server level)
- Global limits (configured at server level)
All applicable limits are enforced - a request must pass all rate limit checks to succeed.
- Start Conservative: Begin with lower limits and increase based on actual usage patterns
- Monitor Tool Usage: Track which tools are called most frequently to optimize limits
- Consider Operation Cost: Set stricter limits for resource-intensive operations
- Use Different Intervals: Shorter windows for lightweight ops, longer for expensive ones
- Test Rate Limits: Verify limits work as expected before production deployment
For server-level rate limiting configuration and Redis setup details, see the server configuration documentation.
# Test STDIO command directly
$ /path/to/executable arg1 arg2
# Check environment variables
$ echo $GITHUB_TOKEN
# Test HTTP connectivity
$ curl -I https://api.example.com/mcp
# Run Nexus with debug logs
$ nexus --log debug
-
Security
- Always use environment variables for secrets
- Enable TLS verification in production
- Use token forwarding only with trusted servers
- Rotate API keys regularly
-
Performance
- Set appropriate cache sizes based on load
- Use
stderr = "null"
in production - Monitor downstream server response times
- Keep number of tools per server reasonable
- Use the info level logs instead of debug, or trace
-
Operations
- Test servers individually before adding to Nexus
- Use descriptive server names
- Document each server's purpose
- Implement health checks for critical servers
-
Configuration Management
- Use separate configs for dev/staging/production
- Version control configurations (without secrets)
- Use config validation before deployment