Debugging MCP-Revit Communication Issues: A Complete Troubleshooting Guide

The most effective way to debug MCP-Revit communication issues is to enable verbose logging in SocketClient.ts, validate JSON-RPC message integrity, and systematically verify the TCP connection lifecycle through withRevitConnection.

The mcp-servers-for-revit/revit-mcp repository implements a lightweight JSON-RPC bridge that enables Model Context Protocol (MCP) servers to communicate with Autodesk Revit. When troubleshooting debugging MCP-Revit communication issues, understanding the TCP socket architecture and message flow between the MCP client and Revit server is essential for rapid diagnosis.

Understanding the MCP-Revit Architecture

Core Components Overview

The communication stack consists of three primary layers:

  • RevitClientConnection (src/utils/SocketClient.ts): Manages the TCP socket connection to Revit, handles incoming data buffering, and parses JSON-RPC responses. It wires up listeners for connect, data, close, and error events in setupSocketListeners() (lines 18-22).

  • withRevitConnection (src/utils/ConnectionManager.ts): A higher-order function that guarantees a live socket before executing any tool command. It creates a RevitClientConnection targeting localhost:8080 and waits up to 5 seconds for the connect event (lines 14-39), ensuring cleanup via disconnect() afterward (lines 44-47).

  • Tool Modules (e.g., src/tools/send_code_to_revit.ts, src/tools/tag_all_walls.ts): Encode specific Revit operations, invoke revitClient.sendCommand(), and propagate errors back to the MCP server. Each tool wraps RPC calls inside withRevitConnection and catches exceptions to return user-friendly error messages.

Communication Flow

When an MCP tool executes, the data flows through this pipeline:

  1. The tool invokes withRevitConnection(), which instantiates RevitClientConnection.
  2. The socket client attempts TCP connection to localhost:8080 with a 5-second timeout.
  3. Upon connection, the tool calls sendCommand(method, params), which generates a unique request ID via generateRequestId() (lines 73-75), constructs the JSON-RPC envelope, and transmits it.
  4. The Revit server processes the command and returns a response, which processBuffer() (lines 42-49) attempts to parse as complete JSON.
  5. handleResponse() (lines 77-90) matches the response ID to the pending callback and resolves or rejects the promise.

Common MCP-Revit Communication Failure Points

Symptom Likely Cause Investigation Location
"connect to revit client failed" Revit socket server not listening on port 8080, firewall blocking TCP traffic, or Revit process crash. withRevitConnection timeout handling (lines 34-38 in ConnectionManager.ts).
"Command timed out after 2 minutes" Revit received the request but failed to respond, typically due to long-running API operations, thread deadlocks, or unhandled exceptions in the Revit add-in. sendCommand() timeout logic (lines 35-41 in SocketClient.ts).
JSON parse errors Malformed or fragmented responses, usually caused by multiple concatenated JSON messages in the buffer or truncated TCP packets. processBuffer() try/catch block (lines 44-51) and handleResponse() (lines 77-90).
response.error present Revit-side execution failure, such as invalid element IDs, missing family types, or API permission errors. The error object is relayed back to the tool. sendCommand() callback handling (lines 13-22).

Debugging Strategies for MCP-Revit Communication Issues

Enable Verbose Logging in SocketClient.ts

The first step in troubleshooting is to instrument the raw data flow. Add debug statements to src/utils/SocketClient.ts around line 18 to capture socket events:

this.socket.on("data", (data) => {
  console.debug("[MCP] Received raw bytes:", data.toString());
  this.buffer += data.toString();
  this.processBuffer();
});

Similarly, log connection state changes in setupSocketListeners():

this.socket.on("connect", () => {
  console.info("[MCP] Socket connected to Revit on localhost:8080");
  this.isConnected = true;
});

Validate JSON-RPC Message Integrity

Communication failures often stem from malformed envelopes. Verify that:

  • The id field is unique per request, generated by generateRequestId() (lines 73-75).
  • The Revit server echoes the identical id in its response; mismatched IDs will leave callbacks hanging indefinitely.
  • The jsonrpc version is consistently "2.0".

Inspect the raw buffer content in processBuffer() (lines 42-49) to ensure complete JSON objects are being extracted before parsing.

Verify Connection Lifecycle with withRevitConnection

The withRevitConnection helper in src/utils/ConnectionManager.ts manages the critical connection window. To debug lifecycle issues:

  1. Check the timeout window: The default 5-second timeout (lines 34-38) may be insufficient on slower systems. Temporarily increase this value to see if the Revit process is simply slow to start.
  2. Confirm cleanup: Ensure disconnect() is called in the finally block (lines 44-47) to prevent socket leaks that could exhaust available ports.
  3. Monitor isConnected state: Log the state of RevitClientConnection.isConnected before and after tool execution to verify the socket is actually ready.

Inspect Buffer Handling in processBuffer()

Fragmented messages are a common source of "JSON parse error" exceptions. The current implementation in processBuffer() (lines 42-49) attempts to parse the entire buffer as a single JSON object. If the Revit server sends multiple concatenated messages or splits a large response across TCP packets, parsing will fail.

To diagnose buffer issues:

  • Log the buffer content before parsing: console.debug("[MCP] Buffer content:", this.buffer);
  • Check for multiple JSON objects by attempting to split on newline characters or by validating JSON length prefixes if the protocol supports them.
  • Look for truncated data by checking if the buffer ends with incomplete JSON structures (e.g., missing closing braces).

Simulate Requests with TCP Clients

Isolate the MCP client from the Revit server by using raw TCP tools to verify connectivity and message format:


# Test basic connectivity

telnet localhost 8080

Or use Node.js to send a valid JSON-RPC request:

const net = require("net");
const client = net.createConnection({ host: "localhost", port: 8080 }, () => {
  const payload = JSON.stringify({ 
    jsonrpc: "2.0", 
    method: "ping", 
    params: {}, 
    id: "test123" 
  });
  client.write(payload);
});
client.on("data", (data) => console.log("Response:", data.toString()));
client.on("error", (err) => console.error("Connection error:", err));

This approach confirms whether issues stem from the transport layer (TCP) or the application layer (JSON-RPC).

Correlate with Revit-Side Logs

The Revit add-in maintains separate logs typically located at %APPDATA%/MCPRevit/log.txt. Cross-reference timestamps between these logs and the MCP client output to identify:

  • Whether commands reached the Revit process.
  • How long Revit took to process specific API calls.
  • Any exceptions thrown by the Revit API before a response was sent.

Quick Diagnostic Checklist

Use this systematic checklist to isolate MCP-Revit communication issues:

Step Action Expected Result
1 Run telnet localhost 8080 or nc -vz localhost 8080 Connection established message appears immediately.
2 Send manual JSON-RPC ping payload Receive response containing matching "id" and "result" fields.
3 Check src/utils/SocketClient.ts logs for "RevitClientConnection error" No error lines; isConnected should be true.
4 Run a simple tool (e.g., send_code_to_revit) from the MCP CLI and verify the JSON response. Successful execution or a clear error message.

Practical Debugging Code Examples

Manual RPC Call Using the MCP Helper

This TypeScript example uses the same withRevitConnection flow that all production tools use, making it ideal for isolating connection issues:

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

async function testPing() {
  try {
    const result = await withRevitConnection(async (client) => {
      return await client.sendCommand("ping", {});
    });
    console.log("Revit responded:", result);
  } catch (e) {
    console.error("Ping failed:", e);
  }
}

testPing();

Enhanced Logging Wrapper

Add this instrumentation to src/utils/SocketClient.ts near line 18 to capture raw network traffic:

// Place inside setupSocketListeners() method
this.socket.on("data", (data) => {
  console.debug("[MCP] Received raw:", data.toString());
  this.buffer += data.toString();
  this.processBuffer();
});

Key Files for Debugging MCP-Revit Communication

Understanding these source files is essential for effective troubleshooting:

File Purpose Critical Functions
src/utils/SocketClient.ts Low-level TCP client implementation, JSON-RPC parsing, and timeout handling. setupSocketListeners() (L18-L22), processBuffer() (L42-L49), sendCommand() (L35-L41), generateRequestId() (L73-L75), handleResponse() (L77-L90)
src/utils/ConnectionManager.ts Connection lifecycle management and resource cleanup. withRevitConnection() (L14-L47)
src/tools/send_code_to_revit.ts Example tool showing error propagation and command execution. Tool implementation wrapping RPC calls (L28-L56)
src/tools/tag_all_walls.ts Reference for element manipulation command patterns. Response handling implementation
src/index.ts MCP server entry point and tool registration. Server initialization and tool registration flow

Summary

  • Start with architecture: Understanding the roles of RevitClientConnection, withRevitConnection, and the tool modules provides the foundation for systematic debugging.
  • Log everything: Instrument src/utils/SocketClient.ts to capture raw TCP data and connection state changes before attempting complex fixes.
  • Validate JSON-RPC integrity: Ensure unique request IDs and complete JSON objects to prevent hanging callbacks and parse errors.
  • Isolate the layers: Use raw TCP clients like telnet or Node.js net to determine if issues are transport-layer (TCP) or application-layer (JSON-RPC).
  • Check both sides: Correlate MCP client logs with Revit-side logs at %APPDATA%/MCPRevit/log.txt to trace command execution across the bridge.

Frequently Asked Questions

Why does my MCP client fail to connect to Revit with a timeout error?

The connection timeout typically indicates that the Revit socket server is not listening on localhost:8080, a firewall is blocking TCP traffic, or the Revit process has crashed. Verify that the Revit add-in is loaded and listening using telnet localhost 8080. If this fails, check the Revit-side logs at %APPDATA%/MCPRevit/log.txt for startup errors before investigating the MCP client code in src/utils/ConnectionManager.ts.

How do I fix "JSON parse error" messages in SocketClient.ts?

JSON parse errors occur when processBuffer() in src/utils/SocketClient.ts (lines 42-49) receives incomplete or concatenated JSON messages. This happens when TCP packets fragment the data or the Revit server sends multiple JSON objects without delimiters. To debug, add console.debug() statements to log the raw buffer content before parsing. For a permanent fix, implement a delimiter-based protocol (such as newline-separated JSON) or use length-prefixed messages rather than assuming single-object packets.

What causes command timeouts after 2 minutes even when Revit is connected?

The 2-minute timeout originates in sendCommand() at lines 35-41 of src/utils/SocketClient.ts. This indicates the Revit server received the JSON-RPC request but failed to send a response, typically due to long-running Revit API operations, thread deadlocks, or unhandled exceptions in the Revit add-in. Check the Revit-side logs for exceptions during command execution, and consider breaking long operations into smaller chunks or increasing the timeout for legitimate long-running tasks.

How can I verify that my JSON-RPC requests are properly formatted?

Valid JSON-RPC requests must include a unique id field (generated by generateRequestId() at lines 73-75), the jsonrpc: "2.0" version string, a valid method name, and a params object. Use a raw TCP client like Node.js net to send test payloads to localhost:8080 and verify that the response echoes the same id and contains either a result or error field. If the id mismatches or is missing, the handleResponse() function (lines 77-90) will be unable to match the response to the pending callback, causing the promise to hang indefinitely.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →