Skip to content

Standalone Components

The building blocks of @casys/mcp-server are useful on their own. Rate limiting, concurrency control, and schema validation — all usable in any Deno or Node.js project, no MCP required.

Sliding-window rate limiter with per-key tracking. Lightweight, no external dependencies.

import { RateLimiter } from "@casys/mcp-server";
const limiter = new RateLimiter({
maxRequests: 10, // 10 requests
windowMs: 1000, // per 1 second
});
limiter.checkLimit(key: string): boolean;

Returns true if within limits, false if rate-limited. Non-blocking — never waits.

if (limiter.checkLimit("client-123")) {
// Process request
} else {
// Rate limited
}
await limiter.waitForSlot(key: string): Promise<void>;

Blocks until a slot opens. Timeout equals windowMs.

await limiter.waitForSlot("client-123");
// Guaranteed to have a slot
limiter.getMetrics(): { keys: number, totalRequests: number };

Concurrency control with configurable backpressure. Protects downstream services from overload.

import { RequestQueue } from "@casys/mcp-server";
const queue = new RequestQueue({
maxConcurrent: 5,
strategy: "queue", // "sleep" | "queue" | "reject"
sleepMs: 10, // For "sleep" strategy only
});
StrategyBehaviorBest for
sleepSpin-wait with sleepMs delay until a slot opensLow-latency, CPU-tolerant
queueFIFO queue — requests wait in orderFair ordering, predictable
rejectImmediately reject if at capacityFail-fast, circuit-breaker style
await queue.acquire(): Promise<void>;
queue.release(): void;

Always use try/finally to prevent slot leaks:

await queue.acquire();
try {
await processRequest(); // 1 of maxConcurrent
} finally {
queue.release();
}
queue.getMetrics(): { inFlight: number, queued: number };

JSON Schema validation powered by ajv. Schemas are compiled once at registration time — validation is fast.

import { SchemaValidator } from "@casys/mcp-server";
const validator = new SchemaValidator();
validator.addSchema(toolName: string, schema: object): void;

Compiles and caches the schema. Call once per tool at startup:

validator.addSchema("my_tool", {
type: "object",
properties: {
count: { type: "number", minimum: 0 },
label: { type: "string", maxLength: 100 },
},
required: ["count"],
});
validator.validate(toolName: string, args: unknown): ValidationResult;
interface ValidationResult {
valid: boolean;
errors: string[]; // Human-readable error messages
}
validator.validate("my_tool", { count: -1 });
// { valid: false, errors: ["count must be >= 0"] }
validator.validate("my_tool", { count: 5 });
// { valid: true, errors: [] }