Skip to main content
Glama

MCP-REPL

by AnEntrypoint
MIT License
3,295
104
  • Linux
  • Apple
execution-state.js5.05 kB
// Shared execution state management for cross-tool status sharing import { v4 as uuidv4 } from 'uuid'; export class ExecutionState { constructor() { this.executions = new Map(); this.currentExecution = null; } // Start tracking a new execution startExecution({ id = uuidv4(), type = 'execute', code = null, commands = null, runtime = null, workingDirectory = null, startTime = Date.now(), timeout = 120000 } = {}) { const execution = { id, type, code, commands, runtime, workingDirectory, startTime, timeout, status: 'running', progress: 0, result: null, error: null }; this.executions.set(id, execution); this.currentExecution = id; return execution; } // Complete an execution with result completeExecution(id, result) { const execution = this.executions.get(id); if (execution) { execution.status = 'completed'; execution.endTime = Date.now(); execution.duration = execution.endTime - execution.startTime; execution.result = result; execution.progress = 100; // Keep current execution reference if it completed quickly if (this.currentExecution === id && execution.duration < 3000) { // Keep as current for cross-tool sharing } else if (this.currentExecution === id) { // Clear current if it was a long execution this.currentExecution = null; } } return execution; } // Fail an execution failExecution(id, error) { const execution = this.executions.get(id); if (execution) { execution.status = 'failed'; execution.endTime = Date.now(); execution.duration = execution.endTime - execution.startTime; execution.error = error; this.currentExecution = null; } return execution; } // Get current execution (for cross-tool sharing) getCurrentExecution() { if (!this.currentExecution) return null; const execution = this.executions.get(this.currentExecution); // Clear current if it's too old (more than 10 seconds) if (execution && Date.now() - execution.startTime > 10000) { this.currentExecution = null; return null; } return execution; } // Get execution by ID getExecution(id) { return this.executions.get(id); } // Format execution status for tool output formatExecutionStatus(execution) { if (!execution) return null; const lines = []; lines.push('🔧 EXECUTION STATUS:'); lines.push(`• ID: ${execution.id}`); lines.push(`• Status: ${execution.status.toUpperCase()}`); lines.push(`• Runtime: ${execution.runtime || 'unknown'}`); lines.push(`• Duration: ${execution.duration || Date.now() - execution.startTime}ms`); if (execution.result) { lines.push(`• Result: ${execution.result.success ? 'SUCCESS' : 'FAILED'}`); if (execution.result.stdout) { lines.push(`• Output: ${execution.result.stdout.substring(0, 100)}${execution.result.stdout.length > 100 ? '...' : ''}`); } } if (execution.error) { lines.push(`• Error: ${execution.error.message || execution.error}`); } return lines.join('\n'); } // Clean up old executions cleanup() { const now = Date.now(); const toDelete = []; for (const [id, execution] of this.executions) { // Delete executions older than 1 hour or completed fast executions older than 1 minute const age = now - execution.startTime; if (age > 3600000 || (execution.status === 'completed' && execution.duration < 3000 && age > 60000)) { toDelete.push(id); } } toDelete.forEach(id => { this.executions.delete(id); if (this.currentExecution === id) { this.currentExecution = null; } }); } } // Global instance export const executionState = new ExecutionState(); // Middleware function to add execution status ONLY to execute tool responses export function addExecutionStatusToResponse(toolResponse, toolName) { const currentExecution = executionState.getCurrentExecution(); // Only add execution status for execute tool responses if (!currentExecution || currentExecution.type !== 'execute' || toolName !== 'execute') { return toolResponse; } const statusText = executionState.formatExecutionStatus(currentExecution); if (!statusText) return toolResponse; // Add execution status as a prefix to the response if (toolResponse.content && toolResponse.content[0] && toolResponse.content[0].type === 'text') { const originalText = toolResponse.content[0].text; toolResponse.content[0].text = `${statusText}\n\n${toolName.toUpperCase()} RESULTS:\n\n${originalText}`; } return toolResponse; } // Helper function to determine if execution should be async (purely time-based) export function shouldExecuteAsync(estimatedDuration, code, commands) { // Always async if estimated duration is over 3 seconds return estimatedDuration > 3000; }

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/AnEntrypoint/mcp-repl'

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