Skip to content

MCP rate limiter buckets never expire #2824

Description

@Widthdom

Evidence

src/CodeIndex/Mcp/RateLimiter.cs keeps buckets in:

private readonly Dictionary<string, TokenBucket> _buckets = new(StringComparer.Ordinal);

TryAcquire creates a new bucket for each (tool, caller) key, but there is no TTL, max bucket count, idle cleanup, or compaction path.

Impact

Rate limiting is opt-in, but shared or HTTP MCP deployments can still have many caller identities over time. Stale (tool, caller) buckets remain for the process lifetime, so memory grows with historical caller cardinality rather than active callers.

Expected

Add a bounded eviction strategy, such as idle TTL cleanup, max bucket count with oldest-idle eviction, or periodic prune on TryAcquire. The response behavior should stay deterministic for active callers.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingsecurity

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions