# How ConnectionManager Handles TCP Connection Timeouts and Failures in revit-mcp

> Discover how ConnectionManager in revit-mcp expertly manages TCP timeouts and failures with a dual-layer strategy and robust error handling. Ensure reliable Revit connections.

- Repository: [MCP servers for Revit/revit-mcp](https://github.com/mcp-servers-for-revit/revit-mcp)
- Tags: internals
- Published: 2026-02-16

---

**The ConnectionManager in revit-mcp implements a dual-layer timeout strategy: a 5-second connection establishment timeout in `withRevitConnection` and a 2-minute per-command timeout in `RevitClientConnection`, with comprehensive error handling via socket event listeners and automatic resource cleanup.**

The revit-mcp repository provides a Model Context Protocol (MCP) server for Autodesk Revit, requiring robust TCP communication handling between the Node.js server and the Revit client. Understanding how the ConnectionManager handles TCP connection timeouts and failures is critical for building reliable integrations that gracefully manage network instability or unresponsive Revit instances.

## Connection Establishment Timeout Handling

The primary entry point for TCP connectivity is the `withRevitConnection` function defined in [`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts). This utility implements a Promise-based wrapper that enforces strict timeout boundaries during the initial handshake phase.

### The withRevitConnection Wrapper

When a tool requires Revit connectivity, it invokes `withRevitConnection` with an async operation callback. The function instantiates a new `RevitClientConnection` targeting `localhost:8080` and attempts to establish the socket connection:

```typescript
const revitClient = new RevitClientConnection("localhost", 8080);

```

If the socket is not already connected, the function creates a Promise that manages the connection lifecycle through event listeners and timeout guards.

### Timeout Guard Implementation

The connection mechanism implements a **5-second timeout** using `setTimeout` to prevent indefinite hanging during TCP handshake attempts. The architecture follows this sequence:

1. **Listener Attachment**: Registers `connect` and `error` event handlers on the socket instance
2. **Connection Initiation**: Calls `revitClient.connect()` to start the TCP handshake
3. **Timeout Scheduling**: Creates a 5-second timer that monitors for successful connection
4. **Resolution Logic**: If the timer expires before connection or error events fire, it removes all listeners and rejects the Promise with `new Error("连接到Revit客户端失败")`

Upon successful connection, the timer is cleared, listeners are removed, and the supplied operation executes with the connected client.

### Error Event Handling

Socket-level errors during connection attempts are captured through the `error` event listener. When the underlying TCP socket emits an error (such as connection refused, network unreachable, or reset by peer), the handler:

- Clears the 5-second timeout timer
- Removes the event listeners to prevent memory leaks
- Rejects the Promise with `new Error("connect to revit client failed")`

This ensures that connection failures surface immediately to the calling tool, allowing for appropriate error messaging or retry logic at the application level.

## Command-Level Timeout Protection

Once the TCP connection is established, the `RevitClientConnection` class in [`src/utils/SocketClient.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/SocketClient.ts) manages individual JSON-RPC command execution with independent timeout safeguards.

### RevitClientConnection Architecture

The socket client maintains connection state through an `isConnected` flag and implements error handling at the socket level. The socket's `error` event handler logs the error details and sets `isConnected = false`, ensuring that subsequent operations recognize the broken connection and trigger reconnection logic through `withRevitConnection`.

### Per-Command Timeout Mechanism

Each command sent via `sendCommand` receives a **2-minute timeout** (120,000 milliseconds) to prevent indefinite waiting for Revit processing. The implementation uses a `setTimeout` that monitors the `responseCallbacks` Map:

```typescript
setTimeout(() => {
  if (this.responseCallbacks.has(requestId)) {
    this.responseCallbacks.delete(requestId);
    reject(new Error(`Command timed out after 2 minutes: ${command}`));
  }
}, 120000);

```

If the Revit client fails to respond within the 2-minute window, the callback is removed from the Map and the Promise rejects with a descriptive timeout message. This protects the MCP server from hanging when Revit is busy processing complex geometry or when the add-in becomes unresponsive.

## Complete Error Handling Flow

The revit-mcp connection architecture implements a comprehensive error handling strategy that addresses both transient network issues and application-level failures.

### Socket Error Recovery

When the underlying TCP socket encounters an error after successful connection, the error handler in `RevitClientConnection` performs immediate state cleanup:

- Logs the error details for debugging
- Sets `isConnected = false` to mark the connection as invalid
- Allows `withRevitConnection` to detect the disconnected state on subsequent calls and initiate a fresh connection attempt

This recovery mechanism ensures that a single socket error does not permanently disable the integration, instead allowing for automatic reconnection when the next tool operation requires Revit access.

### Cleanup and Resource Management

Both connection and command operations implement rigorous cleanup protocols to prevent memory leaks and resource exhaustion:

- **Listener Removal**: Event listeners for `connect` and `error` events are explicitly removed after resolution or timeout
- **Timer Clearing**: All `setTimeout` instances are cleared using `clearTimeout` before Promise resolution
- **Socket Disconnection**: The `finally` block in `withRevitConnection` ensures `revitClient.disconnect()` executes regardless of operation success or failure, properly closing the TCP socket

These cleanup measures are critical for long-running MCP server processes that may handle hundreds of Revit operations without restarting.

## Practical Implementation Example

The following example demonstrates robust error handling when retrieving wall elements from Revit:

```typescript
import { withRevitConnection } from "./utils/ConnectionManager.js";

async function listAllWalls() {
  // Attempts connection with 5-second timeout
  return await withRevitConnection(async (client) => {
    // This call will timeout after 2 minutes if Revit does not respond
    const walls = await client.sendCommand("GetAllWalls");
    return walls;
  });
}

listAllWalls()
  .then((walls) => console.log("Retrieved walls:", walls))
  .catch((err) => {
    // Catches both connection timeouts (5s) and command timeouts (2min)
    console.error("Revit operation failed:", err.message);
  });

```

This pattern ensures that network interruptions, unresponsive Revit instances, or long-running geometry operations all surface as actionable errors rather than hanging the MCP server indefinitely.

## Summary

- **ConnectionManager** in [`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts) provides the `withRevitConnection` wrapper that enforces a **5-second timeout** during TCP handshake and handles connection errors via socket event listeners.
- **RevitClientConnection** in [`src/utils/SocketClient.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/SocketClient.ts) manages the TCP socket state and implements a **2-minute timeout** for individual JSON-RPC commands to prevent indefinite waiting.
- **Error recovery** includes immediate socket error logging, `isConnected` state reset, and automatic cleanup of timers and event listeners to prevent memory leaks.
- **Resource management** guarantees socket disconnection through `finally` blocks, ensuring TCP connections close properly regardless of operation success or failure.

## Frequently Asked Questions

### How long does the ConnectionManager wait before timing out a TCP connection attempt?

The ConnectionManager waits **5 seconds** before timing out a TCP connection attempt. This timeout is implemented in [`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts) using `setTimeout` within the `withRevitConnection` function. If the socket does not emit either a `connect` or `error` event within this window, the Promise rejects with the error message "连接到Revit客户端失败" (Connection to Revit client failed).

### What is the difference between connection timeouts and command timeouts in revit-mcp?

**Connection timeouts** (5 seconds) occur during the initial TCP handshake phase when `withRevitConnection` attempts to establish a socket connection to the Revit client. **Command timeouts** (2 minutes or 120,000 milliseconds) occur after a successful connection, when `RevitClientConnection.sendCommand` waits for a JSON-RPC response from Revit. The connection timeout prevents hanging during network setup, while the command timeout prevents indefinite waiting when Revit is processing complex operations or becomes unresponsive.

### How does revit-mcp handle socket errors after a successful connection?

When a socket error occurs after connection, the `RevitClientConnection` class in [`src/utils/SocketClient.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/SocketClient.ts) handles it through the socket's `error` event listener. The handler logs the error details for debugging and immediately sets `isConnected = false`. This state change ensures that subsequent calls to `withRevitConnection` detect the broken connection and initiate a fresh TCP handshake rather than attempting to use the dead socket. The error does not crash the server; instead, it triggers the reconnection logic on the next operation.

### What cleanup mechanisms prevent memory leaks during connection failures?

The ConnectionManager implements several cleanup mechanisms to prevent memory leaks. First, all event listeners (`connect` and `error`) are explicitly removed using `socket.removeListener` after the Promise resolves, rejects, or times out. Second, all `setTimeout` timers are cleared using `clearTimeout` before any Promise resolution. Third, the `finally` block in `withRevitConnection` guarantees that `revitClient.disconnect()` executes regardless of success or failure, closing the TCP socket and releasing system resources. These measures are essential for the long-running MCP server process.