Skip to main content
Glama

ACE MCP Server

systemPatterns.md12.7 kB
# System Patterns: ACE MCP Server ## Architectural Patterns ### 1. Three-Component ACE Architecture ``` ┌─────────────┐ │ Generator │ → Produces trajectories using playbook └──────┬──────┘ ↓ ┌─────────────┐ │ Reflector │ → Analyzes trajectories for insights └──────┬──────┘ ↓ ┌─────────────┐ │ Curator │ → Creates delta operations └──────┬──────┘ ↓ ┌─────────────┐ │ Playbook │ → Applies deltas, stores bullets └─────────────┘ ``` **Pattern**: Pipeline architecture with clear separation of concerns **Benefit**: Each component is independently testable and replaceable ### 2. Provider Abstraction Pattern (NEW) ```typescript // Abstract interface interface LLMProvider { chat(messages: Message[]): Promise<string>; embed(text: string): Promise<number[]>; } // Concrete implementations class OpenAIProvider implements LLMProvider { } class LMStudioProvider implements LLMProvider { } // Factory pattern function createLLMProvider(config: Config): LLMProvider { return config.provider === 'openai' ? new OpenAIProvider(config.openai) : new LMStudioProvider(config.lmstudio); } ``` **Pattern**: Strategy + Factory **Benefit**: Switch LLM providers without changing core logic ### 3. Delta Update Pattern ```typescript // Instead of full rewrites const fullRewrite = { operation: 'REPLACE', content: [...1000 bullets] // 100KB }; // Use incremental deltas const delta = { operation: 'ADD', bullet: { content: '...' } // 100 bytes }; ``` **Pattern**: Event Sourcing (append-only operations) **Benefit**: Audit trail + minimal data transfer ### 4. Semantic Deduplication Pattern ```typescript // Before adding new bullet async function addBullet(bullet: Bullet): Promise<void> { const similar = await findSimilar(bullet, threshold); if (similar) { // Merge: combine helpful_count, keep best wording similar.helpful_count += bullet.helpful_count; } else { // Insert: truly new knowledge playbook.bullets.push(bullet); } } ``` **Pattern**: Content-addressable storage with similarity matching **Benefit**: Automatic knowledge consolidation ### 5. Context Isolation Pattern ```typescript // Each context has its own playbook const contexts = { 'frontend': Playbook, 'backend': Playbook, 'devops': Playbook }; // No cross-contamination await generator.generate({ query: 'Create API endpoint', context_id: 'backend' // Only uses backend bullets }); ``` **Pattern**: Multi-tenancy with namespace isolation **Benefit**: Strategies don't leak between domains ## Design Patterns ### Repository Pattern (Storage Layer) ```typescript interface PlaybookRepository { get(context_id: string): Promise<Playbook>; save(playbook: Playbook): Promise<void>; delete(context_id: string): Promise<void>; list(): Promise<string[]>; } class FilePlaybookRepository implements PlaybookRepository { constructor(private basePath: string) {} // Implementation with file system } ``` **Usage**: Abstract storage details from business logic **Benefit**: Easy to swap JSON files for PostgreSQL later ### Builder Pattern (Delta Operations) ```typescript class DeltaBuilder { private operations: DeltaOperation[] = []; add(content: string): this { this.operations.push({ operation: 'ADD', bullet: { content } }); return this; } update(id: string, changes: Partial<Bullet>): this { this.operations.push({ operation: 'UPDATE', bullet_id: id, updates: changes }); return this; } build(): DeltaOperation[] { return this.operations; } } // Usage const deltas = new DeltaBuilder() .add('New strategy') .update('b001', { helpful_count: 5 }) .build(); ``` **Usage**: Fluent API for creating delta batches **Benefit**: Readable code, easy composition ### Observer Pattern (Operations Logging) ```typescript interface OperationObserver { onDeltaApplied(delta: DeltaOperation): void; onDeduplication(merged: Bullet, duplicates: Bullet[]): void; } class LoggingObserver implements OperationObserver { onDeltaApplied(delta: DeltaOperation) { logger.info('Delta applied', { delta }); } } class MetricsObserver implements OperationObserver { onDeltaApplied(delta: DeltaOperation) { metrics.increment('delta_operations'); } } ``` **Usage**: Track operations without coupling **Benefit**: Easy to add monitoring, metrics, audit logs ### Singleton Pattern (Configuration) ```typescript class Config { private static instance: Config; private constructor(private env: NodeJS.ProcessEnv) {} static getInstance(): Config { if (!Config.instance) { Config.instance = new Config(process.env); } return Config.instance; } getLLMProvider(): LLMProviderConfig { } getStoragePath(): string { } } ``` **Usage**: Single source of configuration truth **Benefit**: No prop-drilling, consistent config access ## Error Handling Patterns ### Result Type Pattern ```typescript type Result<T, E = Error> = | { ok: true; value: T } | { ok: false; error: E }; async function generate(query: string): Promise<Result<Trajectory>> { try { const trajectory = await llm.generate(query); return { ok: true, value: trajectory }; } catch (error) { return { ok: false, error: error as Error }; } } // Usage const result = await generate('Create endpoint'); if (result.ok) { console.log(result.value); } else { logger.error(result.error); } ``` **Usage**: Explicit error handling without exceptions **Benefit**: Type-safe error propagation ### Circuit Breaker Pattern (LLM Calls) ```typescript class CircuitBreaker { private failures = 0; private state: 'closed' | 'open' | 'half-open' = 'closed'; async call<T>(fn: () => Promise<T>): Promise<T> { if (this.state === 'open') { throw new Error('Circuit breaker open'); } try { const result = await fn(); this.onSuccess(); return result; } catch (error) { this.onFailure(); throw error; } } } ``` **Usage**: Protect against cascading LLM API failures **Benefit**: Fast-fail when provider is down ## Data Flow Patterns ### Request Flow (MCP Tool Call) ``` Client (Cursor AI) ↓ JSON-RPC over stdio MCP Server (tools.ts) ↓ Parse & validate ACE Component (generator/reflector/curator) ↓ Business logic LLM Provider (openai/lmstudio) ↓ HTTP request Storage (playbook.ts) ↓ File I/O ↓ JSON response Client ``` ### Update Flow (Delta Application) ``` Insights (reflector output) ↓ Curator (create deltas) ↓ PlaybookManager (validate) ↓ Deduplicator (check similarity) ↓ BulletStore (persist) ↓ FileSystem (write JSON) ↓ Cache invalidation ``` ## Concurrency Patterns ### Async/Await Pattern ```typescript // All I/O operations are async async function fullACEWorkflow(query: string): Promise<void> { const trajectory = await generator.generate(query); const insights = await reflector.reflect(trajectory); const deltas = await curator.curate(insights); await playbookManager.update(deltas); } ``` **Pattern**: Promise-based async **Benefit**: Non-blocking I/O, readable code ### Mutex Pattern (Playbook Updates) ```typescript class PlaybookLock { private locks = new Map<string, Promise<void>>(); async withLock<T>(context_id: string, fn: () => Promise<T>): Promise<T> { // Wait for existing lock await this.locks.get(context_id); // Create new lock const lock = fn().finally(() => this.locks.delete(context_id)); this.locks.set(context_id, lock); return lock; } } ``` **Usage**: Prevent concurrent playbook modifications **Benefit**: Avoid race conditions in multi-user scenarios ## Docker Patterns (NEW) ### Multi-Stage Build Pattern ```dockerfile # Stage 1: Build FROM node:lts AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Runtime FROM node:lts-slim WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules CMD ["node", "dist/index.js"] ``` **Pattern**: Separate build and runtime environments **Benefit**: Smaller final image, faster deployments ### Docker Compose Service Pattern ```yaml services: ace-server: build: . volumes: - contexts:/app/contexts environment: - LLM_PROVIDER=${LLM_PROVIDER} networks: - ace-network ace-dashboard: build: ./dashboard ports: - "3000:80" depends_on: - ace-server networks: - ace-network volumes: contexts: networks: ace-network: ``` **Pattern**: Service orchestration with shared resources **Benefit**: One command to start entire stack ## Testing Patterns ### Mock LLM Pattern ```typescript class MockLLMProvider implements LLMProvider { async chat(messages: Message[]): Promise<string> { return 'Mock response for testing'; } async embed(text: string): Promise<number[]> { return Array(384).fill(0); // Mock embedding } } // Usage in tests const generator = new Generator(new MockLLMProvider()); ``` **Pattern**: Dependency injection for testing **Benefit**: Fast tests without real API calls ### Fixture Pattern ```typescript const testPlaybook: Playbook = { context_id: 'test', bullets: [ { id: 'b1', content: 'Test strategy 1', helpful_count: 5 }, { id: 'b2', content: 'Test strategy 2', helpful_count: 3 } ], metadata: { /* ... */ } }; describe('Deduplicator', () => { it('should merge similar bullets', async () => { const deduplicator = new Deduplicator(testPlaybook); // Test with known data }); }); ``` **Pattern**: Reusable test data **Benefit**: Consistent, maintainable tests ## Configuration Patterns ### Environment-Based Config (NEW) ```typescript interface EnvironmentConfig { development: Config; production: Config; test: Config; } function loadConfig(): Config { const env = process.env.NODE_ENV || 'development'; return configs[env]; } ``` **Pattern**: Environment-aware configuration **Benefit**: Different settings for dev/prod without code changes ### Validation Pattern ```typescript import { z } from 'zod'; const ConfigSchema = z.object({ llmProvider: z.enum(['openai', 'lmstudio']), openai: z.object({ apiKey: z.string().min(1), model: z.string() }).optional(), lmstudio: z.object({ baseUrl: z.string().url(), model: z.string() }).optional() }); function validateConfig(config: unknown): Config { return ConfigSchema.parse(config); } ``` **Pattern**: Schema-based validation **Benefit**: Type-safe config with clear error messages ## Observability Patterns ### Structured Logging Pattern ```typescript logger.info('ACE generation started', { context_id: 'backend', query_length: query.length, timestamp: Date.now() }); ``` **Pattern**: Key-value logging **Benefit**: Easy to parse, search, analyze ### Metrics Pattern (Future) ```typescript metrics.histogram('ace.generation.duration', duration); metrics.counter('ace.bullets.added').inc(); metrics.gauge('ace.playbook.size', bullets.length); ``` **Pattern**: Prometheus-style metrics **Benefit**: Performance monitoring, alerting ## Common Anti-Patterns to Avoid ❌ **Full Context Rewrites**: Never replace entire playbook ✅ **Delta Updates**: Always use ADD/UPDATE/DELETE operations ❌ **Hardcoded Provider**: Don't couple to OpenAI ✅ **Provider Abstraction**: Use interface-based design ❌ **Shared State**: Don't share playbook references ✅ **Immutable Updates**: Clone before modifying ❌ **Synchronous I/O**: Don't use `fs.readFileSync` ✅ **Async Operations**: Always use `fs.promises` ❌ **Magic Numbers**: `if (similarity > 0.85)` ✅ **Named Constants**: `if (similarity > config.dedupThreshold)` ## Best Practices Summary 1. **Separation of Concerns**: ACE components are independent 2. **Dependency Injection**: Pass providers, don't create them 3. **Type Safety**: Use TypeScript strictly, no `any` 4. **Error Handling**: Use Result types or try-catch with logging 5. **Configuration**: Environment variables, not hardcoded values 6. **Testing**: Mock external dependencies, use fixtures 7. **Logging**: Structured logs with context 8. **Docker**: Multi-stage builds, health checks, volumes for data 9. **Documentation**: Code comments for "why", not "what" 10. **Performance**: Async by default, cache when appropriate

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/Angry-Robot-Deals/ace-mcp'

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