#
tokens: 3014/50000 6/6 files
lines: off (toggle) GitHub
raw markdown copy
# 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:
--------------------------------------------------------------------------------

```
node_modules/
build/
*.log
.env*
```

--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------

```markdown
# 🏗️ Revit MCP Server

A Model Context Protocol server for Revit integration, enabling seamless communication between Claude AI and Autodesk Revit.

[English](./README.md) | [中文](./README.zh-CN.md)

## 🎯 Overview

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:

- ⚡ Real-time access to Revit model information
- 🔍 Element querying and filtering
- 👀 View and level management
- 🛡️ Robust error handling with fallback mock data

## ✨ Features

### 🔌 Revit Integration
- 📡 WebSocket-based communication with Revit plugin
- 🔄 Real-time model data access
- 🔁 Graceful fallback to mock data when connection fails
- ⚙️ Configurable connection settings via environment variables

### 🚀 Core Functionalities
- **📊 Model Information**
  - Access basic model metadata (name, path, version)
  - Get element counts and last modification date
  - Real-time model state synchronization

- **🏗️ Element Management**
  - Query elements with flexible filtering
  - Access element properties and geometry
  - Batch element operations

- **🎪 View & Level Control**
  - List all available views
  - Access level information
  - Navigate through model hierarchy

## 💻 Development

### 📋 Prerequisites
- Node.js (v14 or higher)
- npm
- Autodesk Revit (2023 or later)
- Revit WebSocket Plugin (companion plugin)

### 🔧 Installation

Install dependencies:
```bash
npm install
```
Build the server:

```bash
npm run build
 ```

For development with auto-rebuild:

```bash
npm run watch
 ```

### ⚙️ Configuration
The server can be configured using environment variables:

```plaintext
REVIT_HOST=127.0.0.1    # Revit plugin WebSocket host
REVIT_PORT=8080         # Revit plugin WebSocket port
 ```

## 🔗 Integration with Claude Desktop
Add the server configuration to Claude Desktop:

Windows:

```bash
%APPDATA%/Claude/claude_desktop_config.json
 ```

Configuration format:

```json
{
  "mcpServers": {
    "revit-mcp-server": {
      "command": "D:/path/to/revit-mcp-server/build/index.js"
    }
  }
}
 ```

### 🐛 Debugging


For debugging the MCP communication:

1. Use the built-in MCP Inspector:
```bash
npm run inspector
 ```

2. Monitor WebSocket communication with Revit plugin
3. Check server logs for connection and operation status
## ⚠️ Error Handling
The server implements robust error handling:

- Automatic fallback to mock data when Revit connection fails
- Detailed error logging
- Graceful connection recovery
## 📄 License
MIT License

## 🤝 Contributing
Contributions are welcome! Please feel free to submit pull requests.

## 📬 Contact

If you have any questions or suggestions, feel free to reach out:

- 📧 Email: [email protected]
- 💬 WeChat  Account: modian4500


```

--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------

```json
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "Node16",
    "moduleResolution": "Node16",
    "outDir": "./build",
    "rootDir": "./src",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules"]
}

```

--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------

```json
{
  "name": "revit-mcp-server",
  "version": "0.1.0",
  "description": "A Model Context Protocol server",
  "private": true,
  "type": "module",
  "bin": {
    "revit-mcp-server": "./build/index.js"
  },
  "files": [
    "build"
  ],
  "scripts": {
    "start": "node build/index.js",
    "dev": "ts-node src/index.ts",
    "build": "tsc",
    "watch": "tsc -w"
  },
  "dependencies": {
    "@modelcontextprotocol/sdk": "0.6.0",
    "axios": "^1.8.4",
    "dotenv": "^16.4.7",
    "express": "^5.1.0",
    "ws": "^8.18.1"
  },
  "devDependencies": {
    "@types/node": "^20.17.28",
    "@types/ws": "^8.18.0",
    "typescript": "^5.3.3"
  }
}

```

--------------------------------------------------------------------------------
/src/types.ts:
--------------------------------------------------------------------------------

```typescript
export interface RevitModelInfo {
  name: string;
  path: string;
  version: string;
  elements_count: number;
  last_modified: string;
}

export interface RevitElement {
  id: string;
  category: string;
  family: string;
  type: string;
  name: string;
  level: string;
  parameters: Record<string, any>;
}

export interface GetElementsArgs {
  category?: string;
  family?: string;
  type?: string;
  level?: string;
  limit?: number;
}

export interface GetElementInfoArgs {
  elementId: string;
  getItemPropertyInfo?: boolean;
  getItemParameterInfo?: boolean;
}

// 类型守卫,用于验证查询参数
export function isValidElementsArgs(args: any): args is GetElementsArgs {
  return (
    typeof args === "object" && 
    args !== null && 
    (args.category === undefined || typeof args.category === "string") &&
    (args.family === undefined || typeof args.family === "string") &&
    (args.type === undefined || typeof args.type === "string") &&
    (args.level === undefined || typeof args.level === "string") &&
    (args.limit === undefined || typeof args.limit === "number")
  );
}
```

--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------

```typescript
#!/usr/bin/env node
import { Server } from "@modelcontextprotocol/sdk/server/index.js";
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
import {
  ListResourcesRequestSchema,
  ReadResourceRequestSchema,
  ListToolsRequestSchema,
  CallToolRequestSchema,
  ErrorCode,
  McpError
} from "@modelcontextprotocol/sdk/types.js";
import dotenv from "dotenv";
import { RevitService } from "./revitService.js";
import { isValidElementsArgs } from "./types.js";

dotenv.config();

class RevitMcpServer {
  private server: Server;
  private revitService: RevitService;

  constructor() {
    this.server = new Server({
      name: "revit-mcp-server",
      version: "0.1.0"
    }, {
      capabilities: {
        resources: {},
        tools: {}
      }
    });


    this.revitService = new RevitService();

    this.setupHandlers();
    this.setupErrorHandling();
  }

  private setupErrorHandling(): void {
    this.server.onerror = (error) => {
      console.error("[MCP Error]", error);
    };

    process.on('SIGINT', async () => {
      await this.cleanup();
      process.exit(0);
    });

    process.on('SIGTERM', async () => {
      await this.cleanup();
      process.exit(0);
    });
  }

  private async cleanup(): Promise<void> {
    console.error("[RevitMcpServer] 正在关闭服务...");
    //await this.revitService.close();
    await this.server.close();
    console.error("[RevitMcpServer] 服务已关闭");
  }

  private setupHandlers(): void {
    this.setupResourceHandlers();
    this.setupToolHandlers();
  }

  private setupResourceHandlers(): void {
    // 保持原有的资源处理程序不变
    this.server.setRequestHandler(
      ListResourcesRequestSchema,
      async () => ({
        resources: [{
          uri: "revit://current/model-info",
          name: "当前 Revit 模型信息",
          mimeType: "application/json",
          description: "提供当前打开的 Revit 模型的基本信息,包括名称、路径、版本和元素数量"
        }]
      })
    );

    this.server.setRequestHandler(
      ReadResourceRequestSchema,
      async (request) => {
        if (request.params.uri !== "revit://current/model-info") {
          throw new McpError(
            ErrorCode.InvalidRequest,
            `未知资源: ${request.params.uri}`
          );
        }

        try {
          const modelInfo = await this.revitService.getModelInfo();
          //const modelInfo = '';
          return {
            contents: [{
              uri: request.params.uri,
              mimeType: "application/json",
              text: JSON.stringify(modelInfo, null, 2)
            }]
          };
        } catch (error) {
          throw new McpError(
            ErrorCode.InternalError,
            `Revit API 错误: ${error instanceof Error ? error.message : String(error)}`
          );
        }
      }
    );
  }

  private setupToolHandlers(): void {
    this.server.setRequestHandler(
      ListToolsRequestSchema,
      async () => ({
        tools: [{
          name: "get_categories",
          description: "获取 Revit 模型中的所有类别",
          inputSchema: {
            type: "object",
            properties: {}
          }
        }, {
          name: "get_families",
          description: "获取 Revit 模型中的所有族",
          inputSchema: {
            type: "object",
            properties: {
              categoryId: {
                type: "string",
                description: "族类别 ID(可选)"
              },
              name: {
                type: "string",
                description: "族名称过滤(可选)"
              }
            }
          }
        }, {
          name: "get_elements",
          description: "获取 Revit 模型中的元素",
          inputSchema: {
            type: "object",
            properties: {
              categoryIds: {
                type: "array",
                description: "需要获取的元素所属类别的Id集合"
              },
              viewIds: {
                type: "array",
                description: "需要获取的元素所处的视图的Id集合"
              },
              levelIds: {
                type: "array",
                description: "需要获取的元素所处的标高的Id集合"
              }
            }
          }
        },
        {
          name: "get_levels",
          description: "获取 Revit 模型中的所有楼层",
          inputSchema: {
            type: "object",
            properties: {}
          }
        }, {
          name: "get_views",
          description: "获取 Revit 模型中的所有视图",
          inputSchema: {
            type: "object",
            properties: {}
          }
        }, {
          name: "get_element_info",
          description: "获取 Revit 元素的详细信息",
          inputSchema: {
            type: "object",
            properties: {
              elementId: {
                type: "string",
                description: "元素的 ID"
              },
              getItemPropertyInfo: {
                type: "boolean",
                description: "是否获取元素属性信息",
                default: true
              },
              getItemParameterInfo: {
                type: "boolean",
                description: "是否获取元素参数信息",
                default: false
              }
            },
            required: ["elementId"]
          }
        }]
      })
    );

    this.server.setRequestHandler(
      CallToolRequestSchema,
      async (request) => {
        // 获取工具名称
        const toolName = request.params.name;

        // 将工具名称转换为 camelCase 方法名
        const methodName = toolName.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());

        // 检查 RevitService 是否有对应的方法
        if (typeof (this.revitService as any)[methodName] !== 'function') {
          throw new McpError(
            ErrorCode.MethodNotFound,
            `未知工具: ${toolName}`
          );
        }

        try {
          // 动态调用对应的方法
          const result = await (this.revitService as any)[methodName](request.params.arguments || {});
          //const result = '';
          return {
            content: [{
              type: "text",
              text: JSON.stringify(result, null, 2)
            }]
          };
        } catch (error) {
          return {
            content: [{
              type: "text",
              text: `Revit API 错误: ${error instanceof Error ? error.message : String(error)}`
            }],
            isError: true,
          }
        }
      }
    );
  }

  async run(): Promise<void> {
    const transport = new StdioServerTransport();
    await this.server.connect(transport);

    // 以避免干扰在 stdout 上发生的 MCP 通信
    console.error("Revit MCP 服务器正在通过 stdio 运行");
  }
}

const server = new RevitMcpServer();
server.run().catch(console.error);
```