LogoSkills

flutter-inspector-log

Log debugging specialist. Use for app log collection and error tracking

항ëĒŠë‚´ėšŠ
ToolsRead, Glob, Grep
Modelhaiku
Skillsflutter-inspector

Flutter Inspector - Log Agent#

A specialized agent for managing and analyzing app logs at runtime.

Triggers#

Automatically activated when @flutter-inspector-log is invoked or the following keywords are detected:

  • Log, debug message
  • Error log, warning
  • Log search, filtering

MCP Tools#

log_get_recent#

Returns recent logs.

{
   " name " :  " log_get_recent " ,
   " description " :  " Retrieve recent logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " limit " : {
         " type " :  " integer " ,
         " description " :  " Maximum count " ,
         " default " : 50
      },
       " level " : {
         " type " :  " string " ,
         " description " :  " Filter: log level (debug, info, warning, error) " ,
         " enum " : [ " debug " ,  " info " ,  " warning " ,  " error " ]
      }
    }
  }
}

Response example:

{
   " logs " : [
    {
       " timestamp " :  " 2024-01-01T10:00:00Z " ,
       " level " :  " info " ,
       " tag " :  " AuthBloc " ,
       " message " :  " User logged in successfully " ,
       " data " : { " userId " : 123}
    },
    {
       " timestamp " :  " 2024-01-01T10:00:05Z " ,
       " level " :  " error " ,
       " tag " :  " NetworkService " ,
       " message " :  " Request failed " ,
       " data " : { " url " :  " /api/users " ,  " statusCode " : 500}
    }
  ],
   " totalCount " : 2
}

log_get_errors#

Filters and returns only error logs.

{
   " name " :  " log_get_errors " ,
   " description " :  " Retrieve error logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " limit " : {
         " type " :  " integer " ,
         " description " :  " Maximum count " ,
         " default " : 20
      },
       " includeStackTrace " : {
         " type " :  " boolean " ,
         " description " :  " Whether to include stack trace " ,
         " default " : true
      }
    }
  }
}

Response example:

{
   " errors " : [
    {
       " timestamp " :  " 2024-01-01T10:00:05Z " ,
       " tag " :  " UserRepository " ,
       " message " :  " Failed to fetch user " ,
       " error " :  " SocketException: Connection refused " ,
       " stackTrace " :  " ... " ,
       " context " : { " userId " : 123,  " attempt " : 3}
    }
  ],
   " errorCount " : 1
}

Searches for specific patterns in logs.

{
   " name " :  " log_search " ,
   " description " :  " Search logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " query " : {
         " type " :  " string " ,
         " description " :  " Search string " 
       },
       " tag " : {
         " type " :  " string " ,
         " description " :  " Filter: tag name " 
       },
       " limit " : {
         " type " :  " integer " ,
         " description " :  " Maximum count " ,
         " default " : 50
      }
    },
     " required " : [ " query " ]
  }
}

log_get_stats#

Returns log statistics.

{
   " name " :  " log_get_stats " ,
   " description " :  " Log statistics " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {}
  }
}

Response example:

{
   " stats " : {
     " totalLogs " : 500,
     " byLevel " : {
       " debug " : 200,
       " info " : 250,
       " warning " : 30,
       " error " : 20
    },
     " topTags " : [
      { " tag " :  " AuthBloc " ,  " count " : 50},
      { " tag " :  " NetworkService " ,  " count " : 45},
      { " tag " :  " HomeBloc " ,  " count " : 40}
    ],
     " recentErrors " : 5
  },
   " period " :  " session " 
 }

log_clear#

Clears logs.

{
   " name " :  " log_clear " ,
   " description " :  " Clear logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " level " : {
         " type " :  " string " ,
         " description " :  " Delete only a specific level (omit for all) " 
       }
    }
  }
}

App Integration Code#

// lib/debug/mcp_log_tools.dart
import 'package:mcp_toolkit/mcp_toolkit.dart';
import 'package:logger/logger.dart';

class MCPLogOutput extends LogOutput {
  final _logs = <Map<String, dynamic>>[];
  static final instance = MCPLogOutput._();
  MCPLogOutput._();

  @override
  void output(OutputEvent event) {
    final log = {
      'timestamp': DateTime.now().toIso8601String(),
      'level': event.level.name,
      'lines': event.lines,
    };
    _logs.add(log);

    // Keep maximum 1000 entries
    if (_logs.length > 1000) {
      _logs.removeAt(0);
    }
  }

  List<Map<String, dynamic>> getLogs({int? limit, String? level}) {
    var filtered = _logs.toList();
    if (level != null) {
      filtered = filtered.where((l) => l['level'] == level).toList();
    }
    return filtered.reversed.take(limit ?? 50).toList();
  }

  List<Map<String, dynamic>> getErrors({int? limit}) {
    return _logs
        .where((l) => l['level'] == 'error' || l['level'] == 'wtf')
        .toList()
        .reversed
        .take(limit ?? 20)
        .toList();
  }

  List<Map<String, dynamic>> search(String query, {String? tag, int? limit}) {
    return _logs
        .where((l) => l['lines'].toString().contains(query))
        .where((l) => tag == null || l['tag'] == tag)
        .toList()
        .reversed
        .take(limit ?? 50)
        .toList();
  }

  Map<String, dynamic> getStats() {
    final byLevel = <String, int>{};
    for (final log in _logs) {
      final level = log['level'] as String;
      byLevel[level] = (byLevel[level] ?? 0) + 1;
    }
    return {
      'totalLogs': _logs.length,
      'byLevel': byLevel,
    };
  }

  void clear({String? level}) {
    if (level != null) {
      _logs.removeWhere((l) => l['level'] == level);
    } else {
      _logs.clear();
    }
  }
}

void registerLogTools() {
  if (!kDebugMode) return;

  addMcpTool(MCPCallEntry.tool(
    handler: (params) => MCPCallResult(
      message: 'Recent logs',
      parameters: {
        'logs': MCPLogOutput.instance.getLogs(
          limit: params['limit'] as int?,
          level: params['level'] as String?,
        ),
      },
    ),
    definition: MCPToolDefinition(
      name: 'log_get_recent',
      description: 'Retrieve recent logs',
      inputSchema: {
        'type': 'object',
        'properties': {
          'limit': {'type': 'integer'},
          'level': {'type': 'string'},
        },
      },
    ),
  ));

  // log_get_errors, log_search, log_get_stats, log_clear are implemented similarly
}

Usage Examples#

Check recent logs#

Q: Show me recent logs
A: Run log_get_recent limit=20
   - >   20 logs (15 info, 3 warning, 2 error)

Check error logs#

Q: Show me only error logs
A: Run log_get_errors
   - >   2 errors: SocketException, FormatException

Search specific keywords#

Q: Find authentication related logs
A: Run log_search query= " auth " 
    - >   15 logs related to AuthBloc, AuthRepository

Log statistics#

Q: Summarize the log status
A: Run log_get_stats
   - >   Total 500, 20 errors, top tags: AuthBloc, NetworkService

Common Problem Diagnosis#

Recurring errors#

1. Check error patterns with log_get_errors
2. Confirm repeated occurrences from the same tag
3. Analyze error context

Performance issue tracking#

1. log_search query= " slow "   or  " timeout " 
 2. Analyze logs around relevant timeframes
3. Identify bottleneck points

App crash cause#

1. Check last error with log_get_errors
2. Analyze stack trace
3. Trace logs immediately before the error
  • @flutter-inspector: Master inspector
  • @flutter-inspector-network: Network related logs
  • @flutter-inspector-bloc: BLoC state change tracking