UNPKG

okta-mcp-server

Version:

Model Context Protocol (MCP) server for Okta API operations with support for bulk operations and caching

83 lines 2.45 kB
/** * Token bucket rate limiter implementation */ export class TokenBucketRateLimiter { buckets = new Map(); capacity; refillRate; window; constructor(options) { this.capacity = options.max; this.window = options.window; this.refillRate = options.max / (options.window / 1000); // tokens per second } getBucket(key) { let bucket = this.buckets.get(key); if (!bucket) { bucket = { tokens: this.capacity, lastRefill: Date.now(), capacity: this.capacity, refillRate: this.refillRate, }; this.buckets.set(key, bucket); } return bucket; } refillBucket(bucket) { const now = Date.now(); const timePassed = (now - bucket.lastRefill) / 1000; // seconds const tokensToAdd = timePassed * bucket.refillRate; bucket.tokens = Math.min(bucket.capacity, bucket.tokens + tokensToAdd); bucket.lastRefill = now; } async check(key) { const bucket = this.getBucket(key); this.refillBucket(bucket); return { allowed: bucket.tokens >= 1, remaining: Math.floor(bucket.tokens), reset: Date.now() + this.window, limit: this.capacity, }; } async consume(key, tokens = 1) { const bucket = this.getBucket(key); this.refillBucket(bucket); const allowed = bucket.tokens >= tokens; if (allowed) { bucket.tokens -= tokens; } return { allowed, remaining: Math.max(0, Math.floor(bucket.tokens)), reset: Date.now() + this.window, limit: this.capacity, }; } async reset(key) { this.buckets.delete(key); } async status(key) { return this.check(key); } /** * Clean up old buckets (for memory management) */ cleanup() { const now = Date.now(); const maxAge = this.window * 2; // Keep buckets for 2x the window for (const [key, bucket] of this.buckets) { if (now - bucket.lastRefill > maxAge) { this.buckets.delete(key); } } } /** * Start periodic cleanup */ startCleanup(interval = 60000) { return setInterval(() => this.cleanup(), interval); } } //# sourceMappingURL=token-bucket.js.map