obsidian-mcp-server
Version:
Obsidian Knowledge-Management MCP (Model Context Protocol) server that enables AI agents and development tools to interact with an Obsidian vault. It provides a comprehensive suite of tools for reading, writing, searching, and managing notes, tags, and fr
157 lines (156 loc) • 6.26 kB
TypeScript
/**
* @fileoverview Provides a generic rate limiter class to manage request rates
* based on configurable time windows and request counts. It supports custom
* key generation, periodic cleanup of expired entries, and skipping rate
* limiting in development environments.
* @module src/utils/security/rateLimiter
*/
import { RequestContext } from "../internal/index.js";
/**
* Configuration options for the {@link RateLimiter}.
*/
export interface RateLimitConfig {
/** Time window in milliseconds during which requests are counted. */
windowMs: number;
/** Maximum number of requests allowed from a single key within the `windowMs`. */
maxRequests: number;
/**
* Custom error message template when rate limit is exceeded.
* Use `{waitTime}` as a placeholder for the remaining seconds until reset.
* Defaults to "Rate limit exceeded. Please try again in {waitTime} seconds."
*/
errorMessage?: string;
/**
* If `true`, rate limiting checks will be skipped if `process.env.NODE_ENV` is 'development'.
* Defaults to `false`.
*/
skipInDevelopment?: boolean;
/**
* An optional function to generate a unique key for rate limiting based on an identifier
* and optional request context. If not provided, the raw identifier is used as the key.
* @param identifier - The base identifier (e.g., IP address, user ID).
* @param context - Optional request context.
* @returns A string to be used as the rate limiting key.
*/
keyGenerator?: (identifier: string, context?: RequestContext) => string;
/**
* Interval in milliseconds for cleaning up expired rate limit entries from memory.
* Defaults to 5 minutes. Set to `0` or `null` to disable automatic cleanup.
*/
cleanupInterval?: number | null;
}
/**
* Represents an individual entry in the rate limiter's tracking store.
* @internal
*/
export interface RateLimitEntry {
/** The current count of requests within the window. */
count: number;
/** The timestamp (milliseconds since epoch) when the current window resets. */
resetTime: number;
}
/**
* A generic rate limiter class that can be used to control the frequency of
* operations or requests from various sources. It stores request counts in memory.
*/
export declare class RateLimiter {
private limits;
private cleanupTimer;
private currentConfig;
/**
* Default configuration values for the rate limiter.
*/
private static DEFAULT_CONFIG;
/**
* Creates a new `RateLimiter` instance.
* @param {Partial<RateLimitConfig>} [initialConfig={}] - Optional initial configuration
* to override default settings.
*/
constructor(initialConfig?: Partial<RateLimitConfig>);
/**
* Starts the periodic cleanup timer for expired rate limit entries.
* If a timer already exists, it's cleared and restarted.
* @private
*/
private startCleanupTimer;
/**
* Removes expired entries from the rate limit store to free up memory.
* This method is called periodically by the cleanup timer.
* @private
*/
private cleanupExpiredEntries;
/**
* Updates the rate limiter's configuration.
* @param {Partial<RateLimitConfig>} newConfig - Partial configuration object
* with new settings to apply.
*/
configure(newConfig: Partial<RateLimitConfig>): void;
/**
* Retrieves a copy of the current rate limiter configuration.
* @returns {RateLimitConfig} The current configuration.
*/
getConfig(): RateLimitConfig;
/**
* Resets all rate limits, clearing all tracked keys and their counts.
* @param {RequestContext} [context] - Optional context for logging the reset operation.
*/
reset(context?: RequestContext): void;
/**
* Checks if a request identified by a key exceeds the configured rate limit.
* If the limit is exceeded, an `McpError` is thrown.
*
* @param {string} identifier - A unique string identifying the source of the request
* (e.g., IP address, user ID, session ID).
* @param {RequestContext} [context] - Optional request context for logging and potentially
* for use by a custom `keyGenerator`.
* @throws {McpError} If the rate limit is exceeded for the given key.
* The error will have `BaseErrorCode.RATE_LIMITED`.
*/
check(identifier: string, context?: RequestContext): void;
/**
* Retrieves the current rate limit status for a given key.
* @param {string} key - The rate limit key (as generated by `keyGenerator` or the raw identifier).
* @returns {{ current: number; limit: number; remaining: number; resetTime: number } | null}
* An object with current status, or `null` if the key is not currently tracked (or has expired).
* `resetTime` is a Unix timestamp (milliseconds).
*/
getStatus(key: string): {
current: number;
limit: number;
remaining: number;
resetTime: number;
} | null;
/**
* Stops the cleanup timer and clears all rate limit entries.
* This should be called if the rate limiter instance is no longer needed,
* to prevent resource leaks (though `unref` on the timer helps).
* @param {RequestContext} [context] - Optional context for logging the disposal.
*/
dispose(context?: RequestContext): void;
}
/**
* A default, shared instance of the `RateLimiter`.
* This instance is configured with default settings (e.g., 100 requests per 15 minutes).
* It can be reconfigured using `rateLimiter.configure()`.
*
* Example:
* ```typescript
* import { rateLimiter, RequestContext } from './rateLimiter';
* import { requestContextService } from '../internal';
*
* const context: RequestContext = requestContextService.createRequestContext({ operation: 'MyApiCall' });
* const userIp = '123.45.67.89';
*
* try {
* rateLimiter.check(userIp, context);
* // Proceed with operation
* } catch (e) {
* if (e instanceof McpError && e.code === BaseErrorCode.RATE_LIMITED) {
* console.error("Rate limit hit:", e.message);
* } else {
* // Handle other errors
* }
* }
* ```
*/
export declare const rateLimiter: RateLimiter;