How the send_code_to_revit Tool Executes Custom Code in Revit

The send_code_to_revit tool validates C# input using Zod, opens a TCP socket to a Revit add-in at localhost:8080, transmits the code via JSON-RPC 2.0, and returns the execution result without compiling or running the code itself.

The send_code_to_revit tool is a core component of the mcp-servers-for-revit/revit-mcp repository, acting as a bridge between an MCP (Model Context Protocol) server and a live Autodesk Revit instance. It enables AI agents and automation scripts to inject and execute arbitrary C# code directly within the Revit API context.

Architecture Overview

The tool operates as a thin transport layer. It does not compile or sandbox the C# code; instead, it packages the code into a structured JSON-RPC request and forwards it to a companion Revit add-in listening on a local TCP port. The Revit-side add-in handles Roslyn compilation, execution within the Revit API context, and error handling, then returns the result through the same socket.

Step-by-Step Execution Flow

Input Validation with Zod

Before opening any network connection, the tool validates the incoming MCP request against a strict Zod schema defined in src/tools/send_code_to_revit.ts (lines 10-21). The schema requires a code string containing the C# snippet and accepts an optional parameters array for passing arguments to the Revit-side execution context. This validation prevents malformed requests from reaching the Revit process.

Establishing the TCP Connection

Upon validation, the tool invokes withRevitConnection from src/utils/ConnectionManager.ts (lines 8-48). This helper manages the lifecycle of a RevitClientConnection:

  • Target: Connects to localhost:8080 where the Revit add-in listens.
  • Timeout: Enforces a 5-second connection timeout to prevent hanging.
  • Cleanup: Guarantees the socket closes after the operation completes, regardless of success or failure.

JSON-RPC Request Construction

Inside the connection context, RevitClientConnection.sendCommand (defined in src/utils/SocketClient.ts, lines 93-134) constructs a JSON-RPC 2.0 request. The payload structure is:

{
  "jsonrpc": "2.0",
  "method": "send_code_to_revit",
  "params": {
    "code": "var wall = new Wall(Document, new XYZ(0,0,0), new XYZ(10,0,0), 0);",
    "parameters": []
  },
  "id": "1708151234567abcdef"
}

The id is a unique identifier generated for each request to match responses asynchronously.

Response Handling and Promise Resolution

The socket client buffers incoming data until a complete JSON message is received (src/utils/SocketClient.ts, lines 77-90). Upon parsing a complete message, it extracts the id, retrieves the corresponding pending promise, and resolves it with response.result or rejects it with response.error (lines 112-121).

The tool handler in send_code_to_revit.ts catches any socket or execution errors and formats the final MCP response as a "content" array. A successful execution returns:

{
  "content": [
    {
      "type": "text",
      "text": "Code execution successful!\nResult: {\n  \"status\": \"ok\",\n  \"message\": \"Wall created\"\n}"
    }
  ]
}

Errors from the Revit side (compilation failures, API exceptions) propagate through the same channel:

{
  "content": [
    {
      "type": "text",
      "text": "Code execution failed: Object reference not set to an instance of an object"
    }
  ]
}

Key Implementation Files

File Role
src/tools/send_code_to_revit.ts Defines the MCP tool, validates input with Zod, and orchestrates the connection flow.
src/utils/ConnectionManager.ts Manages TCP socket lifecycle, connection timeouts, and cleanup guarantees.
src/utils/SocketClient.ts Implements JSON-RPC 2.0 framing, request ID generation, and asynchronous response matching.
src/index.ts Bootstraps the MCP server and registers all tools including send_code_to_revit.

Summary

  • Validation: Input is strictly validated using Zod schemas before network operations begin.
  • Transport: The tool uses a raw TCP socket to localhost:8080 managed by ConnectionManager.
  • Protocol: Communication follows JSON-RPC 2.0 with unique request IDs for asynchronous matching.
  • Execution: The Revit-side add-in handles compilation (via Roslyn) and API execution; the MCP tool only relays messages.
  • Safety: Connection timeouts and guaranteed socket cleanup prevent resource leaks.

Frequently Asked Questions

How does send_code_to_revit handle compilation errors?

The tool itself does not compile the C# code; it forwards the code string to the Revit add-in. If the Revit-side compiler (typically Roslyn) encounters syntax errors or missing references, it captures the exception message and returns it via the JSON-RPC error field. The tool then surfaces this message in the MCP response content.

What happens if Revit is not running when the tool is invoked?

If the Revit add-in is not listening on localhost:8080, the withRevitConnection helper will attempt to connect and timeout after 5 seconds. This raises a connection error that the tool catches, returning an MCP response indicating that the Revit client is unavailable.

Can I pass parameters to the C# code execution?

Yes. The tool accepts an optional parameters array in the request schema. These values are serialized into the JSON-RPC params object and passed to the Revit-side execution context, where they become available to the C# code as arguments or variables within the execution scope.

Is the code execution sandboxed or restricted?

The tool provides no sandboxing; security relies on the local TCP connection to localhost:8080 and the assumption that the Revit add-in runs with the user's privileges. The C# code executes with full access to the Revit API and .NET framework within the Revit process, so input should be trusted or validated before invocation.

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 →