Claude Certification Guide

MCP Server được giải thích: Model Context Protocol hoạt động như thế nào

18 tháng 3, 2026 · 11 phút đọc

MCP là một giao thức cho phép Claude giao tiếp với các tool và nguồn dữ liệu bên ngoài. Database, API, hệ thống file, dịch vụ bên thứ ba. Bạn xây dựng một MCP server, và bất kỳ client tương thích nào cũng có thể kết nối tới nó. Không còn phải viết code tích hợp tùy chỉnh cho mỗi dịch vụ bạn muốn mô hình truy cập.

Nếu bạn đang dùng API, Claude Code, hoặc ứng dụng desktop, MCP chính là cách bạn trao cho Claude những khả năng vượt ra ngoài việc sinh văn bản. Nội dung dưới đây bao gồm kiến trúc, một cách triển khai server hoạt động thực tế, và các mẫu hình cụ thể mà bài thi Claude Certified Architect hay kiểm tra.

Kiến trúc

MCP dùng mô hình client-server xây dựng quanh ba yếu tố cơ bản:

Resource là dữ liệu mà server phơi bày để đọc. Hãy nghĩ đến các endpoint GET: schema database, nội dung một file, một đối tượng config. Chỉ đọc.

Tool là các hàm mà mô hình có thể gọi. Chúng thực hiện hành động: truy vấn database, tạo file, gửi tin nhắn. Mỗi tool có một schema input và trả về kết quả có cấu trúc.

Prompt là các mẫu có thể tái sử dụng mà server cung cấp. Bạn sẽ thấy chúng ít xuất hiện hơn resource và tool, nhưng chúng hữu ích để chuẩn hóa cách mô hình giao tiếp với một domain cụ thể.

Sau đó là tầng transport. MCP hỗ trợ hai tùy chọn:

  • stdio chạy server dưới dạng subprocess, giao tiếp qua stdin/stdout. Đây là cách Claude Code và ứng dụng desktop chạy các server cục bộ.
  • HTTP với SSE chạy server dưới dạng một web service. Request đi qua HTTP, phản hồi được stream trả về qua Server-Sent Events. Bạn sẽ dùng cách này cho các triển khai từ xa.

Xây dựng một MCP server

Đây là một server Python tối giản dùng FastMCP với một tool và một resource:

pythonCopy

from mcp.server.fastmcp import FastMCP
 
mcp = FastMCP("demo-server")
 
@mcp.resource("config://app")
def get_config() -> str:
    """Return the application configuration."""
    return '{"version": "1.2.0", "environment": "production"}'
 
@mcp.tool()
def calculate_discount(price: float, percentage: float) -> float:
    """Calculate a discounted price.
 
    Args:
        price: The original price in GBP.
        percentage: The discount percentage (0-100).
 
    Returns:
        The price after discount.
    """
    if not 0 <= percentage <= 100:
        raise ValueError("Percentage must be between 0 and 100")
    return round(price * (1 - percentage / 100), 2)
 
if __name__ == "__main__":
    mcp.run(transport="stdio")

Hãy chú ý đến định nghĩa tool. Có hai điều quan trọng ở đây:

  1. Mô tả gánh vác phần việc nặng nhất. Claude đọc nó để quyết định có gọi tool này hay không. Một mô tả mơ hồ kiểu "tính toán các thứ" sẽ gây ra định tuyến sai. "Tính giá sau khi giảm" cộng với mô tả tham số có kiểu dữ liệu rõ ràng cho mô hình đủ thông tin nó cần.

  2. Xác thực nằm ngay bên trong tool. Server kiểm tra percentage có nằm trong khoảng 0-100 hay không và báo lỗi rõ ràng nếu không. Claude nhận được lỗi đó và có thể tự điều chỉnh.

Mô tả rõ ràng, input đã được xác thực, output có cấu trúc. Đó là mẫu hình, và đó cũng là những gì bài thi kiểm tra trong Task 2.1 — Thiết kế Schema Tool.

Mô tả tool quyết định việc lựa chọn tool

Đây là khái niệm MCP được kiểm tra nhiều nhất trong bài thi. Và vấn đề cốt lõi khá đơn giản: nếu hai tool có mô tả mơ hồ, chồng lấn nhau, Claude không thể chọn đúng tool một cách đáng tin cậy.

Mô tả tệ (gây định tuyến sai):

pythonCopy

@mcp.tool()
def get_customer(identifier: str) -> dict:
    """Retrieves customer information."""
    ...
 
@mcp.tool()
def lookup_order(identifier: str) -> dict:
    """Retrieves order details."""
    ...

Một người dùng hỏi "kiểm tra đơn hàng #12345 của tôi" và Claude gọi get_customer. Tại sao? Cả hai mô tả nói về gần như cùng một thứ. Mô hình đang phải đoán.

Mô tả tốt (định tuyến đáng tin cậy):

pythonCopy

@mcp.tool()
def get_customer(customer_id: str) -> dict:
    """Look up a customer profile by customer ID.
 
    Use this tool when the user asks about their account details,
    contact information, subscription status, or loyalty points.
 
    Input: A customer ID in the format CUST-XXXXX.
    Do NOT use this for order-related queries — use lookup_order instead.
    """
    ...
 
@mcp.tool()
def lookup_order(order_id: str) -> dict:
    """Look up an order by order number.
 
    Use this tool when the user asks about an order status, shipment
    tracking, delivery date, or order contents.
 
    Input: An order number in the format #XXXXX or ORD-XXXXX.
    Do NOT use this for customer profile queries — use get_customer instead.
    """
    ...

Chú ý những gì đã thay đổi. Mỗi mô tả giờ đây nói rõ tool làm gì, mong đợi định dạng input nào, khi nào nên dùng nó, và khi nào không nên dùng. Phần cuối cùng đó hiệu quả đến bất ngờ. Bảo mô hình "đừng dùng cái này cho X, hãy dùng Y thay thế" xóa bỏ hoàn toàn sự mơ hồ trong định tuyến.

Tích hợp MCP client

Kết nối một MCP server với Claude Code chỉ đơn giản là một mục cấu hình:

jsonCopy

{
  "mcpServers": {
    "demo-server": {
      "command": "python",
      "args": ["path/to/server.py"],
      "env": {}
    }
  }
}

Với API, luồng xử lý phức tạp hơn một chút. Client của bạn:

  1. Kết nối đến MCP server
  2. Khám phá các tool khả dụng qua phương thức tools/list
  3. Chuyển đổi schema tool của MCP sang định dạng mà Messages API mong đợi
  4. Truyền chúng vào tham số tools khi thực hiện request

Nếu quy trình bắt tay bốn bước đó vẫn chưa rõ, hãy làm qua nó với code thực tế. Bài thi kiểm tra nội dung này trong Task 2.3 — Tích hợp MCP Client.

Xử lý lỗi trong tool MCP

Tool có thể hỏng. Mạng rớt, API bị giới hạn tốc độ, người dùng gửi input vô nghĩa. Các tool MCP của bạn cần trả về thông tin lỗi mà mô hình thực sự có thể hành động dựa trên đó:

pythonCopy

@mcp.tool()
def query_database(sql: str) -> str:
    """Execute a read-only SQL query against the analytics database.
 
    Args:
        sql: A SELECT query. INSERT, UPDATE, DELETE are rejected.
    """
    if not sql.strip().upper().startswith("SELECT"):
        return "Error: Only SELECT queries are allowed. Received a non-SELECT statement."
 
    try:
        result = db.execute(sql)
        return json.dumps(result.rows)
    except DatabaseError as e:
        return f"Error: Query failed — {e}. Check table and column names against the schema."

Bạn có thấy mỗi thông báo lỗi cho mô hình biết chuyện gì đã xảy ra và nên thử gì tiếp theo không? Đó là sự khác biệt giữa một tool mà Claude có thể phục hồi được và một tool đẩy nó vào vòng lặp retry vô tận. "Đã xảy ra lỗi" không cho mô hình biết gì cả. "Chỉ cho phép truy vấn SELECT" cho nó một hướng khắc phục.

Mẫu hình này được đề cập trong Task 2.4 — Xử lý lỗi Tool.

Khi nào nên tách tool

Bạn nên xây dựng một tool lớn xử lý nhiều thao tác, hay nhiều tool tập trung riêng biệt? Bài thi có quan điểm rõ ràng về chuyện này.

Nên tách khi:

  • Một tool "gộp tất cả" như analyze_document đang được gọi cho những công việc về bản chất hoàn toàn khác nhau (trích xuất, tóm tắt, xác minh)
  • Mô tả cứ phải dùng "hoặc" để bao quát các trường hợp sử dụng
  • Các thao tác khác nhau cần schema input khác nhau

Vậy nên analyze_document trở thành extract_data_points, summarize_content, và verify_claim_against_source. Mỗi tool nhận một mô tả chặt chẽ, không mơ hồ.

Không nên tách khi:

  • Các thao tác liên quan chặt chẽ với nhau và nhận cùng một input
  • Việc tách ra sẽ tạo ra các tool có mô tả gần như giống hệt nhau (bạn chỉ vừa mới chuyển vấn đề định tuyến sang chỗ khác)
  • Bạn sẽ có quá nhiều tool khiến mô hình khó chọn lựa giữa chúng

Các mẫu hình cần chú ý trong bài thi

Năm điều xuất hiện lặp đi lặp lại:

  1. "Bước đầu tiên hiệu quả nhất là gì?" Gần như luôn là: cải thiện mô tả tool. Bộ phân loại định tuyến, gộp tool, ví dụ few-shot đều là các lựa chọn hợp lệ, nhưng chúng tốn công sức hơn và bài thi muốn bạn tìm đến cách khắc phục đơn giản nhất trước tiên.

  2. Tình huống về chất lượng mô tả. Bạn sẽ gặp một tình huống trong đó hai tool bị định tuyến sai và cần xác định mô tả mơ hồ là nguyên nhân gốc rễ. Hãy nắm vững mẫu hình từ các ví dụ trên.

  3. Lựa chọn transport. stdio cho việc dùng cục bộ/subprocess. HTTP+SSE cho dịch vụ từ xa. Chỉ vậy thôi.

  4. Tool so với Resource. Tool có tác dụng phụ (side effect). Resource chỉ đọc. Bài thi kiểm tra xem bạn có phân biệt được cái nào là cái nào không.

  5. Xung đột với system prompt. Các chỉ thị nhạy với từ khóa trong system prompt có thể ghi đè lên các mô tả tool được viết tốt. Bài thi muốn bạn nhận ra khi nào một system prompt đang xung đột với thiết kế tool của bạn.

Đào sâu vào toàn bộ lĩnh vực Thiết kế Tool & MCP cho cả năm nội dung nhiệm vụ, hoặc chuyển thẳng đến câu hỏi luyện tập để xem bạn đang ở đâu.