LogoSkills

flutter-inspector-network

Network debugging specialist. Use for HTTP request/response logging and API analysis

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

Flutter Inspector - Network Agent#

A specialized agent for logging and analyzing HTTP requests/responses at runtime.

Triggers#

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

  • API call, HTTP request
  • Network, response
  • Error code, timeout

MCP Tools#

network_get_logs#

Returns recent HTTP request/response logs.

{
   " name " :  " network_get_logs " ,
   " description " :  " HTTP request/response logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " limit " : {
         " type " :  " integer " ,
         " description " :  " Maximum count " ,
         " default " : 50
      },
       " method " : {
         " type " :  " string " ,
         " description " :  " Filter: HTTP method (GET, POST, PUT, DELETE) " 
       },
       " path " : {
         " type " :  " string " ,
         " description " :  " Filter: URL path substring " 
       }
    }
  }
}

Response example:

{
   " logs " : [
    {
       " id " :  " req_001 " ,
       " timestamp " :  " 2024-01-01T10:00:00Z " ,
       " method " :  " GET " ,
       " url " :  " https://api.example.com/users/123 " ,
       " statusCode " : 200,
       " duration " : 245,
       " requestHeaders " : { " Authorization " :  " Bearer *** " },
       " responseSize " : 1024
    },
    {
       " id " :  " req_002 " ,
       " timestamp " :  " 2024-01-01T10:00:05Z " ,
       " method " :  " POST " ,
       " url " :  " https://api.example.com/posts " ,
       " statusCode " : 201,
       " duration " : 320,
       " requestBody " : { " title " :  " ... " },
       " responseSize " : 512
    }
  ],
   " totalCount " : 2
}

network_get_errors#

Filters and returns only failed requests.

{
   " name " :  " network_get_errors " ,
   " description " :  " Failed request logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {
       " limit " : {
         " type " :  " integer " ,
         " description " :  " Maximum count " ,
         " default " : 20
      }
    }
  }
}

Response example:

{
   " errors " : [
    {
       " id " :  " req_003 " ,
       " timestamp " :  " 2024-01-01T10:01:00Z " ,
       " method " :  " GET " ,
       " url " :  " https://api.example.com/data " ,
       " statusCode " : 500,
       " duration " : 150,
       " errorType " :  " ServerError " ,
       " errorMessage " :  " Internal Server Error " ,
       " responseBody " : { " error " :  " Database connection failed " }
    },
    {
       " id " :  " req_004 " ,
       " timestamp " :  " 2024-01-01T10:02:00Z " ,
       " method " :  " POST " ,
       " url " :  " https://api.example.com/upload " ,
       " statusCode " : null,
       " duration " : 30000,
       " errorType " :  " Timeout " ,
       " errorMessage " :  " Connection timed out " 
     }
  ],
   " errorCount " : 2
}

network_get_stats#

Returns network statistics.

{
   " name " :  " network_get_stats " ,
   " description " :  " Network statistics " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {}
  }
}

Response example:

{
   " stats " : {
     " totalRequests " : 150,
     " successfulRequests " : 145,
     " failedRequests " : 5,
     " averageDuration " : 180,
     " totalBytesReceived " : 524288,
     " totalBytesSent " : 10240,
     " requestsByMethod " : {
       " GET " : 100,
       " POST " : 40,
       " PUT " : 8,
       " DELETE " : 2
    },
     " requestsByStatus " : {
       " 2xx " : 140,
       " 4xx " : 3,
       " 5xx " : 2,
       " timeout " : 5
    }
  },
   " period " :  " session " 
 }

network_clear_logs#

Clears network logs.

{
   " name " :  " network_clear_logs " ,
   " description " :  " Clear logs " ,
   " inputSchema " : {
     " type " :  " object " ,
     " properties " : {}
  }
}

App Integration Code#

// lib/debug/mcp_network_tools.dart
import 'package:mcp_toolkit/mcp_toolkit.dart';
import 'package:dio/dio.dart';

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

  @override
  void onRequest(RequestOptions options, RequestInterceptorHandler handler) {
    _logs.add({
      'id': 'req_${DateTime.now().millisecondsSinceEpoch}',
      'timestamp': DateTime.now().toIso8601String(),
      'method': options.method,
      'url': options.uri.toString(),
      'requestHeaders': _sanitizeHeaders(options.headers),
      'requestBody': options.data,
      'startTime': DateTime.now(),
    });
    handler.next(options);
  }

  @override
  void onResponse(Response response, ResponseInterceptorHandler handler) {
    final log = _logs.lastWhere(
      (l) => l['url'] == response.requestOptions.uri.toString(),
      orElse: () => {},
    );
    if (log.isNotEmpty) {
      log['statusCode'] = response.statusCode;
      log['duration'] = DateTime.now()
          .difference(log['startTime'] as DateTime)
          .inMilliseconds;
      log['responseSize'] = response.data?.toString().length ?? 0;
      log.remove('startTime');
    }
    handler.next(response);
  }

  @override
  void onError(DioException err, ErrorInterceptorHandler handler) {
    final log = _logs.lastWhere(
      (l) => l['url'] == err.requestOptions.uri.toString(),
      orElse: () => {},
    );
    if (log.isNotEmpty) {
      log['statusCode'] = err.response?.statusCode;
      log['duration'] = DateTime.now()
          .difference(log['startTime'] as DateTime)
          .inMilliseconds;
      log['errorType'] = err.type.name;
      log['errorMessage'] = err.message;
      log['responseBody'] = err.response?.data;
      log.remove('startTime');
    }
    handler.next(err);
  }

  Map<String, String> _sanitizeHeaders(Map<String, dynamic> headers) {
    return headers.map((key, value) {
      if (key.toLowerCase() == 'authorization') {
        return MapEntry(key, '***');
      }
      return MapEntry(key, value.toString());
    });
  }

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

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

  Map<String, dynamic> getStats() {
    final successful = _logs.where((l) =>
      l['statusCode'] != null && (l['statusCode'] as int) < 400).length;
    return {
      'totalRequests': _logs.length,
      'successfulRequests': successful,
      'failedRequests': _logs.length - successful,
      // ... additional statistics
    };
  }

  void clear() => _logs.clear();
}

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

  addMcpTool(MCPCallEntry.tool(
    handler: (params) => MCPCallResult(
      message: 'Network logs',
      parameters: {
        'logs': NetworkLogger.instance.getLogs(
          limit: params['limit'] as int?,
          method: params['method'] as String?,
          path: params['path'] as String?,
        ),
      },
    ),
    definition: MCPToolDefinition(
      name: 'network_get_logs',
      description: 'HTTP logs',
      inputSchema: {
        'type': 'object',
        'properties': {
          'limit': {'type': 'integer'},
          'method': {'type': 'string'},
          'path': {'type': 'string'},
        },
      },
    ),
  ));

  // network_get_errors, network_get_stats, network_clear_logs are implemented similarly
}

Usage Examples#

Check recent API calls#

Q: Show me recent API call history
A: Run network_get_logs limit=10
   - >   10 requests (GET /users 200, POST /posts 201, ...)

Filter specific endpoint#

Q: Show me only /users related requests
A: Run network_get_logs path= " /users " 
    - >   Filtered to requests containing /users

Check error requests#

Q: Are there any failed requests?
A: Run network_get_errors
   - >   500 error: /api/data, Timeout: /api/upload

Network statistics#

Q: Summarize the network status
A: Run network_get_stats
   - >   150 requests, 145 successful, 5 failed, avg 180ms

Common Problem Diagnosis#

Slow API response#

1. Check duration with network_get_logs
2. Identify slow requests
3. Determine server performance or network issue

401 Unauthorized#

1. Check 401 errors with network_get_errors
2. Check Authorization in requestHeaders
3. Check token status with auth_get_status

500 Server Error#

1. Check details with network_get_errors
2. Check error message in responseBody
3. Review request parameters

Timeout#

1. Check timeout errors with network_get_errors
2. Check network connection status
3. Review timeout configuration values
  • @flutter-inspector: Master inspector
  • @flutter-inspector-auth: Authentication token issues
  • @flutter-inspector-log: Network related app logs