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
275 lines ⢠12.6 kB
JavaScript
import { BaseToolHandler } from '../base-handler.js';
export class FlutterQuantumHandler extends BaseToolHandler {
localEngine;
quantumDebugger;
constructor(localEngine, quantumDebugger) {
super();
this.localEngine = localEngine;
this.quantumDebugger = quantumDebugger;
}
get tools() {
return [
{
name: 'flutter_quantum_interact',
description: 'Advanced natural language Flutter interaction. Works with ANY Flutter web app without hardcoded coordinates. Examples: "click Submit Report button", "type John Doe in name field", "select California from state dropdown"',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
command: {
type: 'string',
description: 'Natural language command like "click Submit button" or "type hello in search field"'
}
},
required: ['sessionId', 'command']
}
},
{
name: 'flutter_quantum_analyze',
description: 'Analyze Flutter semantic tree and UI structure. Returns detailed information about all interactable elements, forms, and navigation.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
},
{
name: 'flutter_quantum_find',
description: 'Find Flutter elements by text or label. Returns coordinates and properties of matching elements.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
},
searchText: {
type: 'string',
description: 'Text to search for in Flutter UI'
}
},
required: ['sessionId', 'searchText']
}
},
{
name: 'flutter_enable_accessibility',
description: 'Enable Flutter accessibility tree for better element detection. This is required for most Flutter web apps to expose their UI elements for testing.',
inputSchema: {
type: 'object',
properties: {
sessionId: {
type: 'string',
description: 'Debug session ID'
}
},
required: ['sessionId']
}
}
];
}
async handle(toolName, args, sessions) {
const session = sessions.get(args.sessionId);
if (!session) {
throw new Error('Session not found');
}
if (session.framework !== 'flutter' && session.framework !== 'flutter-web') {
throw new Error('This tool only works with Flutter Web applications');
}
switch (toolName) {
case 'flutter_quantum_interact':
return this.quantumInteract(session, args.command);
case 'flutter_quantum_analyze':
return this.quantumAnalyze(session);
case 'flutter_quantum_find':
return this.quantumFind(session, args.searchText);
case 'flutter_enable_accessibility':
return this.enableAccessibility(session);
default:
throw new Error(`Unknown tool: ${toolName}`);
}
}
async quantumInteract(session, command) {
try {
const result = await this.quantumDebugger.interact(session.id, command);
if (!result.success) {
return {
content: [{
type: 'text',
text: `ā **Interaction Failed**\n\nError: ${result.error || 'Unknown error'}\n\nš” **Tip:** Try \`flutter_quantum_analyze\` to see available elements.`
}]
};
}
let details = `ā
**Interaction Successful**\n\n`;
details += `**Command:** ${command}\n`;
// Parse command to extract action details
const lowerCommand = command.toLowerCase();
if (lowerCommand.includes('click')) {
const target = command.replace(/^click\s+/i, '');
details += `**Clicked on:** ${target}\n`;
}
else if (lowerCommand.includes('type')) {
const match = command.match(/type\s+(.+?)\s+in\s+(.+)/i);
if (match) {
details += `**Typed:** ${match[1]}\n`;
details += `**Into:** ${match[2]}\n`;
}
}
if (result.method) {
details += `**Method:** ${result.method}\n`;
}
return {
content: [{
type: 'text',
text: details
}]
};
}
catch (error) {
throw new Error(`Failed to interact with Flutter app: ${error.message}`);
}
}
async quantumAnalyze(session) {
try {
const quantumSession = await this.quantumDebugger.getSession(session.id);
if (!quantumSession) {
throw new Error('Quantum debugging session not initialized. Please run flutter_quantum_interact first.');
}
const structure = quantumSession.structure;
let analysis = `š **Flutter UI Analysis**\n\n`;
// Navigation elements
if (structure.navigation?.navigationElements?.length > 0) {
analysis += `**š± Navigation Elements:**\n`;
structure.navigation.navigationElements.forEach((nav) => {
analysis += ` ⢠${nav.label}\n`;
});
analysis += '\n';
}
// Forms
if (structure.forms?.length > 0) {
analysis += `**š Forms Detected:**\n`;
structure.forms.forEach((form) => {
analysis += ` ⢠${form.name}:\n`;
form.fields.forEach((field) => {
analysis += ` - ${field.label}\n`;
});
});
analysis += '\n';
}
// Detected elements count
const elementCount = quantumSession.detectedElements?.length || 0;
analysis += `**šÆ Total Elements:** ${elementCount} interactive elements detected\n\n`;
analysis += `š” **Usage Tips:**\n`;
analysis += `⢠Use \`flutter_quantum_find "text"\` to search for specific elements\n`;
analysis += `⢠Use \`flutter_quantum_interact "action"\` to interact with elements\n`;
analysis += `⢠Natural language commands work best (e.g., "click Submit button")`;
return {
content: [{
type: 'text',
text: analysis
}]
};
}
catch (error) {
throw new Error(`Failed to analyze Flutter UI: ${error.message}`);
}
}
async quantumFind(session, searchText) {
try {
const quantumSession = await this.quantumDebugger.getSession(session.id);
if (!quantumSession) {
throw new Error('Quantum debugging session not initialized. Please run flutter_quantum_interact first.');
}
// Search through detected elements
const matchingElements = quantumSession.detectedElements?.filter((element) => {
const label = element.label?.toLowerCase() || '';
const search = searchText.toLowerCase();
return label.includes(search);
}) || [];
let result = `š **Flutter Element Search**\n\n`;
result += `**Search Term:** "${searchText}"\n`;
result += `**Found:** ${matchingElements.length} element(s)\n\n`;
if (matchingElements.length === 0) {
result += `No elements found matching "${searchText}".\n\n`;
result += `š” **Tips:**\n`;
result += `⢠Try a partial search term\n`;
result += `⢠Use \`flutter_quantum_analyze\` to see all available elements\n`;
result += `⢠Ensure accessibility is enabled with \`flutter_enable_accessibility\``;
}
else {
result += `**š Matching Elements:**\n`;
matchingElements.slice(0, 5).forEach((element) => {
result += `\n⢠**${element.label}**\n`;
result += ` Type: ${element.type || 'Unknown'}\n`;
if (element.bounds) {
result += ` Location: (${element.bounds.left}, ${element.bounds.top})\n`;
result += ` Size: ${element.bounds.width}x${element.bounds.height}\n`;
}
result += ` Interaction: flutter_quantum_interact "${element.interactionHint || 'click ' + element.label}"\n`;
});
if (matchingElements.length > 5) {
result += `\n... and ${matchingElements.length - 5} more results`;
}
}
return {
content: [{
type: 'text',
text: result
}]
};
}
catch (error) {
throw new Error(`Failed to find Flutter elements: ${error.message}`);
}
}
async enableAccessibility(session) {
try {
// Check if we already have a quantum session
let quantumSession = await this.quantumDebugger.getSession(session.id);
// If no session exists, initialize one
if (!quantumSession) {
quantumSession = await this.quantumDebugger.initialize(session.page, session.id);
}
let response = `āæ **Flutter Accessibility**\n\n`;
if (quantumSession) {
response += `ā
**Accessibility Enabled Successfully**\n\n`;
const elementsFound = quantumSession.detectedElements?.length || 0;
response += `**Elements Found:** ${elementsFound}\n`;
if (quantumSession.structure) {
const nodeCount = quantumSession.structure.forms?.length || 0 +
quantumSession.structure.navigation?.navigationElements?.length || 0;
response += `**Semantic nodes created:** ${nodeCount}\n\n`;
}
response += `**Improvements:**\n`;
response += `- Better element detection for natural language interactions\n`;
response += `- More accurate click targets\n`;
response += `- Improved form field identification\n\n`;
}
else {
response += `ā ļø **Failed to Enable Accessibility**\n\n`;
response += `Could not initialize Flutter debugging session.\n\n`;
}
response += `š” **Next Steps:**\n`;
response += `- Use \`flutter_quantum_analyze\` to see all available elements\n`;
response += `- Use \`flutter_quantum_find\` to search for specific elements\n`;
response += `- Use \`flutter_quantum_interact\` to interact with elements`;
return {
content: [{
type: 'text',
text: response
}]
};
}
catch (error) {
throw new Error(`Failed to enable Flutter accessibility: ${error.message}`);
}
}
}
//# sourceMappingURL=flutter-quantum-handler.js.map