Team bạn có sẵn REST API nội bộ, sếp muốn "mở cho AI agent dùng". Ai đó tìm được tool convert OpenAPI spec sang MCP server, chạy một lệnh, 40 endpoint biến thành 40 tool. Demo chạy được. Hai tuần sau, agent bắt đầu gọi sai tool, trả lời chậm, và hóa đơn token tăng gấp ba. Chuyện này xảy ra ở rất nhiều nơi trong năm qua, vì convert tự động là con đường ngắn nhất — và cũng sai nhất.
MCP giờ đã là chuẩn de facto: SDK đạt khoảng 97 triệu lượt tải mỗi tháng, registry chính thức có gần 9.600 server. Nhưng số lượng server nhiều không có nghĩa là phần lớn được thiết kế đúng. Phần lớn vẫn là REST API đội lốt.
REST phục vụ developer, MCP phục vụ LLM
REST được thiết kế cho người viết code. Nhiều endpoint nhỏ, mỗi cái làm một việc, gọi rẻ, developer đọc docs một lần rồi viết logic ghép chúng lại. GET /orders, GET /orders/{id}, GET /customers/{id}, POST /refunds — chuyện bình thường, thậm chí là best practice.
MCP thì khác về bản chất: mỗi tool definition là token tax. Toàn bộ tên tool, description, JSON schema của tham số đều được nạp vào context window trước khi agent làm bất cứ việc gì. Kết nối 10 MCP server, mỗi server 5 tool, bạn đã đốt hàng nghìn token chỉ để agent "đọc menu" — chưa kể mỗi lượt hội thoại đều trả lại khoản này.
Tệ hơn: LLM chọn tool bằng cách đọc description. 40 tool na ná nhau (get_order, list_orders, get_order_items, get_order_status...) làm model phân vân, chọn nhầm, hoặc gọi 5 lần liên tiếp để ghép dữ liệu mà một developer sẽ ghép trong một hàm. Mỗi lần gọi là một vòng round-trip qua model — chậm và đắt.
| REST API | MCP server | |
|---|---|---|
| Người dùng | Developer | LLM |
| Chi phí mỗi endpoint/tool | Gần như 0 | Token trong mọi context |
| Số lượng lý tưởng | Nhiều, granular | Ít, gom việc |
| Ghép nhiều bước | Developer viết code | Model tự suy luận (đắt, dễ sai) |
| Kết quả trả về | Đầy đủ, máy xử lý | Gọn, model đọc |
Thiết kế theo "việc cần hoàn thành", không mirror CRUD
Câu hỏi đúng không phải "hệ thống mình có resource gì" mà là "agent sẽ được nhờ làm việc gì". Ví dụ hệ thống order nội bộ, thay vì 6 tool CRUD, hãy nghĩ:
- Nhân viên CSKH hỏi: "đơn của khách X đang thế nào, có vấn đề gì không?"
- Việc cần làm: tra đơn theo khách → lấy trạng thái shipping → check ticket liên quan.
Đó là một tool, không phải ba:
{
"name": "investigate_order",
"description": "Tra cứu toàn cảnh một đơn hàng: trạng thái, lịch sử giao vận, và các ticket hỗ trợ liên quan. Dùng khi cần trả lời câu hỏi về tình trạng đơn của khách. Nhận order_id hoặc email khách hàng.",
"inputSchema": {
"type": "object",
"properties": {
"query": { "type": "string", "description": "order_id hoặc email khách" }
},
"required": ["query"]
}
}
Server làm việc gom dữ liệu ở phía sau — gọi 3 REST endpoint nội bộ, join kết quả, cắt bỏ field thừa — rồi trả về một bản tóm gọn. Model nhận một payload sạch thay vì tự orchestrate ba lần gọi với ba response JSON đầy field không ai cần.
Nguyên tắc: logic ghép nối để ở server, không để model suy luận. Model suy luận tốn token và không deterministic; code thì miễn phí và đúng 100 lần như một.
Giữ REST ở đúng chỗ của nó
Đừng hiểu nhầm là MCP thay REST. Sang 2026, setup production phổ biến là chạy song song cả ba lớp trên cùng một data layer:
- REST/gRPC cho batch job, server-to-server, high-throughput — những chỗ không có LLM nào trong vòng lặp, không lý do gì trả token tax.
- SDK cho developer nội bộ viết ứng dụng.
- MCP cho AI agent — một lớp mỏng, task-oriented, gọi xuống chính REST API bên dưới.
Cả WorkOS lẫn Composio đều khuyến nghị hướng hybrid này. MCP server tốt nhất thường chỉ là adapter vài trăm dòng code đứng trước API sẵn có — không phải một hệ thống mới.
graph LR
A[AI Agent] -->|MCP: 5-8 tool task-oriented| M[MCP server<br/>adapter mỏng]
D[Developer app] -->|SDK| R[REST API nội bộ]
B[Batch / cron] -->|REST trực tiếp| R
M --> R
R --> DB[(Data layer)]
Khi tool vẫn quá nhiều: code execution with MCP
Với hệ thống lớn, kể cả thiết kế kỹ vẫn có thể cần vài chục tool. Anthropic công bố pattern "code execution with MCP" cho tình huống này: thay vì nạp mọi tool definition vào context, expose MCP server như một code API — agent viết code (thường TypeScript) import và gọi tool như gọi hàm, khám phá tool khi cần thay vì đọc hết từ đầu.
Kết quả đo được: giảm khoảng 98,7% token, từ 150K xuống còn ~2K cho cùng tác vụ. Block xác nhận mức giảm tương tự khi áp dụng cho Goose ở quy mô toàn công ty. Với hệ thống nội bộ có trên ~20 tool, đây là pattern đáng cân nhắc trước khi nghĩ đến chuyện cắt bớt tính năng.
Checklist thực dụng
Trước khi ship MCP server nội bộ, rà qua:
- Số tool: giữ dưới 10 mỗi server. Nếu vượt, hoặc bạn đang mirror CRUD, hoặc server ôm quá nhiều domain — tách ra.
- Tên tool là động từ + việc:
investigate_order,schedule_maintenance— không phảiget_order_by_id_v2. Tên tự nó phải gợi được khi nào dùng. - Description viết cho model, không phải cho docs. Nói rõ khi nào dùng tool này, input trông thế nào, và khi nào không dùng. Một câu "Returns order data" là vô dụng; model cần biết nó khác
search_orderschỗ nào. - Kết quả trả về gọn. Response REST nội bộ thường 50 field; agent cần 8. Cắt ở server. Mỗi field thừa trả về là token tax nhân với số lần gọi.
- Giới hạn kích thước output. Tool trả 2.000 dòng log sẽ tràn context — phân trang, tóm tắt, hoặc trả về đường dẫn để tool khác đọc tiếp.
- Đừng quên bảo mật. Tool poisoning (giấu chỉ thị trong description) đang là lỗ hổng phổ biến nhất phía client; spec 2026 đã có Enterprise-Managed Authorization và OAuth 2.1 + PKCE — dùng chúng thay vì API key cắm cứng.
Kết
OpenAPI-to-MCP converter trả lời câu hỏi "làm sao expose API cho agent nhanh nhất". Nhưng câu hỏi đúng là "agent cần gì để làm được việc" — và hai câu này gần như không bao giờ có chung đáp án. REST API của bạn là tài sản, cứ giữ; chỉ đừng bắt LLM đọc nó như một developer. Nó không phải developer, và mỗi lần nó giả vờ làm developer, bạn trả tiền cho màn kịch đó.