Skip to main content

Overview

UMCP supports array-based environment variables that automatically rotate through multiple values using a round-robin strategy. This feature is designed for distributing API requests across multiple API keys, tokens, or credentials, helping you:
  • Stay within rate limits by spreading requests across multiple accounts
  • Implement simple load balancing for API usage
  • Rotate credentials for security or compliance reasons

Configuration Syntax

Environment variables can be defined as either a single string or an array of strings. From config.ts:12:

Single Value (Static)

The same value is used for every request.

Array Values (Rotating)

UMCP cycles through the array on each provider invocation.

How Round-Robin Works

In-Memory State

UMCP maintains rotation state in memory using a nested Map structure. From roundRobinEnvPool.ts:7:
Structure:
  • Outer map: providerId → provider state
  • Inner map: envKey → current index
This means:
  • Each provider has independent rotation state
  • Each environment variable key has its own rotation index
  • State is not persisted to disk

Pool Creation

The round-robin pool is created at server startup. From roundRobinEnvPool.ts:32-73:

Rotation Algorithm

For each environment variable:
  1. Check if the value is a string or array
  2. If string: Use the value directly
  3. If array:
    • Get the current index for this provider/key (default: 0)
    • Select the value at currentIndex % arrayLength
    • Increment the index for next time: (currentIndex + 1) % arrayLength
    • Log the rotation event
From roundRobinEnvPool.ts:50-62:

Discovery Values

During tool discovery, UMCP uses the first value from each array to test provider connectivity. From roundRobinEnvPool.ts:16-30:
This ensures that tool discovery succeeds with valid credentials, even when using rotation.

Detecting Rotating Environment Variables

UMCP checks if any provider has rotating env vars. From roundRobinEnvPool.ts:9-14:

Logging and Security

Rotation events are logged with masked values to avoid exposing secrets. From roundRobinEnvPool.ts:56-62 and logger.ts:
The maskSecret function shows only a preview of the credential:

Example Usage

Basic Rotation

Configuration:
Behavior:
  • Request 1: Uses key-account-1
  • Request 2: Uses key-account-2
  • Request 3: Uses key-account-3
  • Request 4: Uses key-account-1 (cycles back)
  • Request 5: Uses key-account-2
  • And so on…

Multiple Rotating Variables

Note: Each variable rotates independently. The combinations might be:
  • Request 1: key-1 + secret-1
  • Request 2: key-2 + secret-2
  • Request 3: key-1 + secret-1 (both cycle)
If you need paired rotation (key-1 always with secret-1), use multiple provider configurations instead.

Mixed Static and Rotating

Only API_KEY rotates; other variables remain constant.

State Behavior

Startup Behavior

When UMCP starts:
  1. All rotation indices initialize to 0
  2. First tool discovery uses the first value in each array
  3. First actual tool call uses the first value and increments the index

Per-Provider Isolation

Each provider maintains independent rotation state. Consider this configuration:
  • Calls to search.brave-1.* rotate between key-a and key-b
  • Calls to search.brave-2.* rotate between key-c and key-d
  • The two providers don’t affect each other’s rotation state

Restart Behavior

Rotation state is not persisted. When UMCP restarts:
  • All indices reset to 0
  • Rotation starts over from the first value in each array
If you need persistent rotation or more sophisticated distribution, consider:
  • External load balancers
  • API gateway services
  • Database-backed credential rotation

Per-Invocation Rotation

Rotation happens per provider invocation, not per tool call. This means:
  • If a provider exposes multiple tools, they share the same credential for that invocation
  • The credential rotates when the provider is invoked again (for any tool)
Example:

Error Handling

Empty Arrays

The schema prevents empty arrays. From config.ts:12:
This validation ensures:
  • Arrays must have at least one element
  • Each element must be a non-empty string

Fallback for Missing Values

If an array value is somehow undefined, UMCP falls back to an empty string. From roundRobinEnvPool.ts:51:

Use Cases

Rate Limit Distribution

API provider allows 100 requests/minute per key:
Effective rate limit: 500 requests/minute across 5 accounts.

Cost Distribution

API charges per request. Rotate across multiple billing accounts to spread costs:

Geographic Distribution

Rotate between regional API keys for data residency:

Development vs. Production Keys

Use rotation to test with multiple environments:

Limitations

  1. No persistence: State resets on server restart
  2. No coordination: Multiple UMCP instances don’t share rotation state
  3. No paired rotation: Each variable rotates independently
  4. No weighted rotation: All values are equally likely
  5. No health awareness: Failed keys still rotate in (unless provider reconnects)

Best Practices

  1. Use consistent array lengths: Makes rotation patterns more predictable
  2. Test all credentials: Ensure every key in the array is valid before deployment
  3. Monitor usage: Watch logs to verify rotation is working as expected
  4. Plan for restarts: Don’t rely on rotation state persisting across restarts
  5. Document ownership: Keep track of which keys belong to which accounts

Example Log Output

When rotation occurs, you’ll see logs like:
This helps you:
  • Confirm rotation is working
  • Debug credential issues
  • Audit API key usage
  • Track which keys are being used