ai-debug-local-mcp
Version:
๐ฏ ENHANCED AI GUIDANCE v4.1.2: Dramatically improved tool descriptions help AI users choose the right tools instead of 'close enough' options. Ultra-fast keyboard automation (10x speed), universal recording, multi-ecosystem debugging support, and compreh
248 lines (232 loc) โข 9.88 kB
JavaScript
import { BaseToolHandler } from './base-handler.js';
/**
* Handler for fault injection tools
*/
export class FaultHandler extends BaseToolHandler {
faultEngine;
constructor(faultEngine) {
super();
this.faultEngine = faultEngine;
}
tools = [
{
name: 'inject_fault',
description: 'Inject a fault into the debugging session to test application resilience',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'The debug session ID'
},
faultType: {
type: 'string',
enum: [
'network_latency',
'network_timeout',
'network_disconnection',
'packet_loss',
'memory_pressure',
'cpu_spike',
'disk_space',
'database_error',
'api_downtime',
'service_degradation'
],
description: 'Type of fault to inject'
},
config: {
type: 'object',
description: 'Fault-specific configuration',
properties: {
latencyMs: { type: 'number', description: 'Latency in milliseconds (for NETWORK_LATENCY)' },
timeoutMs: { type: 'number', description: 'Timeout in milliseconds (for NETWORK_TIMEOUT)' },
lossPercentage: { type: 'number', description: 'Packet loss percentage 0-100 (for PACKET_LOSS)' },
limitMB: { type: 'number', description: 'Memory limit in MB (for MEMORY_PRESSURE)' },
intensity: { type: 'number', description: 'CPU intensity 0-1 (for CPU_SPIKE)' },
durationMs: { type: 'number', description: 'Duration in milliseconds (for CPU_SPIKE)' },
availableKB: { type: 'number', description: 'Available disk space in KB (for DISK_SPACE)' },
errorRate: { type: 'number', description: 'Error rate 0-1 (for DATABASE_ERROR)' },
statusCode: { type: 'number', description: 'HTTP status code (for API_DOWNTIME)' },
degradationFactor: { type: 'number', description: 'Service degradation factor 0-1 (for SERVICE_DEGRADATION)' },
urlPattern: { type: 'string', description: 'URL pattern for network/service faults (e.g., "**/*.json", "**/api/**")' }
}
}
},
required: ['sessionId', 'faultType', 'config']
}
},
{
name: 'remove_fault',
description: 'Remove a specific injected fault',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'The debug session ID'
},
faultId: {
type: 'string',
description: 'The fault ID to remove'
}
},
required: ['sessionId', 'faultId']
}
},
{
name: 'clear_all_faults',
description: 'Remove all injected faults from the session',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'The debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'list_active_faults',
description: 'List all currently active faults in the session',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'The debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'generate_fault_scenarios',
description: 'Generate recommended fault injection test scenarios',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'The debug session ID'
}
},
required: ['sessionId']
}
}
];
async handle(toolName, args, sessions) {
const session = this.getSession(args.sessionId, sessions);
switch (toolName) {
case 'inject_fault':
return this.injectFault(args, session);
case 'remove_fault':
return this.removeFault(args, session);
case 'clear_all_faults':
return this.clearAllFaults(args, session);
case 'list_active_faults':
return this.listActiveFaults(args, session);
case 'generate_fault_scenarios':
return this.generateFaultScenarios(args, session);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
async injectFault(args, session) {
const { faultType, config } = args;
try {
// Create fault object matching the engine's expected format
const fault = {
type: faultType,
config: config
};
const faultId = await this.faultEngine.injectFault(session.page, fault);
return this.createTextResponse(`โ
**Fault Injected Successfully**
**Fault ID:** ${faultId}
**Type:** ${faultType}
**Status:** active
**Configuration:**
${this.formatConfig(config)}
The fault is now active. Monitor your application's behavior under this failure condition.
๐ก **Tips:**
- Use \`list_active_faults\` to see all active faults
- Use \`remove_fault\` with the fault ID to stop this specific fault
- Use \`clear_all_faults\` to remove all faults at once`);
}
catch (error) {
throw new Error(`Failed to inject fault: ${error instanceof Error ? error.message : error}`);
}
}
async removeFault(args, session) {
const { faultId } = args;
try {
await this.faultEngine.removeFault(session.page, faultId);
return this.createTextResponse(`โ
**Fault Removed Successfully**
**Fault ID:** ${faultId}
The fault has been deactivated and normal behavior restored.`);
}
catch (error) {
throw new Error(`Failed to remove fault: ${error instanceof Error ? error.message : error}`);
}
}
async clearAllFaults(args, session) {
try {
// Get count of active faults before clearing
const activeFaults = this.faultEngine.getActiveFaults();
const count = activeFaults.length;
await this.faultEngine.clearAllFaults(session.page);
return this.createTextResponse(`๐งน **All Faults Cleared**
**Removed:** ${count} fault${count !== 1 ? 's' : ''}
All injected faults have been removed. Your application is now running normally.`);
}
catch (error) {
throw new Error(`Failed to clear faults: ${error instanceof Error ? error.message : error}`);
}
}
async listActiveFaults(args, session) {
try {
const faults = this.faultEngine.getActiveFaults();
if (faults.length === 0) {
return this.createTextResponse(`๐ **No Active Faults**
There are currently no injected faults in this session.
Use \`inject_fault\` to add failure conditions for testing.`);
}
const faultList = faults.map(fault => `**${fault.id}** (${fault.fault.type})
Timestamp: ${new Date(fault.timestamp).toLocaleString()}
Config: ${JSON.stringify(fault.fault.config)}`).join('\n\n');
return this.createTextResponse(`๐ **Active Faults: ${faults.length}**
${faultList}
๐ก **Actions:**
- Use \`remove_fault\` with a fault ID to remove specific faults
- Use \`clear_all_faults\` to remove all faults at once`);
}
catch (error) {
throw new Error(`Failed to list faults: ${error instanceof Error ? error.message : error}`);
}
}
async generateFaultScenarios(args, session) {
try {
const scenarios = await this.faultEngine.generateTestScenarios();
const scenarioList = scenarios.map(scenario => `### ${scenario.name}
**Expected Behavior:** ${scenario.expectedBehavior}
**Faults to inject:**
${scenario.faults.map(f => `- ${f.type}: ${JSON.stringify(f.config)}`).join('\n')}`).join('\n\n');
return this.createTextResponse(`๐ฏ **Recommended Fault Scenarios**
Based on your application type and common failure patterns:
${scenarioList}
๐ก **Usage:**
Copy the fault configurations above and use them with \`inject_fault\` to test these scenarios.`);
}
catch (error) {
throw new Error(`Failed to generate scenarios: ${error instanceof Error ? error.message : error}`);
}
}
formatConfig(config) {
return Object.entries(config)
.map(([key, value]) => `- **${key}:** ${value}`)
.join('\n');
}
}
//# sourceMappingURL=fault-handler.js.map