Skip to main content
Glama
pshempel

MCP Time Server Node

by pshempel
cache-wrapper-behavior.md3.04 kB
# Verified Cache Wrapper Behavior **Decision Date:** 2025-08-08 ## Research Findings ### Current Cache Pattern (Duplicated ~10 times) Every tool follows this identical pattern with ~12 lines of boilerplate: ```typescript // 1. Build raw cache key const rawCacheKey = `prefix_${param1}_${param2}_${timezone}`; // 2. Hash the key const cacheKey = hashCacheKey(rawCacheKey); // 3. Check cache const cached = cache.get<ResultType>(cacheKey); if (cached) { return cached; } // 4. Compute result const result = computeExpensiveOperation(); // 5. Store in cache cache.set(cacheKey, result, CacheTTL.APPROPRIATE_TTL); // 6. Return result return result; ``` ### Verified Behavior 1. **Type Safety**: `cache.get<T>()` preserves types correctly 2. **Cache Miss**: Returns `undefined` for missing keys 3. **TTL Values**: - `CALCULATIONS`: 3600 seconds (1 hour) - `CURRENT_TIME`: 1 second - `TIMEZONE_CONVERT`: 300 seconds (5 minutes) - `BUSINESS_DAYS`: 86400 seconds (24 hours) 4. **Key Hashing**: Consistent SHA-256 hashing via `hashCacheKey()` 5. **Complex Objects**: Properly serializes/deserializes nested objects ### Proposed Solution Create a generic wrapper that encapsulates the entire pattern: ```typescript export function withCache<T>( cacheKey: string, ttl: number, compute: () => T ): T { const hashedKey = hashCacheKey(cacheKey); const cached = cache.get<T>(hashedKey); if (cached !== undefined) { return cached; } const result = compute(); cache.set(hashedKey, result, ttl); return result; } ``` ### Usage After Refactoring Before (12 lines): ```typescript const rawCacheKey = `add_${time}_${amount}_${unit}_${timezone}`; const cacheKey = hashCacheKey(rawCacheKey); const cached = cache.get<AddTimeResult>(cacheKey); if (cached) { return cached; } // ... compute result ... cache.set(cacheKey, output, CacheTTL.CALCULATIONS); return output; ``` After (3 lines): ```typescript return withCache( `add_${time}_${amount}_${unit}_${timezone}`, CacheTTL.CALCULATIONS, () => { // ... compute result ... return output; } ); ``` ### Impact - **Lines removed**: ~120 (12 lines × 10 tools) - **Consistency**: Single source of truth for cache logic - **Maintainability**: Changes to cache behavior in one place - **Type safety**: Preserved through generics ### Edge Cases Considered 1. **undefined as valid value**: Current code checks `if (cached)` which fails for falsy values. New wrapper uses `!== undefined` to handle this correctly. 2. **Async operations**: Current tools are synchronous. If async needed later, create `withCacheAsync` variant. 3. **Cache key collisions**: SHA-256 hashing makes this virtually impossible. 4. **Debug logging**: Can be added centrally in the wrapper. ### Decision Rationale The wrapper pattern: - Follows DRY principle by eliminating duplication - KISS: Simple, single-purpose function - Type-safe via TypeScript generics - Non-breaking: Can migrate incrementally - Testable: Single unit to test vs 10 separate implementations

Latest Blog Posts

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/pshempel/mcp-time-server-node'

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