The AVCodex MCP Server enforces rate limits to keep usage fair and the platform stable. Limits scale with subscription tier.
| Tier | Requests/minute | MCP access |
|---|---|---|
| FREE | 0 | Not available |
| BUILDER | 30 | Full access |
| STUDIO | 60 | Full access |
| STUDIO_PRO | 120 | Full access |
| ENTERPRISE | Unlimited | Full access |
Note: MCP server access requires a Builder plan or higher. Free tier users cannot use the MCP server.
Every response includes rate limit information:
| Header | Description |
|---|---|
X-RateLimit-Tier |
Your subscription tier |
X-RateLimit-Limit |
Maximum requests per minute |
X-RateLimit-Remaining |
Requests remaining in current window |
X-RateLimit-Reset |
Unix timestamp when the limit resets |
Example response headers:
HTTP/1.1 200 OK
X-RateLimit-Tier: BUILDER
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 25
X-RateLimit-Reset: 1704067260
When you exceed your limit, the server returns 429 Too Many Requests:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Try again in 45 seconds.",
"tier": "BUILDER",
"limit": 30,
"reset": 1704067260
}
}
Retry-After header#
The Retry-After header tells you exactly when to retry:
HTTP/1.1 429 Too Many Requests
Retry-After: 45
X-RateLimit-Reset: 1704067260
Implementing retry logic#
Basic exponential backoff:
async function callWithRetry(makeRequest, maxRetries = 3) {
for (let attempt = 0; attempt < maxRetries; attempt++) {
const response = await makeRequest();
if (response.status === 429) {
const retryAfter = response.headers.get('Retry-After') || 60;
console.log(`Rate limited. Waiting ${retryAfter}s...`);
await sleep(retryAfter * 1000);
continue;
}
return response;
}
throw new Error('Max retries exceeded');
}
Respecting Retry-After:
import time
import requests
def call_mcp(tool_name, args):
response = requests.post(
"https://app.avcodex.com/mcp",
json={"method": "tools/call", "params": {"name": tool_name, "arguments": args}},
headers={"Authorization": f"Bearer {token}"}
)
if response.status_code == 429:
retry_after = int(response.headers.get('Retry-After', 60))
print(f"Rate limited. Sleeping {retry_after}s...")
time.sleep(retry_after)
return call_mcp(tool_name, args) # Retry
return response.json()
1. Batch operations#
Instead of calling tools one at a time, combine related operations:
# Inefficient: 10 separate calls
for agent in agents:
update_agent(agent.id, {...})
# Better: Use bulk patterns where available,
# or space calls out to stay within limits.
2. Use caching#
Cache responses that don't change frequently. Manufacturer spec metadata, agent definitions, and analytics roll-ups don't move minute-to-minute:
const agentCache = new Map();
const CACHE_TTL = 5 * 60 * 1000; // 5 minutes
async function getAgent(agentId) {
const cached = agentCache.get(agentId);
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
return cached.data;
}
const agent = await mcpCall('get_app', { appId: agentId });
agentCache.set(agentId, { data: agent, timestamp: Date.now() });
return agent;
}
3. Monitor your usage#
Check remaining requests before large operations:
// Check headers from any response
const remaining = parseInt(response.headers['x-ratelimit-remaining']);
const resetTime = parseInt(response.headers['x-ratelimit-reset']);
if (remaining < 5 && operations.length > 5) {
const waitTime = resetTime - Math.floor(Date.now() / 1000);
console.log(`Low on requests. Waiting ${waitTime}s before bulk operation...`);
await sleep(waitTime * 1000);
}
4. Spread requests over time#
For non-urgent bulk operations, spread requests evenly:
async function bulkUpdate(agents, updateFn) {
const REQUESTS_PER_MINUTE = 25; // Stay under the limit
const DELAY_MS = 60000 / REQUESTS_PER_MINUTE; // ~2.4 seconds
for (const agent of agents) {
await updateFn(agent);
await sleep(DELAY_MS);
}
}
5. Use pagination wisely#
Fetch only what you need:
# Good: small pages, specific queries
list_apps(limit=10, offset=0)
search_conversations(appId="xxx", query="Cresnet timeout", limit=20)
# Avoid: large fetches you don't need
list_apps(limit=1000)
export_conversations(appId="xxx") # Use sparingly
Need higher limits? Upgrade your subscription:
| Current tier | Next tier | Limit increase |
|---|---|---|
| BUILDER | STUDIO | 30 to 60 req/min (2x) |
| STUDIO | STUDIO_PRO | 60 to 120 req/min (2x) |
| STUDIO_PRO | ENTERPRISE | 120 to Unlimited |
Bulk agent creation#
Problem: Creating 50 client-specific support agents (one per managed-services site) hits the rate limit.
Solution (BUILDER tier):
// 30 requests/minute = ~2 seconds between requests
for (const agentConfig of agentConfigs) {
await createAgent(agentConfig);
await sleep(2000); // 2 second delay
}
// Total time: ~100 seconds for 50 agents
Analytics dashboard#
Problem: Fetching analytics for 20 client-specific agents exceeds the limit.
Solution:
// Option 1: Fetch in batches
const batches = chunk(agentIds, 5);
for (const batch of batches) {
await Promise.all(batch.map(id => getAgentAnalytics(id)));
await sleep(10000); // Wait 10s between batches
}
// Option 2: Cache results.
// Analytics don't change by the second. Cache for 5+ minutes.
CI/CD integration#
Problem: Automated deployments need multiple tool calls.
Solution:
# In your CI pipeline
steps:
- name: Update AVCodex Agent
run: |
# Use retry logic
./update-agent.sh --retry-on-rate-limit
env:
AVCODEX_RETRY_DELAY: 60
AVCODEX_MAX_RETRIES: 3
Q: Do rate limits apply per user or per organization? A: Per authenticated user (OAuth token or API key). Each team member has their own limit.
Q: Does reading consume the same rate as writing? A: Yes. All tool calls count equally against the rate limit.
Q: What happens if I'm rate-limited mid-workflow? A: Implement retry logic with exponential backoff. Your MCP client should handle 429 responses gracefully.
Q: Can I request higher limits for a specific use case? A: Enterprise customers can negotiate custom limits. Contact sales@avcodex.com for details.
- Tools Reference. All available tools.
- Common Workflows. Efficient usage patterns.
- Authentication. Token management.
*AVCodex · Your AV expertise. Amplified by AI.*