Nếu bạn đã từng thử build một AI agent thực thụ — không phải chatbot demo trả lời vài câu hỏi, mà là một hệ thống cần đọc file, gọi API nội bộ, truy vấn database, hay thao tác trên Jira — chắc chắn bạn đã đụng phải một vấn đề quen thuộc: mỗi lần muốn agent "nói chuyện" được với một hệ thống mới, bạn lại phải viết một lớp tích hợp riêng. Model Context Protocol (MCP) ra đời chính là để giải quyết bài toán này. Trong bài viết này, chúng ta sẽ đi từ gốc rễ vấn đề mà MCP giải quyết, các khái niệm lõi, so sánh với những cách tiếp cận cũ, và điểm qua lịch sử các phiên bản spec chính thức — đủ để bạn có nền tảng vững trước khi đi sâu vào kiến trúc và triển khai ở các bài sau.
Vấn Đề Mà MCP Được Thiết Kế Để Giải Quyết Trong Phát Triển AI
Trước khi Anthropic công bố MCP vào tháng 11/2024, đội ngũ engineering nào cũng từng trải qua cùng một nỗi đau: bài toán tích hợp N×M. Giả sử bạn có N công cụ AI (Claude, một agent tùy biến, một IDE có trợ lý AI...) và M nguồn dữ liệu/hệ thống (GitHub, Slack, PostgreSQL, Google Drive, hệ thống nội bộ...). Nếu không có một chuẩn chung, bạn cần viết N×M lớp tích hợp riêng biệt — mỗi tool AI phải tự viết connector cho từng hệ thống, và mỗi hệ thống phải hỗ trợ nhiều định dạng tích hợp khác nhau tùy theo AI client đang gọi vào.
Kinh nghiệm triển khai thực tế cho thấy hậu quả rõ nhất là ở khâu bảo trì. Một đội dùng function calling (cơ chế để model tự quyết định gọi hàm nào) để nối agent với 5-6 API nội bộ thường kết thúc bằng một mớ code glue rải rác: mỗi API có schema riêng, cách xử lý lỗi riêng, cách auth riêng, và không ai dám refactor vì sợ đứt một nhánh nào đó. Khi công ty đổi từ dùng OpenAI sang Claude, hoặc thêm một agent framework mới, toàn bộ lớp tích hợp phải viết lại từ đầu vì mỗi framework có convention riêng cho tool definition.
MCP giải quyết bài toán này bằng cách tách biệt rõ ràng hai phía:
- Phía cung cấp dữ liệu/năng lực (MCP server) — chỉ cần viết một lần, expose resources/tools/prompts theo chuẩn MCP.
- Phía tiêu thụ (MCP client/host) — bất kỳ AI client nào hỗ trợ MCP đều có thể kết nối vào server đó mà không cần code riêng.
Về bản chất, MCP là một giao thức mở (open protocol), dùng JSON-RPC 2.0 (giao thức gọi hàm từ xa dạng JSON) làm nền, chuẩn hóa cách một AI application giao tiếp với các nguồn ngữ cảnh (context) và công cụ bên ngoài. Anthropic mô tả nó bằng một phép ví rất trực quan: MCP giống như "cổng USB-C cho AI" — một chuẩn cắm là chạy, thay vì mỗi thiết bị một loại cổng riêng.
Điều đáng nói là MCP không phải ý tưởng hoàn toàn mới — Language Server Protocol (LSP) của Microsoft cũng giải quyết một bài toán N×M tương tự cho editor và ngôn ngữ lập trình. MCP áp dụng đúng tư duy đó cho thế giới AI agent, và nhờ học hỏi từ LSP, thiết kế của MCP khá gọn và dễ implement.
Mẹo: Khi giải thích MCP cho stakeholder không rành kỹ thuật (PM, BA), đừng nói "giao thức JSON-RPC" — hãy dùng ví dụ USB-C: trước đây mỗi hãng laptop một loại sạc, giờ một chuẩn cắm mọi thiết bị. MCP làm điều tương tự cho việc kết nối AI với dữ liệu doanh nghiệp, giúp non-technical stakeholder hình dung ngay giá trị kinh doanh thay vì sa vào chi tiết giao thức.
Các Khái Niệm Lõi Của MCP: Resources, Tools, Prompts, và Sampling
MCP định nghĩa bốn primitive (thành phần nguyên thủy) chính mà một server có thể expose ra cho client. Hiểu rõ sự khác biệt giữa bốn khái niệm này là bước quan trọng nhất khi mới học MCP, vì rất nhiều người nhầm lẫn giữa resource và tool.
Resources (tài nguyên)
Resource là dữ liệu tĩnh hoặc bán tĩnh mà server expose cho client đọc — giống như một file, một dòng trong database, hay kết quả của một API GET. Resource được xác định bằng một URI (ví dụ file:///logs/app.log hay postgres://db/customers/42), và client (hay chính người dùng) chủ động quyết định khi nào "kéo" resource đó vào context. Resource không có side-effect — đọc resource không làm thay đổi trạng thái hệ thống.
Tools (công cụ)
Tool là các hàm mà model (LLM) có thể chủ động gọi để thực hiện hành động hoặc lấy dữ liệu động — ví dụ create_jira_ticket, run_sql_query, send_slack_message. Khác với resource, tool có thể có side-effect (tạo ticket, gửi tin nhắn), và quyết định gọi tool nào là do chính model đưa ra dựa trên ngữ cảnh cuộc hội thoại, không phải do người dùng chọn thủ công. Đây chính là primitive tương đương với "function calling" mà nhiều người đã quen thuộc.
Prompts (mẫu prompt)
Prompt trong MCP là các template có thể tái sử dụng, được server định nghĩa sẵn để hướng dẫn cách tương tác hiệu quả với dữ liệu/tool của nó — ví dụ một prompt tên summarize_pr nhận tham số pr_number và trả về một chuỗi hướng dẫn model cách tóm tắt pull request đó theo đúng format công ty mong muốn. Prompt thường được người dùng chủ động chọn (qua UI dạng slash-command), không phải model tự quyết định.
Sampling (lấy mẫu)
Sampling là cơ chế cho phép server gửi ngược yêu cầu về client, nhờ client gọi LLM để hoàn thành một tác vụ con — ví dụ một MCP server xử lý file rất dài cần LLM tóm tắt trước khi trả kết quả, nó có thể "mượn" LLM của client thông qua sampling thay vì tự tích hợp API riêng với nhà cung cấp model. Đây là tính năng ít được dùng nhất trong bốn primitive, và tính đến 2025 chỉ một số ít client (Claude Desktop, một số SDK) hỗ trợ đầy đủ.
Bảng dưới đây tóm tắt sự khác biệt để bạn dễ tra cứu:
| Primitive | Ai chủ động quyết định | Có side-effect? | Ví dụ thực tế |
|---|---|---|---|
| Resource | Người dùng / client | Không | Đọc file log, đọc record trong DB |
| Tool | Model (LLM) | Có thể có | Tạo ticket, gửi email, chạy SQL |
| Prompt | Người dùng | Không | Slash-command /summarize_pr |
| Sampling | Server | Không trực tiếp | Server nhờ client tóm tắt văn bản dài |
Mẹo: Khi thiết kế MCP server, nguyên tắc phân loại đơn giản là tự hỏi "Ai cần chủ động ra quyết định gọi cái này?" Nếu câu trả lời là model dựa trên ngữ cảnh hội thoại → dùng tool. Nếu là người dùng chọn thủ công một dữ liệu cụ thể → dùng resource. Nhầm lẫn hai khái niệm này là lỗi thiết kế phổ biến nhất ở các MCP server mới viết, dẫn đến model gọi nhầm hoặc bỏ sót ngữ cảnh quan trọng.
MCP So Với Gọi API Trực Tiếp và Function Calling
Nhiều engineer khi mới tiếp cận MCP đặt câu hỏi rất hợp lý: "Tôi đã dùng function calling của OpenAI/Claude bao lâu nay rồi, MCP thêm giá trị gì?" Đây là câu hỏi đáng để mổ xẻ kỹ vì nó chạm đúng vào lý do MCP tồn tại.
Function calling (hay tool use) là cơ chế ở tầng model — bạn định nghĩa schema của một hàm (tên, mô tả, tham số dạng JSON Schema), gửi kèm trong request tới LLM, model quyết định có gọi hàm đó không và trả về tham số tương ứng, rồi chính ứng dụng của bạn phải tự viết code để thực thi hàm đó và gửi kết quả về lại model. Function calling là một khả năng của model, không phải giao thức kết nối hệ thống.
Gọi API trực tiếp thì đơn giản hơn nữa — code ứng dụng tự gọi thẳng REST API hay SDK của bên thứ ba, hoàn toàn không có LLM tham gia vào quyết định gọi hay không.
MCP nằm ở một tầng khác: nó là giao thức chuẩn hóa cách expose và khám phá (discover) các tool/resource đó, độc lập với việc model nào đang dùng chúng. Nói cách khác:
- Function calling trả lời câu hỏi: "Model quyết định gọi hàm gì, với tham số gì?"
- MCP trả lời câu hỏi: "Danh sách hàm/tool nào đang có sẵn, được định nghĩa ở đâu, ai maintain, và làm sao một client bất kỳ kết nối vào để lấy danh sách đó mà không cần biết trước?"
Trong thực tế triển khai, một MCP server khi kết nối vào client sẽ tự động "quảng cáo" (advertise) danh sách tool của nó qua request tools/list, sau đó client tự động chuyển đổi các tool đó thành định dạng function-calling phù hợp với model đang dùng (OpenAI tool schema, Anthropic tool schema, Gemini function declaration...). Điều này có nghĩa là MCP không thay thế function calling, mà đứng phía trên nó — MCP server cung cấp tool, client dịch tool đó sang định dạng function calling của model cụ thể, và model dùng cơ chế function calling để gọi.
Lợi ích thực tế lớn nhất: viết một MCP server cho hệ thống ticketing nội bộ một lần, và nó chạy được với Claude Desktop, Claude Code, Cursor, Windsurf, hay bất kỳ agent framework nào hỗ trợ MCP — không cần viết lại tool definition cho từng SDK.
| Tiêu chí | Gọi API trực tiếp | Function calling | MCP |
|---|---|---|---|
| Ai quyết định gọi | Code ứng dụng | Model LLM | Model LLM (qua chuẩn tool của MCP) |
| Cần viết lại khi đổi model/framework? | Không liên quan | Có, thường phải | Không, viết server một lần |
| Chuẩn hóa discovery | Không | Không | Có (tools/list, resources/list...) |
| Hỗ trợ resource/prompt/sampling | Không | Không | Có |
| Độ phức tạp khi tích hợp N hệ thống | Cao (N×M) | Cao (N×M) | Thấp (viết N server, dùng chung) |
Mẹo: Đừng nghĩ MCP là "phải chọn một trong hai" với function calling. Cách tiếp cận thực dụng: nếu bạn chỉ cần gọi 1-2 API nội bộ cho một dự án nhỏ, dùng function calling trực tiếp cho nhanh. Nhưng nếu công cụ/dữ liệu đó sẽ được nhiều AI client khác nhau dùng lại (nội bộ công ty hoặc public), đầu tư viết MCP server sẽ tiết kiệm công sức tích hợp về lâu dài.
Đặc Tả MCP Chính Thức: Các Phiên Bản Quan Trọng và Thay Đổi
MCP được Anthropic công bố lần đầu vào ngày 25/11/2024 dưới dạng open standard, kèm SDK cho TypeScript và Python, cùng một vài MCP server tham khảo (filesystem, GitHub, Google Drive, Slack, Postgres...). Từ đó đến nay, đặc tả (specification) đã trải qua vài lần cập nhật đáng chú ý mà bất kỳ ai xây dựng MCP server nghiêm túc đều nên nắm.
Phiên bản 2024-11-05 (bản khởi điểm)
Đây là phiên bản spec đầu tiên, định nghĩa đầy đủ bốn primitive (resources, tools, prompts, sampling), cơ chế transport ban đầu chỉ gồm stdio (giao tiếp qua process con, dùng cho server chạy local) và HTTP+SSE (cho server chạy remote). Ở giai đoạn này, hệ sinh thái còn khá sơ khai, chủ yếu dùng nội bộ trong Claude Desktop.
Phiên bản 2025-03-26
Đây là bản cập nhật lớn đầu tiên, mang một số thay đổi quan trọng:
- Thay thế cơ chế HTTP+SSE cũ bằng Streamable HTTP — một transport mới gộp cả gửi lẫn nhận qua một endpoint HTTP duy nhất, hỗ trợ cả response dạng stream lẫn dạng JSON thông thường, giải quyết một số vấn đề về việc duy trì kết nối lâu dài và khả năng resume khi mất kết nối.
- Bổ sung cơ chế OAuth 2.1 cho việc xác thực (authorization) với remote MCP server, giúp các server public/enterprise triển khai bảo mật chuẩn hóa thay vì tự chế cơ chế API key.
- Thêm khái niệm tool annotations (đánh dấu tool là read-only, destructive, idempotent...) giúp client và người dùng đánh giá rủi ro trước khi cho phép model gọi tool đó tự động.
- Chuẩn hóa cách trả về lỗi (error) chi tiết hơn theo JSON-RPC.
Phiên bản 2025-06-18
Bản cập nhật gần nhất tính đến thời điểm bài viết này, tập trung vào production-readiness:
- Yêu cầu server phải trả kèm metadata phân loại rõ ràng hơn cho resource/tool để hỗ trợ elicitation (server có thể yêu cầu thêm thông tin từ người dùng giữa chừng một tác vụ).
- Thêm cơ chế structured tool output — cho phép tool trả về dữ liệu có schema rõ ràng thay vì chỉ text, giúp model xử lý kết quả chính xác hơn.
- Củng cố thêm các khuyến nghị bảo mật cho remote server, đặc biệt là chống lại tấn công dạng "confused deputy" khi nhiều client cùng dùng chung một token.
- Loại bỏ hẳn HTTP+SSE cũ, chính thức hóa Streamable HTTP là transport chuẩn cho remote MCP.
Với người mới bắt đầu, điều cần nhớ nhất: MCP là một living standard — vẫn đang phát triển nhanh, và Anthropic duy trì specification tại repo GitHub modelcontextprotocol/specification với changelog công khai. Khi bạn implement một MCP server hay client, luôn kiểm tra field protocolVersion trong bước handshake (bắt tay khởi tạo kết nối) để đảm bảo tương thích, vì server viết theo spec 2024-11-05 có thể thiếu field mà client mới yêu cầu.
Mẹo: Trước khi bắt tay viết MCP server cho dự án thật, luôn kiểm tra version spec mà SDK bạn đang dùng (
@modelcontextprotocol/sdkcho TypeScript haymcppackage cho Python) implement tới đâu — chạynpm view @modelcontextprotocol/sdk versionshoặc xem CHANGELOG trên GitHub, vì có những field/tính năng (như structured tool output) chỉ hoạt động nếu cả client lẫn server cùng hỗ trợ phiên bản spec tương ứng.
MCP đã đi một chặng đường khá nhanh chỉ trong hơn một năm — từ một ý tưởng nội bộ của Anthropic thành chuẩn được OpenAI, Google DeepMind, và hàng loạt công ty công cụ dev (Cursor, Zed, Replit...) áp dụng. Ở bài tiếp theo, chúng ta sẽ đi sâu hơn vào lý do kỹ thuật cụ thể: vì sao MCP giúp AI agent vượt qua giới hạn của context window, và những kịch bản thực tế mà nó mở ra.