How the tag_walls Tool Implements Automatic Wall Tagging in Revit
The tag_walls tool in the revit-mcp repository implements automatic wall tagging by registering an MCP server tool that validates parameters, manages a TCP connection to Revit via withRevitConnection, and dispatches a tag_walls command to the Revit client.
The tag_all_walls tool provides a server-side utility for the Model Context Protocol (MCP) that enables AI assistants to request automatic wall tagging for the active Revit view. This implementation demonstrates a clean separation between API definition, connection lifecycle management, and Revit-specific business logic.
Architecture Overview of the tag_walls Implementation
The implementation follows a four-layer architecture that ensures reliable communication between the MCP server and the Revit application:
- Tool Registration Layer – Defines the JSON schema and parameter validation using Zod
- Connection Management Layer – Handles TCP socket lifecycle via
withRevitConnection - Command Dispatch Layer – Sends the
tag_wallscommand to the Revit client - Response Handling Layer – Processes success and error states for MCP framework consumption
Tool Registration and Schema Definition
In src/tools/tag_all_walls.ts, the tool registers with the MCP server using a descriptive name and Zod-based schema validation. The schema defines two optional parameters that control tagging behavior:
useLeader(boolean, defaults tofalse) – Determines whether leader lines extend from tags to wallstagTypeId(string) – Specifies a custom tag family ID for specialized wall tags
server.tool(
"tag_all_walls",
"Create tags for all walls in the current active view. Tags will be placed at the middle point of each wall.",
{
useLeader: z.boolean().optional().default(false),
tagTypeId: z.string().optional()
},
async (args, extra) => {
// Handler implementation
}
);
Connection Lifecycle Management
The tool delegates network communication to withRevitConnection from src/utils/ConnectionManager.ts. This utility manages the complete lifecycle of a TCP socket connection to the Revit client:
- Creates a
RevitClientConnectioninstance - Enforces a 5-second connection timeout
- Guarantees connection cleanup via automatic disconnection
- Executes the provided async operation only after successful connection establishment
import { withRevitConnection } from "../utils/ConnectionManager.js";
async (args, extra) => {
return await withRevitConnection(async (revitClient) => {
// Command execution within managed connection
});
}
Command Dispatch to Revit
Within the connection callback, the tool constructs and dispatches the tag_walls command. The Revit client (running as an add-in outside this repository) receives the command and executes the actual tagging logic in the active view.
const params = {
useLeader: args.useLeader,
tagTypeId: args.tagTypeId
};
const response = await revitClient.sendCommand("tag_walls", params);
The response handling distinguishes between successful execution and error states, returning structured content that the MCP framework renders appropriately:
if (response.success) {
return {
content: [{ type: "text", text: JSON.stringify(response.data) }]
};
} else {
return {
content: [{ type: "text", text: `Error: ${response.message}` }],
isError: true
};
}
Complete Implementation Example
To register and use the tag_all_walls tool in an MCP server implementation:
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
import { registerTagAllWallsTool } from "./src/tools/tag_all_walls.js";
const server = new McpServer();
registerTagAllWallsTool(server);
await server.start();
Client-side invocation via the MCP SDK:
import { Client } from "@modelcontextprotocol/sdk/client/index.js";
const client = new Client({ name: "revit-client", version: "1.0.0" });
const result = await client.callTool({
name: "tag_all_walls",
arguments: {
useLeader: true,
tagTypeId: "Wall Tag - Generic"
}
});
Summary
The tag_walls tool implementation demonstrates a robust pattern for Revit automation through the Model Context Protocol:
- Clean separation of concerns between tool definition (
src/tools/tag_all_walls.ts), connection management (src/utils/ConnectionManager.ts), and Revit execution - Type-safe parameter validation using Zod schemas for
useLeaderandtagTypeIdoptions - Reliable network handling via
withRevitConnectionwith automatic timeout and cleanup - Extensible architecture that allows additional Revit commands to follow the same pattern
Frequently Asked Questions
What parameters does the tag_all_walls tool accept?
The tool accepts two optional parameters: useLeader (boolean, defaults to false) controls whether leader lines extend from tags to walls, and tagTypeId (string) specifies a custom tag family ID for specialized wall tags. Both parameters are validated using Zod schema validation before being sent to Revit.
How does the tool communicate with the Revit application?
The tool uses a TCP socket connection managed by withRevitConnection in src/utils/ConnectionManager.ts. This utility creates a RevitClientConnection, enforces a 5-second connection timeout, executes the command, and guarantees cleanup by disconnecting after the operation completes. The actual tag_walls command is then dispatched to the Revit client add-in.
Where is the actual wall tagging logic implemented?
The server-side code in src/tools/tag_all_walls.ts only handles API registration and command dispatch. The actual Revit API logic that creates tags at wall midpoints runs in the Revit client add-in, which receives the tag_walls command via the TCP connection. This separation keeps the MCP server stateless and Revit-agnostic.
Can I extend this pattern for other Revit elements?
Yes, the architecture supports extension for doors, windows, or other categories. You would create a new file in src/tools/ following the tag_all_walls.ts pattern: register the tool with a Zod schema, use withRevitConnection for the TCP lifecycle, and dispatch a new command name (e.g., tag_doors) to the Revit client. The connection management and response handling code remains identical.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →