# How the send_code_to_revit Tool Executes Custom Code in Revit

> Discover how send_code_to_revit executes custom C# code in Revit through its TCP socket connection sending JSON-RPC 2.0 data without compilation.

- Repository: [MCP servers for Revit/revit-mcp](https://github.com/mcp-servers-for-revit/revit-mcp)
- Tags: how-to-guide
- Published: 2026-02-19

---

**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](https://github.com/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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/SocketClient.ts), lines 93-134) constructs a JSON-RPC 2.0 request. The payload structure is:

```json
{
  "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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/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:

```json
{
  "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:

```json
{
  "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`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/tools/send_code_to_revit.ts) | Defines the MCP tool, validates input with Zod, and orchestrates the connection flow. |
| [`src/utils/ConnectionManager.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/ConnectionManager.ts) | Manages TCP socket lifecycle, connection timeouts, and cleanup guarantees. |
| [`src/utils/SocketClient.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/src/utils/SocketClient.ts) | Implements JSON-RPC 2.0 framing, request ID generation, and asynchronous response matching. |
| [`src/index.ts`](https://github.com/mcp-servers-for-revit/revit-mcp/blob/main/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.