Skip to content

capture_live_filter/set_enabled timeout cascades and crashes entire MCP server #4

Description

@danbao

Problem Description

When capture_live_filter or capture_live_set_enabled times out, the timeout cascades and crashes the entire MCP server connection. Subsequent calls to unrelated tools (e.g., collection_list) also fail with "MCP server unreachable".

Critical finding: This also reproduces with 0 records after a full app restart — the issue is not solely caused by large record sets.

Root Cause Analysis

From the source code in lib/api/client.dart:

_httpClient.connectionTimeout = const Duration(seconds: 5);

The ReqableApiClient only sets connectionTimeout (5s) but does not set any read/response timeout on the HttpClient. This means:

  1. When Reqable's local API is slow or stuck, the HTTP request hangs indefinitely
  2. The MCP server blocks on the await in _send() and cannot process any other requests
  3. The MCP host (e.g., Hermes, Claude Desktop) has its own timeout (typically 30-300s), after which it marks the entire MCP server as "unreachable"
  4. Since the MCP server is stuck on the hung request, all subsequent tool calls fail — even unrelated ones

Steps to Reproduce

Scenario A: Large record set

  1. Connect to Reqable MCP server via stdio
  2. Start live capture in Reqable and accumulate 3000+ records
  3. Call capture_live_filter with any filter
  4. After timeout, try calling any other tool (e.g., collection_list)
  5. Result: All subsequent calls fail with "MCP server unreachable" for ~45-50 seconds

Scenario B: Clean restart (0 records)

  1. Fully quit and restart the Reqable app (clear all records)
  2. Reconnect MCP (hermes mcp test reqable → success, 46 tools)
  3. Call capture_live_filter(filters: []) (empty filter, 0 records)
  4. Still times out at 300s, then cascades to crash the entire MCP connection

Additional Observations

  • capture_live_set_enabled(true) also hangs when Reqable is processing heavy traffic
  • The cascading failure means a single slow live capture operation can take down the entire MCP server for all tool categories (collections, REST, scripts, etc.)
  • Restarting the Reqable app does NOT reliably fix the issue — the local API server may enter a persistent bad state
  • hermes mcp test reqable succeeds (46 tools discovered, ~150ms), confirming stdio transport is healthy; the hang is in the Reqable local API layer

Possible Causes (beyond missing timeout)

  • Reqable's local API server enters a bad state after the first timeout and doesn't recover on app restart (stale socket/lock)
  • The MCP server's HttpClient keeps a persistent connection that becomes stale
  • A Reqable-side lock/mutex is not released after an interrupted request

Suggested Fix

Add a request-level timeout to the HttpClient in ReqableApiClient:

_httpClient.connectionTimeout = const Duration(seconds: 5);
_httpClient.idleTimeout = const Duration(seconds: 30); // or configurable

Or wrap the _send() method with a timeout:

Future<String> _send(String method, Request req) async {
  // ... existing code ...
  return await _doSend(method, req).timeout(
    const Duration(seconds: 30),
    onTimeout: () => throw TimeoutException('Request to ${req.route} timed out'),
  );
}

This would prevent a single slow request from blocking the entire MCP server.

Environment

  • macOS 15 (Apple Silicon)
  • Reqable MCP Server (latest, stdio transport)
  • Reqable App (latest)
  • MCP Host: Hermes Agent

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions