- MCP là chuẩn mở để ứng dụng AI kết nối với dữ liệu và công cụ bên ngoài. Trang chính thức ví nó như cổng USB-C cho ứng dụng AI.
- Có ba vai: host (ứng dụng AI), client (mỗi server một client) và server (chương trình cung cấp công cụ, dữ liệu, mẫu lời nhắc).
- Thông điệp theo JSON-RPC 2.0, chạy cục bộ qua stdio hoặc từ xa qua Streamable HTTP. Chỉ nối với server bạn tin, vì server có thể đưa nội dung lạ vào ngữ cảnh của AI.
Bài này dựa trên thông báo của Anthropic, trang giới thiệu và trang kiến trúc của Model Context Protocol, cùng tài liệu Claude Code, đọc ngày 11/11/2026. Trang kiến trúc lúc đọc mô tả bản giao thức 2026-07-28; nhiều bài viết trên mạng mô tả bản cũ hơn, nên một số chi tiết sẽ khác (xem mục "Bản 2026-07-28 đã đổi gì").
MCP là gì?
Theo trang chính thức, MCP (Model Context Protocol, giao thức ngữ cảnh mô hình) là chuẩn mã nguồn mở để nối ứng dụng AI với hệ thống bên ngoài. Nhờ MCP, các ứng dụng AI như Claude hay ChatGPT có thể kết nối tới nguồn dữ liệu (tệp trên máy, cơ sở dữ liệu), công cụ (công cụ tìm kiếm, máy tính) và quy trình (các mẫu lời nhắc chuyên biệt), từ đó lấy được thông tin cần và làm được việc.
Anthropic công bố MCP ngày 25/11/2024, gọi đây là giao thức mở để tạo cầu nối hai chiều an toàn giữa nơi chứa dữ liệu và ứng dụng AI. Vấn đề họ muốn giải quyết: trợ lý AI không chạm tới được dữ liệu nằm trong các hệ thống riêng lẻ, và mỗi nguồn dữ liệu mới lại cần một cách tích hợp riêng, nên rất khó mở rộng. MCP thay các tích hợp rời rạc đó bằng một giao thức chung.
Để thấy vì sao một chuẩn chung có ích, hãy tưởng tượng có 5 ứng dụng AI và 20 công cụ. Không có chuẩn chung, mỗi cặp ứng dụng và công cụ có thể cần một đoạn tích hợp riêng, tức tới 100 đoạn. Có chuẩn chung, mỗi công cụ làm một MCP server và mỗi ứng dụng làm phần client một lần, tổng cộng 25 phần. Đây cũng là ý của phép so sánh trên trang chính thức: USB-C cho một cách cắm chung cho các thiết bị điện tử, MCP cho một cách nối chung giữa ứng dụng AI và hệ thống bên ngoài.
Ba vai trong MCP: host, client và server
Trang kiến trúc của MCP mô tả mô hình client và server với ba vai:
| Vai | Là gì | Ví dụ |
|---|---|---|
| Host | Ứng dụng AI, điều phối một hay nhiều client | Claude Code, Claude Desktop, Visual Studio Code |
| Client | Thành phần giữ kết nối tới một server và lấy ngữ cảnh từ server cho host | Host tạo một client cho mỗi server |
| Server | Chương trình cung cấp ngữ cảnh cho client | Server đọc tệp trên máy, server của một dịch vụ theo dõi lỗi |
Ví dụ trong tài liệu: Visual Studio Code là host. Khi nó kết nối tới một server theo dõi lỗi, nó tạo một client cho kết nối đó; khi nối thêm server đọc hệ thống tệp, nó tạo thêm một client nữa. Mỗi client giữ một kết nối riêng với đúng một server.
Chữ "server" ở đây không có nghĩa là máy chủ ở xa. Nó chỉ chương trình cung cấp dữ liệu, dù chạy ở đâu. Server đọc tệp thường chạy ngay trên máy bạn; server của một dịch vụ trực tuyến thì chạy trên hạ tầng của dịch vụ đó.
Server cung cấp gì: tools, resources và prompts
Tài liệu gọi đây là ba "primitive" (thành phần cơ bản) mà server có thể đưa ra. Phân biệt được ba loại này là hiểu được phần lớn MCP.
| Thành phần | Là gì | Ví dụ | Phương thức |
|---|---|---|---|
| Tools (công cụ) | Hàm mà ứng dụng AI gọi để làm việc | Truy vấn cơ sở dữ liệu, gọi API, thao tác tệp | tools/list, tools/call |
| Resources (tài nguyên) | Nguồn dữ liệu cho AI làm ngữ cảnh | Nội dung tệp, bản ghi, cấu trúc bảng | resources/list, resources/read |
| Prompts (mẫu lời nhắc) | Mẫu dùng lại để định hình cuộc trò chuyện với mô hình | Lời nhắc hệ thống, vài ví dụ mẫu | prompts/list, prompts/get |
Tài liệu đưa một ví dụ gọn: một server về cơ sở dữ liệu có thể đưa ra công cụ để truy vấn, một tài nguyên chứa cấu trúc (schema) của cơ sở dữ liệu, và một mẫu lời nhắc có vài ví dụ cách dùng các công cụ đó. Client dùng các phương thức */list để xem server có gì, nên danh sách này có thể thay đổi trong lúc chạy.
Ngược chiều, client cũng có thể đưa ra khả năng cho server dùng. Ở bản 2026-07-28, khả năng chính là elicitation (hỏi thêm người dùng): server xin người dùng nhập thêm thông tin hoặc xác nhận một hành động.
Bên trong MCP: thông điệp JSON-RPC 2.0
MCP có hai lớp. Lớp dữ liệu định nghĩa nội dung thông điệp theo chuẩn JSON-RPC 2.0: mỗi yêu cầu có jsonrpc, id, method, params, và phản hồi có cùng id kèm result hoặc error. Lớp truyền tải lo việc gửi các thông điệp đó đi.
Để thấy luồng thông điệp mà không cần cài gì, đoạn Python dưới đây mô phỏng một client và một server nói chuyện với nhau bằng đúng dạng JSON-RPC đó. Đây không phải SDK MCP, chỉ là bản thu nhỏ để bạn đọc được từng thông điệp. Client hỏi server hỗ trợ gì (server/discover), xin danh sách công cụ (tools/list), gọi một công cụ (tools/call), và cố tình gọi thiếu tham số để xem phản hồi lỗi.
"""Mô phỏng các thông điệp JSON-RPC 2.0 giữa MCP client và MCP server, viết bằng Python thuần.
Đây KHÔNG phải SDK MCP. Nó chỉ dựng lại ba yêu cầu cốt lõi trong tài liệu kiến trúc MCP (bản giao thức 2026-07-28):
server/discover (hỏi server hỗ trợ gì), tools/list (xin danh sách công cụ), tools/call (gọi một công cụ).
Để viết server thật, dùng SDK chính thức (xem bài "Kết nối AI với công cụ qua MCP server").
"""
import json
PHIEN_BAN = "2026-07-28"
class ServerMoPhong:
def __init__(self):
self.cong_cu = {
"cong_hai_so": {
"description": "Cộng hai số nguyên a và b.",
"inputSchema": {"type": "object",
"properties": {"a": {"type": "integer"}, "b": {"type": "integer"}},
"required": ["a", "b"]},
"ham": lambda a, b: a + b,
}
}
def xu_ly(self, chuoi_yeu_cau):
yc = json.loads(chuoi_yeu_cau)
phuong_thuc, tham_so = yc["method"], yc.get("params", {})
if phuong_thuc == "server/discover":
ket_qua = {"supportedVersions": [PHIEN_BAN], "capabilities": {"tools": {}}}
elif phuong_thuc == "tools/list":
ket_qua = {"tools": [{"name": ten, "description": c["description"], "inputSchema": c["inputSchema"]}
for ten, c in self.cong_cu.items()]}
elif phuong_thuc == "tools/call":
c = self.cong_cu.get(tham_so.get("name"))
if c is None:
return self._loi(yc["id"], -32602, f"không có công cụ {tham_so.get('name')}")
thieu = [k for k in c["inputSchema"]["required"] if k not in tham_so.get("arguments", {})]
if thieu:
return self._loi(yc["id"], -32602, f"thiếu tham số {', '.join(thieu)}")
gia_tri = c["ham"](**tham_so["arguments"])
ket_qua = {"content": [{"type": "text", "text": str(gia_tri)}]}
else:
return self._loi(yc["id"], -32601, f"không có phương thức {phuong_thuc}")
return json.dumps({"jsonrpc": "2.0", "id": yc["id"], "result": ket_qua}, ensure_ascii=False)
@staticmethod
def _loi(id_, ma, thong_diep):
return json.dumps({"jsonrpc": "2.0", "id": id_, "error": {"code": ma, "message": thong_diep}}, ensure_ascii=False)
class ClientMoPhong:
def __init__(self, server):
self.server, self.id = server, 0
def gui(self, phuong_thuc, tham_so=None):
self.id += 1
tham_so = dict(tham_so or {})
tham_so["_meta"] = {"io.modelcontextprotocol/protocolVersion": PHIEN_BAN}
yc = json.dumps({"jsonrpc": "2.0", "id": self.id, "method": phuong_thuc, "params": tham_so}, ensure_ascii=False)
return json.loads(self.server.xu_ly(yc))
def chay_thu():
client = ClientMoPhong(ServerMoPhong())
kq = client.gui("server/discover")["result"]
print("1. server/discover ->", "phiên bản", kq["supportedVersions"][0], "| hỗ trợ", list(kq["capabilities"]))
kq = client.gui("tools/list")["result"]
print("2. tools/list ->", [t["name"] for t in kq["tools"]])
kq = client.gui("tools/call", {"name": "cong_hai_so", "arguments": {"a": 2, "b": 3}})["result"]
print("3. tools/call cong_hai_so(2, 3) ->", kq["content"][0]["text"])
loi = client.gui("tools/call", {"name": "cong_hai_so", "arguments": {"a": 2}})["error"]
print("4. tools/call thiếu b -> lỗi", loi["code"], loi["message"])
if __name__ == "__main__":
chay_thu()
Chạy đoạn code sẽ in ra:
1. server/discover -> phiên bản 2026-07-28 | hỗ trợ ['tools']
2. tools/list -> ['cong_hai_so']
3. tools/call cong_hai_so(2, 3) -> 5
4. tools/call thiếu b -> lỗi -32602 thiếu tham số b
Bốn dòng này là toàn bộ vòng đời của một lần dùng công cụ qua MCP. Ứng dụng AI hỏi các server mình nối tới xem có công cụ gì, gộp lại thành danh sách đưa cho mô hình. Khi mô hình quyết định dùng một công cụ, ứng dụng chuyển yêu cầu tới đúng server, chạy, rồi đưa kết quả lại vào cuộc trò chuyện. Mô hình không bao giờ nói chuyện trực tiếp với server; nó chỉ thấy tên, mô tả và tham số của công cụ.
Chú ý phần mô tả và inputSchema của công cụ trong code: đó là thứ mô hình đọc để biết công cụ làm gì và cần tham số nào. Một công cụ có mô tả mơ hồ sẽ bị dùng sai, giống như một skill có mô tả mơ hồ.
Cục bộ hay từ xa: stdio và Streamable HTTP
Lớp truyền tải của MCP có hai cách:
| Cách truyền | Hoạt động | Hợp với |
|---|---|---|
| stdio | Host chạy server như một tiến trình con, trao đổi qua đầu vào và đầu ra chuẩn | Server chạy trên cùng máy: đọc tệp, chạy công cụ cục bộ. Không tốn chi phí mạng |
| Streamable HTTP | Client gửi yêu cầu bằng HTTP POST, server có thể trả về theo luồng | Server ở xa, phục vụ nhiều client. Hỗ trợ xác thực bằng token, khóa API; MCP khuyên dùng OAuth để lấy token |
Theo tài liệu, server cục bộ dùng stdio thường chỉ phục vụ một client, còn server từ xa dùng Streamable HTTP thường phục vụ nhiều client. Tài liệu Claude Code cũng ghi rằng kiểu truyền SSE cũ đã lỗi thời và nên dùng HTTP nếu có.
Một hệ quả thực tế của stdio mà người mới hay vấp: vì thông điệp JSON-RPC đi qua đầu ra chuẩn, server stdio không được in gì khác ra đó. Một lệnh print() để gỡ lỗi là đủ làm hỏng kết nối. Bài kết nối AI qua MCP server chỉ cách ghi nhật ký đúng.
Bản 2026-07-28 đã đổi gì?
Nếu bạn đọc các bài viết cũ về MCP, bạn sẽ thấy mô tả về bước "bắt tay" (khởi tạo phiên) và một số tính năng không còn khuyến khích. Trang kiến trúc hiện hành, mô tả bản giao thức 2026-07-28, ghi những điểm sau:
- Giao thức không giữ trạng thái. Mỗi yêu cầu mang đủ thông tin để xử lý: phiên bản giao thức và các khả năng liên quan nằm trong trường
_metacủa chính yêu cầu đó. - Có yêu cầu
server/discoverbắt buộc ở server, để client hỏi một lần server hỗ trợ phiên bản và khả năng nào. Gọi nó là tùy chọn với client. - Sampling (server xin ứng dụng gọi mô hình hộ) và logging qua giao thức bị đánh dấu lỗi thời. Tài liệu khuyên server mới gọi thẳng API của nhà cung cấp mô hình nếu cần, và ghi nhật ký ra stderr (với stdio) hoặc dùng OpenTelemetry.
- Thông báo thay đổi là tùy chọn: client mở một luồng
subscriptions/listennêu loại thông báo muốn nhận, ví dụ khi danh sách công cụ đổi.
Bạn không cần nhớ hết các chi tiết này nếu chỉ dùng MCP: SDK và ứng dụng host lo phần đó. Nhưng nếu đọc hướng dẫn cũ mà thấy khác với SDK hiện tại, đây là lý do.
MCP khác gì API, function calling và skill?
| Là gì | Ai viết và dùng lại ở đâu | |
|---|---|---|
| API của một dịch vụ | Giao diện để chương trình gọi dịch vụ | Mỗi ứng dụng tự viết code gọi API |
| Gọi hàm (function calling) của một API mô hình | Khai báo công cụ trong code ứng dụng để mô hình gọi | Gắn với ứng dụng đó |
| MCP server | Bọc công cụ và dữ liệu theo một chuẩn chung | Viết một lần, mọi host hỗ trợ MCP dùng được |
| Skill | Chỉ dẫn và script cho một loại việc | Dạy AI quy trình, không phải cách kết nối |
MCP không thay API: MCP server thường gọi API của dịch vụ ở bên trong. MCP cũng không thay skill: một skill có thể dạy AI dùng các công cụ của một MCP server theo quy trình của bạn. Bài Agent Skills là gì nói về phần đó.
Dùng MCP để làm gì?
Trang giới thiệu của MCP liệt kê vài ví dụ: agent truy cập lịch và ghi chú của bạn để làm trợ lý cá nhân, Claude Code dựng cả một ứng dụng web từ một bản thiết kế, chatbot doanh nghiệp nối tới nhiều cơ sở dữ liệu để người dùng phân tích dữ liệu bằng hội thoại. Trang cũng liệt kê các ứng dụng hỗ trợ MCP như Claude, ChatGPT, Visual Studio Code và Cursor.
Với người học lập trình, các tình huống hay gặp là: cho agent đọc tài liệu của dự án, tra cứu cơ sở dữ liệu thử nghiệm, xem lỗi trong hệ thống theo dõi, hoặc gọi API nội bộ. Trong Claude Code, bạn thêm server bằng lệnh claude mcp add và kiểm tra trạng thái bằng lệnh /mcp trong phiên. Tài liệu Claude Code cũng cho biết định nghĩa công cụ của MCP được nạp khi cần chứ không nạp hết từ đầu, nên lúc đầu chỉ tên công cụ và chỉ dẫn của server chiếm ngữ cảnh. Các bước cụ thể và một server viết bằng Python có trong bài kết nối AI qua MCP server.
An toàn khi dùng MCP
Nối AI với một MCP server nghĩa là cho AI dùng công cụ của server đó, và đưa nội dung server trả về vào ngữ cảnh của AI. Tài liệu Claude Code cảnh báo: hãy chắc là bạn tin một server trước khi kết nối, vì server lấy nội dung từ bên ngoài có thể khiến bạn gặp rủi ro chèn lời nhắc (prompt injection), tức nội dung độc hại tìm cách điều khiển AI làm điều bạn không muốn.
Vài nguyên tắc đơn giản:
- Ưu tiên server chính thức của dịch vụ, hoặc server mã nguồn mở bạn đọc được.
- Cấp quyền tối thiểu: server đọc tệp chỉ nên đọc được thư mục cần thiết; token API chỉ có quyền cần dùng.
- Đọc kỹ trước khi cho phép các công cụ có tác dụng ghi, xóa hay gửi đi.
- Không đưa khóa API thẳng vào tệp cấu hình được commit lên git; dùng biến môi trường.
- Nghĩ rằng "server" phải là máy chủ ở xa: server đọc tệp chạy ngay trên máy bạn.
- Nối hàng loạt server lạ "cho đủ công cụ": mỗi server là một nguồn có thể đưa nội dung lạ vào ngữ cảnh.
- In thông tin gỡ lỗi ra đầu ra chuẩn trong server stdio, làm hỏng kết nối.
- Viết mô tả công cụ mơ hồ, khiến mô hình gọi sai công cụ hoặc truyền sai tham số.
- Học theo hướng dẫn cũ mà không đối chiếu với bản giao thức và SDK hiện tại.
Câu hỏi thường gặp
MCP có phải của riêng Anthropic không?
Anthropic công bố MCP năm 2024 dưới dạng giao thức mở. Theo trang chính thức, nhiều ứng dụng khác như ChatGPT, Visual Studio Code và Cursor cũng hỗ trợ MCP, nên một server viết đúng chuẩn dùng được ở nhiều nơi.
MCP server khác API thế nào?
API là cách chương trình gọi một dịch vụ. MCP server bọc các chức năng đó thành công cụ có tên, mô tả và tham số theo một chuẩn chung, để mọi ứng dụng AI hỗ trợ MCP dùng được mà không phải viết tích hợp riêng.
Tôi có cần biết lập trình để dùng MCP không?
Dùng server có sẵn thì chỉ cần chạy vài lệnh thêm server vào ứng dụng AI. Tự viết server thì cần lập trình cơ bản, ví dụ Python với SDK chính thức.
Tools và resources khác nhau ra sao?
Tools là hàm để AI làm việc (truy vấn, gọi API, sửa tệp). Resources là dữ liệu để AI đọc làm ngữ cảnh (nội dung tệp, cấu trúc bảng). Một server có thể đưa ra cả hai.
MCP có an toàn không?
Bản thân giao thức chỉ là cách trao đổi thông điệp. Độ an toàn phụ thuộc vào server bạn chọn và quyền bạn cấp. Chỉ nối server đáng tin và cấp quyền tối thiểu.
Học tiếp
- Muốn tự viết một MCP server bằng Python và nối vào Claude Code, đọc kết nối AI qua MCP server.
- Muốn hiểu MCP nằm ở đâu trong bức tranh agent, đọc AI agent là gì.
- Muốn dạy AI quy trình dùng công cụ của bạn, đọc Agent Skills là gì.
Nếu bạn muốn học nền tảng AI một cách có hệ thống cùng giảng viên, tham khảo khóa học AI của Big-O Coding.
Khóa AI – Introduction to Machine Learning: nền tảng Máy học từ thuật toán cơ bản đến Neural Networks và LLM, học bằng Python. Học thử buổi 1 miễn phí.


