# Bài 1: Giới thiệu tổng quan

> **Khóa học:** Revit API x MCP x AI — Từ Zero đến Plugin hoàn chỉnh **Bài học:** 1/10 — Giới thiệu tổng quan **Thời gian đọc:** \~20 phút **Mã nguồn tham khảo:** [deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) **Tham chiếu triển khai Tool/MCP Server:** [revit-mcp-server](https://github.com/nguyenngocdue/revit-mcp-server)

***

## Mục lục

1. [Giới thiệu](#giới-thiệu)
2. [MCP là gì?](#mcp-là-gì)
3. [Revit API là gì?](#revit-api-là-gì)
4. [Kiến trúc tổng thể](#kiến-trúc-tổng-thể)
5. [Tại sao chọn MCP thay vì gọi API trực tiếp?](#tại-sao-chọn-mcp)
6. [Luồng dữ liệu](#luồng-dữ-liệu)
7. [Câu hỏi tự suy nghĩ](#câu-hỏi-tự-suy-nghĩ)
8. [Tổng kết](#tổng-kết)
9. [Tài liệu tham khảo](#tài-liệu-tham-khảo)

***

## Giới thiệu

Trong ngành xây dựng và thiết kế (AEC — Architecture, Engineering, Construction), **Autodesk Revit** là phần mềm BIM (Building Information Modeling) được sử dụng rộng rãi nhất thế giới. Các kỹ sư, kiến trúc sư hàng ngày làm việc với hàng ngàn đối tượng (tường, cửa, cột, dầm, sàn...) trong mô hình Revit.

Câu hỏi đặt ra là: **Làm thế nào để AI có thể "hiểu" và "thao tác" trực tiếp trên mô hình Revit?**

Trước đây, để tự động hóa Revit, bạn phải viết C# plugin hoặc sử dụng Dynamo. Nhưng với sự phát triển của các mô hình ngôn ngữ lớn (LLM) như ChatGPT, Claude, Gemini... một hướng tiếp cận mới đã xuất hiện:

> **Sử dụng AI làm "bộ não", MCP làm "cầu nối", và Revit API làm "đôi tay"** để thực hiện các tác vụ trên mô hình BIM.

Đây chính là ý tưởng cốt lõi của dự án [deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) — một hệ thống cho phép người dùng nói chuyện với AI bằng ngôn ngữ tự nhiên, và AI sẽ tự động thực hiện các thao tác trên Revit thông qua giao thức MCP.

### Bạn sẽ học được gì trong bài này?

* Hiểu khái niệm MCP (Model Context Protocol) và tại sao nó quan trọng.
* Hiểu Revit API là gì và nó cho phép làm những gì.
* Nắm được kiến trúc tổng thể của hệ thống Revit + MCP + AI.
* Phân biệt được cách tiếp cận MCP với cách gọi API trực tiếp.
* Theo dõi được luồng dữ liệu từ câu hỏi người dùng đến kết quả trả về.

***

## MCP là gì?

![MCP là gì - kiến trúc tổng quan](/files/Sz1cdPCaketASWX8nYxq)

### Định nghĩa

**MCP** (Model Context Protocol) là một **giao thức chuẩn mở** (open standard protocol) do [Anthropic](https://www.anthropic.com/) phát triển, cho phép các mô hình AI (LLM) **giao tiếp với phần mềm và dịch vụ bên ngoài** một cách có cấu trúc, an toàn và nhất quán.

Nói đơn giản:

> MCP giống như một **ổ cắm chuẩn** (universal adapter) giữa AI và thế giới phần mềm bên ngoài. Thay vì mỗi phần mềm phải tự xây dựng cách kết nối riêng với AI, MCP cung cấp một giao thức duy nhất mà tất cả đều có thể sử dụng.

### Tại sao cần MCP?

Trước khi có MCP, để AI tương tác với một phần mềm (ví dụ Revit), bạn phải:

1. Tự thiết kế API riêng.
2. Tự định nghĩa format dữ liệu.
3. Tự xử lý authentication, error handling.
4. Mỗi phần mềm là một cách làm khác nhau.

Với MCP, tất cả đều theo **một chuẩn duy nhất**:

| Không có MCP                           | Có MCP                              |
| -------------------------------------- | ----------------------------------- |
| Mỗi app tự làm integration riêng       | Một giao thức chung cho tất cả      |
| AI không biết app có những khả năng gì | AI tự động khám phá tools/resources |
| Format dữ liệu khác nhau               | JSON-RPC chuẩn, có schema rõ ràng   |
| Khó bảo trì, khó mở rộng               | Dễ plug-and-play, mở rộng linh hoạt |

### Các thành phần chính của MCP (đúng theo kiến trúc chính thức)

Theo kiến trúc MCP, nên tách rõ **2 nhóm khái niệm**: `Participants` (ai tham gia phiên) và `Layers` (giao thức chạy theo lớp nào).

#### 1) Participants (thành phần tham gia phiên MCP)

| Thành phần     | Vai trò đúng theo kiến trúc                                                                       |
| -------------- | ------------------------------------------------------------------------------------------------- |
| **MCP Host**   | Ứng dụng AI điều phối toàn bộ (quản lý kết nối, quyền, vòng đời client, tổng hợp context cho LLM) |
| **MCP Client** | Đối tượng do Host tạo ra để giữ **một phiên stateful** với **một MCP Server**                     |
| **MCP Server** | Chương trình cung cấp context/capabilities cho client; có thể chạy local hoặc remote              |

```mermaid
graph LR
    U["Người dùng"] --> H["MCP Host<br/>(Claude Desktop / VS Code / Cursor...)"]

    H --> C1["MCP Client #1"]
    H --> C2["MCP Client #2"]
    H --> C3["MCP Client #3"]

    C1 <--> S1["MCP Server Revit"]
    C2 <--> S2["MCP Server Filesystem"]
    C3 <--> S3["MCP Server Database/API"]

    S1 --> X1["Revit Plugin + Revit API"]
    S2 --> X2["File system nội bộ"]
    S3 --> X3["DB / Public APIs"]
```

**Ghi chú thực tế (quan trọng):**

* Một host thường kết nối **nhiều server cùng lúc**.
* Quan hệ chuẩn là **1 MCP Client ↔ 1 MCP Server connection**.
* Server local dùng `stdio` thường phục vụ 1 client của host đó; server remote dùng `Streamable HTTP` có thể phục vụ nhiều client.

#### 2) Layers (hai lớp của MCP)

| Lớp                 | Ý nghĩa                                                                        |
| ------------------- | ------------------------------------------------------------------------------ |
| **Data layer**      | JSON-RPC 2.0 + lifecycle + capability negotiation + primitives + notifications |
| **Transport layer** | Cơ chế truyền thông (`stdio` hoặc `Streamable HTTP`) + framing + auth          |

```mermaid
graph TB
    T["Transport Layer<br/>(stdio / Streamable HTTP)"] --> D["Data Layer<br/>(JSON-RPC 2.0, lifecycle, capabilities, primitives)"]
```

### Tools/Resources/Prompts nằm ở đâu?

`Tools`, `Resources`, `Prompts` là **server primitives** trong data layer, **không phải participants**.

| Nhóm primitive        | Thành phần                           | Mục đích                                                                         |
| --------------------- | ------------------------------------ | -------------------------------------------------------------------------------- |
| **Server primitives** | `tools`                              | Hàm thực thi để AI gọi hành động (`tools/list`, `tools/call`)                    |
| **Server primitives** | `resources`                          | Nguồn dữ liệu/context để AI đọc (`resources/list`, `resources/read`)             |
| **Server primitives** | `prompts`                            | Mẫu prompt tái sử dụng (`prompts/list`, `prompts/get`)                           |
| **Client primitives** | `sampling`, `elicitation`, `logging` | Cho phép server yêu cầu client tạo completion, hỏi thêm người dùng, hoặc ghi log |

### Ví dụ thực tế

Khi bạn nói với AI: *"Hãy đếm số lượng tường trong mô hình Revit"*, quá trình phía sau diễn ra như sau:

1. AI nhận câu hỏi từ người dùng.
2. AI biết rằng có **tool** tên là `get_all_walls` thông qua MCP.
3. AI gọi tool đó thông qua MCP Server.
4. MCP Server gọi Revit API để lấy dữ liệu.
5. Kết quả trả về cho AI.
6. AI đưa ra câu trả lời: *"Mô hình hiện tại có 42 tường."*

```python
# Ví dụ một tool được định nghĩa trong MCP Server
from mcp.server.fastmcp import FastMCP

mcp = FastMCP("Revit MCP Server")

@mcp.tool()
async def get_all_walls() -> list:
    """Lấy danh sách tất cả các tường trong mô hình Revit hiện tại."""
    # Gọi Revit API thông qua kết nối nội bộ
    response = await revit_client.execute("GetAllWalls")
    return response["walls"]
```

***

## Revit API là gì?

### Định nghĩa

**Revit API** là bộ công cụ lập trình (Application Programming Interface) do Autodesk cung cấp, cho phép các lập trình viên **mở rộng chức năng** của Revit bằng code.

Với Revit API, bạn có thể:

* **Đọc dữ liệu** từ mô hình (lấy thông tin tường, cửa, sàn, cột...).
* **Tạo mới** đối tượng trong mô hình.
* **Chỉnh sửa** thuộc tính của các đối tượng.
* **Xóa** đối tượng.
* **Tự động hóa** các quy trình lặp đi lặp lại.
* **Tích hợp** với các hệ thống bên ngoài.

### Ngôn ngữ và công nghệ

| Đặc điểm       | Chi tiết                                          |
| -------------- | ------------------------------------------------- |
| Ngôn ngữ chính | C# (.NET Framework)                               |
| Môi trường     | Revit Add-in (chạy trong process của Revit)       |
| Namespace gốc  | `Autodesk.Revit.DB`                               |
| Đăng ký plugin | File `.addin` trong thư mục Revit Addins          |
| Sự kiện        | ExternalCommand, ExternalApplication, IUpdater... |

### Ví dụ Revit API cơ bản

```csharp
// Lấy tất cả tường trong mô hình hiện tại
public List<Wall> GetAllWalls(Document doc)
{
    FilteredElementCollector collector = new FilteredElementCollector(doc);
    List<Wall> walls = collector
        .OfClass(typeof(Wall))
        .Cast<Wall>()
        .ToList();

    return walls;
}

// Lấy thông tin chiều cao của một tường
public double GetWallHeight(Wall wall)
{
    Parameter heightParam = wall.get_Parameter(
        BuiltInParameter.WALL_USER_HEIGHT_PARAM
    );
    return heightParam.AsDouble();  // Đơn vị: feet (nội bộ Revit)
}
```

### Dẫn tài liệu API trên `revitapidocs.com`

Tra cứu nhanh đúng theo ví dụ đang dùng trong mục này:

* [`FilteredElementCollector` Class](https://www.revitapidocs.com/2026/263cf06b-98be-6f91-c4da-fb47d01688f3.htm)
* [`Wall` Class](https://www.revitapidocs.com/2026/b5891733-c602-12df-beab-da414b58d608.htm)
* [`Element.Parameter(BuiltInParameter)`](https://www.revitapidocs.com/2026/2f91a9f3-7f69-72f9-08d6-a2d71dfb33db.htm)
* [`BuiltInParameter` Enumeration](https://www.revitapidocs.com/2026/fb011c91-be7e-f737-28c7-3f1e1917a0e0.htm) (dùng `Ctrl + F` tìm `WALL_USER_HEIGHT_PARAM`)
* [`Transaction` Class](https://www.revitapidocs.com/2026/308ebf8d-d96d-4643-cd1d-34fffcea53fd.htm)
* [`ExternalEvent` Class](https://www.revitapidocs.com/2026/05089477-4612-35b2-81a2-89c4f44370ea.htm)
* [`IExternalEventHandler` Interface](https://www.revitapidocs.com/2026/f265a2c9-8540-9c97-9b37-4f7442becac2.htm)

Gợi ý đọc theo thứ tự:

1. `FilteredElementCollector` + `Wall` để nắm cách đọc dữ liệu.
2. `Element.Parameter(BuiltInParameter)` + `BuiltInParameter` để hiểu cách lấy tham số.
3. `Transaction` để nắm quy tắc thao tác ghi.
4. `ExternalEvent` + `IExternalEventHandler` để hiểu cách chạy an toàn trên main thread.

### Thách thức khi sử dụng Revit API

```mermaid
graph TD
    A["Revit API"] --> B["Single-threaded<br/>Chỉ chạy trên main thread"]
    A --> C["Transaction bắt buộc<br/>Mọi thao tác ghi cần Transaction"]
    A --> D["Đơn vị nội bộ<br/>Sử dụng feet, không phải mét"]
    A --> E["API đóng<br/>Chỉ truy cập khi Revit đang chạy"]

    B --> F["Cần ExternalEvent<br/>để đảm bảo thread-safe"]
    C --> G["Phải commit hoặc rollback<br/>mỗi transaction"]
    D --> H["Cần hàm chuyển đổi<br/>feet ↔ mét"]
    E --> I["Plugin phải chạy<br/>bên trong Revit"]

    style A fill:#E91E63,stroke:#333,color:#fff
    style B fill:#FF5722,stroke:#333,color:#fff
    style C fill:#FF5722,stroke:#333,color:#fff
    style D fill:#FF5722,stroke:#333,color:#fff
    style E fill:#FF5722,stroke:#333,color:#fff
```

> Chính những thách thức này khiến việc kết nối AI với Revit **không thể làm trực tiếp** một cách đơn giản, mà cần một lớp trung gian — đó là lý do MCP ra đời.

***

## Kiến trúc tổng thể

### Sơ đồ kiến trúc tổng quan

```mermaid
graph LR
    subgraph "👤 Người dùng"
        A["Người dùng<br/>(Chat interface)"]
    end

    subgraph "🤖 AI App (MCP Host)"
        B["MCP Host<br/>(Claude Desktop / VS Code / Cursor...)"]
        B1["LLM Runtime<br/>(Claude / GPT / Gemini)"]
        B2["MCP Client<br/>(kết nối Revit server)"]
    end

    subgraph "🔗 MCP Layer"
        C["Revit MCP Server<br/>(Node.js / Python)"]
        D["Server Primitives<br/>(tools/resources/prompts)"]
    end

    subgraph "🏗️ Revit Layer"
        E["Revit Plugin<br/>(C# Add-in)"]
        F["Revit Application<br/>(BIM Model)"]
    end

    A -- "Câu hỏi bằng<br/>ngôn ngữ tự nhiên" --> B
    B <--> B1
    B --> B2
    B2 <--> C
    C --- D
    C -- "HTTP REST<br/>request" --> E
    E -- "Revit API<br/>calls" --> F
    F -- "Kết quả<br/>(dữ liệu BIM)" --> E
    E -- "JSON Response" --> C
    C -- "Tool result<br/>có cấu trúc" --> B2
    B -- "Trả lời bằng<br/>ngôn ngữ tự nhiên" --> A

    style A fill:#4CAF50,stroke:#333,color:#fff
    style B fill:#2196F3,stroke:#333,color:#fff
    style B1 fill:#03A9F4,stroke:#333,color:#fff
    style B2 fill:#00BCD4,stroke:#333,color:#fff
    style C fill:#FF9800,stroke:#333,color:#fff
    style D fill:#FFC107,stroke:#333,color:#000
    style E fill:#9C27B0,stroke:#333,color:#fff
    style F fill:#673AB7,stroke:#333,color:#fff
```

### Giải thích các thành phần

**1. Người dùng (User Interface)**

Người dùng tương tác với hệ thống thông qua giao diện chat — có thể là Claude Desktop, VS Code, Claude Code, hoặc bất kỳ client nào hỗ trợ MCP.

**2. MCP Host + LLM Runtime (Bộ điều phối + Bộ não)**

Host là ứng dụng AI bạn đang dùng. Host:

* Quản lý cuộc hội thoại, quyền truy cập và danh sách MCP server được phép kết nối.
* Gọi LLM để suy luận, chọn tool phù hợp.
* Tổng hợp kết quả tool rồi trả lời lại cho người dùng.

**3. MCP Client (Kênh kết nối 1-1)**

Mỗi kết nối đến một MCP Server được host quản lý bằng một MCP Client riêng:

* Đàm phán capability khi khởi tạo phiên.
* Gửi/nhận message JSON-RPC hai chiều.
* Giữ ranh giới cô lập giữa các server.

**4. MCP Server (Cầu nối năng lực)**

Đây là **trái tim của hệ thống**. MCP Server:

* Expose `tools/resources/prompts` cho host/client.
* Nhận request từ MCP Client, chuyển tiếp đến Revit Plugin.
* Trả kết quả từ Revit về cho host/client.
* Xử lý lỗi, timeout, và các trường hợp đặc biệt.

**5. Revit Plugin (Đôi tay)**

Plugin chạy bên trong Revit, làm nhiệm vụ:

* Lắng nghe request từ MCP Server (qua HTTP).
* Thực thi các lệnh Revit API trên main thread.
* Trả kết quả về cho MCP Server.

**6. Revit Application**

Phần mềm Revit với mô hình BIM đang mở — nơi chứa tất cả dữ liệu thiết kế.

### Trong dự án deepbim-revit-mcp-plugin

Dự án [deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) triển khai kiến trúc này với:

* **MCP Server**: Viết bằng Node.js/Python, sử dụng MCP SDK.
* **Revit Plugin**: Viết bằng C#, chạy như một Revit Add-in.
* **Giao tiếp**: MCP Server và Revit Plugin giao tiếp qua HTTP (localhost).

```python
# Cấu trúc cơ bản của MCP Server trong dự án
from mcp.server.fastmcp import FastMCP

# Khởi tạo MCP Server
mcp = FastMCP("Revit MCP Server")

@mcp.tool()
async def get_all_walls():
    """Lấy tất cả tường trong mô hình Revit."""
    result = await call_revit_api("GetAllWalls")
    return result

@mcp.tool()
async def get_element_by_id(element_id: int):
    """Lấy thông tin chi tiết của một element theo ID."""
    result = await call_revit_api("GetElementById", {"id": element_id})
    return result

# Chạy server
if __name__ == "__main__":
    mcp.run()
```

***

## Tại sao chọn MCP?

### Vấn đề với cách tiếp cận trực tiếp

Một câu hỏi thường gặp: *"Tại sao không để AI gọi thẳng Revit API? Cần gì MCP làm gì cho phức tạp?"*

Để trả lời, hãy xem so sánh sau:

```mermaid
graph TB
    subgraph "❌ Cách 1: Gọi API trực tiếp"
        A1["AI App (Host + LLM)"] -- "Gọi trực tiếp" --> B1["Revit API"]
        B1 -- "Kết quả" --> A1
    end

    subgraph "✅ Cách 2: Sử dụng MCP"
        A2["AI App (Host + LLM)"] -- "MCP Protocol (qua MCP Client)" --> B2["MCP Server"]
        B2 -- "Managed calls" --> C2["Revit Plugin + Revit API"]
        C2 -- "Kết quả" --> B2
        B2 -- "Structured response" --> A2
    end

    style A1 fill:#f44336,stroke:#333,color:#fff
    style B1 fill:#f44336,stroke:#333,color:#fff
    style A2 fill:#4CAF50,stroke:#333,color:#fff
    style B2 fill:#FF9800,stroke:#333,color:#fff
    style C2 fill:#4CAF50,stroke:#333,color:#fff
```

### Bảng so sánh chi tiết

| Tiêu chí              | Gọi API trực tiếp                  | Sử dụng MCP                                 |
| --------------------- | ---------------------------------- | ------------------------------------------- |
| **Khám phá khả năng** | AI không biết app có gì            | AI tự động biết các tools                   |
| **Chuẩn hóa**         | Mỗi app một kiểu                   | JSON-RPC chuẩn                              |
| **Bảo mật**           | AI trực tiếp điều khiển            | MCP làm lớp kiểm soát                       |
| **Mở rộng**           | Sửa code AI mỗi khi thêm tính năng | Chỉ cần thêm tool mới vào MCP Server        |
| **Tái sử dụng**       | Không tái sử dụng được             | Cùng MCP Server, nhiều AI client dùng chung |
| **Xử lý lỗi**         | Tự implement                       | MCP có sẵn cơ chế xử lý lỗi                 |
| **Tài liệu**          | Tự viết                            | Tool có mô tả tự động (schema)              |

### 5 lý do chính chọn MCP

**1. Tool Discovery (Tự động khám phá)**

AI không cần biết trước Revit có những API nào. Khi kết nối với MCP Server, AI tự động nhận được danh sách tất cả các tools cùng với mô tả và tham số.

**2. Standardization (Chuẩn hóa)**

MCP sử dụng JSON-RPC 2.0 — một chuẩn giao tiếp đã được chứng minh và sử dụng rộng rãi. Bất kỳ AI app/client nào hỗ trợ MCP đều có thể tương tác với Revit mà không cần thay đổi MCP Server.

**3. Security Layer (Lớp bảo mật)**

MCP Server đóng vai trò là "người gác cổng" — kiểm soát những gì AI có thể và không thể làm.

**4. Scalability (Khả năng mở rộng)**

Muốn thêm chức năng mới? Chỉ cần thêm một tool vào MCP Server:

```python
# Thêm một tool mới — chỉ cần 5 dòng code
@mcp.tool()
async def count_doors():
    """Đếm số lượng cửa trong mô hình."""
    result = await call_revit_api("CountDoors")
    return result
```

**5. Interoperability (Tương thích đa nền tảng)**

Cùng một MCP Server, bạn có thể dùng với nhiều MCP host/client khác nhau (Claude Desktop, VS Code, Cursor...). Không bị khóa vào một AI provider nào.

***

## Luồng dữ liệu

### Sequence Diagram: Từ câu hỏi đến kết quả

```mermaid
sequenceDiagram
    actor User as 👤 Người dùng
    participant Host as 🤖 MCP Host + LLM<br/>(Claude Desktop)
    participant Client as 🔌 MCP Client
    participant MCP as 🔗 MCP Server<br/>(Node.js)
    participant Plugin as ⚙️ Revit Plugin<br/>(C# Add-in)
    participant Revit as 🏗️ Revit App<br/>(BIM Model)

    User->>Host: "Cho tôi biết có bao nhiêu tường<br/>trong mô hình hiện tại?"

    Note over Host: Host dùng LLM phân tích câu hỏi<br/>và quyết định gọi tool

    Host->>Client: Chọn đúng MCP session
    Client->>MCP: tools/call: get_all_walls()

    Note over MCP: MCP Server nhận request<br/>và chuyển tiếp

    MCP->>Plugin: HTTP POST /api/execute<br/>{"command": "GetAllWalls"}

    Note over Plugin: Plugin chạy trên<br/>Revit main thread

    Plugin->>Revit: FilteredElementCollector<br/>.OfClass(typeof(Wall))

    Revit-->>Plugin: List<Wall> (42 walls)

    Plugin-->>MCP: {"status": "ok",<br/>"walls": [...], "count": 42}

    MCP-->>Client: Tool result:<br/>{"count": 42, "walls": [...]}
    Client-->>Host: Trả kết quả tool

    Note over Host: Host + LLM tổng hợp kết quả<br/>thành câu trả lời tự nhiên

    Host-->>User: "Mô hình hiện tại có 42 tường.<br/>Bao gồm 30 tường gạch và<br/>12 tường kính."
```

### Giải thích chi tiết từng bước

**Bước 1: Người dùng đặt câu hỏi**

Người dùng gõ một câu hỏi bằng ngôn ngữ tự nhiên vào giao diện chat. Không cần biết bất kỳ câu lệnh kỹ thuật nào.

```
"Cho tôi biết có bao nhiêu tường trong mô hình hiện tại?"
```

**Bước 2: MCP Host dùng LLM để phân tích và chọn tool**

Host (ví dụ Claude Desktop) dùng LLM để phân tích câu hỏi và xác định:

* Người dùng muốn biết **số lượng tường**.
* Cần gọi tool `get_all_walls` để lấy dữ liệu.

Quá trình này gọi là **tool selection** — AI tự động chọn tool phù hợp từ danh sách tools được đăng ký trên MCP Server.

**Bước 3: MCP Client gọi tool qua MCP**

MCP Client gửi request đến MCP Server theo chuẩn MCP Protocol:

```json
{
    "jsonrpc": "2.0",
    "method": "tools/call",
    "params": {
        "name": "get_all_walls",
        "arguments": {}
    },
    "id": 1
}
```

**Bước 4: MCP Server chuyển tiếp đến Revit Plugin**

MCP Server nhận request và chuyển đổi thành HTTP call đến Revit Plugin:

```json
// HTTP POST http://localhost:8080/api/execute
{
    "command": "GetAllWalls",
    "params": {}
}
```

**Bước 5: Revit Plugin thực thi**

Plugin nhận request, đặt vào hàng đợi (queue) để thực thi trên Revit main thread:

```csharp
// Thực thi trên main thread của Revit
public string ExecuteCommand(string command, Dictionary<string, object> parameters)
{
    switch (command)
    {
        case "GetAllWalls":
            var collector = new FilteredElementCollector(doc);
            var walls = collector.OfClass(typeof(Wall)).ToList();
            return JsonConvert.SerializeObject(new {
                status = "ok",
                count = walls.Count,
                walls = walls.Select(w => new {
                    id = w.Id.IntegerValue,
                    name = w.Name,
                    length = w.get_Parameter(
                        BuiltInParameter.CURVE_ELEM_LENGTH
                    ).AsDouble()
                })
            });
        // ... các command khác
    }
}
```

**Bước 6: Kết quả trả ngược về**

Dữ liệu chạy ngược lại: Revit → Plugin → MCP Server → AI → Người dùng.

AI nhận dữ liệu thô và chuyển thành câu trả lời dễ hiểu:

```
"Mô hình hiện tại có 42 tường. Bao gồm 30 tường gạch và 12 tường kính."
```

### Tổng quan luồng dữ liệu

```mermaid
graph TD
    A["📝 Câu hỏi ngôn ngữ tự nhiên"] --> B["🤖 AI phân tích ý định"]
    B --> C{"Cần truy cập<br/>dữ liệu Revit?"}
    C -- "Không" --> D["AI trả lời trực tiếp"]
    C -- "Có" --> E["AI chọn tool phù hợp"]
    E --> F["📡 Gọi MCP Server"]
    F --> G["🔗 MCP chuyển tiếp đến Revit Plugin"]
    G --> H["🏗️ Revit API thực thi"]
    H --> I["📦 Kết quả trả về MCP"]
    I --> J["🤖 MCP trả về AI"]
    J --> K["💬 AI tổng hợp và trả lời"]
    K --> L["✅ Người dùng nhận kết quả"]

    style A fill:#E3F2FD,stroke:#1565C0,color:#000
    style L fill:#E8F5E9,stroke:#2E7D32,color:#000
    style C fill:#FFF3E0,stroke:#EF6C00,color:#000
```

***

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

Sau đây là một số câu hỏi giúp bạn tự suy nghĩ và hiểu sâu hơn về nội dung bài học. Hãy thử trả lời trước khi xem đáp án.

***

### Câu hỏi 1: Thread Safety trong Revit

**Câu hỏi:** Revit API yêu cầu tất cả các thao tác phải chạy trên main thread. Vậy MCP Server (chạy ở một process khác) làm cách nào để gọi được Revit API?

<details>

<summary>💡 Xem gợi ý và đáp án</summary>

**Gợi ý:** Suy nghĩ về cách hai process có thể giao tiếp với nhau (Inter-Process Communication).

**Đáp án:**

MCP Server **không gọi trực tiếp** Revit API. Thay vào đó, hệ thống sử dụng một **Revit Plugin** (C# Add-in) chạy bên trong process của Revit. Plugin này:

1. Mở một **HTTP server nội bộ** (ví dụ `localhost:8080`).
2. Lắng nghe các request từ MCP Server.
3. Khi nhận request, dùng cơ chế `ExternalEvent` hoặc `IExternalEventHandler` của Revit để **đẩy lệnh vào main thread**.
4. Chờ kết quả và trả về cho MCP Server.

```csharp
// Ví dụ sử dụng ExternalEvent
public class RevitCommandHandler : IExternalEventHandler
{
    public string Result { get; private set; }

    public void Execute(UIApplication app)
    {
        // Đây là main thread của Revit — an toàn để gọi API
        Document doc = app.ActiveUIDocument.Document;
        // Thực thi lệnh...
    }

    public string GetName() => "RevitCommandHandler";
}
```

Như vậy, MCP Server giao tiếp với Plugin qua HTTP, và Plugin đảm bảo mọi lệnh API đều chạy trên main thread.

</details>

***

### Câu hỏi 2: So sánh với Dynamo

**Câu hỏi:** Dynamo cũng là một công cụ tự động hóa Revit. Vậy sự khác biệt giữa Dynamo và cách tiếp cận MCP + AI là gì? Khi nào nên dùng cách nào?

<details>

<summary>💡 Xem gợi ý và đáp án</summary>

**Gợi ý:** Suy nghĩ về **đối tượng sử dụng** (ai dùng?), **độ linh hoạt** (thay đổi dễ không?), và **khả năng xử lý ngôn ngữ tự nhiên**.

**Đáp án:**

| Tiêu chí                | Dynamo                             | MCP + AI                        |
| ----------------------- | ---------------------------------- | ------------------------------- |
| Giao diện               | Visual programming (kéo thả node)  | Chat (ngôn ngữ tự nhiên)        |
| Đối tượng               | Kỹ sư, người biết lập trình cơ bản | Bất kỳ ai (không cần biết code) |
| Độ linh hoạt            | Cao nhưng cần thiết kế trước       | Rất cao — AI tự suy luận        |
| Xử lý ngôn ngữ tự nhiên | Không                              | Có                              |
| Lặp lại                 | Tốt (chạy lại script)              | Tốt (gọi lại tool)              |
| Thích hợp cho           | Workflow cố định, lặp đi lặp lại   | Truy vấn ad-hoc, tác vụ đa dạng |

**Nên dùng Dynamo khi:** Bạn có một quy trình cố định, lặp đi lặp lại, và muốn người dùng chạy bằng một nút bấm.

**Nên dùng MCP + AI khi:** Bạn muốn người dùng có thể hỏi bất kỳ câu hỏi nào về mô hình và nhận câu trả lời ngay, hoặc thực hiện các tác vụ đa dạng mà không cần thiết kế trước.

</details>

***

### Câu hỏi 3: Bảo mật và quyền truy cập

**Câu hỏi:** Nếu AI có thể thao tác trên Revit thông qua MCP, làm thế nào để đảm bảo AI không thực hiện những hành động nguy hiểm (ví dụ: xóa hết mô hình)?

<details>

<summary>💡 Xem gợi ý và đáp án</summary>

**Gợi ý:** Suy nghĩ về **phân quyền**, **danh sách cho phép (whitelist)**, và **xác nhận từ người dùng**.

**Đáp án:**

Có nhiều lớp bảo mật có thể áp dụng:

1. **Tool-level permissions:** Chỉ đăng ký những tools an toàn trên MCP Server. Nếu bạn không muốn AI xóa dữ liệu, đơn giản là không tạo tool `delete_element`.
2. **Read-only mode:** Tách riêng tools đọc (read) và ghi (write). Mặc định chỉ cho phép read.
3. **Confirmation step:** Với các thao tác nguy hiểm (xóa, sửa), yêu cầu người dùng xác nhận trước khi thực hiện.
4. **Transaction rollback:** Revit có cơ chế Transaction — nếu thao tác thất bại, có thể rollback về trạng thái trước đó.
5. **Audit logging:** Ghi lại tất cả các thao tác AI thực hiện để kiểm tra sau.

```python
@mcp.tool()
async def delete_element(element_id: int, confirm: bool = False):
    """Xóa một element khỏi mô hình. Yêu cầu xác nhận."""
    if not confirm:
        return {
            "status": "pending",
            "message": "Bạn có chắc muốn xóa element này? "
                       "Gọi lại với confirm=True để xác nhận."
        }
    result = await call_revit_api("DeleteElement", {"id": element_id})
    return result
```

</details>

***

### Câu hỏi 4: Giới hạn của MCP

**Câu hỏi:** MCP có những giới hạn gì? Có những trường hợp nào mà MCP không phù hợp?

<details>

<summary>💡 Xem gợi ý và đáp án</summary>

**Gợi ý:** Suy nghĩ về **hiệu năng**, **độ phức tạp của thao tác**, và **real-time requirements**.

**Đáp án:**

Một số giới hạn của MCP:

1. **Latency (Độ trễ):** Dữ liệu phải đi qua nhiều lớp (AI → MCP → Plugin → Revit → quay lại). Không phù hợp cho các thao tác cần real-time (ví dụ: kéo thả đối tượng).
2. **Dữ liệu lớn:** Nếu mô hình có hàng triệu element, việc serialize và gửi dữ liệu qua HTTP có thể chậm. Cần thiết kế pagination hoặc filtering.
3. **Thao tác phức tạp:** Những thao tác cần nhiều bước liên tiếp (ví dụ: tạo một hệ thống MEP hoàn chỉnh) có thể khó diễn đạt qua một tool duy nhất.
4. **Context window:** AI có giới hạn về lượng dữ liệu có thể xử lý cùng lúc (context window). Không thể dump toàn bộ mô hình vào cho AI.
5. **Visual feedback:** AI không "nhìn thấy" giao diện Revit. Không thể thao tác dựa trên vị trí trên màn hình.

**Giải pháp:** Thiết kế tool thông minh — mỗi tool làm một việc cụ thể, trả về dữ liệu vừa đủ, và hỗ trợ filtering/pagination.

</details>

***

### Câu hỏi 5: Mở rộng sang phần mềm khác

**Câu hỏi:** Ngoài Revit, MCP có thể được dùng để kết nối AI với những phần mềm nào khác trong ngành AEC?

<details>

<summary>💡 Xem gợi ý và đáp án</summary>

**Đáp án:**

MCP có thể áp dụng cho bất kỳ phần mềm nào có API:

```mermaid
graph TD
    AI["🤖 AI App (MCP Host + LLM)"] --> MCP["🔗 MCP Protocol"]
    MCP --> R["🏗️ Revit<br/>Thiết kế kiến trúc, kết cấu"]
    MCP --> A["📐 AutoCAD<br/>Bản vẽ 2D"]
    MCP --> N["🔍 Navisworks<br/>Clash detection"]
    MCP --> T["🔩 Tekla<br/>Kết cấu thép"]
    MCP --> RH["🦏 Rhino/Grasshopper<br/>Thiết kế parametric"]
    MCP --> E["📊 Excel<br/>Bóc khối lượng, dự toán"]
    MCP --> B["☁️ BIM 360 / ACC<br/>Quản lý dự án"]

    style AI fill:#2196F3,stroke:#333,color:#fff
    style MCP fill:#FF9800,stroke:#333,color:#fff
```

Tất cả đều theo cùng một mô hình: **AI → MCP Server → Plugin/API → Phần mềm**.

Khả năng mở rộng là **vô hạn** — chỉ cần tạo MCP Server mới cho từng phần mềm.

</details>

***

## Tổng kết

Trong bài học này, chúng ta đã tìm hiểu:

| Khái niệm         | Nội dung chính                                                                               |
| ----------------- | -------------------------------------------------------------------------------------------- |
| **MCP**           | Giao thức chuẩn mở để AI giao tiếp với phần mềm bên ngoài, do Anthropic phát triển           |
| **Revit API**     | Bộ công cụ lập trình mở rộng chức năng Revit, sử dụng C#                                     |
| **Kiến trúc**     | User → AI → MCP Server → Revit Plugin → Revit (và ngược lại)                                 |
| **Tại sao MCP**   | Chuẩn hóa, bảo mật, tự động khám phá tool, dễ mở rộng, tương thích đa nền tảng               |
| **Luồng dữ liệu** | Từ câu hỏi ngôn ngữ tự nhiên → AI chọn tool → MCP chuyển tiếp → Revit xử lý → kết quả trả về |

### Những điều cần nhớ

1. **MCP là cầu nối**, không phải là AI hay Revit API. Nó kết nối hai thế giới lại với nhau.
2. **Revit API chỉ chạy trên main thread** — đây là kỹ thuật cần nắm vững khi xây dựng Plugin.
3. **AI không trực tiếp điều khiển Revit** — mọi thao tác đều đi qua MCP Server và Plugin, đảm bảo an toàn.
4. **Mở rộng dễ dàng** — thêm tool mới chỉ cần vài dòng code.

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

Trong **Bài 2**, chúng ta sẽ:

* Xem demo trực tiếp AI điều khiển Revit.
* Hiểu luồng hoạt động từ prompt → tool call → kết quả.
* Khám phá các use case thực tế trong ngành xây dựng.

***

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

### Mã nguồn dự án

* [deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) — Mã nguồn chính của khóa học này.

### MCP (Model Context Protocol)

* [MCP Official Documentation](https://modelcontextprotocol.io/) — Tài liệu chính thức của MCP.
* [MCP Specification](https://spec.modelcontextprotocol.io/) — Đặc tả kỹ thuật chi tiết.
* [Anthropic MCP Announcement](https://www.anthropic.com/news/model-context-protocol) — Bài giới thiệu MCP từ Anthropic.
* [MCP Python SDK](https://github.com/modelcontextprotocol/python-sdk) — Thư viện Python để xây dựng MCP Server.
* [MCP TypeScript SDK](https://github.com/modelcontextprotocol/typescript-sdk) — Thư viện TypeScript để xây dựng MCP Server.

### Revit API

* [Revit API Documentation](https://www.revitapidocs.com/) — Tài liệu Revit API (community).
* [Autodesk Revit Developer Center](https://www.autodesk.com/developer-network/platform-technologies/revit) — Trung tâm phát triển Revit của Autodesk.
* [The Building Coder](https://thebuildingcoder.typepad.com/) — Blog nổi tiếng về Revit API bởi Jeremy Tammik (Autodesk).

### AI và LLM

* [Anthropic Claude Documentation](https://docs.anthropic.com/) — Tài liệu sử dụng Claude.
* [OpenAI API Documentation](https://platform.openai.com/docs) — Tài liệu API của OpenAI.

### Kiến thức bổ sung

* [JSON-RPC 2.0 Specification](https://www.jsonrpc.org/specification) — Chuẩn giao tiếp được MCP sử dụng.
* [BIM và IFC](https://technical.buildingsmart.org/) — Tiêu chuẩn BIM quốc tế từ buildingSMART.

***

> **Bài tiếp theo:** [Bài 2: Demo kết nối thực tiễn →](/revit-mcp-ai/phan-1-nen-tang/bai-2.md)
>
> Có câu hỏi hoặc góp ý? Tạo issue trên [GitHub repository](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin/issues).


---

# 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-1.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.
