Cursor khác Claude Code hay Gemini CLI ở một điểm quan trọng: nó là một IDE đầy đủ (fork từ VS Code), nơi bạn làm việc hàng giờ liên tục với nhiều file mở, nhiều cuộc trò chuyện Agent Mode song song trên các phần khác nhau của codebase. Điều đó khiến vấn đề "context bị phân tán" còn nghiêm trọng hơn: chat A trong tab 1 quyết định một thứ, chat B trong tab 2 lại không biết gì về quyết định đó. Memory MCP giúp mọi cuộc chat trong Cursor — bất kể tab nào, bất kể mở lại IDE bao nhiêu lần — đều đọc từ cùng một nguồn kiến thức. Bài này hướng dẫn kết nối Memory MCP vào Cursor Agent Mode, cách dạy Cursor một lần và tái dùng nhiều lần cho các quyết định kiến trúc, cách giữ memory luôn "sạch" theo thời gian, và các hạn chế thực tế khi vận hành.
Kết Nối Memory MCP Với Cursor Agent Mode
Cursor đọc cấu hình MCP từ file .cursor/mcp.json trong project (scope theo project) hoặc ~/.cursor/mcp.json (scope global cho toàn bộ máy). Với Memory MCP, nên ưu tiên scope project vì kiến thức codebase gắn chặt với từng repo cụ thể:
{
"mcpServers": {
"memory": {
"command": "npx",
"args": ["-y", "@modelcontextprotocol/server-memory"],
"env": {
"MEMORY_FILE_PATH": "${workspaceFolder}/.cursor/memory.jsonl"
}
}
}
}
Sau khi lưu, mở Cursor Settings → MCP để xác nhận server memory xuất hiện với đèn trạng thái xanh (connected). Nếu đèn đỏ hoặc không hiện tool nào, thường do một trong các lý do: Node.js chưa cài trên máy, đường dẫn ${workspaceFolder} không được resolve đúng trong phiên bản Cursor bạn dùng (khi đó thay bằng đường dẫn tuyệt đối để chắc chắn), hoặc thư mục .cursor/ chưa tồn tại.
Trong Agent Mode (chat với quyền chỉnh sửa file trực tiếp), gọi thử để xác nhận:
Kiểm tra xem tool memory (create_entities, search_nodes...) có khả dụng
không, và đọc toàn bộ graph hiện tại.
Nếu server mới cài, read_graph sẽ trả về graph trống — đó là kết quả đúng, không phải lỗi.
Mẹo: Với monorepo chứa nhiều sub-project, đừng dùng một
MEMORY_FILE_PATHchung cho cả repo — tách theo từng sub-project (packages/api/.cursor/memory.jsonl,packages/web/.cursor/memory.jsonl) để tránh kiến thức của frontend lẫn vào ngữ cảnh khi bạn đang làm backend.
Dạy Cursor Quyết Định Kiến Trúc Một Lần Và Tái Sử Dụng Mãi Mãi
Giá trị lớn nhất của Memory MCP trong một IDE như Cursor là bạn không cần giải thích lại kiến trúc mỗi khi mở một cuộc chat mới trong Agent Mode — điều vốn rất hay xảy ra vì Cursor khuyến khích tạo chat mới cho mỗi task để giữ context sạch (không bị nhiễu bởi lịch sử chat cũ dài).
Ví dụ, sau khi thiết kế xong tầng authentication, dạy Cursor một lần:
Ghi vào memory kiến trúc authentication hiện tại: chúng ta dùng JWT access
token (thời hạn 15 phút) kết hợp refresh token lưu trong httpOnly cookie
(thời hạn 30 ngày). Middleware "AuthGuard" ở backend kiểm tra access token,
tự động gọi endpoint "/auth/refresh" khi access token hết hạn. Tạo entity
"decision-auth-architecture" và relation "implements" tới component
"component-auth-service".
Từ giờ, bất kỳ chat mới nào trong Agent Mode, dù mở lúc nào, bạn chỉ cần:
Tôi cần thêm một route mới yêu cầu đăng nhập ở frontend. Trước khi code,
lấy lại kiến trúc auth hiện tại từ memory.
Agent gọi open_nodes với "decision-auth-architecture", đọc lại toàn bộ observation, và implement route mới đúng theo cơ chế JWT + refresh token đã thiết lập — không đề xuất một cơ chế auth khác (ví dụ session-based) vì "không biết" quyết định cũ đã có.
Một use case rất thực tế khác: dạy Cursor về lý do một đoạn code "kỳ lạ" cố ý tồn tại, để tránh bị "refactor nhầm" trong tương lai (bởi bạn, đồng nghiệp, hoặc chính agent ở lần sau):
Ghi vào memory: hàm formatCurrency() trong utils/format.ts cố ý KHÔNG dùng
Intl.NumberFormat vì gây lỗi hydration mismatch giữa server và client trên
Next.js phiên bản đang dùng. Đây là workaround tạm, không phải lỗi cần fix.
Mẹo: Với mọi đoạn code "trông như bug nhưng thực ra là chủ đích", luôn ghi ngay vào memory tại thời điểm viết code, đừng để "để sau" — đây chính xác là loại kiến thức dễ mất nhất và gây tốn thời gian nhất khi ai đó (kể cả agent) vô tình "fix" nó thành lỗi thật.
Giữ Memory Luôn "Sạch": Update, Prune Và Invalidate Những Entry Đã Cũ
Một kiến trúc auth có thể đúng hôm nay nhưng sai hoàn toàn sau 6 tháng khi team đổi sang một cơ chế khác. Nếu observation cũ không được cập nhật, agent sẽ tiếp tục đề xuất theo kiến trúc đã lỗi thời — tệ hơn cả việc không có memory, vì nó tạo ra sự tự tin sai lệch.
Ba hành động cần làm định kỳ:
- Update (cập nhật): khi quyết định thay đổi, đừng chỉ
add_observationschồng thêm — hãy xoá observation cũ mâu thuẫn bằngdelete_observationsrồi thêm observation mới, để tránh graph chứa hai fact trái ngược nhau cùng lúc.
Kiến trúc auth đã đổi: chúng ta bỏ refresh token cookie, chuyển sang
short-lived access token 5 phút và bắt buộc re-login qua OAuth mỗi lần hết
hạn (theo yêu cầu compliance mới). Xoá observation cũ về refresh token trong
entity "decision-auth-architecture" và thêm observation mới phản ánh đúng
hiện trạng.
- Prune (cắt gọt): định kỳ (gợi ý: đầu mỗi quý) yêu cầu agent rà soát toàn bộ graph, tìm observation nào không còn được tham chiếu tới trong 3-6 tháng và đề xuất xoá.
Đọc toàn bộ memory. Với mỗi entity, đánh giá xem observation có còn liên
quan tới codebase hiện tại không (tôi sẽ xác nhận từng cái trước khi xoá
thật). Liệt kê ra danh sách đề xuất trước, đừng xoá ngay.
- Invalidate (đánh dấu lỗi thời) mà không xoá: với những quyết định "đã từng đúng, giờ sai nhưng có giá trị lịch sử" (ví dụ để tránh lặp lại sai lầm cũ), thay vì xoá hẳn, thêm observation đánh dấu rõ trạng thái:
Thêm observation vào "decision-auth-architecture": [LỖI THỜI kể từ 2026-Q2]
Kiến trúc refresh-token-cookie đã bị thay thế, xem observation mới nhất để
biết kiến trúc hiện hành.
Mẹo: Luôn để agent liệt kê danh sách đề xuất xoá TRƯỚC, và bạn xác nhận thủ công, đặc biệt với entity liên quan tới quyết định kiến trúc quan trọng — thao tác xoá trong batch lớn mà không review trước là nguyên nhân phổ biến khiến team mất kiến thức tích lũy nhiều tháng chỉ trong một prompt.
Hạn Chế Và Cách Khắc Phục Khi Dùng Memory MCP Trong Cursor
- Nhiều chat Agent Mode mở song song có thể ghi memory gần như cùng lúc, dẫn tới việc quan sát thấy observation "biến mất tạm thời" trong một chat khác do độ trễ đọc/ghi file — trong thực tế nên tránh để hai chat cùng chỉnh sửa memory về cùng một entity trong cùng một khung thời gian ngắn.
- Cursor không tự động nhắc agent gọi memory nếu bạn không cấu hình rule (qua
.cursor/rules/— Cursor hỗ trợ rule theo file, tương tựCLAUDE.md). Nếu không có rule tường minh, một số model được cấu hình trong Cursor sẽ không chủ động search memory trừ khi bạn hỏi thẳng. - Không có giao diện trực quan xem graph — mọi thứ vẫn qua việc hỏi agent hoặc mở file
.jsonlbằng tay, không có visualization dạng đồ thị như một số công cụ note-taking chuyên dụng (ví dụ Obsidian graph view). - Đồng bộ qua Git dễ conflict nếu nhiều người cùng chỉnh sửa memory JSON Lines cùng lúc trên các branch khác nhau — vì mỗi dòng là JSON độc lập, merge conflict thường dễ resolve hơn so với JSON lồng nhau, nhưng vẫn cần review thủ công thay vì auto-merge mù.
Cách khắc phục thực tế: tạo file rule .cursor/rules/memory-protocol.mdc với nội dung ép agent luôn search memory trước khi thực hiện các task nhạy cảm (auth, payment, migration schema), và luôn coi file .cursor/memory.jsonl như một artifact cần review trong PR, không phải file tự động ẩn đi.
Mẹo: Thêm dòng
alwaysApply: truetrong frontmatter của file rule.cursor/rules/memory-protocol.mdcđể đảm bảo rule này được nạp vào MỌI chat Agent Mode, không phụ thuộc vào việc bạn có nhớ gắn rule vào context hay không.
Mẹo Hay Khi Dùng Memory MCP Với Cursor
- Với mỗi sub-project trong monorepo, dùng riêng một file memory — không share chung, tránh nhiễu context giữa các phần không liên quan.
- Ghi ngay vào memory tại thời điểm viết ra một đoạn code "trông kỳ lạ nhưng có chủ đích" — đừng để lại sau, vì đây là kiến thức dễ mất nhất.
- Luôn yêu cầu agent liệt kê trước khi xoá batch lớn observation, không xoá tự động không kiểm soát.
Mẹo: Kết hợp
.cursor/rules/(rule cố định luôn nạp) với Memory MCP (kiến thức tra cứu theo nhu cầu) — rule nói CÁCH hành xử, memory nói NHỮNG GÌ đã xảy ra và đã quyết định; nhầm lẫn vai trò của hai lớp này là lý do phổ biến nhất khiến người dùng thấy Cursor "không nhớ" dù đã cấu hình Memory MCP.