Product Management
Đăng nhập
ESC

Nhập từ khóa để tìm kiếm

↑↓ Di chuyển
Enter Mở
ESC Đóng

Bài 4 — Xây MCP server đầu tiên: phơi bày Tool

Đã đọc 0/11 mục · còn khoảng 4 phút
Cách chúng tôi ghi nhận

Một mục được tính là đã đọc khi nó nằm giữa màn hình đủ lâu so với độ dài của nó (bảng và sơ đồ tính một nửa), bạn vẫn đang cuộn hoặc bấm phím, và bạn đã thấy tới cuối mục. Lướt nhanh hoặc để tab mở không được tính. Chúng tôi chỉ lưu thời gian đọc từng mục — không lưu gì khác.

Đến lúc viết code. Bài này bạn dựng một MCP server có một tool get_weather (giả lập), chạy qua stdio. Ta dùng SDK chính thức (ví dụ Python), nhưng ý tưởng áp dụng cho mọi ngôn ngữ.

Bước 1 — Cài đặt và khởi tạo

pip install "mcp[cli]"

Tạo file weather_server.py:

from mcp.server.fastmcp import FastMCP

mcp = FastMCP("weather")  # tên server

FastMCP lo phần handshake, tools/list, JSON-RPC — bạn chỉ tập trung vào logic.

Bước 2 — Định nghĩa một tool

@mcp.tool()
def get_weather(city: str) -> str:
    """Lấy thời tiết hiện tại của một thành phố.

    Args:
        city: Tên thành phố, ví dụ 'Ha Noi'.
    """
    fake = {"Ha Noi": "32°C, nắng", "Da Nang": "29°C, mưa rào"}
    return fake.get(city, "Không có dữ liệu cho thành phố này.")

Ba yếu tố quan trọng để model chọn đúng tool:

  • Tên tool rõ nghĩa (get_weather, không phải gw).
  • Docstring/description mô tả tool làm gì — model đọc cái này để quyết định.
  • Type hint tham số (city: str) → SDK tự sinh JSON Schema cho input, giúp model điền đúng.

Bước 3 — Chạy server

if __name__ == "__main__":
    mcp.run(transport="stdio")

Bước 4 — Đăng ký với host

Thêm vào config host:

{
  "mcpServers": {
    "weather": {
      "command": "python",
      "args": ["/tuyet/doi/weather_server.py"]
    }
  }
}

Khởi động lại host. Agent giờ thấy tool get_weather.

Bước 5 — Kiểm thử độc lập bằng Inspector

Đừng test qua agent ngay — quá nhiều biến. Dùng MCP Inspector:

npx @modelcontextprotocol/inspector python weather_server.py

Inspector mở UI cho bạn: xem tools/list, tự tay gọi get_weather với city="Ha Noi", kiểm tra kết quả JSON. Đây là cách gỡ lỗi nhanh nhất.

Khung tư duy: viết tool cho model đọc, không phải cho người

Mô tả tool là giao diện giữa model và code của bạn. Hãy viết như đang hướng dẫn một đồng nghiệp mới:

  • Tool này làm gì?
  • Khi nào nên dùng nó?
  • Mỗi tham số nghĩa là gì, định dạng ra sao?
  • Trả về cái gì?

Checklist một tool tốt

  • [ ] Tên động từ + danh từ rõ ràng (create_ticket, list_orders).
  • [ ] Description nói rõ mục đích và khi nào dùng.
  • [ ] Mỗi tham số có kiểu và mô tả.
  • [ ] Tool làm một việc (single responsibility).
  • [ ] Trả về text/JSON gọn, có cấu trúc để model diễn giải.
  • [ ] Xử lý lỗi trả message rõ ràng thay vì để văng exception.

Ví dụ xử lý lỗi đúng cách

@mcp.tool()
def get_weather(city: str) -> str:
    if not city.strip():
        return "Lỗi: 'city' rỗng. Hãy cung cấp tên thành phố."
    ...

Trả message lỗi dạng text giúp model tự sửa (hỏi lại người dùng), thay vì làm sập cả lời gọi.

Từ tool giả lập tới tool thật

get_weather trên là giả lập để bạn thấy cơ chế. Trong thực tế, thân hàm sẽ gọi API/database thật. Ba điều cần thêm khi chuyển sang tool thật:

  • Biến môi trường cho cấu hình bí mật: khóa API, chuỗi kết nối lấy từ os.environ, không hardcode. Host truyền vào qua env trong config.
  • Validate và chuẩn hóa input trước khi gọi hệ thống ngoài — model có thể điền tham số sai định dạng.
  • Giới hạn và định dạng output: nếu API trả JSON dài, hãy trích những trường model cần rồi trả lại gọn gàng, thay vì đổ nguyên payload.
Ví dụ tool thật gọn:

@mcp.tool()
def get_weather(city: str) -> str:
    """Thời tiết hiện tại của một thành phố (nguồn: OpenWeather)."""
    key = os.environ["OWM_KEY"]
    r = requests.get(API, params={"q": city, "appid": key}, timeout=5)
    if r.status_code == 404:
        return f"Không tìm thấy thành phố '{city}'."
    d = r.json()
    return f"{d['main']['temp']}°C, {d['weather'][0]['description']}"

Lưu ý timeout=5: một tool không được để agent treo vô hạn vì API chậm. Đây là thói quen bạn nên có ngay từ tool đầu tiên.

Sai lầm thường gặp

  • Docstring qua loa hoặc bỏ trống → model không biết khi nào gọi tool, chọn sai hoặc bỏ qua.
  • Tool đa năng làm 5 việc → khó cho model, khó bảo trì. Tách nhỏ.
  • Trả về khối dữ liệu khổng lồ (cả nghìn dòng) → tốn context, model rối. Lọc/tóm tắt trước khi trả.
  • Test thẳng qua agent thay vì Inspector → không phân biệt được lỗi ở tool hay ở prompt.
  • Để exception văng ra thay vì trả message lỗi thân thiện với model.
Bạn đã có tool đầu tiên. Bài 5 ta thêm Resources — phơi bày dữ liệu chỉ-đọc cho agent làm ngữ cảnh.

Học xong bài này rồi? Tạo tài khoản miễn phí để lưu lại — lần sau vào là biết ngay đang dở ở đâu, và học hết khóa thì có chứng chỉ. Lưu tiến độ của tôi