CodeGym /Các khóa học /ChatGPT Apps /MCP là gì và tại sao nó cần cho ChatGPT App của bạn

MCP là gì và tại sao nó cần cho ChatGPT App của bạn

ChatGPT Apps
Mức độ , Bài học
Có sẵn

1. Vì sao cần một giao thức riêng biệt

Trong mô‑đun này, cuối cùng chúng ta sẽ làm rõ MCP (Model Context Protocol) là gì và nó khớp vào stack của ChatGPT App như thế nào. Hãy bắt đầu bằng việc cố định vị trí của MCP trong kiến trúc, so sánh nó với “REST điển hình” và phân tích các thực thể chính của giao thức: tools, resourcesprompts.

Hãy tưởng tượng bạn đang viết một web service thông thường. Theo thói quen, bạn dựng một REST API: bạn có /api/gifts, /api/users, /api/orders, mỗi endpoint có định dạng vào/ra riêng, mã lỗi và cơ chế xác thực riêng. Điều này quen thuộc, nhưng có một điểm: bạn buộc phải giải thích cho từng client biết bạn đã hiện thực cái gì và như thế nào. Tài liệu, OpenAPI, ví dụ, SDK — tất cả đều cần vì format API là do bạn tự nghĩ ra.

Với ChatGPT App, tình hình phức tạp hơn. Client của bạn không chỉ là frontend, mà còn là chính mô hình. Mô hình cần:

  • biết những thao tác nào đang sẵn có;
  • hiểu đối số cần cho từng thao tác;
  • gọi các thao tác đó trong lúc hội thoại, đôi khi nhiều lần, đôi khi với tham số khác nhau;
  • diễn giải phản hồi có cấu trúc và quyết định phần nào hiển thị cho người dùng, phần nào dùng làm ngữ cảnh cho lượt nhắn tiếp theo.

Nếu mỗi nhà phát triển lại tự nghĩ ra format API riêng, mô hình sẽ rơi vào “địa ngục tích hợp”: mỗi App sẽ cần một client tùy biến, rất nhiều lớp “bọc” và logic mong manh. Ý tưởng về một giao thức chung giải quyết vấn đề này.

MCP (Model Context Protocol) là một đặc tả mở về cách chuẩn để LLM‑client (ChatGPT, plugin IDE, agent, v.v.) giao tiếp với máy chủ công cụ và dữ liệu của bạn. Nó đặt ra một ngôn ngữ chung, trong đó server công bố các công cụ, tài nguyên và prompts của mình, còn client — gọi chúng và nhận kết quả.

Một cách trực quan, MCP giống như cổng USB‑C cho thế giới AI: nếu bạn làm một “USB‑flash” (dịch vụ, cơ sở dữ liệu, CRM, công cụ tìm kiếm), bạn chỉ cần hiện thực một chuẩn kết nối. Khi đó bất kỳ “laptop” nào (ChatGPT, agent khác, IDE) cũng có thể kết nối mà không cần dây cáp tùy biến.

2. Góc nhìn tổng quan: MCP nằm ở đâu trong kiến trúc ChatGPT App

Để cố định bức tranh, hãy nhớ lại kiến trúc quen thuộc, nhưng giờ có lớp MCP hiển thị rõ ràng.

Hình dung tinh thần mà bạn đã thấy: người dùng trò chuyện với ChatGPT, trong hội thoại có widget được render (Apps SDK), và đâu đó bên ngoài là backend của bạn. Giờ thêm MCP và phân lớp mọi thứ.

Sơ đồ đơn giản hóa như sau:

Người dùng
   ↓ (ngôn ngữ tự nhiên)
ChatGPT (mô hình + UI)
   ↓ (gọi tool theo MCP)
MCP client bên trong ChatGPT
   ↓ (JSON-RPC, MCP)
MCP server của bạn (backend)
   ↓
CSDL của bạn / API bên ngoài / queue

Ở đây, “MCP‑client bên trong ChatGPT” là phần nội bộ của nền tảng, phần này nói chuyện với MCP‑server của bạn theo giao thức: thực hiện discovery, gọi công cụ và đọc tài nguyên.

Từ góc nhìn của Apps SDK, một ChatGPT App tối thiểu gồm ba thành phần. Thứ nhất — MCP‑server, nơi công bố công cụ và trả dữ liệu có cấu trúc. Thứ hai — gói UI (widget), được render bên trong ChatGPT và đọc dữ liệu này qua window.openai. Thứ ba — chính mô hình, mô hình quyết định khi nào gọi công cụ nào và trả lời người dùng ra sao.

Điều quan trọng ở đây là: trong các mô‑đun trước, bạn làm việc nhiều ở tầng Apps SDK và widget, tức phần trên của sơ đồ. Bây giờ, chúng ta hạ xuống tầng MCP‑server — đây là “ngôn ngữ giao tiếp” chính thức của bạn với ChatGPT và bất kỳ client nào khác muốn dùng App của bạn.

3. MCP so với “REST điển hình”: khác nhau ở đâu

Trên sơ đồ ở trên, ta đã cố định vị trí của MCP trong kiến trúc ChatGPT App. Giờ hãy so sánh cẩn thận cách “REST tự thiết kế” và MCP, để thấy vì sao trong ngữ cảnh ChatGPT Apps, phương án thứ hai gần như luôn thắng.

Với cách REST, bạn thiết kế endpoint, định dạng request/response theo cách bạn thấy tiện. Để làm việc với bạn, client cần biết URL, method, schema và mã lỗi. Đôi khi có OpenAPI hỗ trợ, đôi khi bạn chỉ gửi ví dụ request trong README. Riêng mô hình thì không hiểu gì trong số đó: nó cần một lớp code để biến “hãy gợi ý quà cho mẹ 50 tuổi” thành một HTTP request cụ thể, rồi biến JSON response thành dữ liệu phù hợp với hội thoại.

Trong MCP thì khác. Chính giao thức đã quy định:

  • cách client có thể biết danh sách công cụ của bạn;
  • cách mô tả đối số và kết quả qua JSON Schema;
  • cách mô tả tài nguyên và prompts;
  • cách một lời gọi công cụ và phản hồi của nó trông như thế nào.

Nhờ vậy, ChatGPT và các MCP‑client khác có thể tự động:

  • thực hiện discovery — biết bạn có tools/resources/prompts nào;
  • xây dựng schema tham số nội bộ cho từng công cụ;
  • gọi chúng mà không cần logic client hard‑code tùy biến;
  • cache metadata và dùng chúng cho tìm kiếm và xếp hạng ứng dụng.

Có thể tóm tắt khác biệt trong một bảng nhỏ.

Câu hỏi REST / gRPC tự thiết kế MCP
Client biết bạn làm được gì bằng cách nào? Từ tài liệu, README, OpenAPI Qua phương thức discovery chuẩn (danh sách tools/resources)
Ai mô tả tham số? Bạn, tùy ý (JSON, FormData, v.v.) JSON Schema trong trường của công cụ
Mô hình gọi hàm như thế nào? Qua code client tùy biến của bạn Trực tiếp qua các thực thể nguyên thủy của MCP
Client cần bao nhiêu lớp bọc? Nhiều và khác nhau cho mỗi dịch vụ Một giao thức chung cho mọi MCP‑server
Hỗ trợ bởi nhiều client Phải viết SDK cho từng client MCP‑server tự mô tả, client có thể tái sử dụng logic

Nói một cách cảm tính: REST là “mỗi nhà một kiểu”, còn MCP là “thỏa ước giữa các bên trong hệ sinh thái về cách nói chuyện với mô hình và dữ liệu”.

4. Các thực thể chính của MCP: tools, resources, prompts

Giờ hãy gọi tên ba nhân vật chính của MCP: công cụ (tools), tài nguyên (resources) và prompts.

Tools: các hành động bạn đã quen thuộc

Với tools bạn đã gặp trong Mô‑đun 4: khi đó ta mô tả công cụ, đặt tên, mô tả và JSON Schema cho đối số, sau đó mô hình gọi công cụ qua callTool. Ở tầng MCP, công cụ là một thao tác phía server với hợp đồng rõ ràng:

  • tên và mô tả (cho mô hình và cho UX/discovery);
  • JSON Schema cho đối số;
  • JSON Schema hoặc mô tả cấu trúc cho kết quả;
  • metadata bổ sung (ví dụ liên kết tới một UI component cụ thể trong Apps SDK).

MCP server phải có khả năng, tối thiểu, trả lời “yêu cầu danh sách công cụ” và xử lý “gọi công cụ”, trả về kết quả có cấu trúc.

Trong ứng dụng học tập Gift‑assistant của chúng ta đã có, giả sử, công cụ suggest_gifts, nhận tuổi, giới tính, ngân sách và vài sở thích, rồi trả về danh sách quà tặng gợi ý.

Phác thảo TypeScript giả của công cụ như vậy trong code MCP‑server có thể trông như sau (pseudo/stub):

// Pseudo-code, không phải API SDK cuối cùng
const suggestGiftsTool = defineTool({
  name: "suggest_gifts",
  description: "Gợi ý ý tưởng quà tặng theo tham số của người nhận",
  inputSchema: z.object({
    age: z.number(),
    relation: z.enum(["friend", "partner", "parent"]),
    budgetUsd: z.number(),
  }),
  handler: async (input) => {
    // TODO: business logic của bạn
    return { items: [] };
  },
});

Chúng ta sẽ phân tích chữ ký thực tế trong các bài sau, ở đây điều quan trọng là ý tưởng: công cụ không chỉ là một endpoint REST; đó là một phần tử của giao thức với schema đã công bố.

Tài nguyên (resources): dữ liệu có thể truy cập qua ID/URI

Resources trong MCP là cách mô tả dữ liệu sẵn có: file, thư mục, bản ghi DB, trang wiki, thậm chí kết quả từ chỉ mục tìm kiếm. Client có thể:

  • lấy danh sách tài nguyên;
  • đọc một tài nguyên cụ thể theo ID/URI;
  • đôi khi — thực hiện tìm kiếm trên chúng.

Khác với tools “làm điều gì đó”, resources thường “lưu giữ điều gì đó”. Ví dụ, trong Gift‑App bạn có thể biểu diễn catalog sản phẩm như một resource gift_catalog, để mô hình truy cập nhằm biết các danh mục, bộ lọc, khoảng giá, v.v.

Trong code, về mặt khái niệm có thể như sau:

const giftCatalogResource = defineResource({
  uri: "catalog://gifts",
  description: "Catalog quà tặng có thể đề xuất",
  read: async () => {
    // Trả về cấu trúc catalog
    return { categories: [], priceRanges: [] };
  },
});

Hiện ta chưa đi sâu vào format thông điệp MCP, nhưng hãy ghi nhớ: resources là các thực thể có địa chỉ, MCP server có thể tham chiếu tới chúng, còn client — đọc và dùng chúng như một phần của ngữ cảnh.

Prompts: các mẫu nhắc sẵn

Trong ngữ cảnh MCP, prompts là các template yêu cầu hoặc chỉ dẫn mà server có thể cung cấp cho client. Ví dụ, bạn có thể công bố prompt gift_followup, mô tả cách mô hình nên hỏi làm rõ về người nhận quà trước khi gọi công cụ.

Ví dụ điển hình theo tinh thần giao thức: server đưa tên prompt, mục đích của nó, đôi khi có tham số. Client có thể lấy danh sách prompts, chọn cái cần và chèn vào yêu cầu gửi tới mô hình.

Tại sao điều này cần cho ChatGPT App? Thứ nhất, đây là cách thống nhất để tái sử dụng các prompt phức tạp giữa nhiều client. Thứ hai, MCP khiến các prompt này trở nên rõ ràng và “theo hợp đồng”, thay vì nằm rải rác ở những nơi ngẫu nhiên trong code.

Capabilities: tuyên bố những gì bạn hỗ trợ

Cuối cùng là yếu tố thứ tư — capabilities. Đây đơn giản là bản khai: server nói mình hỗ trợ những thực thể nào (tools, resources, prompts, notification, v.v.) và cụ thể đã hiện thực phương thức nào. Với client, đây là cách để khỏi phải đoán xem cái gì làm được, cái gì không, và tinh chỉnh hành vi một cách khéo léo theo khả năng của server.

Trong thực tế, khi kết nối tới MCP‑server của bạn, ChatGPT trước hết thực hiện “bắt tay”, nhận về danh sách capabilities, rồi mới hỏi: “Ok, cho tôi xem tools và resources của bạn”.

5. MCP gắn vào App hiện tại của bạn như thế nào

Nghe có vẻ hơi trừu tượng, nhưng thực ra bạn đã gặp MCP qua Apps SDK rồi. Có lẽ nên bắt đầu bằng việc xem nó khớp với những gì bạn đã viết trong Apps SDK ra sao? Hãy nối các thực thể vừa giới thiệu với cách mà template App của bạn đang hoạt động.

Hãy nhớ lại chuỗi mà bạn đã hiện thực trong template:

  1. Widget thông qua window.openai hoặc các hook sẵn có sẽ gọi callTool với tên công cụ và đối số.
  2. Apps SDK bên trong ChatGPT chuyển đổi nó thành lời gọi tới phần server của App.
  3. Server thực thi công cụ và trả về ToolOutput, bao gồm structuredContent, content_meta.
  4. Widget nhận ToolOutput và render UI.

Điều then chốt là: bước 2–3 được hiện thực như một cuộc hội thoại theo MCP. Template Next.js của bạn có một endpoint (thường là app/mcp/route.ts hoặc tương tự), và đó chính là MCP‑server. Nó:

  • đăng ký các công cụ của bạn;
  • mô tả chúng qua JSON Schema;
  • hiện thực các handler;
  • trả lời ChatGPT cho các yêu cầu MCP list toolscall tool.

Nghĩa là ngay cả hiện tại, dùng template, bạn đã làm việc với MCP theo kiểu “tự động”: phần lớn “phép màu” của giao thức nằm trong SDK.

Mô‑đun 6 nhằm giúp bạn thôi coi MCP như “hộp đen ma thuật” và bắt đầu thiết kế có chủ đích:

  • thêm và tạo version cho công cụ;
  • dùng resources và prompts, không chỉ tools;
  • đọc và hiểu log MCP;
  • khi cần, dựng các MCP‑server riêng ngoài template Next.js (ví dụ dịch vụ Python cho mô hình ML hoặc dịch vụ truy cập cơ sở dữ liệu doanh nghiệp).

6. MCP dưới góc nhìn khác nhau: product vs. developer

Sẽ hữu ích nếu tách bạch những gì MCP mang lại cho product manager và cho kỹ sư.

MCP cho product

Từ góc độ sản phẩm, MCP là cách biến dịch vụ của bạn thành “mô‑đun có thể cắm” cho cả một hệ các client: ChatGPT, LLM‑client khác, plugin IDE, agent nội bộ. Chỉ cần mô tả khả năng của server dưới dạng bộ tools/resources/prompts, bạn cho phép bất kỳ client nào:

  • tự động phát hiện dịch vụ của bạn;
  • hiểu các bài toán nó giải quyết;
  • gọi các thao tác cần thiết một cách an toàn.

Với ChatGPT App, điều này còn tăng khả năng App của bạn được chọn: mô hình dùng metadata về công cụ của bạn để quyết định khi nào đề xuất App cho người dùng và cách trình bày cho đúng.

Tóm lại: MCP khiến dịch vụ của bạn trở thành “viên gạch” tiêu chuẩn của hệ sinh thái, chứ không phải một tích hợp tùy biến cho một‑hai client.

MCP cho developer

Từ góc độ kỹ sư, MCP là hợp đồng và giao thức. Nó trả lời các câu hỏi:

  • Tôi phải công bố công cụ ở format nào?
  • Mô tả đối số và trả kết quả ra sao?
  • Client hiểu thế nào là tôi hỗ trợ tài nguyên và prompts?
  • JSON nào sẽ đi qua mạng?

Khi có giao thức như vậy, mọi thứ trở nên dễ hơn:

  • viết server bằng nhiều ngôn ngữ (có SDK chính thức cho TypeScript và Python);
  • debug ứng dụng qua MCP Inspector hoặc công cụ tương tự;
  • phân chia trách nhiệm giữa các nhóm: một nhóm làm MCP‑server với dữ liệu và công cụ, nhóm khác — widget trên Apps SDK, nhóm thứ ba — có thể xây agent của riêng họ trên cùng MCP‑server đó.

7. Góc nhìn thực hành nhỏ: MCP‑server đầu tiên của chúng ta

Trong bài này, chúng ta cố ý chưa đi vào chi tiết format thông điệp và hiện thực server — đó là nội dung của các chủ đề tiếp theo. Nhưng để bạn có hình dung trước, sẽ hữu ích khi nhìn cấu trúc tổng thể của một MCP‑server tối thiểu bằng TypeScript.

Trong thực tế, thư viện TypeScript chính thức của MCP cung cấp cho bạn các primitive để tạo server, đăng ký tools/resources/prompts và khởi chạy transport (thường là HTTP hoặc SSE).

Ví dụ giả khái niệm có thể như sau:

// Đây là ví dụ khái niệm, API SDK sẽ xem sau
import { createServer } from "@modelcontextprotocol/sdk";

const server = createServer({
  name: "gift-genius",
  version: "1.0.0",
});

// Đăng ký công cụ
server.tool("suggest_gifts", {
  description: "Gợi ý quà tặng dựa trên sở thích của người nhận",
  inputSchema: {/* ... */},
  handler: async (input) => {
    // logic của bạn
    return { items: [] };
  },
});

// Khởi chạy transport (ví dụ, HTTP)
server.listen(3001);

Điểm quan trọng: ở đây không hề nhắc đến ChatGPT, Apps SDK hay frontend cụ thể của bạn. MCP‑server là tự đủ. Nó chỉ biết trả lời các yêu cầu MCP. ChatGPT App — chỉ là một kiểu client có thể sử dụng server như vậy.

Trong khuôn khổ khóa học, chúng ta sẽ bám theo template Next.js, nơi MCP‑server sống như một phần của dự án, nhưng đó không phải là lựa chọn duy nhất.

8. MCP trong hệ sinh thái: Apps SDK, Agents SDK và ACP

Để không coi MCP là “tính năng chỉ dành cho Apps SDK”, hãy nhìn nó trong bức tranh rộng hơn.

Thứ nhất, Apps SDK dựa trực tiếp vào MCP như cây cầu chuẩn giữa ChatGPT và dịch vụ bên ngoài. Tài liệu chính thức nhấn mạnh: Apps SDK làm việc với mọi MCP‑server. Bản thân giao thức cho phép mô tả công cụ, trả dữ liệu có cấu trúc và chỉ ra component để render trong UI.

Thứ hai, Agents SDK, mà bạn sẽ học ở mô‑đun riêng, cũng có thể nối tới MCP‑server. Tức là cùng một MCP‑server với business logic có thể được dùng:

  • bên trong ChatGPT như một phần của App của bạn;
  • bên trong một agent tự chủ, chạy chẳng hạn ở background của sản phẩm hoặc ở chế độ batch.

Thứ ba, ACP (Agentic Commerce Protocol), sẽ cần cho mua sắm và Instant Checkout, về mặt logic được xây trên cách tiếp cận MCP: mô hình và agent gọi các công cụ thương mại, cũng được mô tả qua hợp đồng chuẩn hóa.

Như vậy, MCP trở thành nền tảng, trên đó UI (Apps SDK), kịch bản agent (Agents SDK) và thương mại (ACP) được xây dựng. Nếu bạn nắm vững MCP, mọi thứ khác sẽ dễ hiểu và có thể dự đoán hơn.

Ghi chú: Về mặt hình thức, ACP không phụ thuộc vào MCP như một đặc tả, nhưng trong hiện thực, các công cụ ACP rất có thể sẽ được mô hình gọi thông qua các giao diện MCP. Hai cách tiếp cận khớp với nhau rất đẹp, nên có lẽ chúng ta sẽ sớm thấy điều đó.

9. Bài tập nhỏ “trong đầu” trước khi thực hành

Trước khi ở bài tiếp theo lặn vào format thông điệp MCP, sẽ hữu ích nếu chạy vài bài tập tư duy. Điều này giúp “chuyển số” từ “REST điển hình” sang “giao thức + hợp đồng”.

Hãy tưởng tượng không chỉ ChatGPT mà một plugin IDE cho VS Code và một trợ lý nội bộ trong Slack cũng muốn kết nối tới Gift‑App của bạn. Hãy mô tả bằng một câu điều mà tất cả chúng cần biết về dịch vụ của bạn. Có lẽ câu trả lời sẽ là: “Chúng tôi có công cụ suggest_gifts với các tham số như sau, và một catalog quà tặng có sẵn qua tài nguyên này.” Đó chính là điều MCP chuẩn hóa.

Hãy thử diễn đạt bằng hai câu nữa:

  • MCP là gì với product của App bạn (gợi ý: cách chuẩn để “đóng gói” chức năng cho nhiều client khác nhau);
  • MCP là gì với developer (gợi ý: giao thức JSON‑RPC với các nguyên thủy rõ ràng tools/resources/prompts).

Nếu bạn có thể nói trôi chảy — bạn đã đi được nửa chặng đường để làm việc tự tin với MCP.

Nếu tóm lại tất cả những điều trên thành một mệnh đề: MCP không phải một API bọc thêm, mà là hợp đồng nền tảng giữa logic của bạn và các LLM‑client. Trong các bài tới, chúng ta sẽ nhìn vào bên trong giao thức: phân tích format thông điệp MCP, handshake/capabilities và học cách quan sát traffic qua inspector, để tất cả nguyên tắc đó không còn là lý thuyết mà trở thành công cụ làm việc thực sự.

10. Những lỗi và hiểu lầm thường gặp xung quanh MCP

Lỗi số 1: coi MCP là “một lớp API nữa nằm trên REST của tôi”.
Đôi khi có cám dỗ: “Tôi đã có REST, vậy tôi chỉ cần làm một adapter mỏng để biến lời gọi MCP thành REST và ngược lại, rồi quên nó đi.” Về hình thức có thể làm vậy, nhưng khi đó bạn thường “kéo” đặc thù của API cũ vào trong MCP: kiểu dữ liệu lạ, phản hồi không có cấu trúc, thiếu schema rõ ràng. Theo thời gian adapter phình to, và lợi ích từ MCP giảm đi. Tốt hơn hãy coi MCP là hợp đồng chính, còn REST cũ — là chi tiết nội bộ nếu bạn vẫn cần.

Lỗi số 2: nghĩ rằng MCP “chỉ dành cho ChatGPT Apps”.
MCP là giao thức mở chung cho mọi LLM‑client: ChatGPT, plugin IDE, agent tự chủ. Nếu bạn thiết kế MCP‑server với tầm nhìn chỉ cho một App, bạn đang tự giới hạn mình trong tương lai. Lợi hơn là hãy nghĩ ngay từ đầu: “server này có thể được dùng bởi các client khác”, và thiết kế công cụ và tài nguyên mang tính tổng quát hơn.

Lỗi số 3: bỏ qua JSON Schema và mô tả đối số “bằng lời”.
Ngay cả khi SDK cho phép bạn truyền “bất kỳ JSON” ở đâu đó, đừng ngại mô tả schema của đối số và kết quả. Điều này ảnh hưởng trực tiếp tới khả năng mô hình gọi đúng công cụ, chất lượng gợi ý/tự hoàn thành và discovery, cũng như sự tiện lợi khi debug qua inspector. Đối số không được mô tả, hoặc mô tả kém — là con đường thẳng đến lỗi tool‑call khó hiểu.

Lỗi số 4: coi MCP như “transport ma thuật” và không xem log.
Khi mọi thứ chạy ổn, có vẻ như MCP là thứ vô hình chẳng cần để ý. Vấn đề là ngay khi có sự cố, nếu không hiểu cấu trúc MCP, bạn sẽ phải đoán rất lâu: “đó là Apps SDK? mô hình? hay backend của tôi?”. Thói quen xem thông điệp MCP và log từ sớm sẽ cứu bạn khỏi hàng giờ “cúng bái vô ích”.

Lỗi số 5: cố thiết kế workflow phức tạp chỉ qua REST, bỏ qua các nguyên thủy của MCP.
Khi có các kịch bản nhiều bước (tìm quà → hỏi rõ sở thích → chọn → đặt hàng), bạn có thể muốn “làm một endpoint REST thật to”. Trong ngữ cảnh ChatGPT Apps, điều này thường làm giảm tính kiểm soát: mô hình hiểu kém các bước trung gian, còn MCP‑client mất khả năng tái sử dụng tài nguyên và prompts. Tốt hơn là chia nhỏ chức năng thành vài tools/resources được mô tả rõ ràng, còn logic kết nối các phần với nhau bằng system prompt và mô tả đúng đắn.

Bình luận
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION