# Directory Structure
```
├── .gitignore
├── LICENSE
├── package-lock.json
├── package.json
├── README.md
├── README.zh-CN.md
├── src
│   ├── index.ts
│   ├── revitService.ts
│   ├── revitSocketClient.ts
│   └── types.ts
└── tsconfig.json
```
# Files
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
```
1 | node_modules/
2 | build/
3 | *.log
4 | .env*
```
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
```markdown
  1 | # 🏗️ Revit MCP Server
  2 | 
  3 | A Model Context Protocol server for Revit integration, enabling seamless communication between Claude AI and Autodesk Revit.
  4 | 
  5 | [English](./README.md) | [中文](./README.zh-CN.md)
  6 | 
  7 | ## 🎯 Overview
  8 | 
  9 | This TypeScript-based MCP server provides a bridge between Claude AI and Revit, allowing direct interaction with Revit models through a WebSocket connection. It implements the Model Context Protocol to enable:
 10 | 
 11 | - ⚡ Real-time access to Revit model information
 12 | - 🔍 Element querying and filtering
 13 | - 👀 View and level management
 14 | - 🛡️ Robust error handling with fallback mock data
 15 | 
 16 | ## ✨ Features
 17 | 
 18 | ### 🔌 Revit Integration
 19 | - 📡 WebSocket-based communication with Revit plugin
 20 | - 🔄 Real-time model data access
 21 | - 🔁 Graceful fallback to mock data when connection fails
 22 | - ⚙️ Configurable connection settings via environment variables
 23 | 
 24 | ### 🚀 Core Functionalities
 25 | - **📊 Model Information**
 26 |   - Access basic model metadata (name, path, version)
 27 |   - Get element counts and last modification date
 28 |   - Real-time model state synchronization
 29 | 
 30 | - **🏗️ Element Management**
 31 |   - Query elements with flexible filtering
 32 |   - Access element properties and geometry
 33 |   - Batch element operations
 34 | 
 35 | - **🎪 View & Level Control**
 36 |   - List all available views
 37 |   - Access level information
 38 |   - Navigate through model hierarchy
 39 | 
 40 | ## 💻 Development
 41 | 
 42 | ### 📋 Prerequisites
 43 | - Node.js (v14 or higher)
 44 | - npm
 45 | - Autodesk Revit (2023 or later)
 46 | - Revit WebSocket Plugin (companion plugin)
 47 | 
 48 | ### 🔧 Installation
 49 | 
 50 | Install dependencies:
 51 | ```bash
 52 | npm install
 53 | ```
 54 | Build the server:
 55 | 
 56 | ```bash
 57 | npm run build
 58 |  ```
 59 | 
 60 | For development with auto-rebuild:
 61 | 
 62 | ```bash
 63 | npm run watch
 64 |  ```
 65 | 
 66 | ### ⚙️ Configuration
 67 | The server can be configured using environment variables:
 68 | 
 69 | ```plaintext
 70 | REVIT_HOST=127.0.0.1    # Revit plugin WebSocket host
 71 | REVIT_PORT=8080         # Revit plugin WebSocket port
 72 |  ```
 73 | 
 74 | ## 🔗 Integration with Claude Desktop
 75 | Add the server configuration to Claude Desktop:
 76 | 
 77 | Windows:
 78 | 
 79 | ```bash
 80 | %APPDATA%/Claude/claude_desktop_config.json
 81 |  ```
 82 | 
 83 | Configuration format:
 84 | 
 85 | ```json
 86 | {
 87 |   "mcpServers": {
 88 |     "revit-mcp-server": {
 89 |       "command": "D:/path/to/revit-mcp-server/build/index.js"
 90 |     }
 91 |   }
 92 | }
 93 |  ```
 94 | 
 95 | ### 🐛 Debugging
 96 | 
 97 | 
 98 | For debugging the MCP communication:
 99 | 
100 | 1. Use the built-in MCP Inspector:
101 | ```bash
102 | npm run inspector
103 |  ```
104 | 
105 | 2. Monitor WebSocket communication with Revit plugin
106 | 3. Check server logs for connection and operation status
107 | ## ⚠️ Error Handling
108 | The server implements robust error handling:
109 | 
110 | - Automatic fallback to mock data when Revit connection fails
111 | - Detailed error logging
112 | - Graceful connection recovery
113 | ## 📄 License
114 | MIT License
115 | 
116 | ## 🤝 Contributing
117 | Contributions are welcome! Please feel free to submit pull requests.
118 | 
119 | ## 📬 Contact
120 | 
121 | If you have any questions or suggestions, feel free to reach out:
122 | 
123 | - 📧 Email: [email protected]
124 | - 💬 WeChat  Account: modian4500
125 | 
126 | 
```
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "compilerOptions": {
 3 |     "target": "ES2022",
 4 |     "module": "Node16",
 5 |     "moduleResolution": "Node16",
 6 |     "outDir": "./build",
 7 |     "rootDir": "./src",
 8 |     "strict": true,
 9 |     "esModuleInterop": true,
10 |     "skipLibCheck": true,
11 |     "forceConsistentCasingInFileNames": true
12 |   },
13 |   "include": ["src/**/*"],
14 |   "exclude": ["node_modules"]
15 | }
16 | 
```
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
```json
 1 | {
 2 |   "name": "revit-mcp-server",
 3 |   "version": "0.1.0",
 4 |   "description": "A Model Context Protocol server",
 5 |   "private": true,
 6 |   "type": "module",
 7 |   "bin": {
 8 |     "revit-mcp-server": "./build/index.js"
 9 |   },
10 |   "files": [
11 |     "build"
12 |   ],
13 |   "scripts": {
14 |     "start": "node build/index.js",
15 |     "dev": "ts-node src/index.ts",
16 |     "build": "tsc",
17 |     "watch": "tsc -w"
18 |   },
19 |   "dependencies": {
20 |     "@modelcontextprotocol/sdk": "0.6.0",
21 |     "axios": "^1.8.4",
22 |     "dotenv": "^16.4.7",
23 |     "express": "^5.1.0",
24 |     "ws": "^8.18.1"
25 |   },
26 |   "devDependencies": {
27 |     "@types/node": "^20.17.28",
28 |     "@types/ws": "^8.18.0",
29 |     "typescript": "^5.3.3"
30 |   }
31 | }
32 | 
```
--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------
```typescript
 1 | export interface RevitModelInfo {
 2 |   name: string;
 3 |   path: string;
 4 |   version: string;
 5 |   elements_count: number;
 6 |   last_modified: string;
 7 | }
 8 | 
 9 | export interface RevitElement {
10 |   id: string;
11 |   category: string;
12 |   family: string;
13 |   type: string;
14 |   name: string;
15 |   level: string;
16 |   parameters: Record<string, any>;
17 | }
18 | 
19 | export interface GetElementsArgs {
20 |   category?: string;
21 |   family?: string;
22 |   type?: string;
23 |   level?: string;
24 |   limit?: number;
25 | }
26 | 
27 | export interface GetElementInfoArgs {
28 |   elementId: string;
29 |   getItemPropertyInfo?: boolean;
30 |   getItemParameterInfo?: boolean;
31 | }
32 | 
33 | // 类型守卫,用于验证查询参数
34 | export function isValidElementsArgs(args: any): args is GetElementsArgs {
35 |   return (
36 |     typeof args === "object" && 
37 |     args !== null && 
38 |     (args.category === undefined || typeof args.category === "string") &&
39 |     (args.family === undefined || typeof args.family === "string") &&
40 |     (args.type === undefined || typeof args.type === "string") &&
41 |     (args.level === undefined || typeof args.level === "string") &&
42 |     (args.limit === undefined || typeof args.limit === "number")
43 |   );
44 | }
```
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
```typescript
  1 | #!/usr/bin/env node
  2 | import { Server } from "@modelcontextprotocol/sdk/server/index.js";
  3 | import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
  4 | import {
  5 |   ListResourcesRequestSchema,
  6 |   ReadResourceRequestSchema,
  7 |   ListToolsRequestSchema,
  8 |   CallToolRequestSchema,
  9 |   ErrorCode,
 10 |   McpError
 11 | } from "@modelcontextprotocol/sdk/types.js";
 12 | import dotenv from "dotenv";
 13 | import { RevitService } from "./revitService.js";
 14 | import { isValidElementsArgs } from "./types.js";
 15 | 
 16 | dotenv.config();
 17 | 
 18 | class RevitMcpServer {
 19 |   private server: Server;
 20 |   private revitService: RevitService;
 21 | 
 22 |   constructor() {
 23 |     this.server = new Server({
 24 |       name: "revit-mcp-server",
 25 |       version: "0.1.0"
 26 |     }, {
 27 |       capabilities: {
 28 |         resources: {},
 29 |         tools: {}
 30 |       }
 31 |     });
 32 | 
 33 | 
 34 |     this.revitService = new RevitService();
 35 | 
 36 |     this.setupHandlers();
 37 |     this.setupErrorHandling();
 38 |   }
 39 | 
 40 |   private setupErrorHandling(): void {
 41 |     this.server.onerror = (error) => {
 42 |       console.error("[MCP Error]", error);
 43 |     };
 44 | 
 45 |     process.on('SIGINT', async () => {
 46 |       await this.cleanup();
 47 |       process.exit(0);
 48 |     });
 49 | 
 50 |     process.on('SIGTERM', async () => {
 51 |       await this.cleanup();
 52 |       process.exit(0);
 53 |     });
 54 |   }
 55 | 
 56 |   private async cleanup(): Promise<void> {
 57 |     console.error("[RevitMcpServer] 正在关闭服务...");
 58 |     //await this.revitService.close();
 59 |     await this.server.close();
 60 |     console.error("[RevitMcpServer] 服务已关闭");
 61 |   }
 62 | 
 63 |   private setupHandlers(): void {
 64 |     this.setupResourceHandlers();
 65 |     this.setupToolHandlers();
 66 |   }
 67 | 
 68 |   private setupResourceHandlers(): void {
 69 |     // 保持原有的资源处理程序不变
 70 |     this.server.setRequestHandler(
 71 |       ListResourcesRequestSchema,
 72 |       async () => ({
 73 |         resources: [{
 74 |           uri: "revit://current/model-info",
 75 |           name: "当前 Revit 模型信息",
 76 |           mimeType: "application/json",
 77 |           description: "提供当前打开的 Revit 模型的基本信息,包括名称、路径、版本和元素数量"
 78 |         }]
 79 |       })
 80 |     );
 81 | 
 82 |     this.server.setRequestHandler(
 83 |       ReadResourceRequestSchema,
 84 |       async (request) => {
 85 |         if (request.params.uri !== "revit://current/model-info") {
 86 |           throw new McpError(
 87 |             ErrorCode.InvalidRequest,
 88 |             `未知资源: ${request.params.uri}`
 89 |           );
 90 |         }
 91 | 
 92 |         try {
 93 |           const modelInfo = await this.revitService.getModelInfo();
 94 |           //const modelInfo = '';
 95 |           return {
 96 |             contents: [{
 97 |               uri: request.params.uri,
 98 |               mimeType: "application/json",
 99 |               text: JSON.stringify(modelInfo, null, 2)
100 |             }]
101 |           };
102 |         } catch (error) {
103 |           throw new McpError(
104 |             ErrorCode.InternalError,
105 |             `Revit API 错误: ${error instanceof Error ? error.message : String(error)}`
106 |           );
107 |         }
108 |       }
109 |     );
110 |   }
111 | 
112 |   private setupToolHandlers(): void {
113 |     this.server.setRequestHandler(
114 |       ListToolsRequestSchema,
115 |       async () => ({
116 |         tools: [{
117 |           name: "get_categories",
118 |           description: "获取 Revit 模型中的所有类别",
119 |           inputSchema: {
120 |             type: "object",
121 |             properties: {}
122 |           }
123 |         }, {
124 |           name: "get_families",
125 |           description: "获取 Revit 模型中的所有族",
126 |           inputSchema: {
127 |             type: "object",
128 |             properties: {
129 |               categoryId: {
130 |                 type: "string",
131 |                 description: "族类别 ID(可选)"
132 |               },
133 |               name: {
134 |                 type: "string",
135 |                 description: "族名称过滤(可选)"
136 |               }
137 |             }
138 |           }
139 |         }, {
140 |           name: "get_elements",
141 |           description: "获取 Revit 模型中的元素",
142 |           inputSchema: {
143 |             type: "object",
144 |             properties: {
145 |               categoryIds: {
146 |                 type: "array",
147 |                 description: "需要获取的元素所属类别的Id集合"
148 |               },
149 |               viewIds: {
150 |                 type: "array",
151 |                 description: "需要获取的元素所处的视图的Id集合"
152 |               },
153 |               levelIds: {
154 |                 type: "array",
155 |                 description: "需要获取的元素所处的标高的Id集合"
156 |               }
157 |             }
158 |           }
159 |         },
160 |         {
161 |           name: "get_levels",
162 |           description: "获取 Revit 模型中的所有楼层",
163 |           inputSchema: {
164 |             type: "object",
165 |             properties: {}
166 |           }
167 |         }, {
168 |           name: "get_views",
169 |           description: "获取 Revit 模型中的所有视图",
170 |           inputSchema: {
171 |             type: "object",
172 |             properties: {}
173 |           }
174 |         }, {
175 |           name: "get_element_info",
176 |           description: "获取 Revit 元素的详细信息",
177 |           inputSchema: {
178 |             type: "object",
179 |             properties: {
180 |               elementId: {
181 |                 type: "string",
182 |                 description: "元素的 ID"
183 |               },
184 |               getItemPropertyInfo: {
185 |                 type: "boolean",
186 |                 description: "是否获取元素属性信息",
187 |                 default: true
188 |               },
189 |               getItemParameterInfo: {
190 |                 type: "boolean",
191 |                 description: "是否获取元素参数信息",
192 |                 default: false
193 |               }
194 |             },
195 |             required: ["elementId"]
196 |           }
197 |         }]
198 |       })
199 |     );
200 | 
201 |     this.server.setRequestHandler(
202 |       CallToolRequestSchema,
203 |       async (request) => {
204 |         // 获取工具名称
205 |         const toolName = request.params.name;
206 | 
207 |         // 将工具名称转换为 camelCase 方法名
208 |         const methodName = toolName.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
209 | 
210 |         // 检查 RevitService 是否有对应的方法
211 |         if (typeof (this.revitService as any)[methodName] !== 'function') {
212 |           throw new McpError(
213 |             ErrorCode.MethodNotFound,
214 |             `未知工具: ${toolName}`
215 |           );
216 |         }
217 | 
218 |         try {
219 |           // 动态调用对应的方法
220 |           const result = await (this.revitService as any)[methodName](request.params.arguments || {});
221 |           //const result = '';
222 |           return {
223 |             content: [{
224 |               type: "text",
225 |               text: JSON.stringify(result, null, 2)
226 |             }]
227 |           };
228 |         } catch (error) {
229 |           return {
230 |             content: [{
231 |               type: "text",
232 |               text: `Revit API 错误: ${error instanceof Error ? error.message : String(error)}`
233 |             }],
234 |             isError: true,
235 |           }
236 |         }
237 |       }
238 |     );
239 |   }
240 | 
241 |   async run(): Promise<void> {
242 |     const transport = new StdioServerTransport();
243 |     await this.server.connect(transport);
244 | 
245 |     // 以避免干扰在 stdout 上发生的 MCP 通信
246 |     console.error("Revit MCP 服务器正在通过 stdio 运行");
247 |   }
248 | }
249 | 
250 | const server = new RevitMcpServer();
251 | server.run().catch(console.error);
```