mcp-workflow-server-enhanced
Version:
Enhanced MCP Workflow Server with smart problem routing, comprehensive validation, guide compliance, and robust error handling. Intelligently routes to appropriate AI functions based on problem type.
167 lines (144 loc) • 3.83 kB
text/typescript
import { randomUUID } from 'crypto';
import { WorkflowContext, WorkflowError } from './types.js';
/**
* Generate a unique session ID for workflow tracking
*/
export function generateSessionId(): string {
return randomUUID();
}
/**
* Create a new workflow context
*/
export function createWorkflowContext(
originalPrompt: string,
currentStep: WorkflowContext['currentStep']
): WorkflowContext {
return {
sessionId: generateSessionId(),
originalPrompt,
currentStep,
stepResults: {},
metadata: {},
timestamp: new Date().toISOString(),
};
}
/**
* Update workflow context with step results
*/
export function updateWorkflowContext(
context: WorkflowContext,
step: string,
result: any,
nextStep?: WorkflowContext['currentStep']
): WorkflowContext {
return {
...context,
currentStep: nextStep || context.currentStep,
stepResults: {
...context.stepResults,
[step]: result,
},
timestamp: new Date().toISOString(),
};
}
/**
* Validate and sanitize user input
*/
export function sanitizeInput(input: string): string {
return input.trim().replace(/[<>]/g, '');
}
/**
* Format error messages for user display
*/
export function formatError(error: Error): string {
if (error instanceof WorkflowError) {
return `Error in ${error.step}: ${error.message}`;
}
return `Error: ${error.message}`;
}
/**
* Deep clone an object
*/
export function deepClone<T>(obj: T): T {
return JSON.parse(JSON.stringify(obj));
}
/**
* Retry a function with exponential backoff
*/
export async function retryWithBackoff<T>(
fn: () => Promise<T>,
maxRetries: number = 3,
baseDelay: number = 1000
): Promise<T> {
let lastError: Error;
for (let attempt = 0; attempt <= maxRetries; attempt++) {
try {
return await fn();
} catch (error) {
lastError = error as Error;
if (attempt === maxRetries) {
throw lastError;
}
const delay = baseDelay * Math.pow(2, attempt);
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError!;
}
/**
* Validate that required environment variables are set
*/
export function validateEnvironment(requiredVars: string[]): void {
const missing = requiredVars.filter(varName => !process.env[varName]);
if (missing.length > 0) {
throw new Error(`Missing required environment variables: ${missing.join(', ')}`);
}
}
/**
* Create a standardized response format
*/
export function createResponse(success: boolean, data: any, message?: string) {
return {
success,
data,
message,
timestamp: new Date().toISOString(),
};
}
/**
* Log workflow progress
*/
export function logWorkflowProgress(
context: WorkflowContext,
step: string,
message: string
): void {
console.log(`[${context.sessionId}] ${step}: ${message}`);
}
/**
* Extract key information from text using simple patterns
*/
export function extractKeyInfo(text: string): {
requirements: string[];
constraints: string[];
goals: string[];
} {
const requirements: string[] = [];
const constraints: string[] = [];
const goals: string[] = [];
// Simple pattern matching for common requirement indicators
const lines = text.split('\n');
for (const line of lines) {
const trimmed = line.trim().toLowerCase();
if (trimmed.includes('need') || trimmed.includes('require') || trimmed.includes('must')) {
requirements.push(line.trim());
}
if (trimmed.includes('cannot') || trimmed.includes('should not') || trimmed.includes('constraint')) {
constraints.push(line.trim());
}
if (trimmed.includes('goal') || trimmed.includes('objective') || trimmed.includes('want to')) {
goals.push(line.trim());
}
}
return { requirements, constraints, goals };
}