Cách triển khai MCP
Model Context Protocol, sử dụng và xây dựng MCP
MCP, một giao thức mã nguồn mở được phát triển bởi Anthropic, cung cấp một giao diện tiêu chuẩn để kết nối các mô hình LLM với các công cụ, API, dịch vụ đa dạng bên ngoài, qua đó nâng cao đáng kể năng lực của các ứng dụng AI. MCP sử dụng JSON-RPC 2.0 làm nền tảng, giúp nó không phụ thuộc vào ngôn ngữ lập trình và dễ dàng triển khai.
Xây dựng công cụ một lần, sử dụng ở mọi nơi. MCP thống nhất cách AI tương tác với thế giới.
MCP là gì?
MCP (Model Context Protocol) là một giao thức được thiết kế để tiêu chuẩn hóa cách các ứng dụng cung cấp, sử dụng các dịch vụ và hỗ trợ tool-calling cho các mô hình LLM.
Hãy tưởng tượng việc kết nối một laptop với nhiều thiết bị — màn hình, bàn phím, ổ cứng — mà không có cổng chung như USB-C; việc tích hợp sẽ trở nên phức tạp. MCP giải quyết vấn đề tương tự trong AI, một tool được phát triển cho một agent có thể dùng cho bất kỳ agent tương thích MCP nào khác — Claude Desktop, Cursor hoặc bất kỳ nền tảng nào khác.
MCP giảm sự phức tạp trong việc phát triển agent cần nhiều dịch vụ tích hợp và giúp cho việc mở rộng trở nên dễ dàng hơn

Kiến trúc của MCP
MCP có kiến trúc bao gồm ba thành phần chính:
- MCP Host: Ứng dụng AI điều phối và quản lý một hoặc nhiều MCP Client
- MCP Client: Thành phần duy trì kết nối với MCP Server và lấy dịch vụ từ MCP Server để MCP Host sử dụng
- MCP Server: Chương trình cung cấp dịch vụ cho các MCP Client
Lưu ý: MCP Server đề cập đến là một chương trình cung cấp dịch vụ, bất kể nó chạy ở cục bộ hoặc từ xa.
MCP Server
Một MCP Server có thể cung cấp các chức năng thông qua ba thành phần chính:
| Thành phần | Kiểm soát bởi | Mục đích |
|---|---|---|
| Tools | LLM | Một hàm mà LLM có thể gọi một cách chủ động, quyết định dựa trên yêu cầu của người dùng |
| Resources | Ứng dụng | Các nguồn dữ liệu chỉ đọc mà ứng dụng có thể truy xuất và cung cấp cho các agent |
| Prompts | Người dùng | Các mẫu hướng dẫn được xây dựng sẵn hướng dẫn LLM sử dụng các công cụ và tài nguyên cụ thể |
Tool là thành phần phổ biến và quan trọng nhất. Định nghĩa tool sẽ được cung cấp cho LLM để ra quyết định cho việc sử dụng:
name— định danh duy nhất, ví dụ:get_keyword_volumedescription— mô tả cho LLM về chức năng của công cụ và khi nào sử dụng nóinputSchema— JSON Schema định nghĩa các tham số đầu vào (kiểu dữ liệu, giá trị mặc định, enums)annotations— thông tin metadata tuỳ chỉnh về hành vi (readOnlyHint,destructiveHint...)
{
"name": "get_keyword_volume",
"description": "Get monthly search volume for a keyword. Use when you need to evaluate keyword demand for content planning.",
"inputSchema": {
"type": "object",
"properties": {
"keyword": { "type": "string" },
"country": { "type": "string", "default": "vn" }
},
"required": ["keyword"]
}
}
MCP Client
Một MCP Client cung cấp ba tính năng cho MCP Server:
| Tính năng | Mục đích | Tại sao cần thiết |
|---|---|---|
| Roots | Giới hạn không gian thư mục cho các thao tác của server | Ngăn server vượt ngoài ranh giới cho phép |
| Sampling | Cho phép server yêu cầu LLM phía client thực hiện các thao tác cụ thể | Thực thi các agentic workflow mà không cần LLM ở phía server |
| Elicitation | Cho phép server hỏi người dùng các thông tin cần thiết trong khi thực thi | Server có thể thu thập các dữ liệu còn thiếu thay vì báo lỗi |
Transport
MCP định nghĩa hai phương thức transport tiêu chuẩn:
-
stdio — Client khởi chạy server là một tiến trình con trong cùng máy tính. Giao tiếp qua
stdin/stdout. Chỉ hỗ trợ một client duy nhất và không cần kết nối mạng nên sẽ phù hợp cho các dịch vụ cục bộ. Lưu ý: không ghi bất cứ gì khác vàostdout(không dùngprint(),console.log()...) — sử dụngstderrnếu cần log. -
Streamable HTTP — Server cung cấp một HTTP endpoint. Client gửi qua
POST, và server sẽ phản hồi bằng JSON hoặc SSE. Hỗ trợ nhiều client đồng thời nên sẽ phù hợp cho các server từ xa, cloud. Được sử dụng để thay thế cho transportHTTP+SSE.
Sử dụng MCP Server có sẵn
Nên sử dụng MCP Server có sẵn khi:
- Các tính năng phổ biến (filesystem, web fetch...)
- Đã có sẵn server được hỗ trợ tốt
- Không cần các logic doanh nghiệp cụ thể
Một số MCP Server tiêu biểu có thể kể đến như:
| Tính năng | Thư viện | Mục đích |
|---|---|---|
| Filesystem | @modelcontextprotocol/server-filesystem | Các thao tác an toàn với file |
| Memory | @modelcontextprotocol/server-memory | Bộ nhớ graph-based bền vững |
| Fetch | @modelcontextprotocol/server-fetch | Truy xuất nội dung web |
| Everything | @modelcontextprotocol/server-everything | Mẫu với đầy đủ các thành phần của MCP Server |
Nhiều MCP Server chính thức (Brave Search, Slack, GitHub...) cũng đã có sẵn. Ngoài ra, rất nhiều server khác đã được phát triển bởi cộng đồng — có thể tìm kiếm tại MCP Registry.
Xây dựng MCP Server riêng
Nên tự xây dựng MCP Server khi:
- Cần các tool chuyên dụng cho lĩnh vực cụ thể (SEO data, API nội bộ)
- Các server hiện có không đáp ứng đủ nhu cầu
- Cần logic doanh nghiệp cụ thể hoặc bảo mật
Các MCP SDK
Bạn có thể phát triển các MCP Server bằng các ngôn ngữ khác nhau, hỗ trợ bởi các SDK, một trong số đó như:
| Ngôn ngữ | Thư viện | Hỗ trợ bởi |
|---|---|---|
| Python | mcp (FastMCP) | Anthropic |
| TypeScript | @modelcontextprotocol/sdk | Anthropic |
| Go | github.com/modelcontextprotocol/go-sdk |
Ví dụ, một MCP Server đơn giản được xây dựng bởi FastMCP - high-level API trong thư viện mcp của Python:
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("seo-tools")
@mcp.tool()
def get_keyword_volume(keyword: str, country: str = "us") -> dict:
"""Get monthly search volume for a keyword.
Use when you need to evaluate keyword demand for content planning.
Returns volume, trend data, and difficulty score."""
# Thực hiện các logic cụ thể tại đây
return seo_api.get_volume(keyword, country=country)
@mcp.resource("config://settings")
def get_settings() -> str:
"""Current SEO tool configuration."""
return json.dumps(load_settings())
if __name__ == "__main__":
mcp.run() # Sử dụng transport mặc định là stdio
Các điểm chính:
- Tên của hàm sẽ trở thành
namecủa tool - Các kiểu dữ liệu của tham số sẽ tự động tạo ra JSON Schema (
inputSchema) - Docstring trở thành
descriptioncủa tool — LLM đọc mô tả này để quyết định khi nào gọi nó mcp.run()mặc định sử dụng stdio. Truyềntransport="sse"để sử dụng Streamable HTTP
Xây dựng tool
Tool là thành phần cơ bản phổ biến nhất, vì vậy việc thiết kế chúng một cách chính xác là điều quan trọng nhất. Sau đây là các quy tắc để xây dựng các tools một cách hiệu quả.
Tính nhỏ gọn
Mỗi tool nên thực hiện một tác vụ cụ thể một cách tốt nhất. Đừng gộp nhiều tác vụ vào một tool duy nhất — thay vào đó, hãy kết hợp các tool nhỏ lại với nhau.
| Không nên | Nên |
|---|---|
do_seo_analysis (làm tất cả mọi thứ) | get_keyword_volume + get_serp_rankings + compare_competitors |
Đặt tên
Sử dụng quy tắc đặt tên theo verb_noun để LLM (cũng như con người) có thể dễ dàng hiểu tool này để làm gì. name phải có độ dài từ 1 đến 128 ký tự.
- Ví dụ:
search_keywords,get_rankings,analyze_serp,check_ai_overview - Tránh sử dụng các tên chung chung như
do_seohayhelper
Mô tả
description là cách LLM quyết định khi nào nên gọi tool. Nó nên trả lời được ba câu hỏi sau: tool này làm gì, khi nào nên sử dụng nó và nó trả về kết quả gì.
| Không nên | Nên |
|---|---|
| "Gets keyword data" | "Get search volume, difficulty, and related keywords. Use when you need keyword metrics for content planning." |
Tham số
Các tham số được định nghĩa trong inputSchema. Giữ số lượng các tham số bắt buộc ở mức tối thiểu, các tham số tuỳ chọn nâng cao nên có các giá trị mặc định hợp lý.
- Dùng enum cho các giá trị cố định (
mode: "single" | "multiple") - Đặt các giá trị mặc định hợp lý
- Mô tả rõ từng tham số trong
description - Giới hạn đầu vào
Chú thích
annotations là các chú thích cho biết cách một công cụ hoạt động — tính chất chỉ đọc, phá hủy hay tương tác với các hệ thống bên ngoài:
| Chú thích | Ý nghĩa |
|---|---|
readOnlyHint | Tool không làm thay đổi môi trường |
destructiveHint | Tool có thể thực hiện các thao tác mang tính phá hủy |
idempotentHint | Các lần gọi lặp lại với cùng tham số sẽ không gây ảnh hưởng lớn |
openWorldHint | Tool có thể tương tác với các thực thể bên ngoài |
Client sử dụng những gợi ý này để quyết định liệu có cần yêu cầu người dùng xác nhận hay không.
Ví dụ tổng hợp
Đây là một ví dụ áp dụng tất cả các hướng dẫn bên trên:
from enum import Enum
from mcp.server.fastmcp import FastMCP
mcp = FastMCP("seo-tools")
class SearchEngine(Enum):
GOOGLE = "google"
BING = "bing"
@mcp.tool(annotations={"readOnlyHint": True})
def get_keyword_volume(
keyword: str,
engine: SearchEngine = SearchEngine.GOOGLE,
country: str = "us",
) -> dict:
"""Get monthly search volume for a keyword.
Use when you need to evaluate keyword demand for content planning.
Returns volume, trend data, and difficulty score."""
...
@mcp.tool(annotations={"readOnlyHint": True})
def get_serp_rankings(
keyword: str,
limit: int = 10,
) -> dict:
"""Get current SERP rankings for a keyword.
Use when you need to see who ranks and what content types appear.
Returns top results with titles, URLs, and positions."""
...
@mcp.tool(annotations={"readOnlyHint": True, "openWorldHint": True})
def check_ai_overview(keyword: str) -> dict:
"""Check if a keyword triggers an AI Overview in Google.
Use when evaluating whether AI summaries affect organic traffic.
Returns whether AI Overview exists and its content summary."""
...
Xử lý lỗi
Các tool có thể gặp lỗi — sự cố API, chạm rate limit, dữ liệu đầu vào không hợp lệ. Điểm mấu chốt là cần trả về các lỗi giúp mô hình LLM phục hồi một cách trơn tru thay vì làm sập hệ thống agent.
Protocol Error và Tool Error
MCP phân biệt hai mức lỗi:
-
Protocol Error xảy ra khi bản thân request không hợp lệ — tên tool không hợp lệ, các lỗi không được bắt và xử lý. Máy chủ trả về response JSON-RPC lỗi kèm mã lỗi và thông báo lỗi. Client cần xử lý các lỗi.
-
Tool Error xảy ra khi tool đã chạy nhưng thất bại — API timeout, chạm rate limit. Những lỗi này được trả về trong response bình thường với trường
isError: true. LLM đọc kết quả và quyết định các bước tiếp theo.
ToolError của FastMCP sẽ tự động đặt isError: true trong response, do đó LLM có thể xử lý nó:
from mcp.server.fastmcp import FastMCP
from mcp.server.fastmcp.utilities.types import ToolError
mcp = FastMCP("seo-tools")
@mcp.tool()
def get_keyword_volume(keyword: str, country: str = "us") -> dict:
"""Get monthly search volume for a keyword."""
try:
return seo_api.get_volume(keyword, country=country)
except RateLimitError:
raise ToolError(
"Rate limit exceeded. Wait 60 seconds or try fewer keywords."
)
except KeywordNotFoundError:
raise ToolError(
f"Keyword '{keyword}' not found. Try a more common term or check spelling."
)
except APIConnectionError:
raise ToolError(
"SEO API is temporarily unavailable. Try again in a few minutes."
)
Thông báo lỗi
Một thông báo lỗi tốt có thể cho LLM biết cái gì đã xảy ra, có nên thử lại hay không và các hướng thay thế.
| Không nên | Nên |
|---|---|
| "Error" | "Rate limit exceeded. Wait 60 seconds or try fewer keywords." |
| "Failed" | "Keyword not found. Try a more common term or check spelling." |