Skip to main content
Full API reference for the @frontmcp/guard package. This library is SDK-agnostic and works with any StorageAdapter backend.
npm install @frontmcp/guard
When using @frontmcp/sdk, guard features are integrated automatically via the throttle config and tool/agent decorators. You only need to import from @frontmcp/guard directly if building custom integrations.

Configuration Types

GuardConfig

Top-level configuration for the guard system. Passed to @FrontMcp({ throttle: ... }) or createGuardManager().
FieldTypeDefaultDescription
enabledbooleanrequiredEnable or disable all guard features
storageStorageConfigin-memoryStorage backend configuration
keyPrefixstring'mcp:guard:'Prefix for all storage keys
globalRateLimitConfigGlobal rate limit for all requests
globalConcurrencyConcurrencyConfigGlobal concurrency limit
defaultRateLimitRateLimitConfigDefault rate limit for entities without explicit config
defaultConcurrencyConcurrencyConfigDefault concurrency for entities without explicit config
defaultTimeoutTimeoutConfigDefault timeout for entity execution
ipFilterIpFilterConfigIP filtering configuration

RateLimitConfig

Configuration for sliding window rate limiting.
FieldTypeDefaultDescription
maxRequestsnumberrequiredMaximum requests allowed in the window
windowMsnumber60000Time window in milliseconds
partitionByPartitionKey'global'How to bucket rate limits

ConcurrencyConfig

Configuration for distributed semaphore concurrency control.
FieldTypeDefaultDescription
maxConcurrentnumberrequiredMaximum simultaneous executions
queueTimeoutMsnumber0Max time (ms) to wait for a slot. 0 = reject immediately
partitionByPartitionKey'global'How to bucket concurrency limits

TimeoutConfig

Configuration for execution timeout.
FieldTypeDefaultDescription
executeMsnumberrequiredMaximum execution time in milliseconds

IpFilterConfig

Configuration for IP-based access control.
FieldTypeDefaultDescription
allowListstring[][]IPs or CIDR ranges to always allow
denyListstring[][]IPs or CIDR ranges to always block
defaultAction'allow' | 'deny''allow'Action when IP matches neither list
trustProxybooleanfalseTrust X-Forwarded-For header
trustedProxyDepthnumber1Max proxy hops to trust

PartitionKey

Determines how limits are bucketed across requests.
type PartitionKey = PartitionKeyStrategy | CustomPartitionKeyFn;

type PartitionKeyStrategy = 'ip' | 'session' | 'userId' | 'global';

type CustomPartitionKeyFn = (ctx: PartitionKeyContext) => string;
PartitionKeyContext:
FieldTypeDescription
sessionIdstringMCP session identifier
clientIpstring | undefinedClient IP address
userIdstring | undefinedAuthenticated user identifier

Classes

GuardManager

Orchestrates all guard features. Created via createGuardManager() or automatically by the SDK when throttle is configured.
class GuardManager {
  readonly config: GuardConfig;

  constructor(storage: NamespacedStorage, config: GuardConfig);
}

checkRateLimit()

Check per-entity rate limit.
async checkRateLimit(
  entityName: string,
  entityConfig?: RateLimitConfig,
  context?: PartitionKeyContext,
): Promise<RateLimitResult>
ParameterDescription
entityNameTool or agent name
entityConfigPer-entity rate limit config. Falls back to config.defaultRateLimit if not provided
contextPartition key context for key resolution
Returns { allowed: true, remaining: Infinity, resetMs: 0 } if no config applies.

checkGlobalRateLimit()

Check global (server-wide) rate limit.
async checkGlobalRateLimit(
  context?: PartitionKeyContext,
): Promise<RateLimitResult>
Uses config.global configuration. Returns allowed result if no global config.

acquireSemaphore()

Acquire a concurrency slot for an entity.
async acquireSemaphore(
  entityName: string,
  entityConfig?: ConcurrencyConfig,
  context?: PartitionKeyContext,
): Promise<SemaphoreTicket | null>
ParameterDescription
entityNameTool or agent name
entityConfigPer-entity concurrency config. Falls back to config.defaultConcurrency
contextPartition key context for key resolution
Returns SemaphoreTicket on success, null if no config applies. May throw QueueTimeoutError if queue timeout expires.

acquireGlobalSemaphore()

Acquire a global concurrency slot.
async acquireGlobalSemaphore(
  context?: PartitionKeyContext,
): Promise<SemaphoreTicket | null>
Uses config.globalConcurrency configuration.

checkIpFilter()

Check if a client IP is allowed.
checkIpFilter(clientIp?: string): IpFilterResult | undefined
Returns undefined if no IP filter configured or clientIp is falsy. Otherwise returns IpFilterResult.

isIpAllowListed()

Check if a client IP is explicitly on the allow list.
isIpAllowListed(clientIp?: string): boolean
Returns true only if an IP filter is configured, clientIp is provided, and the IP matches the allow list.

destroy()

Disconnect storage backend and clean up resources.
async destroy(): Promise<void>

SlidingWindowRateLimiter

Implements sliding window rate limiting with O(1) storage per key.
class SlidingWindowRateLimiter {
  constructor(storage: StorageAdapter);
}

check()

Check and consume a rate limit token.
async check(
  key: string,
  maxRequests: number,
  windowMs: number,
): Promise<RateLimitResult>
Algorithm: Uses two adjacent fixed-window counters with weighted interpolation. The estimated count is:
estimatedCount = previousWindowCount * (1 - elapsedRatio) + currentWindowCount
If estimatedCount < maxRequests, the request is allowed and the current window counter is atomically incremented. RateLimitResult:
FieldTypeDescription
allowedbooleanWhether the request is allowed
remainingnumberRequests remaining in the window
resetMsnumberMilliseconds until window resets
retryAfterMsnumber | undefinedRecommended retry time (only when denied)

reset()

Reset rate limit counters for a key.
async reset(key: string, windowMs: number): Promise<void>

DistributedSemaphore

Implements a distributed counting semaphore with optional queuing.
class DistributedSemaphore {
  constructor(storage: StorageAdapter, ticketTtlSeconds?: number);
}
Default ticketTtlSeconds: 300 (5 minutes).

acquire()

Acquire a semaphore slot.
async acquire(
  key: string,
  maxConcurrent: number,
  queueTimeoutMs: number,
  entityName: string,
): Promise<SemaphoreTicket | null>
  • Returns SemaphoreTicket if a slot is acquired.
  • Returns null if queueTimeoutMs <= 0 and no slot is available.
  • Throws QueueTimeoutError if queued and timeout expires.
Uses pub/sub when available for efficient slot release detection, falls back to polling with exponential backoff (100ms to 1000ms). SemaphoreTicket:
FieldTypeDescription
ticketstringUnique ticket identifier (UUID)
release()() => Promise<void>Release the slot back to the pool

getActiveCount()

Get current number of active tickets for a key.
async getActiveCount(key: string): Promise<number>

forceReset()

Force-clear all tickets and reset the counter for a key.
async forceReset(key: string): Promise<void>

IpFilter

IP-based access control with CIDR support for IPv4 and IPv6.
class IpFilter {
  constructor(config: IpFilterConfig);
}
Parses all CIDR rules at construction time using BigInt bitmask representation.

check()

Check if a client IP is allowed.
check(clientIp: string): IpFilterResult
Evaluation order:
  1. Deny list (takes precedence)
  2. Allow list
  3. Default action
IpFilterResult:
FieldTypeDescription
allowedbooleanWhether the IP is allowed
reason'allowlisted' | 'denylisted' | 'default' | undefinedReason for the decision
matchedRulestring | undefinedSpecific IP or CIDR that matched

isAllowListed()

Check if an IP is explicitly on the allow list.
isAllowListed(clientIp: string): boolean

Functions

createGuardManager()

Factory function to create a fully initialized GuardManager.
async function createGuardManager(args: CreateGuardManagerArgs): Promise<GuardManager>
CreateGuardManagerArgs:
FieldTypeDescription
configGuardConfigFull guard configuration
loggerGuardLogger | undefinedOptional logger for diagnostic output
Behavior:
  1. Creates storage backend from config.storage (or in-memory if not set)
  2. Connects the storage backend
  3. Creates namespaced storage with config.keyPrefix
  4. Returns initialized GuardManager
import { createGuardManager } from '@frontmcp/guard';

const manager = await createGuardManager({
  config: {
    enabled: true,
    storage: { provider: 'redis', host: 'localhost', port: 6379 },
    global: { maxRequests: 1000, windowMs: 60_000, partitionBy: 'ip' },
  },
  logger: console,
});

withTimeout()

Wraps an async function with an execution deadline.
async function withTimeout<T>(
  fn: () => Promise<T>,
  timeoutMs: number,
  entityName: string,
): Promise<T>
ParameterTypeDescription
fn() => Promise<T>Async function to execute
timeoutMsnumberMaximum execution time in milliseconds
entityNamestringName included in error message
Throws ExecutionTimeoutError if the deadline is exceeded. Uses AbortController + Promise.race internally.
import { withTimeout } from '@frontmcp/guard';

const result = await withTimeout(
  () => fetchData(),
  5000,
  'data-fetcher',
);

resolvePartitionKey()

Resolve a partition key strategy to a concrete string value.
function resolvePartitionKey(
  partitionBy?: PartitionKey,
  context?: PartitionKeyContext,
): string
StrategyResolved Value
undefined'global'
'global''global'
'ip'context.clientIp or 'unknown-ip'
'session'context.sessionId
'userId'context.userId or 'anonymous'
Custom functionfn(context)

buildStorageKey()

Build a namespaced storage key from components.
function buildStorageKey(
  entityName: string,
  partitionKey: string,
  suffix?: string,
): string
Examples:
buildStorageKey('search', 'user-123', 'rl');
// → 'search:user-123:rl'

buildStorageKey('search', 'global');
// → 'search:global'

Error Classes

All guard errors extend GuardError, which has code (string) and statusCode (number) properties.
class GuardError extends Error {
  readonly code: string;
  readonly statusCode: number;
}

ExecutionTimeoutError

Thrown when execution exceeds the configured timeout.
PropertyTypeValue
codestring'EXECUTION_TIMEOUT'
statusCodenumber408
entityNamestringName of the tool/agent
timeoutMsnumberConfigured timeout value

ConcurrencyLimitError

Thrown when no concurrency slot is available and queueTimeoutMs is 0.
PropertyTypeValue
codestring'CONCURRENCY_LIMIT'
statusCodenumber429
entityNamestringName of the tool/agent
maxConcurrentnumberConfigured concurrency limit

QueueTimeoutError

Thrown when a queued request exceeds its wait time.
PropertyTypeValue
codestring'QUEUE_TIMEOUT'
statusCodenumber429
entityNamestringName of the tool/agent
queueTimeoutMsnumberConfigured queue timeout

IpBlockedError

Thrown when a client IP matches the deny list.
PropertyTypeValue
codestring'IP_BLOCKED'
statusCodenumber403
clientIpstringThe blocked IP address

IpNotAllowedError

Thrown when a client IP is not on the allow list and defaultAction is 'deny'.
PropertyTypeValue
codestring'IP_NOT_ALLOWED'
statusCodenumber403
clientIpstringThe rejected IP address

Zod Schemas

Validation schemas for all configuration types. Useful for validating user-provided configuration.
import {
  guardConfigSchema,
  rateLimitConfigSchema,
  concurrencyConfigSchema,
  timeoutConfigSchema,
  ipFilterConfigSchema,
  partitionKeySchema,
} from '@frontmcp/guard';
SchemaValidates
guardConfigSchemaGuardConfig
rateLimitConfigSchemaRateLimitConfig
concurrencyConfigSchemaConcurrencyConfig
timeoutConfigSchemaTimeoutConfig
ipFilterConfigSchemaIpFilterConfig
partitionKeySchemaPartitionKey (string strategy or function)