1. Giới thiệu
Nếu xem ChatGPT App đơn thuần như “một máy chủ web nữa”, rất nhanh bạn sẽ rơi vào hỗn loạn kiến trúc: chỗ này Next.js, chỗ kia máy chủ MCP, đâu đó có agent, nơi khác là backend commerce — và tất cả hoà trộn trong đầu thành một “máy chủ” lớn.
Hợp lý hơn là chấp nhận ngay từ đầu rằng đây là một chiếc bánh nhiều lớp:
- bên trên — ChatGPT UI, chúng ta không kiểm soát nhưng phải thích ứng theo;
- bên dưới — widget của chúng ta trên Apps SDK (Next.js 16, React 19), được render trong khung chat;
- thấp nữa — máy chủ MCP với công cụ (tools/resources/prompts);
- tùy chọn — lớp tác nhân (agents) điều phối các kịch bản phức tạp;
- và thấp nhất — các dịch vụ “trần gian” của bạn: CSDL, API bên ngoài, commerce/ACP (giao thức cho kịch bản thương mại), v.v.
Trong đề cương khoá học, có thể vẽ hành trình này như một chuỗi:
User → ChatGPT Widget → Apps SDK → MCP Gateway (Auth) → Agent Service → ACP / Stripe.
Nhiệm vụ bây giờ của chúng ta là biến chuỗi này thành một mô hình tinh gọn, dễ hiểu.
2. Sơ đồ tổng quan ngăn xếp
Đầu tiên nhìn bức tranh toàn cảnh, sau đó đi từng lớp một.
flowchart TD
U[Người dùng trong ChatGPT] --> C["ChatGPT UI chat + bảng Apps"]
C --> W["Widget của App của bạn (Apps SDK, Next.js)"]
W --> M["Máy chủ MCP (tools/resources/prompts)"]
M --> AG["Tác nhân (Agents SDK, điều phối)"]
AG --> B["Backends và ACP CSDL, dịch vụ, thanh toán"]
Có một vài điều quan trọng.
Thứ nhất, người dùng chỉ thấy hai lớp: ChatGPT UI và widget của bạn. Tất cả phần còn lại là “hậu trường”.
Thứ hai, giao thức MCP không phải là một chữ viết tắt ngẫu nhiên, mà là tiêu chuẩn chính thức để Apps SDK nói chuyện với các công cụ của bạn: máy chủ phải biết liệt kê tools, nhận call_tool và trả về liên kết đến tài nguyên UI để render trong ChatGPT.
Thứ ba, các lớp Agents và ACP về hình thức là tùy chọn, nhưng trong các ứng dụng thương mại thực tế thì gần như luôn cần: nơi thì phải lên kế hoạch nhiều bước, nơi thì cần thu tiền.
Bây giờ chúng ta phân tích từng lớp riêng biệt.
Insight: ChatGPT là một framework
Tích hợp với ChatGPT không nằm ở một chỗ — nó rải ra rất nhiều điểm tích hợp. Với lập trình viên, điều này rất giống làm việc với framework. Framework tự quyết định khi nào và ở đâu gọi mã của bạn, việc của bạn là viết đúng thứ vào đúng chỗ.
Với ChatGPT cũng đúng như vậy:
- widget — đăng ký qua mcp-resources, GPT tự quyết định khi nào hiển thị
- mcp-tools — GPT tự quyết định khi nào gọi
- product feed — có thể đưa vào model qua mcp-tool, nhưng cách chuẩn là qua site register merchant
- ACP/InstantCheckout — API riêng
- Ủy quyền/xác thực — máy chủ mcp auth riêng.
3. Lớp 1 — ChatGPT UI: “máy chủ” của chúng ta
ChatGPT UI là giao diện (trình duyệt và di động) của OpenAI, nơi người dùng thực hiện cuộc hội thoại chính. Ở đây có ô nhập quen thuộc, lịch sử tin nhắn, nút chọn model và tab ứng dụng (Store/Composer).
Lớp này chúng ta không lập trình. Chúng ta không có quyền truy cập vào mã, DOM hay style của nó. Nhưng nó đặt ra khuôn khổ:
- chính tại đây người dùng “chọn” ứng dụng của bạn một cách rõ ràng (qua Store/Composer) hoặc ngầm (model tự đề xuất App);
- chính tại đây ChatGPT quyết định: trả lời bằng văn bản thường, gọi tool của bạn, render widget hay làm tất cả cùng lúc;
- chính tại đây tồn tại các mẫu UX cơ bản: widget inline, chế độ fullscreen, cửa sổ PiP, v.v. (chi tiết ở mô-đun 8).
Về mặt thực tế cần nhớ: ChatGPT UI là ứng dụng chủ của chúng ta. Chúng ta nhúng vào bên trong nó, chứ không phải ngược lại. Máy chủ GPT sẽ tải mã widget của bạn lên máy chủ của họ, dọn sạch những thứ thừa và chỉ sau đó mới nạp nó vào khung chat của họ từ chính domain của họ.
4. Lớp 2 — Apps SDK và widget (Next.js 16 trong khung chat)
Lớp tiếp theo là mã UI của bạn, viết bằng React/Next.js với Apps SDK.
Mô hình tinh gọn rất đơn giản: như một mini‑SPA được render thành widget nhúng trong chat. Nhưng có vài lưu ý:
- mã của bạn chạy trong sandbox: DOM bị giới hạn, quy tắc riêng cho yêu cầu mạng, đối tượng đặc biệt window.openai để liên lạc với ChatGPT (sẽ có bài giảng riêng);
- widget không kiểm soát luồng hội thoại: người dùng gõ trong chat chung, model quyết định khi nào gọi App của bạn, và bạn chỉ trả lời trong “khung” của mình;
- Apps SDK đảm nhận mọi thứ: đồng bộ trạng thái widget với lịch sử hội thoại, xử lý kết quả tool, làm việc với MCP, v.v.
Từ góc nhìn nhà phát triển Next.js, mọi thứ trông khá quen thuộc: bạn có pages/components, hooks, props. Nhưng thay vì fetch('/api/...') kinh điển, bạn sẽ thường dựa vào các công cụ (tools) được mô tả trong máy chủ MCP và các hook đặc biệt của Apps SDK (sẽ đề cập sau trong khoá học).
Để cụ thể hơn một chút, nhớ tới dự án của chúng ta — GiftGenius giả định. Đây là App giúp chọn quà theo tham số: cho ai, ngân sách bao nhiêu, dịp gì, v.v.
Một mẩu nhỏ UI tương lai (chưa có đặc thù SDK, chỉ là ý tưởng):
// GiftSummary.tsx — component React đơn giản của App chúng ta
type GiftIdea = {
id: string;
title: string;
price: number;
};
interface GiftSummaryProps {
ideas: GiftIdea[];
}
export function GiftSummary({ ideas }: GiftSummaryProps) {
return (
<ul>
{ideas.map((idea) => (
<li key={idea.id}>
{idea.title} — ${idea.price}
</li>
))}
</ul>
);
}
Sau này component này sẽ nhận ideas không phải “từ không khí”, mà từ kết quả của công cụ trên máy chủ MCP (ToolOutput), nhưng ở mức kiến trúc điều quan trọng là: toàn bộ mã như vậy sống ở “lớp thứ hai” và chỉ hiển thị trạng thái.
5. Lớp 3 — Máy chủ MCP: thế giới công cụ và dữ liệu
Giờ đi xuống thấp hơn — phần phía máy chủ.
Model Context Protocol (MCP) là tiêu chuẩn mô tả cách LLM‑client (ChatGPT, Apps SDK, Agents) giao tiếp với máy chủ của bạn. Nó quy định các công cụ nào khả dụng, input/output schema của chúng, cách gọi và các tài nguyên/prompts khác có thể được nạp.
Một máy chủ MCP tối thiểu cho Apps SDK cần làm được ba việc:
- trả về danh sách công cụ (List tools) cùng JSON Schema và metadata của chúng;
- xử lý lời gọi công cụ (Call tools) — nhận yêu cầu call_tool, thực thi nghiệp vụ và trả về kết quả có cấu trúc;
- trả về html, js, css,... — tùy chọn, nếu tool gắn với widget cụ thể cần hiển thị.
Điểm quan trọng: MCP là giao thức độc lập với lớp truyền tải. Với ChatGPT Apps, chúng ta quan tâm tới biến thể HTTP với việc stream/push, nhưng chi tiết transport và định dạng thông điệp sẽ thuộc mô‑đun MCP (mức 6). Hiện tại, bạn chỉ cần hiểu rằng Apps SDK “bên dưới” sẽ gọi tới máy chủ MCP, chứ không phải các REST endpoint tuỳ tiện.
Về mặt kiến trúc, lớp MCP thường là một microservice riêng:
flowchart LR
subgraph App["ChatGPT App của bạn"]
W["Widget (Next.js + Apps SDK)"]
M["Máy chủ MCP (@modelcontextprotocol/sdk)"]
end
W <-- JSON-RPC over HTTP/SSE --> M
M --> DB[(Danh mục quà tặng)]
M --> EXT[API bên ngoài]
Bên trong máy chủ MCP, bạn viết mã TypeScript/Node “bình thường”, dùng cơ sở dữ liệu, hàng đợi, API bên thứ ba, v.v. SDK chính thức TypeScript cho MCP đảm nhận serial hoá JSON‑RPC, kiểm định schema và định tuyến lời gọi.
Với GiftGenius, một công cụ MCP có thể tên là search_gifts. Ở mức TypeScript, nó trông như một hàm bình thường:
// Mã giả: nghiệp vụ bên trong máy chủ MCP
export async function searchGifts(params: {
recipient: string;
budget: number;
}) {
// ở đây bạn truy vấn CSDL/danh mục
const items = await findGiftsInCatalog(params);
return items.slice(0, 10);
}
Sau đó chúng ta sẽ bọc nó thành MCP‑tool với mô tả schema, nhưng điều chính yếu là: lớp này là “backend bình thường” của bạn, chỉ khác là nói chuyện với thế giới qua MCP.
6. Lớp 4 — Agents SDK: “bộ não” cho kịch bản phức tạp
Không phải ứng dụng nào cũng cần agents, nhưng khi kịch bản không còn là “một lần gọi công cụ — một câu trả lời”, lớp tác nhân trở nên rất hữu ích.
Agent về bản chất là một tiến trình LLM được quản lý, có thể:
- đọc yêu cầu của người dùng và các sự kiện trong lịch sử hội thoại;
- lập kế hoạch chuỗi bước: gọi những công cụ nào, theo thứ tự nào, với tham số gì;
- phân tích kết quả, có thể quyết định “gọi lại tool”, “hỏi người dùng làm rõ”, “xây dựng câu trả lời phức tạp hơn”;
- đôi khi lưu trạng thái giữa các bước (bộ nhớ, phiên, checkpoint — đó là mức 12).
Agents SDK cung cấp cách có cấu trúc để mô tả các kịch bản như vậy: công cụ nào agent được phép dùng, lưu/khôi phục trạng thái ra sao, giới hạn vòng lặp thế nào, v.v. Agents chạy trong backend và cho phép bạn tận dụng sức mạnh OpenAI theo ý mình: không bị giới hạn bởi widget của ChatGPT Apps.
Trong bối cảnh ngăn xếp của chúng ta, agent thường nằm trong backend giữa lớp MCP và các API miền của bạn. Nó có thể dùng API bên ngoài, hàm nội bộ và MCP‑tools như “đôi tay”, còn bản thân nó đảm nhiệm “bộ não”.
Ví dụ, kịch bản GiftGenius có thể như sau:
- Người dùng viết “hãy chọn quà cho mẹ tới 50 $”.
- ChatGPT gọi công cụ search_gifts của ứng dụng bạn.
- Đằng sau search_gifts trên backend là một Agent, quyết định trước tiên cần làm rõ vài chi tiết (sở thích, dịp).
- Người dùng nêu thêm yêu cầu.
- ChatGPT lại gọi công cụ search_gifts của ứng dụng bạn với tham số bổ sung.
- Agent trên máy chủ có thể gọi thêm công cụ (ví dụ kiểm tra tồn kho).
- Trả về cho ChatGPT các phương án đã chuẩn bị và có thể là liên kết tới widget để trực quan hoá.
Sau này trong khoá học, chúng ta sẽ phân tích kỹ vòng chạy (run‑cycle) của agent, tính idempotent và an toàn. Nhưng với kiến trúc tổng thể, điều cần nhớ: lớp agent là tuỳ chọn nhưng rất mạnh mẽ, giúp bạn giảm bớt phần điều phối phức tạp.
7. Lớp 5 — ACP/Backend: tiền bạc, dữ liệu và các lo toan “trần gian”
Lớp thấp nhất là các dịch vụ thông thường của bạn:
- cơ sở dữ liệu (danh mục sản phẩm, người dùng, đơn hàng);
- API bên ngoài (nhà cung cấp thanh toán, logistics, SaaS bên thứ ba);
- các giao thức chuyên biệt như ACP (Agentic Commerce Protocol) cho kịch bản commerce và Instant Checkout.
ACP mô tả cách ChatGPT và agents giao tiếp với backend commerce của bạn: yêu cầu chọn SKU, tạo giỏ hàng, đặt hàng, hoàn tiền, webhooks về giao dịch thành công/thất bại, v.v.
Với GiftGenius, điều này sẽ như sau:
- MCP‑tool search_gifts đọc từ product feed/CSDL;
- agent, sau khi chọn hàng cụ thể, khởi tạo intent commerce (qua ACP);
- backend tương thích ACP của bạn nói với PaymentService: “thu tiền”, thông báo trạng thái cho ChatGPT;
- người dùng thấy trong ChatGPT rằng đơn đã được tạo, không cần mở trang ngoài.
Bây giờ, khi đã lướt qua các lớp, hãy xem một kịch bản cụ thể end‑to‑end.
8. Kịch bản xuyên suốt: yêu cầu của người dùng đi qua các lớp như thế nào
Lấy yêu cầu: “Hãy chọn quà cho mẹ trong tầm 50 đô la, bà thích đọc sách và trà”.
Chúng ta tách thành các bước.
- Người dùng viết trong ChatGPT. Đây là lớp đầu tiên — ChatGPT UI. Với người dùng, mọi thứ trông như một chat bình thường.
- Model đọc lịch sử hội thoại, metadata App của bạn (mô tả, danh mục, quyền hạn) và quyết định rằng GiftGenius là ứng viên phù hợp. Theo quy tắc discovery của Apps SDK, model cân nhắc cả mô tả văn bản của tools, kinh nghiệm sử dụng trước đó, ngữ cảnh và thậm chí cả nhắc tới thương hiệu.
- ChatGPT hoặc:
- gọi công cụ của App bạn ngay lập tức mà không có UI (kịch bản tool‑first);
- hoặc đề xuất trong câu trả lời: “Tôi có thể dùng GiftGenius để giúp chọn quà” và gọi tool của bạn.
- ChatGPT gửi tới máy chủ MCP yêu cầu call_tool cho công cụ search_gifts. Máy chủ MCP thực thi nghiệp vụ: truy vấn CSDL/feed, lọc theo ngân sách và sở thích và trả về JSON với danh sách sản phẩm phù hợp.
- Kết quả công cụ được trả về ChatGPT. Nó có thể:
- đơn giản dùng dữ liệu đó để tạo câu trả lời dạng văn bản (“Dưới đây là 3 ý tưởng quà tặng...”), không hiển thị widget;
- hoặc hiển thị widget, truyền ToolOutput vào component của bạn để render thẻ sản phẩm.
- Và chỉ lúc này widget GiftGenius (Apps SDK) của bạn mới được khởi chạy, mã Next.js của bạn được render trong chat. Widget có thể hiển thị form hỏi chi tiết: “Tặng cho ai?”, “Ngân sách”, “Sở thích”. Người dùng có thể bấm nút hoặc tiếp tục gõ trong chat — model sẽ đồng bộ điều này với App.
- Khi widget cần dữ liệu thực (danh mục quà), nó sẽ không fetch('https://my-backend/gifts') trực tiếp. Thay vào đó, chính widget khởi tạo việc gọi MCP tool: ChatGPT lại gửi tới máy chủ MCP yêu cầu call_tool cho công cụ search_gifts.
- Nếu kịch bản nhiều bước (cần hỏi làm rõ, xếp hạng, kiểm tra tồn kho bổ sung, đề xuất thay thế), lớp agent đảm nhận việc lập kế hoạch, quản lý workflow và điều phối tác nhân.
- Khi người dùng quyết định “mua” sản phẩm cụ thể, ChatGPT khởi tạo mua hàng theo giao thức ACP. Backend commerce qua ACP và Instant Checkout thực hiện giao dịch, phản hồi trạng thái, gọi webhooks, và ChatGPT hiển thị trạng thái cuối cùng cho người dùng (“Đơn hàng đã được tạo, đây là hóa đơn”).
Từ góc nhìn nhà phát triển, điều tuyệt vời là ở mỗi lớp đều có ranh giới trách nhiệm rõ ràng. Đồng thời các lớp được kết nối bằng những giao thức mới được tiêu chuẩn hoá (MCP, ACP), chứ không phải các yêu cầu REST nhàm chán cũ.
Tất cả đây là bức tranh logic: có những lớp nào và yêu cầu đi qua chúng ra sao. Tiếp theo chúng ta sẽ quan tâm đến khía cạnh vật lý: các lớp này triển khai trong mã và hạ tầng như thế nào — một Next monolith hay nhiều dịch vụ (không bàn về kiến trúc monolith vs microservices).
9. Next.js nguyên khối vs kiến trúc tách rời
Câu hỏi hợp lý: “Tất cả thứ này có nhất thiết phải là một đống dịch vụ riêng lẻ không? Tôi chỉ làm một Next.js nguyên khối là xong được không?”
Câu trả lời: được. Trong khoá học, chúng ta sẽ đi từ đơn giản đến phức tạp. Ban đầu hoàn toàn ổn khi gom “gần như tất cả” vào một repository và thậm chí một runtime:
flowchart LR
U[ChatGPT] --> W["Next.js App (Apps SDK)"]
W --> M["MCP endpoint (trong chính Next.js)"]
M --> DB[(CSDL/danh mục)]
Tức là máy chủ Next.js của bạn (API routes hoặc máy chủ riêng) đồng thời:
- phục vụ UI‑widget (pages/components Apps SDK),
- hiện thực MCP endpoint (JSON‑RPC trên HTTP),
- truy cập CSDL/API bên ngoài.
Cái này tiện trong chế độ dev và cho các phiên bản đầu của App: ít phần chuyển động hơn, triển khai đơn giản hơn.
Tuy nhiên, khi tính năng tăng lên, sẽ có lý do để tách lớp:
- cần scale máy chủ MCP riêng (nhiều công cụ nặng);
- backend tài chính chạy trên domain riêng, do đội khác quản lý, yêu cầu bảo mật đặc thù;
- logic agent có thể tách thành ứng dụng riêng với monitoring và SLA của chính nó.
Sau đó bức tranh sẽ gần giống những gì ta đã thấy:
flowchart TD
U[ChatGPT] --> W[Next.js + Apps SDK]
W --> MG[MCP Gateway]
MG --> M1[MCP Gifts Server]
MG --> M2[MCP Analytics Server]
M1 --> AG[Agent Service]
AG --> ACP[Commerce/ACP Backend]
Xuất hiện khái niệm MCP Gateway — cổng vào chung cho ChatGPT. Nó định tuyến lời gọi tới các máy chủ MCP khác nhau, làm việc với REST API, quản lý ủy quyền, giới hạn tốc độ (rate limiting), v.v.
Chúng ta sẽ bắt đầu viết ví dụ theo kịch bản thiên về nguyên khối hơn, nhưng ngay từ đầu sẽ tổ chức mã sao cho có thể tách ra tương đối dễ dàng.
10. Bạn sẽ viết mã ở đâu (và uỷ thác gì cho phần khác)
Một khi đã phác hoạ cách các lớp có thể gom trong monolith hoặc kiến trúc phân tán, hữu ích là ghi rõ những nơi bạn sẽ viết mã và những gì thuộc về dịch vụ/đội khác.
Từ góc nhìn nhà phát triển TypeScript/Next.js, hãy đánh dấu rõ các vùng bạn kiểm soát.
Trong widget (Apps SDK + Next.js) bạn:
- viết các component React để hiển thị trạng thái công cụ và đầu vào người dùng;
- dùng các hook của Apps SDK để đọc ToolInput/ToolOutput và trạng thái widget (widget state);
- cấu hình chế độ hiển thị (inline/fullscreen/PiP, theme, kích thước — ở mức 8);
- tương tác với ChatGPT qua window.openai cho các kịch bản nâng cao (mô‑đun riêng của khoá học).
Trong máy chủ MCP bạn:
- mô tả tools/resources/prompts bằng MCP SDK;
- hiện thực nghiệp vụ của công cụ (về cơ bản là các hàm TypeScript bình thường truy vấn CSDL, API, v.v.);
- tối ưu schema và phản hồi để model dễ “đọc” (ít ảo giác hơn, có cấu trúc hơn).
Trong lớp agent (nếu dùng Agents SDK) bạn:
- mô tả những công cụ agent có thể dùng và mục tiêu của nó;
- cấu hình run‑cycle, bộ nhớ, kiểm soát vòng lặp;
- đảm bảo agent không làm điều vô nghĩa và không sa vào lập kế hoạch vô tận.
Trong ACP/backend bạn:
- hoặc tích hợp với các dịch vụ commerce sẵn có (Stripe, cửa hàng của bạn với product feed, v.v.);
- hoặc thiết kế backend mới hiểu ACP và biết nhận/trả đơn hàng.
Quan trọng: hiếm khi một người làm chủ hoàn toàn tất cả các lớp trong một sản phẩm trưởng thành. Nhưng ở giai đoạn prototype (và trong khoá học này), chúng tôi kỳ vọng bạn hiểu được mã sống ở đâu trong mỗi phần.
11. Kiến trúc ảnh hưởng thế nào tới UX và chính sách nền tảng
Dù chủ đề UX và chính sách là mô‑đun riêng, ngay ở mức kiến trúc đã cần hiểu lựa chọn tách lớp ra sao sẽ ảnh hưởng tới UX và yêu cầu nền tảng. Vậy nên ghi chú trước vài điểm.
Thứ nhất, sandbox. Widget không thể tuỳ tiện truy cập internet và thu thập dữ liệu người dùng — mọi thứ đi qua các công cụ có kiểm soát và quyền hạn được mô tả trong MCP/Store. Nền tảng kỳ vọng bạn mô tả trung thực dữ liệu/hành động App cần, và sẽ dựa vào đó để discovery/đề xuất App.
Thứ hai, luồng UX. Do model có thể tạm “quên” App của bạn hoặc ngược lại đề xuất quá tích cực, kiến trúc cần thân thiện với gián đoạn: nếu agent chưa kịp hoàn tất workflow dài mà người dùng đổi chủ đề, ứng dụng phải xử lý êm. Kịch bản nhiều bước và điều phối workflow trong khoá học này sẽ xây trên MCP‑tools và lớp agent.
Thứ ba, bán hàng. Ngay khi App của bạn bắt đầu thu tiền, các yêu cầu bổ sung về bảo mật, logging, hợp đồng ACP, v.v. có hiệu lực. Cách bạn tách lớp (UI, MCP, Agents, ACP/Backend) ảnh hưởng lớn tới mức “đau” khi trải qua duyệt Store và kiểm toán bảo mật.
Kết luận ban đầu
Hy vọng bạn đã xây được bản đồ tổng quan trong đầu:
- các lớp trên (ChatGPT UI + Apps SDK) quyết định người dùng thấy và cảm nhận App của bạn ra sao;
- lớp giữa (MCP) — cách tiêu chuẩn để cung cấp công cụ và dữ liệu cho model;
- lớp agent và commerce biến App của bạn từ “trình xem dữ liệu” thành sản phẩm hoàn chỉnh với logic và tiền bạc.
Ở mức thứ hai, chúng ta sẽ bắt đầu từ phần thú vị nhất: tải template chính thức của Apps SDK dựa trên Next.js, chạy local và kết nối với ChatGPT ở Dev Mode. Tức là trước hết “chạm tay” vào lớp Apps SDK/widget, còn MCP/agents sẽ tạm thời là stub hoặc backend tích hợp.
Nhưng hãy giữ sơ đồ hiện tại trong đầu ngay bây giờ: giống như nhìn một monorepo và hiểu rằng thư mục apps/ — là UI, services/mcp — là giao thức, services/agent — là bộ điều phối, còn services/commerce — là tiền.
12. Các lỗi thường gặp khi hiểu kiến trúc ngăn xếp
Lỗi số 1: nghĩ rằng ChatGPT App = chỉ là “webhook tới REST API của tôi”.
Đây là thói quen từ thế giới “bot”: model chỉ gửi POST tới URL của tôi, còn lại tuỳ cơ ứng biến. Thực tế, giữa model và mã của bạn có Apps SDK và MCP. Bạn cần mô tả công cụ, schema và hành vi của chúng, chứ không chỉ “nghe” các HTTP request tuỳ ý.
Lỗi số 2: trộn lẫn lớp UI và nghiệp vụ.
Anti‑pattern phổ biến — kéo logic miền phức tạp vào widget, còn lớp MCP chỉ là “miếng đệm mỏng”. Kết quả là UI nặng nề, khó kiểm thử và khó tái sử dụng ngoài ChatGPT. Bền vững hơn là giữ luật lệ và truy cập dữ liệu ở lớp MCP/agent, còn widget chỉ lo hiển thị và tương tác đơn giản.
Lỗi số 3: bỏ qua MCP và viết “giao thức riêng”.
Đôi khi nảy sinh cám dỗ: “cần gì MCP, tôi trả JSON là model tự hiểu”. Trong các demo ngắn điều này có thể “hoạt động”, nhưng bạn mất ngay các khả năng tiêu chuẩn như discovery, inspection, ủy quyền và hỗ trợ nhiều client mà MCP và Apps SDK cung cấp “từ hộp”.
Lỗi số 4: xây cả App quanh một lớp duy nhất.
Có người làm “mọi thứ trong agent”, chất đống trách nhiệm. Có người lại cố nhét hết vào MCP‑tools. Có người dựng một Next.js nguyên khối khổng lồ. Đúng hơn là chấp nhận mỗi lớp có phạm vi trách nhiệm riêng: UI — hiển thị, MCP — truy cập dữ liệu/hành động, agent — điều phối, ACP/Backend — bất biến miền và tiền.
Lỗi số 5: đánh giá thấp ảnh hưởng của kiến trúc tới duyệt Store và bảo mật.
Nếu bạn có một máy chủ vừa là MCP endpoint, vừa là tài nguyên ACP, lưu bí mật và ghi log “nguyên xi”, — quá trình duyệt về bảo mật và chính sách nội dung có thể kéo dài. Kiến trúc tách rời với ranh giới và giao thức rõ ràng giúp cuộc sống dễ dàng hơn nhiều ở giai đoạn sau.
GO TO FULL VERSION