Nexus API Balancer is a high-performance proxy server and intelligent key balancer for various AI providers built on Rust. The system provides a Dynamic Model Registry (automatic model discovery via /models endpoints of providers), context caching capabilities, detailed latency logging, dynamic load balancing, and client isolation.
graph TD
Client[AI Client / Cline / Roo Code] -- OAuth 2.1 Bearer --> API[Axum REST/MCP API]
Admin[Administrator] -- X-Admin-Key --> API
API -- Authorization check --> DB[(SQLite DB)]
API -- KV cache check --> DB
API -- Model routing --> Registry[Model Registry]
subgraph "Dynamic Model Discovery"
Registry -- in-memory cache --> Cache[model → pool mapping]
Registry -- periodic sync (6h) --> ProviderAPI["/models endpoints of providers"]
ProviderAPI -- OpenAI-compat / Gemini format --> Registry
Registry -- model upsert --> DB
end
API -- Key acquisition --> Pool[Key Pool]
Pool -- Load from storage --> Storage[Isolated Storage]
API -- v1beta conversion --> Provider[Gemini / OpenAI / Anthropic / Groq / Mistral / Cerebras / SambaNova / DeepSeek / Cohere / xAI]
API -- Latency logging --> Log[Console/DB]
- High Concurrency: Efficient async request pool management using
tokioandasync-channel. - Dynamic Model Registry: Automatic discovery of available models via provider
/modelsendpoints on startup and every 6 hours. Models are stored in SQLite with an in-memory cache for fast O(1) lookup. - Priority-based routing: Pool priority (
priorityin config) determines which provider receives a request when a model is available from multiple providers. - Capability-aware routing: Pools can declare capabilities such as
chatandstt. Existing configs default tochat. - STT failover: Multipart
/v1/audio/transcriptionsand/v1/audio/translationsrequests can move to the next eligible provider after 429, 5xx, timeout, or transport failure. - Unified Routing Gateway: Automatic request routing to the appropriate providers based on the dynamic model registry (with fallback to prefix-based heuristics).
- Multi-Provider Support: Built-in support for OpenAI, Google Gemini, Anthropic Claude, Groq, Mistral, Cerebras, Cohere, DeepSeek, xAI (Grok), and SambaNova.
- Aggregated
/v1/modelsEndpoint: OpenAI-compatible endpoint returning all models available to the client from the registry. - Intelligent KV Cache: Context cache management per pool with automatic endpoint transformation (e.g., for Google Gemini v1beta).
- Multi-Key Secrets: Ability to load multiple API keys from a single file (one key per line) with automatic unique identifier generation and rotation.
- Client Isolation: Secure key separation and client access restriction to assigned pools.
- CORS Protection: Configurable CORS policy via
cors_allowed_originconfig orCORS_ALLOWED_ORIGINenv var (default:http://localhost:3317). - MCP Protocol Support: Full Model Context Protocol integration for dynamic pool discovery and administration.
- Interactive Documentation: Built-in interactive API specification via Scalar at
/scalar.
Create configuration and environment files from templates, along with a directory for storing secrets:
cp .env.example .env
cp config.yaml.example config.yaml
mkdir -p secretsConfigure parameters in the .env file (e.g., admin secrets, ports, and database connection settings).
The config.yaml file defines the pool structure and request distribution rules. Each pool is tied to a specific provider.
Example pool structure with Model Registry fields:
pools:
- name: "openai-pool"
description: "Main pool for requests to OpenAI-compatible APIs"
provider: "openai"
target_url: "https://api.openai.com"
capacity: 20
capabilities: ["chat"] # e.g. ["chat"], ["stt"], or ["chat", "stt"]
priority: 10 # Pool priority (higher = preferred when models conflict)
models_endpoint: "/models" # Custom endpoint for model discovery (optional)
skip_model_sync: false # Disable auto-discovery for this pool
keys:
- id: "OPENAI_KEY_GROUP"
secret_name: "openai_keys.txt" # Filename inside the secrets/ directory
secret_type: "api_key"
concurrency: 5 # Maximum concurrent requests per key
rps_limit: 10 # Requests per second limit (RPS)
tpm_limit: 60000 # Tokens per minute limit (TPM)
max_request_tokens: 16000 # Maximum context size limit per request
cooldown_on_limit: true # Send key to cooldown when limits are exceededModel Registry Fields:
priority— integer. When models conflict (the same model available from multiple providers), the request is routed to the pool with the highestpriority.models_endpoint— optional path to the provider's model list endpoint. Defaults to/models. For Google Gemini —/models(parsed separately).skip_model_sync— iftrue, the pool is excluded from model auto-discovery on startup and periodic sync.
Keys are stored in isolated text files within the secrets/ directory. The balancer supports both single keys and key lists.
To add multiple keys for a pool (e.g., for openai-pool with secret_name: "openai_keys.txt"):
- Create the file
secrets/openai_keys.txt. - Enter your API keys, separated by newlines:
sk-proj-11111111111111111111
sk-proj-22222222222222222222
sk-proj-33333333333333333333
The balancer automatically reads all keys from the file, registers them under unique names (OPENAI_KEY_GROUP#1, OPENAI_KEY_GROUP#2, etc.), and evenly distributes and rotates requests among them.
Run the project using Cargo:
cargo runThe balancer will start an HTTP server on the host and port specified in config.yaml (default http://0.0.0.0:3317).
The balancer provides a Unified Gateway at http://localhost:3317/v1/chat/completions, fully compatible with the OpenAI API standard. The balancer automatically parses the model field in the request and routes it to the appropriate provider pool.
Authorization uses a client token (JWT) generated during client registration, or a master token from the configuration.
To integrate the balancer into VS Code extensions (e.g., Cline or Roo Code), follow these steps:
- Open the model provider settings in the extension.
- Select provider: OpenAI Compatible.
- Specify connection parameters:
- Base URL (API URL):
http://localhost:3317 - API Key: Paste your client token (JWT) or master key (e.g.,
nexus-master-key-2026). - Model ID: Enter the desired model name.
- Base URL (API URL):
- Click the connect/save button.
Method 1: OpenAI Compatible (default)
-
Open the OpenCode extension settings.
-
Set the following values in configuration:
- Endpoint URL:
http://localhost:3317 - Authorization token (API Key):
<your JWT client token>
- Endpoint URL:
-
Select or specify a model. The balancer will automatically route based on the dynamic model registry:
Automatic Routing: The model is resolved through the Dynamic Model Registry — on startup and every 6 hours, the balancer queries the
/modelsendpoints of all providers and builds amodel → poolmapping. If the model is found in the registry, the request is routed to the pool with the highestpriority. If the model is not found, a prefix-based fallback is used.Explicit Provider (
//provider//model): You can force a specific provider in the model name://cerebras//llama-3.1-8b— route to Cerebras//groq//llama-3.1-8b— route to Groq//sambanova//llama-3.1-8b— route to SambaNova//openai//gpt-4o— route to OpenAI
Aggregated
/v1/modelsEndpoint: Allows clients to retrieve a list of all available models:curl http://localhost:3317/v1/models -H "Authorization: Bearer <token>"
Method 2: Custom Provider In the "Custom Provider" section, you can configure direct endpoint access.
- Enable the option: Use custom API URL.
- In the Custom API URL field, enter:
http://localhost:3317/v1/chat/completions - Enable the option: Pass API key in custom call headers.
- In the Custom call API key header name field, enter:
Authorization - In the Custom call API key field, enter the token with the Bearer prefix:
Bearer <your JWT client token>
Since Nexus Balancer primarily runs in Docker and exposes MCP as an HTTP endpoint at /mcp, to connect local clients expecting standard stdio MCP (such as Roo Code, OpenCode, LM Studio, or Cline), you need to use the built-in bridge adapter.
The nexus_balancer binary itself can operate in adapter mode, translating stdio requests from the local machine into HTTP POST requests to the balancer (running in Docker or on a remote host).
Make sure to set the correct server URL and authorization key via environment variables. By default, the adapter connects to http://localhost:3317/mcp.
Add the following block to the mcp.json file (usually located at ~/.config/roocode/mcp.json or in the extension settings):
{
"mcpServers": {
"nexus-balancer": {
"command": "cargo",
"args": [
"run",
"--manifest-path",
"/path/to/nexus_balancer/Cargo.toml",
"--",
"mcp"
],
"env": {
"NEXUS_MCP_URL": "http://localhost:3317/mcp",
"NEXUS_API_KEY": "<YOUR_API_KEY>"
}
}
}
}(If you already have a compiled binary, you can use command: "/path/to/nexus_balancer" and args: ["mcp"] instead of cargo run)
In LM Studio's MCP settings (section "Developer" -> "MCP"), add a similar configuration:
{
"mcpServers": {
"nexus-balancer": {
"command": "cargo",
"args": [
"run",
"--quiet",
"--manifest-path",
"/path/to/nexus_balancer/Cargo.toml",
"--",
"mcp"
],
"env": {
"NEXUS_MCP_URL": "http://localhost:3317/mcp",
"NEXUS_API_KEY": "<YOUR_API_KEY>"
}
}
}
}The balancer automatically discovers provider models through their /models endpoints.
- On startup: for each pool (except
skip_model_sync: true), an HTTP request is made to{target_url}/models. - Response parsing: OpenAI-compatible providers (
{data: [{id, owned_by, ...}]}) and Google Gemini ({models: [{name, inputTokenLimit, ...}]}) are handled by different parsers. - SQLite storage: models are upserted into the
provider_modelstable. Old records are markedis_stale = 1and deleted after 24 hours. - In-memory cache: after sync, a
HashMap<model_id, Vec<(pool_name, priority)>>is built, sorted bypriorityDESC. - Routing: on request,
resolve_model(model_id)returns the pool_name with the highest priority in O(1). - Periodic sync: every 6 hours, a background process updates the registry.
If a provider's API is unavailable or the key is invalid — the sync skips that pool with a warning, without crashing the server. Models from the previous sync remain in the DB until stale cleanup (>24h).
On startup, a summary of discovered models is displayed:
[ModelRegistry] Starting initial model discovery...
[ModelRegistry] Discovered 15 models from cerebras-pool
[ModelRegistry] Discovered 23 models from groq-pool
...
Models: 47 discovered across 3 providers
Each proxied request is logged in real-time with precise latency measurements:
[13:14:02.795] [DEBUG] Proxy: Processing request (Body size: 137060 bytes)
[13:14:12.264] [DEBUG] Proxy: Upstream status 200 OK, Acquire: 487.2µs, Total: 9.46s
- Acquire: Time spent obtaining a free key from the pool (typically less than 1 ms).
- Total: Total request processing time on the server from receipt to response delivery.
- Authorization: Access to the proxy server is only possible with a valid
Authorization: Bearer <token>header. - Secret isolation: All client key files are physically isolated at the filesystem level.
- CORS: Restricted to configured origin (default
http://localhost:3317), configurable viacors_allowed_originorCORS_ALLOWED_ORIGINenv var. - Path traversal protection: All file paths are validated against
..and absolute path components. - Interactive panel: For testing and exploring all endpoints, use the Scalar documentation at
http://localhost:3317/scalar. - See docs/SECURITY.md for a full security reference.
This project is distributed under the Apache-2.0 license. See the LICENSE file for details.