Skip to main content
Glama

Sentry MCP

Official
by getsentry
rate-limiter.ts2.76 kB
import type { RateLimit } from "@cloudflare/workers-types"; /** * Result from rate limit check */ export interface RateLimitCheckResult { /** * Whether the request is allowed */ allowed: boolean; /** * Error message if rate limited (only present when allowed=false) */ errorMessage?: string; } /** * Hash a string using SHA-256 for privacy-preserving rate limit keys * * @param value - The value to hash (e.g., IP address, access token) * @returns Hex-encoded SHA-256 hash (first 16 characters) */ async function hashValue(value: string): Promise<string> { const encoder = new TextEncoder(); const data = encoder.encode(value); const hashBuffer = await crypto.subtle.digest("SHA-256", data); const hashArray = Array.from(new Uint8Array(hashBuffer)); const hashHex = hashArray .map((b) => b.toString(16).padStart(2, "0")) .join(""); return hashHex.substring(0, 16); // Use first 16 chars of hash } /** * Check rate limit for a given identifier * * @param identifier - The identifier to rate limit (e.g., IP address, user ID) * @param rateLimiter - The Cloudflare rate limiter binding * @param options - Configuration options * @returns Result indicating whether the request is allowed * * @example * ```typescript * const result = await checkRateLimit( * clientIP, * env.MCP_RATE_LIMITER, * { * keyPrefix: "mcp:ip", * errorMessage: "Rate limit exceeded. Please wait before trying again." * } * ); * * if (!result.allowed) { * return new Response(result.errorMessage, { status: 429 }); * } * ``` */ export async function checkRateLimit( identifier: string, rateLimiter: RateLimit | undefined, options: { /** * Prefix for the rate limit key (e.g., "mcp:ip", "chat:user") */ keyPrefix: string; /** * Error message to return when rate limited */ errorMessage: string; }, ): Promise<RateLimitCheckResult> { // If rate limiter binding is not available (e.g., in development), // allow the request to proceed if (!rateLimiter) { return { allowed: true }; } try { // Hash the identifier for privacy const hashedIdentifier = await hashValue(identifier); const rateLimitKey = `${options.keyPrefix}:${hashedIdentifier}`; // Check rate limit const { success } = await rateLimiter.limit({ key: rateLimitKey }); if (!success) { return { allowed: false, errorMessage: options.errorMessage, }; } return { allowed: true }; } catch (error) { // If rate limiter fails, log error but allow request to proceed // This prevents rate limiter issues from breaking the service console.error("Rate limiter error:", error); return { allowed: true }; } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/getsentry/sentry-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server