# Bài 6: Chuẩn bị sẵn sàng kết nối

> **Khóa học:** Revit API × MCP × AI — Từ Zero đến Plugin hoàn chỉnh
>
> **Mục tiêu:** Cài đặt, cấu hình và kiểm tra tất cả các thành phần — Revit Plugin, MCP Server, VS Code, Claude Code — để sẵn sàng kết nối thành một hệ thống hoàn chỉnh.
>
> **Mã nguồn tham khảo:** [github.com/nguyenngocdue/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 bài học](#giới-thiệu-bài-học)
2. [Sơ đồ triển khai tổng quan](#sơ-đồ-triển-khai-tổng-quan)
3. [Phần 1 — Build Plugin C# (Visual Studio)](#phần-1--build-plugin-c-visual-studio)
4. [Phần 2 — Tạo file .addin (Manifest XML)](#phần-2--tạo-file-addin-manifest-xml)
5. [Phần 3 — Load Plugin vào Revit](#phần-3--load-plugin-vào-revit)
6. [Phần 4 — Cấu hình VS Code gọi MCP Server](#phần-4--cấu-hình-vs-code-gọi-mcp-server)
7. [Phần 5 — Cấu hình Claude Code gọi MCP Server](#phần-5--cấu-hình-claude-code-gọi-mcp-server)
8. [Phần 6 — Checklist trước khi kết nối](#phần-6--checklist-trước-khi-kết-nối)
9. [Phần 7 — Kiểm tra sức khoẻ hệ thống (Healthcheck)](#phần-7--kiểm-tra-sức-khoẻ-hệ-thống-healthcheck)
10. [Phần 8 — Troubleshooting các lỗi thường gặp](#phần-8--troubleshooting-các-lỗi-thường-gặp)
11. [Câu hỏi tự suy nghĩ](#câu-hỏi-tự-suy-nghĩ)
12. [Tổng kết](#tổng-kết)
13. [Tài liệu tham khảo](#tài-liệu-tham-khảo)

***

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

Trong các bài trước, chúng ta đã xây dựng từng thành phần riêng lẻ:

| Bài   | Thành phần đã xây dựng             | Trạng thái    |
| ----- | ---------------------------------- | ------------- |
| Bài 3 | Revit API Tools cơ bản (C#)        | Đã viết code  |
| Bài 4 | MCP Server bằng Node.js            | Đã dựng xong  |
| Bài 5 | Core MCP Listener trong Revit (C#) | Đã hoàn thiện |

Bây giờ là lúc **ghép tất cả lại với nhau**. Bài học này sẽ hướng dẫn bạn:

1. Build và load plugin C# vào Revit
2. Tạo file manifest `.addin` đúng cú pháp
3. Cấu hình VS Code để gọi MCP Server
4. Cấu hình Claude Code để gọi MCP Server
5. Kiểm tra từng thành phần trước khi kết nối toàn bộ
6. Xử lý các lỗi thường gặp trong quá trình thiết lập

> **Lưu ý quan trọng:** Bài này là bài **"chuẩn bị phòng"** — bạn sẽ không chạy kết nối end-to-end ở đây. Việc kết nối thực tế sẽ được thực hiện trong Bài 7. Mục tiêu của bài này là đảm bảo khi bước vào Bài 7, tất cả các thành phần đều ở trạng thái sẵn sàng.

***

## Sơ đồ triển khai tổng quan

Trước khi bắt tay vào cấu hình, hãy nhìn toàn cảnh hệ thống mà chúng ta cần chuẩn bị:

```mermaid
graph TB
    subgraph HOST ["AI Host (Máy tính người dùng)"]
        direction TB
        A["VS Code + Copilot Chat<br/>hoặc Claude Code CLI"]
    end

    subgraph MCP ["MCP Server — Node.js (stdio transport)"]
        direction TB
        C["MCP Server Process"]
        D["Tool Registry<br/>get_walls · create_wall<br/>get_elements · delete_element"]
        C --> D
    end

    subgraph PLUGIN ["Revit Plugin — C# (.NET Framework 4.8)"]
        direction TB
        E["HTTP Listener<br/>localhost:8080"]
        F["Revit API Context<br/>FilteredElementCollector<br/>Wall.Create · Transaction"]
        E -->|"ExternalEvent<br/>(thread-safe)"| F
    end

    subgraph REVIT ["Autodesk Revit"]
        G["BIM Model<br/>3D Elements · Parameters · Levels"]
    end

    A -->|"MCP Protocol — stdio<br/>JSON-RPC 2.0"| C
    D -->|"HTTP REST<br/>POST localhost:8080"| E
    F -->|"Revit API calls"| G

    style A fill:#4FC3F7,stroke:#0288D1,color:#000
    style C fill:#81C784,stroke:#388E3C,color:#000
    style D fill:#81C784,stroke:#388E3C,color:#000
    style E fill:#FFB74D,stroke:#F57C00,color:#000
    style F fill:#FFB74D,stroke:#F57C00,color:#000
    style G fill:#E57373,stroke:#D32F2F,color:#000
```

**Giải thích sơ đồ:**

| Thành phần   | Công nghệ                | Vai trò                            | Giao tiếp                      |
| ------------ | ------------------------ | ---------------------------------- | ------------------------------ |
| AI Host      | VS Code / Claude Code    | Giao diện người dùng, gửi prompt   | Gọi MCP Server qua stdio       |
| MCP Server   | Node.js + MCP SDK        | Cầu nối trung gian, đăng ký tools  | Nhận stdio → gọi HTTP          |
| Revit Plugin | C# (.NET)                | Nhận lệnh HTTP, gọi Revit API      | HTTP port 8080 → ExternalEvent |
| Revit        | Autodesk Revit 2022–2025 | Phần mềm BIM, chứa dữ liệu mô hình | Chỉ được gọi từ Main Thread    |

***

## Phần 1 — Build Plugin C# (Visual Studio)

### 1.1. Mở project trong Visual Studio

Mở solution `DeepBimRevitMcpPlugin.sln` trong Visual Studio 2019 trở lên.

```
Cấu trúc thư mục dự án:
deepbim-revit-mcp-plugin/
├── DeepBimRevitMcpPlugin.sln          ← File solution Visual Studio
├── DeepBimRevitMcpPlugin/
│   ├── DeepBimRevitMcpPlugin.csproj   ← File project C#
│   ├── App.cs                         ← IExternalApplication (entry point)
│   ├── Core/
│   │   ├── RevitMcpListener.cs        ← HTTP Listener
│   │   ├── McpEventHandler.cs         ← ExternalEvent handler
│   │   └── McpRouter.cs               ← Tool routing
│   └── Tools/
│       ├── GetWallsTool.cs
│       └── CreateWallTool.cs
└── mcp-server/                        ← MCP Server Node.js (riêng biệt)
    ├── package.json
    └── src/index.ts
```

> **Nguồn code tham khảo:** [github.com/nguyenngocdue/deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin)

### 1.2. Kiểm tra cấu hình project trước khi build

Trước khi build, đảm bảo các thiết lập sau đây đã đúng:

**Mở Properties của project** (chuột phải vào project → Properties):

| Thiết lập        | Giá trị yêu cầu         | Lý do                                   |
| ---------------- | ----------------------- | --------------------------------------- |
| Target Framework | `.NET Framework 4.8`    | Revit 2022–2025 dùng .NET Framework 4.8 |
| Platform Target  | `x64`                   | Revit chỉ chạy trên 64-bit              |
| Output Type      | `Class Library`         | Plugin là .dll, không phải .exe         |
| Assembly Name    | `DeepBimRevitMcpPlugin` | Phải khớp với `<Assembly>` trong .addin |

### 1.3. Kiểm tra References (tham chiếu Revit API)

Đảm bảo project đã tham chiếu đúng các Revit API DLL:

```
References cần thiết:
  ✓ RevitAPI.dll          → C:\Program Files\Autodesk\Revit 2024\RevitAPI.dll
  ✓ RevitAPIUI.dll        → C:\Program Files\Autodesk\Revit 2024\RevitAPIUI.dll
  ✓ System.Net.Http       → Built-in .NET Framework
  ✓ Newtonsoft.Json       → Cài qua NuGet (phiên bản 13.x)
```

> **Quan trọng:** Sau khi thêm `RevitAPI.dll` và `RevitAPIUI.dll`, hãy đặt thuộc tính **Copy Local = False** cho cả hai. Revit sẽ tự load đúng phiên bản khi runtime — không cần copy vào thư mục output.

### 1.4. Build project

**Cách 1 — Build trong Visual Studio (khuyến nghị):**

1. Chọn cấu hình **Debug** (để phát triển) hoặc **Release** (để phân phối)
2. Nhấn `Ctrl + Shift + B` hoặc vào menu **Build → Build Solution**
3. Kiểm tra cửa sổ **Output** (View → Output) — đảm bảo không có lỗi

**Cách 2 — Build bằng dòng lệnh (MSBuild / dotnet CLI):**

```bash
# Di chuyển đến thư mục chứa solution
cd C:\Projects\deepbim-revit-mcp-plugin

# Build Debug (dành cho phát triển, có debug symbols)
dotnet build --configuration Debug

# Hoặc build Release (dành cho phân phối)
dotnet build --configuration Release

# Nếu dùng .NET Framework (không phải .NET Core/5+), dùng MSBuild trực tiếp:
"C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Current\Bin\MSBuild.exe" ^
    DeepBimRevitMcpPlugin.sln ^
    /p:Configuration=Release ^
    /p:Platform=x64 ^
    /t:Build
```

**Kết quả build thành công sẽ hiển thị:**

```
Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:03.42

Output path: bin\Release\DeepBimRevitMcpPlugin.dll
```

### 1.5. Xác nhận file DLL đã được tạo

Sau khi build thành công, kiểm tra thư mục output:

```
bin/
  Release/
    DeepBimRevitMcpPlugin.dll        ← File plugin chính (bắt buộc)
    Newtonsoft.Json.dll               ← Thư viện phụ thuộc (bắt buộc copy)
    DeepBimRevitMcpPlugin.pdb        ← Debug symbols (tuỳ chọn, chỉ dùng Debug)
```

> **Ghi chú:** `RevitAPI.dll` và `RevitAPIUI.dll` **không được copy** vào thư mục output (vì Copy Local = False). Đây là hành vi đúng.

***

## Phần 2 — Tạo file .addin (Manifest XML)

### 2.1. File .addin là gì và tại sao cần thiết?

File `.addin` là file **manifest khai báo** để Autodesk Revit biết cần tải plugin nào khi khởi động. Đây là file XML với cấu trúc cố định, được Revit đọc tự động từ các thư mục Addins.

**Không có file `.addin` = Revit sẽ không bao giờ load plugin của bạn.**

### 2.2. Nội dung file .addin đầy đủ

Tạo file `DeepBimRevitMcpPlugin.addin` với nội dung sau:

```xml
<?xml version="1.0" encoding="utf-8"?>
<RevitAddIns>
  <AddIn Type="Application">

    <!-- Tên hiển thị của plugin trong Revit UI -->
    <Name>DeepBIM Revit MCP Plugin</Name>

    <!-- Full qualified class name của class implement IExternalApplication -->
    <!-- Cú pháp: Namespace.ClassName -->
    <FullClassName>DeepBimRevitMcpPlugin.App</FullClassName>

    <!-- Đường dẫn tuyệt đối đến file DLL của plugin -->
    <!-- Đây là nơi Revit sẽ tìm và load file .dll -->
    <Assembly>C:\RevitPlugins\DeepBimRevitMcpPlugin\DeepBimRevitMcpPlugin.dll</Assembly>

    <!-- GUID duy nhất cho plugin — KHÔNG được trùng với plugin khác -->
    <!-- Tạo mới bằng PowerShell: [guid]::NewGuid() -->
    <AddInId>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</AddInId>

    <!-- Thông tin nhà phát triển (tuỳ chọn nhưng nên điền) -->
    <VendorId>DeepBIM</VendorId>
    <VendorDescription>DeepBIM — Revit MCP Plugin cho AI điều khiển Revit</VendorDescription>
    <VendorEmail>contact@deepbim.com</VendorEmail>

  </AddIn>
</RevitAddIns>
```

### 2.3. Giải thích từng phần tử XML

| Phần tử             | Mô tả                                                                  | Bắt buộc | Ghi chú                                             |
| ------------------- | ---------------------------------------------------------------------- | -------- | --------------------------------------------------- |
| `Type`              | `Application` (IExternalApplication) hoặc `Command` (IExternalCommand) | Có       | Dùng `Application` cho MCP server cần chạy liên tục |
| `Name`              | Tên hiển thị trong Add-Ins tab của Revit                               | Có       | Tuỳ chọn tên bất kỳ                                 |
| `FullClassName`     | `Namespace.ClassName` của entry point                                  | Có       | Phải khớp 100% với code C#                          |
| `Assembly`          | Đường dẫn tuyệt đối đến file .dll                                      | Có       | Revit sẽ không tìm file nếu sai đường dẫn           |
| `AddInId`           | GUID duy nhất, dạng `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`             | Có       | Phải là GUID mới, không trùng plugin nào khác       |
| `VendorId`          | ID nhà phát triển (chữ và số, không dấu cách)                          | Không    | Dùng cho Autodesk App Store                         |
| `VendorDescription` | Mô tả nhà phát triển                                                   | Không    | Hiển thị trong Revit security dialog                |
| `VendorEmail`       | Email nhà phát triển                                                   | Không    | Tuỳ chọn                                            |

### 2.4. Tạo GUID mới cho plugin của bạn

Mỗi plugin cần một GUID duy nhất. Tạo GUID mới bằng một trong các cách sau:

```powershell
# Cách 1: PowerShell (khuyến nghị, nhanh nhất)
[guid]::NewGuid()

# Kết quả ví dụ: 3f2504e0-4f89-11d3-9a0c-0305e82c3301
```

```bash
# Cách 2: Command line (Node.js)
node -e "const crypto = require('crypto'); console.log(crypto.randomUUID());"

# Kết quả ví dụ: 9b1deb4d-3b7d-4bad-9bdd-2b0d7b3dcb6d
```

Hoặc dùng Visual Studio: **Tools → Create GUID → Format 4 (Registry Format)**.

> **Cảnh báo:** Nếu hai plugin có cùng GUID, Revit sẽ chỉ load một trong hai và bỏ qua cái còn lại mà không báo lỗi. Hãy luôn tạo GUID mới cho mỗi plugin.

### 2.5. Ví dụ FullClassName — cách kiểm tra cho đúng

Giả sử code C# của bạn là:

```csharp
// File: App.cs
namespace DeepBimRevitMcpPlugin
{
    public class App : IExternalApplication
    {
        public Result OnStartup(UIControlledApplication app) { ... }
        public Result OnShutdown(UIControlledApplication app) { ... }
    }
}
```

Thì `FullClassName` trong file `.addin` phải là:

```xml
<FullClassName>DeepBimRevitMcpPlugin.App</FullClassName>
```

**Quy tắc:** `FullClassName = [Namespace].[ClassName]` — ghép chính xác, phân biệt chữ hoa/thường.

***

## Phần 3 — Load Plugin vào Revit

### 3.1. Thư mục Addins của Revit

Revit tự động scan các file `.addin` trong hai thư mục sau khi khởi động:

**Cho tất cả người dùng trên máy (All Users):**

```
C:\ProgramData\Autodesk\Revit\Addins\2024\
```

**Chỉ cho người dùng hiện tại (Current User — khuyến nghị khi phát triển):**

```
C:\Users\<TênNgườiDùng>\AppData\Roaming\Autodesk\Revit\Addins\2024\
```

> **Lưu ý:** Thay `2024` bằng phiên bản Revit tương ứng của bạn: `2022`, `2023`, `2025`, ...

**Cách mở nhanh thư mục này:**

```powershell
# Mở thư mục Addins cho Revit 2024 (Current User)
explorer "%AppData%\Autodesk\Revit\Addins\2024"

# Hoặc dùng Run (Win + R)
# %AppData%\Autodesk\Revit\Addins\2024
```

### 3.2. Các bước deploy plugin

**Bước 1 — Copy file .addin vào thư mục Addins:**

```batch
:: Tạo thư mục nếu chưa tồn tại
mkdir "%AppData%\Autodesk\Revit\Addins\2024" 2>nul

:: Copy file .addin
copy DeepBimRevitMcpPlugin.addin ^
    "%AppData%\Autodesk\Revit\Addins\2024\"
```

**Bước 2 — Copy file DLL và dependencies vào thư mục Assembly:**

```batch
:: Tạo thư mục đích (phải khớp với <Assembly> trong .addin)
mkdir "C:\RevitPlugins\DeepBimRevitMcpPlugin" 2>nul

:: Copy DLL chính và thư viện phụ thuộc
copy bin\Release\DeepBimRevitMcpPlugin.dll ^
    "C:\RevitPlugins\DeepBimRevitMcpPlugin\"

copy bin\Release\Newtonsoft.Json.dll ^
    "C:\RevitPlugins\DeepBimRevitMcpPlugin\"
```

**Bước 3 — Khởi động (hoặc khởi động lại) Revit.**

**Bước 4 — Khi Revit hỏi về plugin mới:**

Revit sẽ hiển thị hộp thoại bảo mật:

* Chọn **"Always Load"** để Revit tự động load plugin trong các lần sau
* Chọn **"Load Once"** nếu chỉ muốn test lần này

### 3.3. Xác nhận plugin đã load thành công

Sau khi Revit khởi động, kiểm tra theo thứ tự sau:

**Kiểm tra 1 — Add-Ins tab:** Plugin sẽ xuất hiện trong ribbon Add-Ins (nếu bạn có tạo UI button).

**Kiểm tra 2 — HTTP Listener đang chạy:**

```bash
# Mở terminal và gõ lệnh này
curl -s http://localhost:8080/api/health

# Kết quả mong đợi:
# {"status":"ok","revit_version":"2024","plugin_version":"1.0.0","tools_count":4}
```

Nếu nhận được JSON response → Plugin đã load và HTTP Listener đang hoạt động.

**Kiểm tra 3 — Revit Journal file (nếu cần debug sâu hơn):**

```
%LOCALAPPDATA%\Autodesk\Revit\Autodesk Revit 2024\Journals\
```

Mở file `.txt` mới nhất và tìm dòng chứa `DeepBimRevitMcpPlugin`.

***

## Phần 4 — Cấu hình VS Code gọi MCP Server

### 4.1. Tại sao cần cấu hình?

VS Code (với Copilot Chat hoặc extension hỗ trợ MCP) cần biết:

* Chạy MCP Server bằng lệnh gì
* Truyền tham số nào vào process
* Đặt biến môi trường nào

Thông tin này được lưu trong file `settings.json` của workspace.

### 4.2. Tạo file cấu hình `.vscode/settings.json`

Tạo hoặc chỉnh sửa file `.vscode/settings.json` trong thư mục gốc của project:

```json
{
  "mcp": {
    "servers": {
      "revit-mcp": {
        "command": "node",
        "args": [
          "./mcp-server/dist/index.js"
        ],
        "env": {
          "REVIT_API_URL": "http://localhost:8080",
          "MCP_LOG_LEVEL": "info"
        }
      }
    }
  }
}
```

### 4.3. Giải thích từng trường cấu hình

```json
{
  "mcp": {
    "servers": {
      "revit-mcp": {            ← Tên định danh tùy chọn (xuất hiện trong MCP panel)
        "command": "node",      ← Chương trình thực thi (node, npx, python, ...)
        "args": [
          "./mcp-server/dist/index.js"   ← Đường dẫn tương đối đến entry point
        ],
        "env": {
          "REVIT_API_URL": "http://localhost:8080",  ← Địa chỉ Revit Plugin
          "MCP_LOG_LEVEL": "info"                    ← Mức độ log (debug/info/warn/error)
        }
      }
    }
  }
}
```

| Trường          | Mô tả                                              | Ví dụ                            |
| --------------- | -------------------------------------------------- | -------------------------------- |
| `command`       | Chương trình dùng để khởi động MCP Server          | `node`, `npx`, `python3`         |
| `args`          | Danh sách tham số dòng lệnh                        | `["./mcp-server/dist/index.js"]` |
| `env`           | Biến môi trường cho process MCP Server             | `{"REVIT_API_URL": "..."}`       |
| `REVIT_API_URL` | Địa chỉ HTTP của Revit Plugin (mặc định port 8080) | `http://localhost:8080`          |
| `MCP_LOG_LEVEL` | Mức độ chi tiết của log                            | `debug`, `info`, `warn`, `error` |

### 4.4. Cấu hình thay thế — Chạy trực tiếp từ TypeScript (không cần build)

Nếu bạn muốn chạy TypeScript trực tiếp mà không cần bước build:

```json
{
  "mcp": {
    "servers": {
      "revit-mcp": {
        "command": "npx",
        "args": [
          "-y",
          "tsx",
          "./mcp-server/src/index.ts"
        ],
        "env": {
          "REVIT_API_URL": "http://localhost:8080"
        }
      }
    }
  }
}
```

> **Ghi chú:** Cách này chậm hơn vì phải biên dịch TypeScript mỗi lần khởi động. Dùng cho môi trường phát triển, không dùng cho production.

### 4.5. Kiểm tra cấu hình trong VS Code

1. Mở VS Code
2. Mở **Command Palette** (`Ctrl + Shift + P`)
3. Tìm và chọn **"MCP: List Servers"**
4. Xác nhận `revit-mcp` xuất hiện trong danh sách
5. Chọn **"MCP: Start Server"** để khởi động thử

Nếu thành công, bạn sẽ thấy trạng thái **connected** trong MCP panel.

***

## Phần 5 — Cấu hình Claude Code gọi MCP Server

### 5.1. Claude Code là gì?

Claude Code là CLI (Command Line Interface) chính thức của Anthropic, cho phép sử dụng Claude trực tiếp trong terminal. Claude Code hỗ trợ MCP native — có thể gọi tool từ MCP Server mà không cần cài thêm extension.

### 5.2. Tạo file `.mcp.json`

Tạo file `.mcp.json` tại thư mục **gốc của project** (cùng cấp với `package.json`):

```json
{
  "mcpServers": {
    "revit-mcp": {
      "command": "node",
      "args": [
        "./mcp-server/dist/index.js"
      ],
      "env": {
        "REVIT_API_URL": "http://localhost:8080",
        "MCP_LOG_LEVEL": "info"
      }
    }
  }
}
```

### 5.3. So sánh cấu trúc VS Code vs Claude Code

Hai file cấu hình có cấu trúc tương tự nhưng khác nhau ở root key và vị trí file:

| Thuộc tính           | VS Code (`settings.json`) | Claude Code (`.mcp.json`)             |
| -------------------- | ------------------------- | ------------------------------------- |
| Root key             | `mcp.servers`             | `mcpServers`                          |
| Vị trí file          | `.vscode/settings.json`   | `.mcp.json` (thư mục gốc project)     |
| Phạm vi              | Theo workspace VS Code    | Theo thư mục làm việc của Claude Code |
| Transport mặc định   | stdio                     | stdio                                 |
| Hỗ trợ nhiều servers | Có                        | Có                                    |

### 5.4. Kiểm tra cấu hình trong Claude Code

```bash
# Bước 1: Khởi động Claude Code trong thư mục project
cd C:\Projects\deepbim-revit-mcp-plugin
claude

# Bước 2: Trong giao diện Claude Code, kiểm tra MCP servers
/mcp

# Kết quả mong đợi:
# MCP Servers:
#
#   revit-mcp
#     Status: connected
#     Tools:
#       - get_walls: Lấy danh sách tất cả tường trong Revit model
#       - create_wall: Tạo một bức tường mới trong Revit
#       - get_elements: Lấy danh sách elements theo category
#       - delete_element: Xóa element theo ID
```

### 5.5. Cấu hình nâng cao — Nhiều MCP Server cùng lúc

Bạn có thể cấu hình nhiều MCP server trong cùng một file `.mcp.json`:

```json
{
  "mcpServers": {
    "revit-mcp": {
      "command": "node",
      "args": ["./mcp-server/dist/index.js"],
      "env": {
        "REVIT_API_URL": "http://localhost:8080"
      }
    },
    "filesystem": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-filesystem",
        "C:\\Projects"
      ]
    },
    "memory": {
      "command": "npx",
      "args": [
        "-y",
        "@modelcontextprotocol/server-memory"
      ]
    }
  }
}
```

> **Ghi chú:** Claude Code sẽ load tất cả các servers được khai báo. Tools từ nhiều servers sẽ được gộp lại và AI có thể dùng tất cả trong cùng một cuộc hội thoại.

### 5.6. Cấu hình toàn cục (Global) vs cấu hình riêng Project

| Loại          | Vị trí file                | Phạm vi áp dụng                                    |
| ------------- | -------------------------- | -------------------------------------------------- |
| Global        | `~/.mcp.json`              | Áp dụng cho mọi project khi dùng Claude Code       |
| Project-level | `<project-root>/.mcp.json` | Chỉ áp dụng khi Claude Code chạy trong project này |

Claude Code sẽ **merge** cấu hình global và project-level. Nếu cùng tên server, project-level sẽ ghi đè global.

***

## Phần 6 — Checklist trước khi kết nối

### 6.1. Danh sách kiểm tra đầy đủ

Sử dụng checklist sau để đảm bảo mọi thứ đã sẵn sàng trước khi bước vào Bài 7:

```
╔══════════════════════════════════════════════════════════════╗
║              CHECKLIST TRƯỚC KHI KẾT NỐI — BÀI 6            ║
╠══════════════════════════════════════════════════════════════╣
║                                                              ║
║  REVIT PLUGIN (C#)                                           ║
║  ☐ Visual Studio đã build thành công (0 errors, 0 warnings)  ║
║  ☐ File .dll tồn tại trong bin\Release\                      ║
║  ☐ File .addin đã đặt đúng thư mục Addins của Revit          ║
║  ☐ Đường dẫn <Assembly> trong .addin trỏ đúng đến .dll       ║
║  ☐ GUID trong .addin là GUID duy nhất (vừa tạo mới)          ║
║  ☐ FullClassName trong .addin khớp với code C#               ║
║  ☐ Revit đã khởi động và load plugin thành công              ║
║  ☐ HTTP Listener đang chạy tại localhost:8080                ║
║  ☐ curl http://localhost:8080/api/health trả về 200 OK        ║
║                                                              ║
║  MCP SERVER (Node.js)                                        ║
║  ☐ Đã chạy npm install (cài đặt dependencies)               ║
║  ☐ Đã build thành công (npm run build)                       ║
║  ☐ File dist/index.js tồn tại                                ║
║  ☐ MCP Inspector hiển thị danh sách tools đúng              ║
║  ☐ Biến REVIT_API_URL trỏ đúng đến http://localhost:8080      ║
║                                                              ║
║  VS CODE                                                     ║
║  ☐ File .vscode/settings.json đã cấu hình MCP               ║
║  ☐ MCP server "revit-mcp" hiển thị trong Command Palette     ║
║  ☐ Trạng thái: connected                                     ║
║                                                              ║
║  CLAUDE CODE                                                 ║
║  ☐ File .mcp.json tồn tại ở thư mục gốc project             ║
║  ☐ JSON hợp lệ (không có lỗi cú pháp)                       ║
║  ☐ Lệnh /mcp hiển thị revit-mcp ở trạng thái connected       ║
║  ☐ Các tools được liệt kê đầy đủ                             ║
║                                                              ║
╚══════════════════════════════════════════════════════════════╝
```

### 6.2. Sơ đồ quy trình kiểm tra từng bước

```mermaid
flowchart TD
    START(["Bắt đầu kiểm tra"])

    START --> CHECK_BUILD{"Plugin đã<br/>build thành công?"}
    CHECK_BUILD -->|"Chưa"| BUILD["Build lại trong Visual Studio<br/>Ctrl + Shift + B"]
    BUILD --> CHECK_BUILD
    CHECK_BUILD -->|"Rồi"| CHECK_DLL

    CHECK_DLL{"File .dll tồn tại<br/>trong bin/Release?"}
    CHECK_DLL -->|"Chưa"| REBUILD["Kiểm tra Output path<br/>trong Project Properties"]
    REBUILD --> CHECK_DLL
    CHECK_DLL -->|"Rồi"| CHECK_ADDIN

    CHECK_ADDIN{"File .addin đặt<br/>đúng thư mục?"}
    CHECK_ADDIN -->|"Chưa"| COPY_ADDIN["Copy .addin vào<br/>%AppData%\\Autodesk\\Revit\\Addins\\2024\\"]
    COPY_ADDIN --> CHECK_ADDIN
    CHECK_ADDIN -->|"Rồi"| CHECK_REVIT

    CHECK_REVIT{"Revit đã load<br/>plugin thành công?"}
    CHECK_REVIT -->|"Chưa"| RESTART_REVIT["Khởi động lại Revit<br/>Chọn 'Always Load'"]
    RESTART_REVIT --> CHECK_REVIT
    CHECK_REVIT -->|"Rồi"| CHECK_HTTP

    CHECK_HTTP{"HTTP Listener<br/>đang chạy port 8080?"}
    CHECK_HTTP -->|"Chưa"| DEBUG_HTTP["Kiểm tra port 8080<br/>netstat -ano | findstr :8080<br/>Kiểm tra Revit Journal"]
    DEBUG_HTTP --> CHECK_HTTP
    CHECK_HTTP -->|"Rồi"| CHECK_MCP_BUILD

    CHECK_MCP_BUILD{"MCP Server<br/>đã build?"}
    CHECK_MCP_BUILD -->|"Chưa"| BUILD_MCP["cd mcp-server<br/>npm install && npm run build"]
    BUILD_MCP --> CHECK_MCP_BUILD
    CHECK_MCP_BUILD -->|"Rồi"| CHECK_CONFIG

    CHECK_CONFIG{"File cấu hình<br/>đã tạo đúng?"}
    CHECK_CONFIG -->|"Chưa"| CREATE_CONFIG["Tạo .vscode/settings.json<br/>và .mcp.json theo hướng dẫn"]
    CREATE_CONFIG --> CHECK_CONFIG
    CHECK_CONFIG -->|"Rồi"| DONE

    DONE(["Sẵn sàng kết nối!<br/>Chuyển sang Bài 7"])

    style START fill:#4FC3F7,stroke:#0288D1,color:#000
    style DONE fill:#81C784,stroke:#388E3C,color:#000
    style BUILD fill:#FFB74D,stroke:#F57C00,color:#000
    style REBUILD fill:#FFB74D,stroke:#F57C00,color:#000
    style COPY_ADDIN fill:#FFB74D,stroke:#F57C00,color:#000
    style RESTART_REVIT fill:#FFB74D,stroke:#F57C00,color:#000
    style DEBUG_HTTP fill:#E57373,stroke:#D32F2F,color:#000
    style BUILD_MCP fill:#FFB74D,stroke:#F57C00,color:#000
    style CREATE_CONFIG fill:#FFB74D,stroke:#F57C00,color:#000
```

***

## Phần 7 — Kiểm tra sức khoẻ hệ thống (Healthcheck)

Trước khi kết nối tất cả, hãy kiểm tra từng thành phần riêng lẻ theo thứ tự từ trong ra ngoài.

### 7.1. Kiểm tra Revit Plugin (HTTP Listener)

```bash
# Kiểm tra plugin có đang lắng nghe không
curl -s http://localhost:8080/api/health

# Kết quả thành công:
# {"status":"ok","revit_version":"2024","tools_count":4}

# Kiểm tra danh sách tools đã đăng ký
curl -s http://localhost:8080/api/tools

# Kết quả thành công:
# {"tools":["get_walls","create_wall","get_elements","delete_element"]}

# Test gọi thử một tool (phải có Revit project đang mở)
curl -s -X POST http://localhost:8080/ \
  -H "Content-Type: application/json" \
  -d '{"jsonrpc":"2.0","id":1,"method":"tools/list","params":{}}'
```

### 7.2. Kiểm tra MCP Server (Node.js)

```bash
# Cách 1: Chạy MCP Server độc lập và quan sát output
cd mcp-server
node dist/index.js

# Cách 2: Dùng MCP Inspector (công cụ debug chính thức của MCP)
npx @modelcontextprotocol/inspector node dist/index.js
```

**MCP Inspector** sẽ mở một giao diện web tại `http://localhost:5173` (hoặc cổng khác) cho phép bạn:

* Xem danh sách tools đã đăng ký
* Gọi thử từng tool với tham số tuỳ chỉnh
* Xem JSON request/response đầy đủ
* Debug schema validation lỗi

### 7.3. Kiểm tra VS Code MCP

1. Mở VS Code với workspace của project
2. Mở **Command Palette** (`Ctrl + Shift + P`)
3. Gõ **"MCP: List Servers"**
4. Đảm bảo `revit-mcp` hiển thị trạng thái **connected**

### 7.4. Kiểm tra Claude Code MCP

```bash
# Trong terminal, khởi động Claude Code tại thư mục project
cd C:\Projects\deepbim-revit-mcp-plugin
claude

# Trong giao diện Claude Code, kiểm tra
/mcp

# Kết quả mong đợi:
# revit-mcp
#   Status: connected
#   Tools: get_walls, create_wall, get_elements, delete_element
```

***

## Phần 8 — Troubleshooting các lỗi thường gặp

### 8.1. Cây quyết định xử lý lỗi

```mermaid
flowchart TD
    ERR(["Gặp lỗi!"])
    ERR --> TYPE{"Lỗi xảy ra<br/>ở đâu?"}

    TYPE -->|"Build thất bại"| B_ROOT{"Thiếu reference<br/>RevitAPI.dll?"}
    B_ROOT -->|"Có"| B1_FIX["Thêm reference từ<br/>C:\\Program Files\\Autodesk\\Revit 2024\\<br/>Set Copy Local = False"]
    B_ROOT -->|"Không"| B2{"Target framework<br/>sai?"}
    B2 -->|"Có"| B2_FIX["Đổi sang .NET Framework 4.8<br/>trong Project Properties"]
    B2 -->|"Không"| B3_FIX["Đọc Output window<br/>trong Visual Studio<br/>để tìm lỗi chi tiết"]

    TYPE -->|"Plugin không load"| P_ROOT{"File .addin<br/>có lỗi cú pháp?"}
    P_ROOT -->|"Có"| P1_FIX["Kiểm tra XML hợp lệ<br/>Kiểm tra FullClassName<br/>Kiểm tra đường dẫn Assembly"]
    P_ROOT -->|"Không"| P2{"Revit đã chọn<br/>'Do Not Load'?"}
    P2 -->|"Có"| P2_FIX["Xóa file cache:<br/>%AppData%\\Autodesk\\Revit\\...<br/>\\AddInManager\\*.dat"]
    P2 -->|"Không"| P3_FIX["Kiểm tra Revit Journal file<br/>để xem lỗi chi tiết"]

    TYPE -->|"HTTP không hoạt động"| H_ROOT{"Port 8080<br/>đã bị chiếm?"}
    H_ROOT -->|"Có"| H1_FIX["Đổi port trong code C#<br/>và cập nhật REVIT_API_URL<br/>trong file cấu hình MCP"]
    H_ROOT -->|"Không"| H2{"Firewall<br/>chặn kết nối?"}
    H2 -->|"Có"| H2_FIX["Thêm exception cho port 8080<br/>trong Windows Firewall"]
    H2 -->|"Không"| H3_FIX["Kiểm tra Revit có<br/>đang chạy với quyền Admin<br/>hoặc thử netsh add urlacl"]

    TYPE -->|"MCP không kết nối"| M_ROOT{"File cấu hình<br/>đúng cú pháp JSON?"}
    M_ROOT -->|"Không"| M1_FIX["Kiểm tra JSON syntax<br/>node -e 'JSON.parse(...)'\nHoặc dùng jsonlint.com"]
    M_ROOT -->|"Có"| M2{"Node.js đã<br/>cài đặt?"}
    M2 -->|"Không"| M2_FIX["Cài đặt Node.js LTS (>= 18.x)<br/>từ nodejs.org"]
    M2 -->|"Có"| M3_FIX["Kiểm tra đường dẫn trong args<br/>có trỏ đúng đến dist/index.js<br/>Thử chạy thủ công: node ./mcp-server/dist/index.js"]

    style ERR fill:#E57373,stroke:#D32F2F,color:#fff
    style B1_FIX fill:#81C784,stroke:#388E3C,color:#000
    style B2_FIX fill:#81C784,stroke:#388E3C,color:#000
    style B3_FIX fill:#81C784,stroke:#388E3C,color:#000
    style P1_FIX fill:#81C784,stroke:#388E3C,color:#000
    style P2_FIX fill:#81C784,stroke:#388E3C,color:#000
    style P3_FIX fill:#81C784,stroke:#388E3C,color:#000
    style H1_FIX fill:#81C784,stroke:#388E3C,color:#000
    style H2_FIX fill:#81C784,stroke:#388E3C,color:#000
    style H3_FIX fill:#81C784,stroke:#388E3C,color:#000
    style M1_FIX fill:#81C784,stroke:#388E3C,color:#000
    style M2_FIX fill:#81C784,stroke:#388E3C,color:#000
    style M3_FIX fill:#81C784,stroke:#388E3C,color:#000
```

### 8.2. Bảng lỗi thường gặp và cách xử lý

| # | Thông báo lỗi                               | Nguyên nhân                                    | Cách xử lý nhanh                                                   |
| - | ------------------------------------------- | ---------------------------------------------- | ------------------------------------------------------------------ |
| 1 | `CS0246: 'Autodesk' could not be found`     | Thiếu reference RevitAPI.dll                   | Add Reference → Browse → chọn RevitAPI.dll từ thư mục Revit        |
| 2 | Plugin không xuất hiện trong Revit          | File .addin sai vị trí hoặc sai cú pháp XML    | Kiểm tra thư mục Addins, validate XML                              |
| 3 | `Address already in use (port 8080)`        | Ứng dụng khác đang dùng port 8080              | \`netstat -ano                                                     |
| 4 | `spawn node ENOENT`                         | Node.js chưa được cài hoặc không có trong PATH | Cài Node.js LTS từ nodejs.org, restart terminal                    |
| 5 | `Cannot find module './dist/index.js'`      | Chưa build MCP Server                          | `cd mcp-server && npm install && npm run build`                    |
| 6 | `revit-mcp: disconnected` trong Claude Code | File .mcp.json lỗi JSON hoặc đường dẫn sai     | Validate JSON, thử chạy thủ công `node ./mcp-server/dist/index.js` |
| 7 | `No active document in Revit`               | Revit chưa mở project nào                      | Mở một file .rvt hoặc tạo project mới trong Revit                  |
| 8 | `HttpListenerException: Access is denied`   | Không có quyền bind port trên Windows          | Chạy Revit với quyền Admin, hoặc dùng `netsh http add urlacl`      |

### 8.3. Lỗi 1 — Build thất bại: "Could not find RevitAPI"

**Thông báo lỗi đầy đủ:**

```
Error CS0246: The type or namespace name 'Autodesk' could not be found
(are you missing a using directive or an assembly reference?)
```

**Nguyên nhân:** Chưa thêm reference đến Revit API DLL.

**Cách xử lý:**

1. Chuột phải vào **References** trong Solution Explorer
2. Chọn **Add Reference → Browse**
3. Điều hướng đến `C:\Program Files\Autodesk\Revit 2024\`
4. Chọn `RevitAPI.dll` và `RevitAPIUI.dll`
5. Nhấn **Add** rồi **OK**
6. **Quan trọng:** Với mỗi reference vừa thêm, vào Properties và đặt **Copy Local = False**

### 8.4. Lỗi 2 — Plugin không xuất hiện trong Revit

**Triệu chứng:** Revit khởi động bình thường nhưng không thấy plugin trong Add-Ins tab và không thể curl port 8080.

**Các nguyên nhân cần kiểm tra theo thứ tự:**

```bash
# Kiểm tra 1: File .addin có ở đúng thư mục không?
dir "%AppData%\Autodesk\Revit\Addins\2024\*.addin"

# Kiểm tra 2: FullClassName trong .addin có khớp với code C# không?
# Trong code: namespace DeepBimRevitMcpPlugin { public class App : IExternalApplication
# Trong .addin: <FullClassName>DeepBimRevitMcpPlugin.App</FullClassName>

# Kiểm tra 3: Revit có đang "nhớ" không load plugin này không?
dir "%AppData%\Autodesk\Revit\Autodesk Revit 2024\AddInManager\"
# Nếu có file .dat, xóa đi để Revit hỏi lại
del "%AppData%\Autodesk\Revit\Autodesk Revit 2024\AddInManager\*.dat"
```

### 8.5. Lỗi 3 — HTTP Listener không hoạt động: "Address already in use"

**Thông báo lỗi trong Revit Journal:**

```
System.Net.HttpListenerException: Failed to listen on prefix 'http://localhost:8080/'
because it conflicts with an existing registration on the machine.
```

**Cách xử lý:**

```bash
# Tìm ứng dụng nào đang dùng port 8080
netstat -ano | findstr :8080

# Kết quả ví dụ:
# TCP    0.0.0.0:8080    0.0.0.0:0    LISTENING    12345

# Tìm tên process từ PID (12345)
tasklist | findstr 12345

# Tắt process đó, hoặc đổi port trong code C#:
```

```csharp
// Trong RevitMcpListener.cs — đổi port từ 8080 sang 9090
_httpListener.Prefixes.Add("http://localhost:9090/api/");
```

Sau khi đổi port, nhớ cập nhật biến `REVIT_API_URL` trong tất cả file cấu hình:

```json
{
  "env": {
    "REVIT_API_URL": "http://localhost:9090"
  }
}
```

### 8.6. Lỗi 4 — MCP Server không kết nối: "spawn node ENOENT"

**Thông báo lỗi:**

```
Error: spawn node ENOENT
    at Process.ChildProcess._handle.onexit (node:internal/child_process:...)
```

**Nguyên nhân:** Node.js chưa được cài đặt hoặc chưa được thêm vào PATH.

**Cách xử lý:**

```bash
# Kiểm tra Node.js đã cài chưa
node --version
# Nếu chưa có → tải và cài Node.js LTS từ https://nodejs.org/

# Sau khi cài, restart terminal hoặc VS Code
# Kiểm tra lại
node --version
# Kết quả mong đợi: v18.x.x hoặc v20.x.x (LTS versions)
```

### 8.7. Lỗi 5 — Claude Code báo "MCP server disconnected"

**Triệu chứng:** Kết quả `/mcp` hiển thị `revit-mcp: disconnected`.

**Các bước debug:**

```bash
# Bước 1: Kiểm tra cú pháp JSON của .mcp.json
node -e "
  const fs = require('fs');
  try {
    const config = JSON.parse(fs.readFileSync('.mcp.json', 'utf8'));
    console.log('JSON hợp lệ:', JSON.stringify(config, null, 2));
  } catch(e) {
    console.error('Lỗi JSON:', e.message);
  }
"

# Bước 2: Chạy MCP Server thủ công để xem lỗi
node ./mcp-server/dist/index.js
# Đọc thông báo lỗi nếu có

# Bước 3: Nếu báo "Cannot find module"
cd mcp-server
npm install
npm run build

# Bước 4: Khởi động lại Claude Code
# Thoát Claude Code (Ctrl+C), vào lại
claude
/mcp
```

### 8.8. Lỗi 8 — HttpListenerException: "Access is denied"

**Thông báo lỗi:**

```
System.Net.HttpListenerException (0x80004005):
Access is denied
```

**Nguyên nhân:** Windows không cho phép ứng dụng thường (non-admin) bind HTTP prefix.

**Cách xử lý — Cấp quyền cho prefix (khuyến nghị, chỉ cần làm một lần):**

```cmd
:: Chạy với quyền Administrator
netsh http add urlacl url=http://localhost:8080/ user=Everyone

:: Kết quả thành công:
:: URL reservation successfully added
```

Hoặc chạy Revit với quyền Administrator (chuột phải → "Run as administrator").

***

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

### Câu 1: Tại sao MCP Server dùng stdio transport mà không dùng HTTP?

<details>

<summary>Xem gợi ý và trả lời</summary>

**Trả lời:**

MCP Protocol hỗ trợ nhiều loại transport: **stdio**, **SSE (Server-Sent Events)**, và **HTTP Streamable**.

Chúng ta chọn **stdio** cho giao tiếp giữa AI Host (VS Code, Claude Code) và MCP Server vì:

1. **Đơn giản về cấu hình:** AI Host tự động khởi động và quản lý process MCP Server. Không cần cấu hình port, không cần lo về firewall hay xung đột port.
2. **Bảo mật cao hơn:** Giao tiếp qua stdin/stdout của process — không mở thêm port mạng nào, không thể bị tấn công từ bên ngoài máy.
3. **Phù hợp với local development:** AI Host và MCP Server chạy trên cùng một máy, stdio là lựa chọn tự nhiên nhất.
4. **Lifecycle được quản lý tự động:** Khi VS Code đóng, MCP Server process cũng tự động dừng.

**Lưu ý quan trọng:** Giao tiếp giữa MCP Server (Node.js) và Revit Plugin (C#) vẫn dùng HTTP REST vì chúng là hai process độc lập và Revit Plugin cần lắng nghe request từ bên ngoài.

```
AI Host ←—stdio—→ MCP Server ←—HTTP:8080—→ Revit Plugin
 (cùng process)    (Node.js)                    (C#)
```

</details>

***

### Câu 2: Tại sao file .addin phải đặt Copy Local = False cho RevitAPI.dll?

<details>

<summary>Xem gợi ý và trả lời</summary>

**Trả lời:**

Khi đặt **Copy Local = True** (mặc định), Visual Studio sẽ copy `RevitAPI.dll` vào thư mục output (bin/Release). Điều này gây ra vấn đề:

1. **Xung đột phiên bản (version mismatch):** Revit đã có sẵn `RevitAPI.dll` trong thư mục cài đặt của nó. Nếu plugin mang theo một bản sao khác (dù cùng phiên bản), .NET có thể load nhầm bản, dẫn đến lỗi `FileNotFoundException` hoặc `InvalidCastException` khó debug.
2. **Tăng kích thước không cần thiết:** `RevitAPI.dll` có kích thước lớn (hàng chục MB). Copy không cần thiết làm thư mục plugin phình to.
3. **Best practice của Revit API:** Revit tự động cung cấp đúng phiên bản `RevitAPI.dll` cho plugin khi runtime. Bạn chỉ cần reference để compile — không cần copy.

**Quy tắc chung:**

* Revit API DLLs (`RevitAPI.dll`, `RevitAPIUI.dll`): **Copy Local = False**
* Thư viện của bạn (`Newtonsoft.Json.dll`, `YourHelper.dll`): **Copy Local = True**

</details>

***

### Câu 3: Nếu muốn chạy MCP Server trên máy khác (không phải máy cài Revit), cần thay đổi gì?

<details>

<summary>Xem gợi ý và trả lời</summary>

**Trả lời:**

Để chạy MCP Server trên máy khác (ví dụ: máy của AI developer, không phải máy có Revit), bạn cần thay đổi:

**1. Transport của MCP Server:** Đổi từ `stdio` sang `SSE` hoặc `HTTP Streamable`, vì AI Host và MCP Server không còn trên cùng máy:

```typescript
// Thay vì StdioServerTransport
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
const transport = new SSEServerTransport("/message", response);
```

**2. REVIT\_API\_URL:** Đổi từ `localhost` sang địa chỉ IP của máy cài Revit:

```json
{
  "env": {
    "REVIT_API_URL": "http://192.168.1.100:8080"
  }
}
```

**3. Cấu hình Revit Plugin:** Đổi binding từ `localhost` sang IP cụ thể hoặc `0.0.0.0` để nhận kết nối từ máy khác:

```csharp
// Thay localhost bằng địa chỉ IP hoặc 0.0.0.0
_httpListener.Prefixes.Add("http://+:8080/api/");
```

**4. Firewall:** Mở port 8080 trên máy cài Revit trong Windows Firewall.

**5. Bảo mật:** Thêm API Key authentication vì HTTP endpoint bây giờ có thể truy cập qua mạng:

```csharp
var apiKey = request.Headers["X-API-Key"];
if (apiKey != _config.ExpectedApiKey)
{
    response.StatusCode = 401;
    return;
}
```

```mermaid
graph LR
    A["AI Host<br/>Máy A"] -->|"SSE/HTTP"| B["MCP Server<br/>Máy B"]
    B -->|"HTTP REST + Auth"| C["Revit Plugin<br/>Máy C (có Revit)"]
```

**Lưu ý:** Trong khoá học này, chúng ta giữ mọi thứ trên cùng một máy để đơn giản.

</details>

***

### Câu 4: Làm thế nào để debug khi không biết lỗi đang ở thành phần nào?

<details>

<summary>Xem gợi ý và trả lời</summary>

**Trả lời:**

Áp dụng phương pháp **cô lập từng thành phần (isolation testing)** — kiểm tra từ trong ra ngoài:

**Bước 1 — Kiểm tra Revit Plugin trước tiên:**

```bash
curl http://localhost:8080/api/health
```

* Nếu thất bại → lỗi ở Revit Plugin (kiểm tra Journal, xem Revit có load plugin không)
* Nếu thành công → tiếp tục bước 2

**Bước 2 — Kiểm tra MCP Server:**

```bash
npx @modelcontextprotocol/inspector node ./mcp-server/dist/index.js
```

Dùng MCP Inspector để gọi thử tool `get_walls`.

* Nếu thất bại → lỗi ở MCP Server hoặc kết nối MCP Server → Revit Plugin
* Nếu thành công → tiếp tục bước 3

**Bước 3 — Kiểm tra AI Host:**

```bash
# Trong Claude Code
/mcp
```

* Nếu server không connected → lỗi cấu hình file `.mcp.json` hoặc `settings.json`

**Bước 4 — Kiểm tra end-to-end:**

```
Gửi prompt: "Liệt kê tất cả tường trong model"
```

* Nếu thất bại sau khi 3 bước trên thành công → lỗi kết nối end-to-end

**Nguyên tắc vàng:** Luôn kiểm tra từ **trong ra ngoài** — Revit → MCP Server → AI Host. Không bao giờ nhảy thẳng vào debug AI Host khi chưa xác nhận Revit Plugin hoạt động.

</details>

***

### Câu 5: File .mcp.json nên đặt ở đâu trong dự án thực tế và có nên commit vào Git không?

<details>

<summary>Xem gợi ý và trả lời</summary>

**Trả lời:**

**Vị trí tốt nhất:** Thư mục gốc của project (project root), cùng cấp với `package.json` và `.gitignore`.

**Lý do:**

1. Claude Code đọc `.mcp.json` từ current working directory khi khởi động
2. Đặt ở root đảm bảo file luôn được tìm thấy khi mở project
3. Dễ chia sẻ với toàn bộ team

**Về việc commit vào Git:**

```
✓ NÊN commit .mcp.json nếu:
  - Cấu hình không chứa thông tin nhạy cảm (API keys, passwords)
  - Bạn muốn toàn bộ team dùng chung cấu hình MCP
  - Đây là cấu hình tiêu chuẩn cho project

✗ KHÔNG NÊN commit .mcp.json nếu:
  - File chứa API keys, tokens, passwords
  - Đường dẫn trong args là đường dẫn tuyệt đối trên máy của bạn
  - Mỗi thành viên team có cấu hình khác nhau
```

**Giải pháp tốt nhất:** Tạo file `.mcp.json.example` để commit (mẫu không có thông tin nhạy cảm), và thêm `.mcp.json` vào `.gitignore` cho cấu hình thực tế:

```gitignore
# .gitignore
.mcp.json          # Cấu hình cá nhân, không commit
.mcp.json.local    # Cấu hình local override
```

**Về cấu hình toàn cục (global):**

```
~/.mcp.json                    ← Cấu hình global (áp dụng mọi project)
~/project-a/.mcp.json          ← Cấu hình riêng project A
~/project-b/.mcp.json          ← Cấu hình riêng project B
```

Claude Code sẽ **merge** cấu hình global và project-level khi khởi động.

</details>

***

## Tổng kết

Trong bài học này, chúng ta đã hoàn thành việc chuẩn bị tất cả các thành phần:

### Trạng thái các thành phần sau khi hoàn thành Bài 6

| Thành phần           | Trạng thái                              | Cách kiểm tra                               |
| -------------------- | --------------------------------------- | ------------------------------------------- |
| Revit Plugin (C#)    | Build xong, đã load vào Revit           | `curl localhost:8080/api/health` trả về 200 |
| File .addin          | Đặt đúng thư mục Addins, cú pháp hợp lệ | Kiểm tra Add-Ins tab trong Revit            |
| MCP Server (Node.js) | Build xong, dist/index.js tồn tại       | `npx @modelcontextprotocol/inspector`       |
| VS Code config       | `.vscode/settings.json` đã cấu hình     | MCP: List Servers → connected               |
| Claude Code config   | `.mcp.json` đã tạo, JSON hợp lệ         | `/mcp` → revit-mcp connected                |

### Sơ đồ trạng thái cuối bài

```mermaid
graph LR
    A["Revit Plugin\nREADY"] -->|"HTTP :8080"| B["MCP Server\nREADY"]
    B -->|"stdio"| C["VS Code\nCONFIGURED"]
    B -->|"stdio"| D["Claude Code\nCONFIGURED"]

    style A fill:#81C784,stroke:#388E3C,color:#000
    style B fill:#81C784,stroke:#388E3C,color:#000
    style C fill:#4FC3F7,stroke:#0288D1,color:#000
    style D fill:#4FC3F7,stroke:#0288D1,color:#000
```

### Kiến thức chính trong bài

| Chủ đề          | Nội dung đã học                                         |
| --------------- | ------------------------------------------------------- |
| Build Plugin    | Thiết lập Target Framework, Platform Target, Copy Local |
| File .addin     | Cú pháp XML, các phần tử bắt buộc, cách tạo GUID        |
| Deploy Plugin   | Thư mục Addins của Revit, thứ tự copy file              |
| VS Code MCP     | Cấu trúc `mcp.servers` trong settings.json              |
| Claude Code MCP | Cấu trúc `mcpServers` trong .mcp.json                   |
| Healthcheck     | Kiểm tra từng thành phần bằng curl và MCP Inspector     |
| Troubleshooting | 8 lỗi thường gặp và cách xử lý                          |

> **Bài tiếp theo — Bài 7:** Chúng ta sẽ **kết nối tất cả lại với nhau** và chạy thử end-to-end lần đầu tiên. Đây sẽ là khoảnh khắc **"It works!"** mà bạn mong đợi!

***

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

### Mã nguồn

| Tài nguyên                                        | Đường dẫn                                                                                                      |
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
| DeepBIM Revit MCP Plugin (source code tham khảo)  | [github.com/nguyenngocdue/deepbim-revit-mcp-plugin](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin) |
| Revit MCP Server (tham chiếu tool/server thực tế) | [github.com/nguyenngocdue/revit-mcp-server](https://github.com/nguyenngocdue/revit-mcp-server)                 |
| MCP SDK TypeScript                                | [github.com/modelcontextprotocol/typescript-sdk](https://github.com/modelcontextprotocol/typescript-sdk)       |
| MCP Inspector                                     | [github.com/modelcontextprotocol/inspector](https://github.com/modelcontextprotocol/inspector)                 |

### Tài liệu chính thức

| Tài nguyên                | Đường dẫn                                                                                                          |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------ |
| MCP Specification         | [spec.modelcontextprotocol.io](https://spec.modelcontextprotocol.io/)                                              |
| MCP Documentation         | [modelcontextprotocol.io/docs](https://modelcontextprotocol.io/docs)                                               |
| Revit API Documentation   | [revitapidocs.com](https://www.revitapidocs.com/)                                                                  |
| Claude Code Documentation | [docs.anthropic.com/en/docs/claude-code](https://docs.anthropic.com/en/docs/claude-code)                           |
| VS Code MCP Support       | [code.visualstudio.com/docs/copilot/chat/mcp-servers](https://code.visualstudio.com/docs/copilot/chat/mcp-servers) |

### Công cụ hỗ trợ

| Công cụ                | Mục đích                            | Cách dùng                                                |
| ---------------------- | ----------------------------------- | -------------------------------------------------------- |
| MCP Inspector          | Test và debug MCP Server            | `npx @modelcontextprotocol/inspector node dist/index.js` |
| Postman / curl         | Test HTTP endpoint của Revit Plugin | `curl http://localhost:8080/api/health`                  |
| Revit Lookup           | Xem chi tiết element trong Revit    | Cài từ Autodesk App Store                                |
| Visual Studio Debugger | Debug plugin C#                     | F5 trong Visual Studio (Attach to Process: Revit.exe)    |
| jsonlint.com           | Validate cú pháp JSON               | Paste nội dung .mcp.json để kiểm tra                     |

***

> **Ghi chú:** Bài học này là phần của khoá học [Revit API × MCP × AI — Từ Zero đến Plugin hoàn chỉnh](https://github.com/nguyenngocdue/deepbim-revit-mcp-plugin). Vui lòng tham khảo repository để có source code đầy đủ.

***

[← Bài 5: Dựng Core MCP cho Revit (C#)](/revit-mcp-ai/phan-2-xay-dung-tung-thanh-phan/bai-5.md) | [Bài 7: Kết nối mọi thứ lại với nhau →](/revit-mcp-ai/phan-3-ket-noi-and-van-hanh/bai-7.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-3-ket-noi-and-van-hanh/bai-6.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.
