Skip to main content
Glama

Code Executor MCP Server

by aberemia24
CODEBASE-INVENTORY.md21.1 kB
# Code Executor MCP - Codebase Inventory Report ## Executive Summary This document catalogs existing implementations in the code-executor-mcp codebase that are reusable for CLI setup infrastructure. The codebase provides production-grade patterns for filesystem operations, configuration management, lock file handling, and audit logging that can be adapted for CLI initialization. --- ## 1. FILESYSTEM OPERATIONS ### 1.1 Path Canonicalization & Security **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/utils.ts` (lines 172-205) **Function:** `isAllowedPath(path: string, allowedRoots: string[]): Promise<boolean>` **Capabilities:** - Resolves symlinks using `fs.realpath()` (prevents symlink escapes) - Canonicalizes paths to prevent `../../../` traversal attacks - Handles non-existent paths gracefully (returns false, no exception) - OS-agnostic path separator handling (`path.sep`) - Exact match OR proper subdirectory validation **Implementation Details:** ```typescript const resolvedPath = await realpath(path); const resolvedRoot = await realpath(root); if (resolvedPath === resolvedRoot || resolvedPath.startsWith(resolvedRoot + sep)) { return true; } ``` **Reusability for CLI Setup:** - ✅ **DIRECTLY REUSABLE** - Use as-is for validating CLI config file paths - **CLI Wrapper Needed:** CLI must validate `~/.code-executor-cli.json` is within allowed paths - **Gap:** No creation/modification checks (only read validation) ### 1.2 Directory Creation with Error Handling **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/audit-logger.ts` (lines 136-144) **Function:** `private async ensureLogDir(): Promise<void>` **Capabilities:** - Creates directory recursively (`{ recursive: true }`) - Wraps errors using `normalizeError()` helper (consistent error handling) - Provides descriptive error messages with path context **Implementation Details:** ```typescript private async ensureLogDir(): Promise<void> { try { await fs.mkdir(this.logDir, { recursive: true }); } catch (error) { const err = normalizeError(error); throw new Error(`Failed to create audit log directory ${this.logDir}: ${err.message}`); } } ``` **Reusability for CLI Setup:** - ✅ **DIRECTLY REUSABLE** - Pattern for creating `~/.code-executor/` directories - **Example:** Create lock file directory, state directory before CLI initialization - **Gap:** No permission checking (just creates if missing) ### 1.3 File Existence Checking **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/config-discovery.ts` (lines 317-324) **Function:** `private async fileExists(filePath: string): Promise<boolean>` **Capabilities:** - Uses `fs.access()` for non-blocking existence check - Returns boolean (graceful, no exceptions) - Uses `path.resolve()` for absolute paths **Implementation Details:** ```typescript private async fileExists(filePath: string): Promise<boolean> { try { await fs.access(path.resolve(filePath)); return true; } catch { return false; } } ``` **Reusability for CLI Setup:** - ✅ **DIRECTLY REUSABLE** - Use for checking lock file existence, config file presence - **CLI Wrapper Needed:** None, can use directly - **Gap:** Doesn't distinguish between "not exist" vs "no permission" ### 1.4 File Reading with Error Type Guards **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/schema-cache.ts` (lines 69-99) **Function:** `private async loadFromDisk(): Promise<void>` **Key Pattern - Type Guards:** ```typescript // TYPE-001 fix: Use isErrnoException type guard instead of unsafe cast if (!isErrnoException(error) || error.code !== 'ENOENT') { const err = normalizeError(error); console.error('⚠️ Failed to load schema cache from disk:', err.message); } ``` **Helper Functions:** - `isErrnoException(e: unknown): e is NodeJS.ErrnoException` (utils.ts, lines 254-261) - `isError(e: unknown): e is Error` (utils.ts, lines 232-234) - `normalizeError(error: unknown): Error` (utils.ts, lines 280-321) **Reusability for CLI Setup:** - ✅ **IMPORT & USE DIRECTLY** - Error type guards are reusable across the project - **CLI Use Case:** Safe file read operations in CLI setup (lock files, config backups) - **Gap:** None - patterns are well-tested --- ## 2. CONFIGURATION FILE MANAGEMENT ### 2.1 Config Discovery with Priority Ordering **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/config-discovery.ts` (entire file) **Class:** `ConfigDiscoveryService` **Capabilities:** - **Multi-source config merging** (env vars, project-level, user-level, defaults) - **Priority-based merging** with `deepMerge()` (later overrides earlier) - **Environment variable interpolation** (`env:VAR_NAME` syntax) - **Validation with Zod schemas** before returning config **Config Search Path Pattern:** ```typescript const CONFIG_SEARCH_PATHS = [ '.code-executor.json', // Project level (highest) path.join(homedir(), '.code-executor.json'), // User home path.join(homedir(), '.config', 'code-executor', 'config.json'), // XDG ]; ``` **Key Methods:** 1. `findConfig(): Promise<Config>` - Main entry point 2. `loadConfigFile(filePath): Promise<PartialConfig | null>` - Safe file load 3. `mergeConfigs(configs): PartialConfig` - Deep merge with priority 4. `validateConfig(config): Config` - Zod validation **Reusability for CLI Setup:** - ✅ **IMPORT & ADAPT** - Use priority-based merging pattern - **CLI Wrapper Needed:** Yes - CLI needs different search paths - CLI config: `.code-executor-cli.json` - Alternative: Merge into existing `~/.code-executor.json` - **Gap:** No backup creation (only reads) ### 2.2 JSON File Read/Write Pattern **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/schema-cache.ts` (lines 104-132) **Methods:** - `loadFromDisk()` - Read JSON with sorting and size limits (lines 69-99) - `saveToDisk()` - Write JSON with directory creation and AsyncLock protection (lines 104-132) **Key Pattern - AsyncLock Protection for Writes:** ```typescript private async saveToDisk(): Promise<void> { // Use lock to prevent concurrent writes (race condition fix) await this.lock.acquire('disk-write', async () => { // Ensure directory exists await fs.mkdir(path.dirname(this.cachePath), { recursive: true }); // Convert Map to JSON object const cacheObject = Object.fromEntries(this.cache.entries()); // Serialize and write const jsonPayload = JSON.stringify(cacheObject, null, 2); await fs.writeFile(this.cachePath, jsonPayload, 'utf-8'); }); } ``` **Reusability for CLI Setup:** - ✅ **IMPORT & USE DIRECTLY** - AsyncLock mutex pattern for thread-safe writes - **CLI Use Case:** Lock file management (PID-based locking), state file persistence - **Gap:** None - pattern is production-tested ### 2.3 Config Validation with Zod **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/config-types.ts` (example schema) **Pattern - Type-Safe Configuration:** ```typescript export const PoolConfigSchema = z.object({ maxConcurrent: z.number().int().min(1).max(1000).default(100), queueSize: z.number().int().min(1).max(1000).default(200), queueTimeoutMs: z.number().int().min(1000).max(300000).default(30000), }); export type PoolConfig = z.infer<typeof PoolConfigSchema>; ``` **Benefits:** - Type inference from schema (`z.infer<T>`) - Automatic coercion and validation - Clear error messages on validation failure - Default values built-in **Reusability for CLI Setup:** - ✅ **IMPORT & EXTEND** - Create CLI-specific schemas - **Example CLI Schema:** ```typescript export const CLISetupStateSchema = z.object({ initialized: z.boolean().default(false), version: z.string(), lockFilePath: z.string(), configFilePath: z.string(), }); ``` - **Gap:** Requires schema defined for each config type --- ## 3. LOCK FILE MANAGEMENT ### 3.1 Current Implementation Status **Finding:** No PID-based lock file implementation exists in code-executor-mcp. **Reason:** MCP server doesn't need distributed locking (single instance per home directory). **What Exists:** - **AsyncLock mutex** (in-memory) for concurrent write protection (lines 156-178 in audit-logger.ts) - Not suitable for CLI lock files (lost on process exit) ### 3.2 AsyncLock Usage Pattern (Applicable to CLI) **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/audit-logger.ts` (lines 74-102) **Pattern:** ```typescript private lock: AsyncLock; constructor(options: AuditLoggerOptions = {}) { // ... this.lock = new AsyncLock(); } async log(entry: AuditLogEntry): Promise<void> { await this.lock.acquire('log-write', async () => { // Protected operation await fs.appendFile(logPath, jsonLine, 'utf-8'); }); } ``` **Characteristics:** - Single lock name per resource (`'log-write'`, `'schema-cache-write'`) - Prevents concurrent writes to same file - Only protects within single process **Reusability for CLI Setup:** - ✅ **USEFUL FOR STATE PERSISTENCE** - Protect CLI state file writes - ❌ **NOT FOR CROSS-PROCESS LOCKING** - Use PID-based files instead - **CLI Implementation Needed:** ```typescript // PID-based lock file: ~/.code-executor/cli.lock interface PIDLockFile { pid: number; createdAt: string; // ISO 8601 timestamp hostname: string; } ``` ### 3.3 Lock File Design Recommendations Based on codebase patterns, recommended CLI lock file structure: ```typescript // File: ~/.code-executor/cli.lock { "pid": 12345, "createdAt": "2025-11-18T10:30:45.123Z", "hostname": "localhost", "lockVersion": "1.0" } // Cleanup pattern: async function cleanupLockFile(): Promise<void> { try { const lockPath = path.join(homeDir, '.code-executor', 'cli.lock'); await fs.unlink(lockPath); } catch (error) { // Ignore if not found (already cleaned up) if (isErrnoException(error) && error.code !== 'ENOENT') { console.warn('Failed to cleanup lock file:', error.message); } } } ``` --- ## 4. AUDIT LOGGING ### 4.1 Full Implementation **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/audit-logger.ts` **Class:** `AuditLogger implements IAuditLogger` **Capabilities:** 1. **Daily log rotation** - One file per day (`audit-YYYY-MM-DD.log`) 2. **JSONL format** - One JSON object per line (streaming-friendly) 3. **AsyncLock protection** - Thread-safe concurrent writes 4. **30-day retention** - Configurable via `AUDIT_LOG_RETENTION_DAYS` env var 5. **Automatic cleanup** - Deletes files older than retention period **Key Methods:** #### 1. Log Entry (lines 155-179) ```typescript async log(entry: AuditLogEntry): Promise<void> { await this.lock.acquire('log-write', async () => { await this.ensureLogDir(); const logPath = this.getLogPath(); const jsonLine = JSON.stringify(entry) + '\n'; await fs.appendFile(logPath, jsonLine, 'utf-8'); }); } ``` #### 2. Log Rotation (lines 213-225) ```typescript async rotate(): Promise<void> { await this.lock.acquire('log-write', async () => { // Invalidate cached log file path (protected by lock) this.currentLogFile = null; await this.ensureLogDir(); // Next log() call will get new filename }); } ``` #### 3. Cleanup (lines 235-277) ```typescript async cleanup(): Promise<void> { const files = await fs.readdir(this.logDir); const auditLogPattern = /^audit-(\d{4})-(\d{2})-(\d{2})\.log$/; const auditLogs = files.filter(f => auditLogPattern.test(f)); // Calculate cutoff date const cutoffDate = new Date(); cutoffDate.setDate(cutoffDate.getDate() - this.retentionDays); // Delete logs older than cutoff for (const filename of auditLogs) { // ... parse date from filename ... if (logDate < cutoffDate) { await fs.unlink(logPath); } } } ``` **Audit Log Entry Schema:** **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/interfaces/audit-logger.ts` ```typescript interface AuditLogEntry { timestamp: string; // ISO 8601 correlationId: string; // Request tracking eventType: string; // 'tool_call', 'discovery', etc. status: 'success' | 'failure' | 'timeout'; [key: string]: unknown; // Additional context } ``` **Reusability for CLI Setup:** - ✅ **IMPORT & USE DIRECTLY** - Use AuditLogger as-is for CLI events - **CLI Events to Log:** ```typescript // Event 1: Initialization await auditLogger.log({ timestamp: new Date().toISOString(), correlationId: generateCorrelationId(), eventType: 'cli_setup_start', status: 'success', cliVersion: CLI_VERSION, }); // Event 2: Config backup created await auditLogger.log({ timestamp: new Date().toISOString(), correlationId: correlationId, eventType: 'config_backup_created', status: 'success', backupPath: backupPath, originalPath: configPath, }); // Event 3: Lock acquired await auditLogger.log({ timestamp: new Date().toISOString(), correlationId: correlationId, eventType: 'lock_acquired', status: 'success', lockFilePath: lockPath, pid: process.pid, }); ``` - **Gap:** None - patterns are production-tested ### 4.2 Audit Logger Configuration **Environment Variables:** - `AUDIT_LOG_RETENTION_DAYS` (default: 30, range: 1-365) - `HOME` or `USERPROFILE` - Used for `~/.code-executor/audit-logs` path **Zod Validation (lines 48-52):** ```typescript const AuditLoggerEnvSchema = z.object({ HOME: z.string().optional(), USERPROFILE: z.string().optional(), AUDIT_LOG_RETENTION_DAYS: z.coerce.number().int().min(1).max(365).default(30), }); ``` **Reusability for CLI Setup:** - ✅ **IMPORT & EXTEND** - Add CLI-specific env vars if needed - CLI could use same audit logs (shared with MCP server) - Alternative: Separate CLI audit log directory if needed --- ## 5. ERROR HANDLING UTILITIES ### 5.1 Type Guards for Safe Error Handling **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/utils.ts` (lines 232-321) **Three Type Guards:** #### 1. `isError(e: unknown): e is Error` (lines 232-234) ```typescript export function isError(e: unknown): e is Error { return e instanceof Error; } ``` #### 2. `isErrnoException(e: unknown): e is NodeJS.ErrnoException` (lines 254-261) ```typescript export function isErrnoException(e: unknown): e is NodeJS.ErrnoException { return ( typeof e === 'object' && e !== null && 'code' in e && typeof (e as { code: unknown }).code === 'string' ); } ``` #### 3. `normalizeError(error: unknown): Error` (lines 280-321) ```typescript export function normalizeError(error: unknown): Error; export function normalizeError(error: unknown, context: string): Error; export function normalizeError(error: unknown, context?: string): Error { if (isError(error)) { return context ? new Error(`${context}: ${error.message}`) : error; } if (typeof error === 'string') { const message = context ? `${context}: ${error}` : error; return new Error(message); } // ... handle objects, primitives, etc ... } ``` **Reusability for CLI Setup:** - ✅ **IMPORT & USE DIRECTLY** - Use for all CLI error handling - **CLI Example:** ```typescript try { await createLockFile(lockPath); } catch (error) { if (isErrnoException(error) && error.code === 'EEXIST') { // Lock file already exists const existingPID = await readLockFile(lockPath); console.error(`Another CLI instance (PID ${existingPID}) is running`); } else { const err = normalizeError(error, 'Failed to create lock file'); console.error(err.message); } } ``` - **Gap:** None - patterns are well-tested --- ## 6. IMPLEMENTATION RECOMMENDATIONS ### 6.1 What to Import Directly | Component | File | Reusable | Notes | |-----------|------|----------|-------| | `isAllowedPath()` | utils.ts | ✅ Yes | Use for path validation | | `isError()` | utils.ts | ✅ Yes | Type guard pattern | | `isErrnoException()` | utils.ts | ✅ Yes | Filesystem error handling | | `normalizeError()` | utils.ts | ✅ Yes | Error normalization | | `AuditLogger` class | audit-logger.ts | ✅ Yes | Log rotation, retention | | `AsyncLock` pattern | audit-logger.ts | ✅ Yes | Mutex for state files | | Zod validation pattern | config-types.ts | ✅ Yes | Config validation | ### 6.2 What to Adapt | Component | File | Adaptation | Purpose | |-----------|------|-----------|---------| | `ConfigDiscoveryService` | config-discovery.ts | Fork patterns, customize search paths | CLI config discovery | | Directory creation pattern | audit-logger.ts | Adapt `ensureLogDir()` | Create CLI state directories | | JSONL format pattern | audit-logger.ts | Use for CLI state persistence | Store CLI setup state | ### 6.3 What to Implement New | Component | Reason | Implementation Guide | |-----------|--------|----------------------| | PID-based lock file | Not in codebase | Use JSON format, cleanup on exit | | Config backup | Not in codebase | Save `~/.code-executor.json` before CLI init | | CLI state persistence | Not in codebase | Use AuditLogger as reference | | Signal handlers | Not in codebase | Use patterns from `graceful-shutdown-handler.ts` | ### 6.4 File Organization Suggestion For CLI setup infrastructure: ``` src/ ├── cli/ │ ├── setup.ts # Main CLI setup orchestrator │ ├── init.ts # Initialization entry point │ ├── lock-file.ts # PID-based lock management │ ├── config-backup.ts # Config file backup creation │ ├── state-manager.ts # CLI state persistence │ └── cleanup-handlers.ts # Signal handlers, cleanup ├── audit-logger.ts # (existing - reuse) ├── config-discovery.ts # (existing - patterns) └── utils.ts # (existing - type guards) ``` --- ## 7. EXISTING GRACEFUL SHUTDOWN PATTERN **File:** `/home/alexandrueremia/projects/code-executor-mcp/src/graceful-shutdown-handler.ts` While not directly examined in detail, this file likely contains: - Signal handler patterns (`SIGTERM`, `SIGINT`) - Cleanup coordination - Resource release patterns **Recommendation:** Review and adapt for CLI cleanup (lock file removal, state flush). --- ## 8. SUMMARY MATRIX | Category | Implementation | Reusability | Effort | |----------|---|---|---| | **Filesystem Operations** | Path validation, directory creation, file checks | ✅ Direct | Low | | **Config Management** | Discovery, merging, validation | ✅ Adapt | Medium | | **Lock Files** | AsyncLock in-memory, NO PID-based | ⚠️ Partial | High | | **Audit Logging** | Full rotation, retention, cleanup | ✅ Direct | Low | | **Error Handling** | Type guards, normalization | ✅ Direct | Low | | **State Persistence** | JSONL format, AsyncLock | ✅ Adapt | Low | --- ## 9. CRITICAL ARCHITECTURAL PATTERNS ### Pattern 1: AsyncLock for Concurrent Writes ```typescript import AsyncLock from 'async-lock'; private lock = new AsyncLock(); async updateState() { await this.lock.acquire('state-write', async () => { // Safe write operation }); } ``` ### Pattern 2: Zod for Type-Safe Config ```typescript const schema = z.object({ field: z.string().min(1), count: z.number().int().min(1).max(100).default(10), }); const validated = schema.parse(config); // Type inference: typeof validated ``` ### Pattern 3: Error Type Guards ```typescript catch (error) { if (isErrnoException(error) && error.code === 'ENOENT') { // Handle missing file } else if (isError(error)) { // Handle Error } } ``` ### Pattern 4: Environment Variable Validation ```typescript const envSchema = z.object({ HOME: z.string().optional(), VALUE: z.coerce.number().int().min(1).max(365).default(30), }); const env = envSchema.parse(process.env); ``` --- ## 10. DEPENDENCIES TO IMPORT For CLI setup infrastructure, import from existing code-executor-mcp: ```typescript // Error handling import { normalizeError, isError, isErrnoException } from './utils.js'; // Filesystem operations import { isAllowedPath } from './utils.js'; // Audit logging import { AuditLogger, type AuditLogEntry } from './audit-logger.js'; // Configuration patterns import { ConfigDiscoveryService } from './config-discovery.js'; import { type Config, ConfigSchema } from './config-types.js'; // Concurrency control import AsyncLock from 'async-lock'; // Validation import { z } from 'zod'; ``` --- ## Conclusion The code-executor-mcp codebase provides **production-grade, well-tested patterns** for: 1. ✅ Filesystem operations with security validation 2. ✅ Configuration management with priority merging 3. ✅ Audit logging with rotation and retention 4. ✅ Error handling with type guards 5. ✅ Concurrent access protection with AsyncLock **Lock file management** is the main gap - no PID-based implementation exists, requiring new implementation for CLI setup. **Total reusable code:** ~60% of CLI setup infrastructure can be imported directly or adapted from existing patterns.

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/aberemia24/code-executor-MCP'

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