Skip to main content
Glama
README.md
# mcp-view

Máy chủ MCP dựng một trang web trong máy để xem kế hoạch, báo cáo và sơ đồ của trợ lý AI,
thay vì đọc một khối chữ dài trong khung chat.

Nguyên tắc xuyên suốt: **AI chỉ gửi con trỏ, không gửi nội dung.** Mọi thứ đắt token —
nội dung tệp, phần thay đổi, mã SVG, toạ độ, màu sắc — do máy chủ tự lấy hoặc tự tính.
Giá trị trả về cho AI luôn chỉ là một dòng:

```
Đã dựng: http://127.0.0.1:7391/s/a3f9
```

## Cài đặt

Cần Node.js ≥ 22. Không cần đăng ký npm — cài thẳng từ GitHub, hai lệnh:

```bash
npm i -g https://github.com/zivhdinfo/mcp-view/archive/refs/heads/claude/mcp-view-server-scdc2o.tar.gz

cd /duong/dan/du-an-cua-ban
mcp-view init
```

Bản đã dựng nằm sẵn trong kho nên cài xong là chạy được ngay, không phải chờ biên dịch.

`mcp-view init` hỏi hai câu rồi tự làm phần còn lại:

```
  mcp-view 0.1.0
  xem kế hoạch, báo cáo và sơ đồ của trợ lý trên trang web trong máy

  Cài cho trình soạn thảo nào?  ↑↓ chọn dòng · space bật tắt · a tất cả · enter xác nhận

   ❯ ◉ Claude Code      thấy trên máy
     ◉ Cursor           thấy trên máy
     ◯ VS Code          không thấy
     ◯ Claude Desktop   không thấy

  Cài ở đâu?  ↑↓ chọn · enter xác nhận

   ❯ dự án hiện tại   ~/du-an
     toàn máy         mọi dự án
```

Những cái nó dò thấy trên máy đã được tích sẵn, nên phần lớn trường hợp chỉ cần nhấn enter
hai lần. Sau đó nó in ra đúng những gì đã ghi:

```
  ✓  .mcp.json                         Claude Code
  ✓  .cursor/mcp.json                  Cursor
  ✓  .claude/skills/mcp-view/SKILL.md  skill, riêng dự án này
  ✓  CLAUDE.md                         thêm phần nhắc trợ lý dùng mcp-view
  ✓  .gitignore                        thêm .mcp-view/
```

Phạm vi quyết định nơi ghi: **dự án hiện tại** dùng `.mcp.json`, `.cursor/mcp.json`,
`.vscode/mcp.json` và `.claude/skills/` ngay trong thư mục; **toàn máy** dùng `~/.claude.json`,
`~/.cursor/mcp.json` và `~/.claude/skills/`.

Chạy lại nhiều lần cũng không sao — cái gì đã có thì giữ nguyên và nói rõ là đã bỏ qua. Tệp
cấu hình sẵn có được gộp thêm chứ không ghi đè; nếu tệp đó là JSON hỏng thì nó dừng và báo,
không dám đụng vào.

| Cờ | Việc |
|---|---|
| `-y`, `--yes` | không hỏi, dùng luôn những gì dò được |
| `-n`, `--dry-run` | xem trước, không ghi gì |
| `--project` / `--global` | chọn sẵn phạm vi, bỏ qua câu hỏi |
| `--ide=claude-code,cursor` | chọn sẵn trình soạn thảo |
| `--no-rules` | đừng đụng vào `CLAUDE.md` |
| `--force` | ghi đè những thứ đã có |

Không phải terminal thật (chạy trong script, CI) thì nó bỏ qua phần hỏi và dùng mặc định.

Khởi động lại trình soạn thảo, gõ `/mcp` để kiểm tra ba công cụ đã kết nối chưa.

### Dựng từ nguồn

```bash
git clone -b claude/mcp-view-server-scdc2o https://github.com/zivhdinfo/mcp-view
cd mcp-view
npm install
npm run build     # dựng giao diện rồi biên dịch máy chủ
node dist/index.js init
```

`dist/` và `ui/dist/` được đưa vào git có chủ đích, vì gói này cài thẳng từ GitHub. Sửa
`src/` hay `ui/src/` thì chạy `npm run build` trước khi commit.

### Gốc dự án

Lấy từ thư mục làm việc của tiến trình. Nếu trình soạn thảo chạy máy chủ từ chỗ khác, đặt
`MCP_VIEW_ROOT` trỏ tới gốc dự án.

| Biến môi trường | Mặc định | Việc |
|---|---|---|
| `MCP_VIEW_ROOT` | thư mục làm việc | gốc dự án để đọc tệp và so sánh thay đổi |
| `MCP_VIEW_OPEN` | bật | đặt `0` để không tự mở trình duyệt (container, SSH) |

Thêm `.mcp-view/` vào `.gitignore` của dự án — đó là chỗ máy chủ ghi phiên và ảnh chụp mốc.

## Skill

`mcp-view init` cài kèm một skill ở `~/.claude/skills/mcp-view/SKILL.md`. Đó là thứ dạy trợ
lý **khi nào** nên gọi, chứ không chỉ là gọi thế nào:

- sắp viết một kế hoạch nhiều bước trước khi sửa code → `view_plan`
- vừa làm xong một việc → `view_report`
- câu trả lời đúng ra là một cái hình → `view_diagram`
- phép thử: nếu viết ra sẽ dài quá một đoạn ngắn, hoặc phải chèn code, thì nó thuộc về trang web

Skill cũng dặn trợ lý trả lời bằng đúng dòng URL, gửi con trỏ chứ không dán nội dung, chọn
`anchor` là chữ nó thật sự đọc thấy trong tệp, và khi bị máy chủ từ chối thì sửa đúng trường
được nêu rồi gọi lại — chứ không quay về đổ chữ ra chat.

Nguồn nằm ở `skill/mcp-view/SKILL.md` trong kho, sửa được rồi chạy lại `mcp-view init --force`.

Skill nạp theo tình huống, nên không đảm bảo lần nào cũng kích hoạt. Vì vậy `init` còn ghi
thêm một phần ngắn vào `CLAUDE.md` — thứ luôn có mặt trong ngữ cảnh — đặt giữa hai dấu
`<!-- mcp-view -->` để lần sau nhận ra và cập nhật đúng chỗ đó thay vì chèn trùng. Không
muốn thì thêm cờ `--no-rules`.

## Ba công cụ

| Công cụ | Gọi khi nào | Nhận vào |
|---|---|---|
| `view_plan` | trước khi bắt tay làm, sau khi đã nghĩ xong hướng đi | `summary`, `steps`, `diagram?`, `refs?` |
| `view_report` | sau khi làm xong | `summary`, `done`, `diagram?`, `refs?`, `notes?` |
| `view_diagram` | chỉ cần vẽ, không kèm kế hoạch hay báo cáo | `title`, `diagram` |

### Trỏ tới code bằng `anchor`, không bằng số dòng

```ts
{ path: "src/core/queue.ts", anchor: "async function claim", note: "chỗ khoá việc" }
```

Mô hình đếm dòng rất kém và số dòng lệch ngay khi tệp bị sửa, nên máy chủ nhận một mẩu chữ
có thật rồi tự đi tìm:

- khớp đúng một chỗ → tô sáng vùng đó
- khớp nhiều chỗ → chỉ chỗ đầu tiên, ghi chú "còn N chỗ khác khớp"
- không khớp → hiện cả tệp kèm cảnh báo, **không bao giờ đoán vị trí**

Nếu không khớp nguyên văn, máy chủ thử lại một lần nữa sau khi bỏ qua khoảng trắng thừa —
vẫn là chỗ có thật, không phải phỏng đoán.

### Sơ đồ

```ts
{ kind: "flow" | "architecture",
  nodes: [{ id, label, sub?, group?, role? }],
  edges: [{ from, to, label?, role? }] }
```

`flow` xếp dọc theo thứ tự các bước. `architecture` trải ngang, các nút cùng `group` nằm
trong một khung viền nét đứt có tên nhóm.

Máy chủ chặn cứng ở **9 nút**. Quá thì trả về lỗi kèm câu nhắc tách thành nhiều sơ đồ nhỏ.
AI không được gửi màu, toạ độ hay mã SVG — gửi là bị từ chối kèm lời giải thích.

### Màu theo vai trò

AI nói cái hộp đó **là gì**, máy chủ chọn màu. Một bảng màu cho cả ứng dụng nên sơ đồ vẽ
hôm nay vẫn khớp với sơ đồ tháng trước, và đổi nền sáng thì cả bảng đổi theo một lượt.

| `role` | Nghĩa | Màu |
|---|---|---|
| `add` | vừa tạo mới | xanh lá |
| `edit` | vừa sửa | hổ phách |
| `remove` | vừa xoá | đỏ |
| `store` | cơ sở dữ liệu, hàng đợi, nơi lưu tệp | xanh ngọc |
| `external` | dịch vụ bên ngoài dự án | tím |
| `neutral` | mặc định, không có gì đặc biệt | xám |

`add` và `remove` cố ý mượn đúng xanh lá và đỏ của phần code: trong sơ đồ chúng mang đúng
nghĩa đó. Gửi vai trò lạ thì bị từ chối kèm danh sách vai trò có thật.

Cạnh cũng nhận `role` — chỉ nên dùng khi bản thân mũi tên mới là điều đáng nói.

### Khi AI gửi sai định dạng

Máy chủ trả về lỗi nói rõ sai ở trường nào và cần sửa thành gì, để mô hình tự gọi lại đúng
mà không tốn thêm lượt của bạn:

```
'diagram.nodes' has 12 nodes, over the hard limit of 9. Split this into several
diagrams instead of shrinking the labels: one overview diagram of at most 9 boxes,
then one diagram per sub-flow. Call the tool again for each.
```

## Mốc so sánh

Ngay khi máy chủ khởi động, nó ghi lại một ảnh chụp trạng thái dự án:

- là kho git → lưu mã commit của HEAD, cộng bản sao nội dung mọi tệp đang sửa dở
- không phải kho git → băm nội dung mọi tệp, cộng bản sao để so sánh từng dòng

Phần thay đổi hiển thị trên web luôn là **so với ảnh chụp lúc mở phiên**, không phải so với
commit gần nhất — để bạn thấy đúng những gì AI đụng vào trong lượt này, không lẫn với những
gì bạn tự sửa từ hôm qua. Có nút "đặt lại mốc" ở cột phải.

Mỗi tiến trình giữ ảnh chụp riêng theo pid, nên mở hai cửa sổ trình soạn thảo trên cùng một
dự án cũng không cái nào xoá mốc của cái nào. Cổng cũng vậy: dò tìm từ 7391 trở lên, cổng
đang dùng ghi vào `.mcp-view/port`.

## Giao diện

Ba cột: danh sách phiên bên trái, nội dung ở giữa (giới hạn 880px), cây tệp đã thay đổi bên
phải. Trang tự cập nhật qua SSE — mỗi lời gọi công cụ mới hiện thành một dòng trong thanh
bên, đánh dấu "mới", và tab đang mở **không** bị nhảy đi chỗ khác.

Chọn hai phiên bằng checkbox rồi bấm "so sánh" để đặt kế hoạch cạnh báo cáo: bước nào rơi
rụng, việc nào phát sinh ngoài kế hoạch.

Phiên xếp theo ngày. Nút mắt ở đầu thanh bên hiện lại những phiên đã ẩn, và mỗi phiên có nút
**xoá** riêng — hỏi lại một lần rồi xoá hẳn khỏi đĩa, không khôi phục được.

### Nền sáng và nền tối

Nút mặt trời/mặt trăng trên thanh trên cùng, trạng thái nhớ lại giữa các lần mở. Cả sơ đồ lẫn
màu cú pháp đều đổi theo: SVG dùng biến CSS thay vì mã màu cố định, và mỗi token code mang sẵn
hai bảng màu nên chuyển chế độ không phải dựng lại gì. Phiên tạo trước bản này giữ sơ đồ màu
cố định, chỉ phiên mới theo được nền sáng.

### Xem sơ đồ từng bước

Kéo chuột để di chuyển sơ đồ, `ctrl` + lăn chuột để phóng to thu nhỏ quanh con trỏ. Nút
**toàn màn hình** mở sơ đồ ra kín cửa sổ — lúc đó lăn chuột là phóng luôn, không cần `ctrl`,
và `esc` để thoát. Nút "vừa khung" đưa về đúng cỡ nhìn được cả hình.

Bấm **xem từng bước** dưới sơ đồ: bản vẽ tự chạy lại từ đầu như một đoạn phim ngắn — mỗi nút
sáng lên, rồi mũi tên tự vẽ từ nút này sang nút kia, kèm một dòng thuyết minh `A → B · nhãn`.
Phần chưa tới thì mờ đi, phần đã qua thì dịu lại. Có nút lùi/tới, phím mũi tên và space, thoát
bằng Esc. Trình tự do máy chủ tính sẵn: bắt đầu từ nút không có mũi tên nào trỏ vào, rồi đi hết
một nhánh mới sang nhánh khác — đúng cách người ta kể lại một luồng.

### Quy tắc màu

Màu trong giao diện này mang nghĩa, không trang trí. Chỉ ba màu được phép bão hoà, và cả ba
đều nằm trong phần code:

| Màu | Nghĩa duy nhất |
|---|---|
| `#3FB950` xanh lá | dòng được thêm |
| `#F85149` đỏ | dòng bị bớt |
| `#388BFD` xanh nước biển | chỗ AI chỉ tới |

Ngoài ba chỗ đó, toàn bộ giao diện là thang xám — nút bấm, thẻ, nhãn, trạng thái, cây tệp
đều không dùng màu. Hai lớp chồng nhau và bật tắt riêng được: lớp thay đổi tô nền, lớp
"AI chỉ tới" chỉ vẽ một vạch dọc ở lề trái cộng một dấu ở thanh cuộn — **không tô nền**, để
dòng vừa sửa vừa được nhắc tới không mất lớp nào.

Ràng buộc này được kiểm tra tự động, không phải chỉ ghi trong tài liệu: `npm run test:visual`
mở trình duyệt thật rồi đo màu, phông, cỡ chữ, độ đậm, bo góc và đổ bóng của từng phần tử.

## Kiểm tra

```bash
npm test           # 66 phép thử: ba công cụ, chặn đầu vào, tìm anchor, so sánh, phiên, lệnh init
npm run test:visual  # 53 phép thử qua trình duyệt thật; cần: npm i --no-save playwright
```

## Cấu trúc

```
src/
  mcp/       máy chủ stdio, khai báo và xử lý ba công cụ, chặn đầu vào
  web/       Hono, các tuyến đường, SSE, phục vụ tệp tĩnh
  core/      phiên, ảnh chụp, so sánh thay đổi, tìm anchor, tô màu cú pháp
  diagram/   elkjs, sinh SVG, bảng màu
ui/          React + Vite + Tailwind + shadcn/ui, dựng ra ui/dist
test/        smoke.mjs (MCP + API), visual.mjs (trình duyệt)
```

TDQS

A4.5/5.0

Scored across 3 tools

Disambiguation5/5

Each tool targets a distinct phase: planning before work, reporting after work, and standalone diagramming. Even though all produce web pages, their intended invocation context is clearly separated. No overlap that would confuse an agent.

Naming Consistency5/5

All three tools share a consistent 'view_' prefix followed by a specific noun (plan, report, diagram). This creates a predictable pattern that makes it easy to guess the tool for a given need. No mixed conventions.

Tool Count5/5

3 tools is well-scoped for a focused presentation server. Each tool covers a distinct need and none feel redundant. This falls comfortably in the ideal range.

Completeness5/5

The server's domain is showing plans, reports, and diagrams on a web page. It covers the before-work, after-work, and standalone diagram cases. Optional diagram inclusion in plan/report fills any cross-cutting need, so no gaps.

Maintenance

ActivitySlowing
ResponsivenessNo issues