# Bài 2: Demo kết nối thực tiễn

> *Xem trước thành quả cuối khóa học để hình dung mục tiêu — AI thực sự điều khiển Revit như thế nào?*
>
> **Tham chiếu triển khai Tool/MCP Server:** [revit-mcp-server](https://github.com/nguyenngocdue/revit-mcp-server)

***

## Giới thiệu bài học

Trong Bài 1, chúng ta đã tìm hiểu kiến trúc tổng thể của hệ thống **Revit API x MCP x AI**. Bây giờ là lúc chúng ta **nhìn thấy nó hoạt động thật**. Bài học này là một buổi demo trực tiếp, nơi bạn sẽ:

* Chứng kiến AI gửi lệnh cho Revit tạo tường, đặt cột, đọc thông tin model
* Hiểu luồng dữ liệu từ prompt người dùng đến kết quả trên Revit
* Khám phá các use case thực tế trong ngành xây dựng
* Tự tay thử viết prompt và phân tích cách AI suy luận

> **Tại sao bài này quan trọng?** Trước khi bắt tay vào code (từ Bài 3 trở đi), bạn cần hình dung rõ ràng sản phẩm cuối cùng sẽ như thế nào. Điều này giúp bạn có động lực và định hướng đúng trong suốt khóa học.

### Mục tiêu bài học

| STT | Mục tiêu           | Mô tả                                              |
| --- | ------------------ | -------------------------------------------------- |
| 1   | Quan sát demo      | Xem AI điều khiển Revit tạo/đọc/sửa dữ liệu BIM    |
| 2   | Hiểu luồng dữ liệu | Nắm rõ từng bước từ prompt → tool call → kết quả   |
| 3   | Nhận diện use case | Biết những gì AI có thể làm trong thực tế xây dựng |
| 4   | Thực hành prompt   | Viết prompt và dự đoán kết quả trước khi chạy      |

***

## Demo: AI điều khiển Revit

### Tình huống demo

Hãy tưởng tượng bạn đang ngồi trước máy tính, Revit đang mở một project trống. Bạn không cần chạm vào giao diện Revit — thay vào đó, bạn gõ một câu lệnh bằng tiếng Việt trong Claude Code:

```
"Hãy tạo 4 bức tường tạo thành hình chữ nhật 10m x 5m"
```

Và đây là những gì xảy ra:

### Bước 1 — Người dùng nhập prompt

Trong terminal của Claude Code (hoặc VS Code với Copilot), người dùng nhập yêu cầu bằng ngôn ngữ tự nhiên:

```
User: Hãy tạo 4 bức tường tạo thành hình chữ nhật 10m x 5m,
      chiều cao 3m, bắt đầu từ gốc tọa độ (0, 0)
```

### Bước 2 — AI phân tích và suy luận

AI (Claude) nhận prompt và suy luận:

> *"Người dùng muốn 4 bức tường hình chữ nhật. Kích thước 10m x 5m. Bắt đầu từ (0,0). Tôi cần tính tọa độ 4 góc rồi gọi tool `create_wall` 4 lần."*

AI tự động tính toán tọa độ:

```
Tường 1: (0, 0)   → (10, 0)    // Cạnh dưới  - 10m
Tường 2: (10, 0)  → (10, 5)    // Cạnh phải  - 5m
Tường 3: (10, 5)  → (0, 5)     // Cạnh trên  - 10m
Tường 4: (0, 5)   → (0, 0)     // Cạnh trái  - 5m
```

### Bước 3 — AI gọi tool qua MCP

AI gửi 4 tool call liên tiếp đến MCP Server:

```json
// Tool call 1: Cạnh dưới
{
  "tool": "create_wall",
  "arguments": {
    "startX": 0, "startY": 0,
    "endX": 10, "endY": 0,
    "height": 3
  }
}
```

```json
// Tool call 2: Cạnh phải
{
  "tool": "create_wall",
  "arguments": {
    "startX": 10, "startY": 0,
    "endX": 10, "endY": 5,
    "height": 3
  }
}
```

```json
// Tool call 3: Cạnh trên
{
  "tool": "create_wall",
  "arguments": {
    "startX": 10, "startY": 5,
    "endX": 0, "endY": 5,
    "height": 3
  }
}
```

```json
// Tool call 4: Cạnh trái
{
  "tool": "create_wall",
  "arguments": {
    "startX": 0, "startY": 5,
    "endX": 0, "endY": 0,
    "height": 3
  }
}
```

### Bước 4 — Revit thực thi và trả kết quả

Mỗi tool call được MCP Server chuyển tiếp đến Revit Plugin (C#). Plugin gọi Revit API để tạo tường, rồi trả về kết quả:

```json
{
  "status": "success",
  "wallId": 184523,
  "message": "Wall created from (0,0) to (10,0), height 3m"
}
```

### Bước 5 — AI tổng hợp và phản hồi

AI nhận được 4 kết quả thành công và phản hồi:

```
AI: Đã tạo thành công 4 bức tường hình chữ nhật:
    - Tường 1 (cạnh dưới):  10m, từ (0,0) đến (10,0)
    - Tường 2 (cạnh phải):  5m,  từ (10,0) đến (10,5)
    - Tường 3 (cạnh trên):  10m, từ (10,5) đến (0,5)
    - Tường 4 (cạnh trái):  5m,  từ (0,5) đến (0,0)
    Chiều cao: 3m. Tổng chu vi: 30m.
```

> **Mô tả màn hình Revit:** Trong cửa sổ 3D View của Revit, 4 bức tường xuất hiện tạo thành hình hộp chữ nhật. Người dùng có thể xoay, zoom để kiểm tra kết quả.

***

## Giải thích luồng dữ liệu chi tiết

### Sơ đồ tổng thể

```mermaid
sequenceDiagram
    participant U as 👤 Người dùng
    participant AI as 🤖 AI Model (Claude)
    participant MCP as 🔗 MCP Server (Node.js)
    participant RP as ⚙️ Revit Plugin (C#)
    participant R as 🏗️ Autodesk Revit

    U->>AI: "Tạo 4 bức tường hình chữ nhật 10m x 5m"

    Note over AI: Suy luận: Cần tính tọa độ<br/>4 góc và gọi create_wall 4 lần

    AI->>MCP: Tool call: create_wall(0,0 → 10,0)
    MCP->>RP: HTTP POST /api/create-wall
    RP->>R: Revit API: Wall.Create(...)
    R-->>RP: Wall ID: 184523
    RP-->>MCP: {"status": "success", "wallId": 184523}
    MCP-->>AI: Tool result: Wall created

    AI->>MCP: Tool call: create_wall(10,0 → 10,5)
    MCP->>RP: HTTP POST /api/create-wall
    RP->>R: Revit API: Wall.Create(...)
    R-->>RP: Wall ID: 184524
    RP-->>MCP: {"status": "success", "wallId": 184524}
    MCP-->>AI: Tool result: Wall created

    AI->>MCP: Tool call: create_wall(10,5 → 0,5)
    MCP->>RP: HTTP POST /api/create-wall
    RP->>R: Revit API: Wall.Create(...)
    R-->>RP: Wall ID: 184525
    RP-->>MCP: {"status": "success", "wallId": 184525}
    MCP-->>AI: Tool result: Wall created

    AI->>MCP: Tool call: create_wall(0,5 → 0,0)
    MCP->>RP: HTTP POST /api/create-wall
    RP->>R: Revit API: Wall.Create(...)
    R-->>RP: Wall ID: 184526
    RP-->>MCP: {"status": "success", "wallId": 184526}
    MCP-->>AI: Tool result: Wall created

    AI-->>U: "Đã tạo thành công 4 bức tường..."
```

### Chi tiết từng tầng giao tiếp

#### Tầng 1: Người dùng → AI (Ngôn ngữ tự nhiên)

Người dùng gõ prompt bằng tiếng Việt hoặc tiếng Anh. AI hiểu ngữ nghĩa và chuyển thành hành động cụ thể. Đây là điểm mạnh của việc dùng LLM — bạn không cần biết cú pháp lệnh, chỉ cần mô tả ý định.

#### Tầng 2: AI → MCP Server (MCP Protocol / JSON-RPC)

AI không gọi trực tiếp Revit. Thay vào đó, nó gọi **tool** đã được đăng ký trên MCP Server. Mỗi tool có:

* **Tên** (`create_wall`, `get_walls`, ...)
* **Mô tả** (để AI biết khi nào nên dùng)
* **Tham số** (schema của input)

```typescript
// Định nghĩa tool trên MCP Server
server.tool(
  "create_wall",
  "Tạo một bức tường mới trong Revit với tọa độ bắt đầu, kết thúc và chiều cao",
  {
    startX: z.number().describe("Tọa độ X điểm bắt đầu (mét)"),
    startY: z.number().describe("Tọa độ Y điểm bắt đầu (mét)"),
    endX:   z.number().describe("Tọa độ X điểm kết thúc (mét)"),
    endY:   z.number().describe("Tọa độ Y điểm kết thúc (mét)"),
    height: z.number().describe("Chiều cao tường (mét)"),
  },
  async ({ startX, startY, endX, endY, height }) => {
    // Gọi sang Revit Plugin
    const response = await fetch("http://localhost:8080/api/create-wall", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify({ startX, startY, endX, endY, height }),
    });
    const result = await response.json();
    return {
      content: [{ type: "text", text: JSON.stringify(result) }],
    };
  }
);
```

#### Tầng 3: MCP Server → Revit Plugin (HTTP REST)

MCP Server gửi HTTP request đến Revit Plugin đang lắng nghe tại `localhost:8080`. Plugin nhận request, phân tích tham số, rồi gọi Revit API.

#### Tầng 4: Revit Plugin → Revit (Revit API / C#)

Plugin sử dụng `Wall.Create()` để tạo tường trong model:

```csharp
public static string Execute(Document doc, WallRequest request)
{
    // Chuyển đổi từ mét sang feet (Revit dùng đơn vị feet)
    double startX = request.StartX * 3.28084;
    double startY = request.StartY * 3.28084;
    double endX   = request.EndX * 3.28084;
    double endY   = request.EndY * 3.28084;
    double height = request.Height * 3.28084;

    // Tạo line từ điểm bắt đầu đến điểm kết thúc
    XYZ start = new XYZ(startX, startY, 0);
    XYZ end   = new XYZ(endX, endY, 0);
    Line line  = Line.CreateBound(start, end);

    // Tạo tường bằng Revit API
    using (Transaction tx = new Transaction(doc, "Create Wall"))
    {
        tx.Start();
        Wall wall = Wall.Create(doc, line, levelId, height, 0, false, false);
        tx.Commit();

        return JsonConvert.SerializeObject(new {
            status = "success",
            wallId = wall.Id.IntegerValue,
            message = $"Wall created from ({request.StartX},{request.StartY}) " +
                      $"to ({request.EndX},{request.EndY})"
        });
    }
}
```

> **Lưu ý quan trọng:** Revit sử dụng đơn vị **feet**, nhưng người dùng và AI làm việc với đơn vị **mét**. Plugin phải chuyển đổi đơn vị trước khi gọi API.

***

## Sơ đồ trạng thái hệ thống trong quá trình demo

```mermaid
stateDiagram-v2
    [*] --> Idle: Hệ thống sẵn sàng

    Idle --> NhậnPrompt: Người dùng nhập prompt
    NhậnPrompt --> AISuyLuận: AI nhận và phân tích

    AISuyLuận --> GọiTool: AI quyết định gọi tool
    AISuyLuận --> TrảLờiTrựcTiếp: Không cần tool (câu hỏi chung)

    GọiTool --> MCPXửLý: MCP Server nhận tool call
    MCPXửLý --> RevitThựcThi: Chuyển tiếp đến Revit Plugin
    RevitThựcThi --> ThànhCông: Revit API thành công
    RevitThựcThi --> ThấtBại: Revit API thất bại

    ThànhCông --> AITổngHợp: Trả kết quả về AI
    ThấtBại --> AIXửLýLỗi: Trả lỗi về AI

    AITổngHợp --> CònToolKhác: Cần gọi thêm tool?
    CònToolKhác --> GọiTool: Có
    CònToolKhác --> PhảnHồi: Không

    AIXửLýLỗi --> PhảnHồi: Thông báo lỗi cho người dùng
    TrảLờiTrựcTiếp --> PhảnHồi

    PhảnHồi --> Idle: Chờ prompt tiếp theo
```

***

## Các use case thực tế trong ngành xây dựng

### Sơ đồ use case

```mermaid
mindmap
  root((AI x Revit<br/>Use Cases))
    Đọc dữ liệu
      Liệt kê tất cả tường trong model
      Đếm số lượng cột theo tầng
      Lấy thông tin phòng và diện tích
      Xuất danh sách vật liệu
      Đọc thông số kỹ thuật của family
    Tạo đối tượng
      Tạo tường theo tọa độ
      Đặt cột tại vị trí chỉ định
      Tạo sàn cho tầng mới
      Thêm cửa đi và cửa sổ
      Tạo lưới trục
    Phân tích
      Tính tổng diện tích sàn theo tầng
      So sánh kích thước phòng với tiêu chuẩn
      Kiểm tra xung đột giữa các hệ thống
      Thống kê khối lượng vật tư
    Chỉnh sửa
      Đổi chiều cao tường
      Di chuyển đối tượng
      Xóa phần tử theo điều kiện
      Cập nhật thông số family
    Tự động hóa
      Tạo layout phòng từ yêu cầu
      Sinh báo cáo từ model
      Kiểm tra tiêu chuẩn thiết kế
      Batch update thông tin
```

### Chi tiết các use case

#### 1. Đọc thông tin model

```
Prompt: "Liệt kê tất cả các phòng ở tầng 1, bao gồm tên, diện tích và số hiệu phòng"
```

AI sẽ gọi tool `get_rooms` và lọc theo tầng 1:

```json
[
  { "Id": 20001, "Name": "Phòng khách",   "Number": "101", "Area": 25.5,  "Level": "Level 1" },
  { "Id": 20002, "Name": "Phòng bếp",     "Number": "102", "Area": 12.8,  "Level": "Level 1" },
  { "Id": 20003, "Name": "Phòng ngủ 1",   "Number": "103", "Area": 18.2,  "Level": "Level 1" },
  { "Id": 20004, "Name": "Nhà vệ sinh",   "Number": "104", "Area": 6.5,   "Level": "Level 1" }
]
```

#### 2. Tạo đối tượng tự động

```
Prompt: "Đặt 6 cột bê tông 400x400mm tại các vị trí giao nhau của lưới trục A-C và 1-2,
         khoảng cách trục 6m theo phương X và 8m theo phương Y"
```

AI sẽ tính tọa độ và gọi `create_column` 6 lần:

| Cột | Trục | X (m) | Y (m) |
| --- | ---- | ----- | ----- |
| 1   | A-1  | 0     | 0     |
| 2   | A-2  | 6     | 0     |
| 3   | B-1  | 0     | 8     |
| 4   | B-2  | 6     | 8     |
| 5   | C-1  | 0     | 16    |
| 6   | C-2  | 6     | 16    |

#### 3. Phân tích và báo cáo

```
Prompt: "Tính tổng diện tích sàn của từng tầng và so sánh với quy định
         diện tích sàn tối thiểu 50m² cho mỗi căn hộ"
```

AI sẽ:

1. Gọi `get_floors` — lấy danh sách sàn
2. Gọi `get_rooms` — lấy danh sách phòng
3. Tự tính toán và so sánh
4. Trả về báo cáo dạng bảng

#### 4. Chỉnh sửa hàng loạt

```
Prompt: "Đổi chiều cao tất cả tường từ tầng 2 trở lên thành 3.2m"
```

AI sẽ:

1. Gọi `get_walls` — lấy danh sách tường
2. Lọc tường từ tầng 2 trở lên
3. Gọi `update_wall_height` cho từng tường
4. Báo cáo số lượng tường đã cập nhật

***

## Ví dụ prompt và kết quả

### Ví dụ 1: Tạo tường đơn giản

**Prompt:**

```
Tạo một bức tường dài 8m, chiều cao 3m, bắt đầu từ điểm (2, 3) theo hướng ngang
```

**AI suy luận:**

* Điểm bắt đầu: (2, 3)
* Hướng ngang = theo trục X
* Dài 8m → điểm kết thúc: (10, 3)
* Chiều cao: 3m

**Tool call:**

```json
{
  "tool": "create_wall",
  "arguments": {
    "startX": 2, "startY": 3,
    "endX": 10, "endY": 3,
    "height": 3
  }
}
```

**Kết quả:**

```
AI: Đã tạo thành công 1 bức tường:
    - Vị trí: từ (2, 3) đến (10, 3)
    - Chiều dài: 8m
    - Chiều cao: 3m
```

***

### Ví dụ 2: Truy vấn thông tin phức tạp

**Prompt:**

```
Trong model hiện tại, có bao nhiêu bức tường? Tường nào dài nhất và ngắn nhất?
```

**AI suy luận:**

* Cần gọi `get_walls` để lấy danh sách
* Sau đó phân tích dữ liệu để tìm tường dài nhất và ngắn nhất

**Tool call:**

```json
{
  "tool": "get_walls",
  "arguments": {}
}
```

**Kết quả trả về từ Revit:**

```json
[
  { "Id": 12001, "Name": "Basic Wall: Generic - 200mm", "Length": 10.0 },
  { "Id": 12002, "Name": "Basic Wall: Generic - 200mm", "Length": 5.0 },
  { "Id": 12003, "Name": "Basic Wall: Generic - 300mm", "Length": 8.5 },
  { "Id": 12004, "Name": "Basic Wall: Generic - 200mm", "Length": 3.2 },
  { "Id": 12005, "Name": "Basic Wall: Generic - 300mm", "Length": 12.7 }
]
```

**AI phản hồi:**

```
Trong model hiện tại có 5 bức tường:

- Tường dài nhất: ID 12005 (Basic Wall: Generic - 300mm) — 12.7m
- Tường ngắn nhất: ID 12004 (Basic Wall: Generic - 200mm) — 3.2m

Tổng chiều dài tất cả tường: 39.4m
```

***

### Ví dụ 3: Tác vụ phức tạp — kết hợp nhiều tool

**Prompt:**

```
Tạo một căn phòng họp 6m x 4m với 1 cửa đi ở tường phía Nam và 2 cửa sổ ở tường phía Đông.
Chiều cao tường 3.5m.
```

**AI suy luận:**

> *"Tôi cần thực hiện nhiều bước:*
>
> 1. *Tạo 4 tường tạo thành phòng 6m x 4m*
> 2. *Thêm 1 cửa đi (door) trên tường phía Nam*
> 3. *Thêm 2 cửa sổ (window) trên tường phía Đông* *Phương Nam là hướng Y âm, tức là tường có Y = 0"*

**Chuỗi tool call:**

```
Tool call 1: create_wall(0,0 → 6,0, h=3.5)    // Tường Nam
Tool call 2: create_wall(6,0 → 6,4, h=3.5)    // Tường Đông
Tool call 3: create_wall(6,4 → 0,4, h=3.5)    // Tường Bắc
Tool call 4: create_wall(0,4 → 0,0, h=3.5)    // Tường Tây
Tool call 5: insert_door(wallId=..., position=3.0, width=0.9)     // Cửa đi giữa tường Nam
Tool call 6: insert_window(wallId=..., position=1.5, width=1.2)   // Cửa sổ 1 tường Đông
Tool call 7: insert_window(wallId=..., position=3.0, width=1.2)   // Cửa sổ 2 tường Đông
```

***

## Phân tích: AI suy luận như thế nào

### Quá trình suy luận của AI

Khi nhận một prompt, AI không đơn giản là "dịch" ngôn ngữ sang lệnh. Nó thực hiện một quá trình suy luận phức tạp:

```mermaid
graph TD
    A["📝 Nhận prompt từ người dùng"] --> B["🔍 Phân tích ý định"]
    B --> C["📋 Xem danh sách tools có sẵn"]
    C --> D["🧮 Tính toán tham số cần thiết"]
    D --> E["📐 Lập kế hoạch thực hiện"]
    E --> F["🔧 Gọi tool lần lượt"]
    F --> G{"Kiểm tra kết quả"}
    G -- "Thành công" --> H["Tiếp tục tool tiếp theo"]
    G -- "Thất bại" --> I["Điều chỉnh và thử lại"]
    H --> J{"Còn tool nào không?"}
    J -- "Có" --> F
    J -- "Không" --> K["💬 Tổng hợp và trả lời"]
    I --> F

    style A fill:#E3F2FD,stroke:#333
    style K fill:#E8F5E9,stroke:#333
```

### Tại sao AI có thể làm được điều này?

| Khả năng              | Giải thích                                                            |
| --------------------- | --------------------------------------------------------------------- |
| **Hiểu ngôn ngữ**     | LLM được huấn luyện trên hàng tỷ văn bản, hiểu được ý định người dùng |
| **Suy luận toán học** | Tính tọa độ, kích thước, đơn vị tự động                               |
| **Lập kế hoạch**      | Chia tác vụ phức tạp thành các bước nhỏ                               |
| **Sử dụng tool**      | Biết chọn đúng tool và truyền đúng tham số                            |
| **Xử lý lỗi**         | Khi một bước thất bại, có thể điều chỉnh và thử lại                   |

### Hạn chế của AI trong bối cảnh này

AI không phải là hoàn hảo. Có những điều cần lưu ý:

* **Không nhìn thấy màn hình Revit** — AI chỉ biết dữ liệu trả về từ tool, không thấy giao diện 3D
* **Có thể tính sai** — Đặc biệt với bài toán hình học phức tạp
* **Phụ thuộc vào tool** — AI chỉ làm được những gì tool cho phép
* **Không hiểu ngữ cảnh dự án** — Chưa biết quy chuẩn thiết kế cụ thể của dự án

***

## Câu hỏi tự suy nghĩ

Hãy suy nghĩ về các câu hỏi dưới đây trước khi xem đáp án. Đây là cách tốt nhất để hiểu sâu bài học.

***

**Câu 1:** Tại sao AI cần gọi tool `create_wall` 4 lần riêng biệt thay vì 1 lần tạo 4 tường cùng lúc?

<details>

<summary>💡 Xem đáp án</summary>

Mỗi tool call tương ứng với **một hành động đơn lẻ** trên Revit API. Revit API function `Wall.Create()` tạo **một bức tường mỗi lần gọi**. Việc tách thành 4 tool call có ưu điểm:

1. **Dễ kiểm soát lỗi** — nếu 1 tường thất bại, 3 tường kia vẫn thành công
2. **Phù hợp với Revit API** — API không có hàm "tạo nhiều tường cùng lúc"
3. **AI có thể điều chỉnh** — nếu tường 1 thất bại, AI có thể sửa tham số và thử lại

Tuy nhiên, trong thực tế có thể tạo tool `create_room_layout` nhận nhiều tường cùng lúc để tối ưu hiệu suất.

</details>

***

**Câu 2:** Trong ví dụ tạo tường 10m x 5m, nếu người dùng không nói "bắt đầu từ gốc tọa độ (0,0)", AI sẽ xử lý như thế nào?

<details>

<summary>💡 Xem đáp án</summary>

AI sẽ phải **tự quyết định** điểm bắt đầu. Thường thì AI sẽ:

1. **Mặc định dùng gốc tọa độ (0, 0)** — đây là lựa chọn an toàn nhất
2. **Hỏi lại người dùng** — nếu AI được cấu hình để hỏi khi thiếu thông tin
3. **Dùng tool đọc model** — gọi `get_elements` để xem các đối tượng hiện có và đặt tường ở vị trí phù hợp

Điều này cho thấy **prompt càng chi tiết, kết quả càng chính xác**. Đây là nguyên tắc quan trọng của Prompt Engineering trong BIM.

</details>

***

**Câu 3:** Khi AI gọi tool `create_wall`, đơn vị được truyền là mét (10, 5, 3). Nhưng Revit dùng đơn vị feet. Ai chịu trách nhiệm chuyển đổi?

<details>

<summary>💡 Xem đáp án</summary>

**Revit Plugin (C#)** chịu trách nhiệm chuyển đổi đơn vị. Đây là thiết kế tốt vì:

1. **AI và người dùng làm việc với mét** — đơn vị quen thuộc trong ngành xây dựng Việt Nam
2. **Plugin chuyển đổi sang feet trước khi gọi Revit API** — `value * 3.28084`
3. **MCP Server không cần quan tâm đơn vị** — chỉ chuyển tiếp dữ liệu

Công thức chuyển đổi: `1 mét = 3.28084 feet`

Nếu để AI tự chuyển đổi, có nguy cơ sai sót. Việc chuyển đổi ở tầng plugin đảm bảo tính nhất quán và chính xác.

</details>

***

**Câu 4:** Điều gì xảy ra nếu Revit bị treo hoặc plugin không phản hồi trong khi AI đang gọi tool?

<details>

<summary>💡 Xem đáp án</summary>

Đây là tình huống thực tế cần xử lý:

1. **Timeout** — MCP Server sẽ đặt timeout cho HTTP request (ví dụ 30 giây). Nếu Revit không trả lời, server trả về `timeout error`
2. **AI nhận lỗi** — AI nhận được thông báo lỗi từ tool và có thể:
   * Thông báo cho người dùng: *"Revit không phản hồi. Vui lòng kiểm tra Revit có đang chạy không"*
   * Thử lại lần nữa nếu lỗi tạm thời
3. **Không mất dữ liệu** — Các tường đã tạo trước đó vẫn tồn tại trong model Revit

Trong code, cần xử lý bằng `try-catch` và timeout:

```typescript
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 30000);

try {
  const response = await fetch(url, { signal: controller.signal });
  // Xử lý kết quả
} catch (error) {
  return {
    content: [{
      type: "text",
      text: "Revit không phản hồi. Vui lòng thử lại."
    }]
  };
} finally {
  clearTimeout(timeout);
}
```

</details>

***

**Câu 5:** Ngoài tường và cột, hãy liệt kê 5 đối tượng BIM khác mà AI có thể tạo/đọc/sửa trong Revit qua MCP. Với mỗi đối tượng, hãy đề xuất tên tool và tham số cần thiết.

<details>

<summary>💡 Xem đáp án</summary>

| STT | Đối tượng           | Tên tool        | Tham số chính                                                |
| --- | ------------------- | --------------- | ------------------------------------------------------------ |
| 1   | **Sàn (Floor)**     | `create_floor`  | `points[]` (đa giác), `thickness`, `level`                   |
| 2   | **Cửa đi (Door)**   | `insert_door`   | `wallId`, `position`, `width`, `height`, `familyType`        |
| 3   | **Cửa sổ (Window)** | `insert_window` | `wallId`, `position`, `width`, `height`, `sillHeight`        |
| 4   | **Phòng (Room)**    | `create_room`   | `level`, `x`, `y` (điểm đặt trong vùng kín)                  |
| 5   | **Dầm (Beam)**      | `create_beam`   | `startX`, `startY`, `startZ`, `endX`, `endY`, `endZ`, `type` |

Mỗi tool cần có mô tả rõ ràng để AI biết khi nào nên sử dụng. Ví dụ:

```typescript
server.tool(
  "create_floor",
  "Tạo sàn mới trong Revit từ danh sách các điểm tạo thành đa giác kín",
  {
    points: z.array(z.object({
      x: z.number(),
      y: z.number()
    })).describe("Danh sách điểm (mét) tạo thành đường bao sàn"),
    level: z.string().describe("Tên tầng, ví dụ: Level 1"),
    thickness: z.number().describe("Độ dày sàn (mét)")
  },
  async ({ points, level, thickness }) => { /* ... */ }
);
```

</details>

***

## Tổng kết

### Những gì đã học trong bài này

| Nội dung                                                | Trạng thái |
| ------------------------------------------------------- | ---------- |
| Demo AI điều khiển Revit tạo tường, đọc thông tin       | Hoàn thành |
| Hiểu luồng dữ liệu: Prompt → AI → MCP → Revit → Kết quả | Hoàn thành |
| Các use case thực tế trong ngành xây dựng               | Hoàn thành |
| Viết prompt và dự đoán kết quả                          | Hoàn thành |
| Hiểu cách AI suy luận và lập kế hoạch                   | Hoàn thành |

### Sơ đồ tóm tắt luồng hoạt động

```
Người dùng        AI              MCP Server        Revit Plugin         Revit
    |                |                  |                  |                  |
    |--- Prompt ---->|                  |                  |                  |
    |                |--- Tool call --->|                  |                  |
    |                |                  |--- HTTP POST --->|                  |
    |                |                  |                  |--- API call ---->|
    |                |                  |                  |<--- Kết quả -----|
    |                |                  |<--- Response ----|                  |
    |                |<--- Kết quả -----|                  |                  |
    |<--- Phản hồi --|                  |                  |                  |
```

### Chuẩn bị cho bài tiếp theo

Trong **Bài 3: Triển khai Tool cơ bản với Revit API**, chúng ta sẽ bắt đầu **viết code C#** — tạo tool đầu tiên trong Revit. Bạn sẽ tự tay:

1. Tạo project C# plugin cho Revit
2. Viết hàm lấy danh sách tường (`GetWallsTool`)
3. Test tool trực tiếp trong Revit
4. Hiểu cách Revit API hoạt động

> **Lời khuyên:** Trước khi sang Bài 3, hãy xem lại sơ đồ kiến trúc tổng thể ở Bài 1 và đảm bảo bạn hiểu rõ vai trò của từng thành phần. Code sẽ dễ hiểu hơn nếu bạn nắm vững bức tranh tổng thể.

***

## Tài liệu tham khảo

### Source code

* [deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) — Repository chính của khóa học, chứa toàn bộ source code plugin Revit và MCP Server

### MCP Protocol

* [Model Context Protocol - Specification](https://spec.modelcontextprotocol.io/) — Tài liệu chính thức về MCP
* [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) — SDK để xây dựng MCP Server bằng Node.js
* [MCP Examples](https://github.com/modelcontextprotocol/servers) — Các ví dụ MCP Server tham khảo

### Revit API

* [Revit API Documentation](https://www.revitapidocs.com/) — Tài liệu tra cứu Revit API
* [Revit API Developer Guide](https://help.autodesk.com/view/RVT/2024/ENU/?guid=Revit_API_Revit_API_Developers_Guide_html) — Hướng dẫn chính thức từ Autodesk

### AI và Tool Use

* [Claude Tool Use Documentation](https://docs.anthropic.com/en/docs/build-with-claude/tool-use) — Cách Claude sử dụng tool
* [Prompt Engineering Guide](https://docs.anthropic.com/en/docs/build-with-claude/prompt-engineering/overview) — Hướng dẫn viết prompt hiệu quả

***

> **Bài trước:** [← Bài 1: Giới thiệu tổng quan](/revit-mcp-ai/phan-1-nen-tang/bai-1.md)
>
> **Bài tiếp theo:** [Bài 3: Triển khai Tool cơ bản với Revit API →](/revit-mcp-ai/phan-2-xay-dung-tung-thanh-phan/bai-3.md)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://deepbim.gitbook.io/revit-mcp-ai/phan-1-nen-tang/bai-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
