MCP server cung cấp một lớp giao tiếp chuẩn JSON-RPC để AI client có thể gọi các công cụ trong hệ thống admin. Với nhu cầu truy vấn dữ liệu, công cụ chính là admin_graphql_data_fetching, dùng để chạy các truy vấn đọc dữ liệu dạng SELECT qua SQL hoặc JPQL.
Thiết kế này giúp AI trả lời các câu hỏi như thống kê, danh sách, báo cáo, đối soát dữ liệu hoặc tra cứu thông tin thực tế từ database, nhưng vẫn đi qua lớp kiểm soát quyền và lớp chặn truy vấn nguy hiểm.

Kiến Trúc Tổng Quát

MCP endpoint nhận request JSON-RPC, kiểm tra request hợp lệ, gắn thông tin admin hiện tại vào params, rồi dispatch sang event handler tương ứng với method hoặc tool được gọi.
flowchart TD
    A[AI client] --> B[MCP endpoint]
    B --> C{JSON-RPC hợp lệ?}
    C -- Không --> D[Trả lỗi JSON-RPC]
    C -- Có --> E[Gắn adminId, roles, access token]
    E --> F[Dispatch theo method]
    F --> G[tools/list]
    F --> H[resources/read]
    F --> I[tools/call]
    I --> J[admin_graphql_data_fetching]
    J --> K[Kiểm tra quyền admin]
    K --> L[Validate query]
    L --> M[Thực thi SQL hoặc JPQL]
    M --> N[Trả content + structuredContent]
MCP server hỗ trợ các nhóm method chính:
  • initialize: trả protocol version, capabilities, server info và instruction tổng quát cho client.
  • tools/list: liệt kê các tool có thể gọi.
  • tools/call: gọi một tool cụ thể.
  • resources/list: liệt kê tài nguyên hướng dẫn.
  • resources/read: đọc nội dung một resource, ví dụ guide truy vấn dữ liệu.
  • ping, prompts/list, prompts/get và một số method phụ trợ khác.

Nguyên Lý Hoạt Động

Khi client gọi initialize, server trả về instruction yêu cầu client đọc guide guide://admin-data-fetching trước khi trả lời các câu hỏi báo cáo hoặc truy vấn database admin.
Guide này định hướng AI theo nguyên tắc: đi từ câu hỏi của người dùng tới một truy vấn SELECT ngắn nhất, đúng nhất, và chỉ tra cứu schema khi thật sự cần.
Luồng chuẩn là:
sequenceDiagram
    participant U as Người dùng
    participant AI as AI client
    participant MCP as MCP server
    participant DB as Database

    U->>AI: Hỏi số liệu, danh sách hoặc báo cáo
    AI->>MCP: resources/read guide://admin-data-fetching
    MCP-->>AI: Hướng dẫn truy vấn dữ liệu
    AI->>MCP: tools/call admin_graphql_data_fetching
    MCP->>MCP: Kiểm tra quyền và validate query
    MCP->>DB: Chạy SELECT SQL/JPQL
    DB-->>MCP: Rows
    MCP-->>AI: structuredContent
    AI-->>U: Trả lời kèm filter và khoảng thời gian đã dùng
Tool admin_graphql_data_fetching nhận các tham số:
{
  "queryType": "SQL",
  "queryString": "SELECT ...",
  "skip": 0,
  "limit": 100
}
Trong đó:
  • queryString là bắt buộc.
  • queryType có thể là SQL hoặc JPQL; nếu bỏ qua thì hệ thống xử lý như SQL.
  • skip mặc định là 0.
  • limit mặc định là 100, tối đa 1000.
Kết quả trả về gồm hai phần:
  • content: bản text JSON để AI đọc.
  • structuredContent: dữ liệu có cấu trúc gồm success, queryType, queryString, skip, limit, rowCount, rows hoặc error.
Các dòng dữ liệu trong rows là mảng giá trị theo đúng thứ tự cột trong câu SELECT, vì vậy prompt nên yêu cầu chọn cột rõ ràng và dùng alias dễ hiểu.

Cơ Chế Bảo Vệ Query

Truy vấn không được chạy trực tiếp một cách tự do. Hệ thống áp dụng nhiều lớp kiểm soát:
  • MCP endpoint yêu cầu admin đã xác thực.
  • Tool truy vấn kiểm tra quyền admin đối với API fetch data.
  • Query bắt buộc phải là một câu SELECT.
  • Không cho phép nhiều statement, dấu ;, comment --, /* */, #.
  • Không cho phép DDL/DML như insert, update, delete, drop, alter, truncate, grant, revoke, v.v.
  • Không cho phép lock clause như for update.
  • Không cho phép truy cập schema hệ thống như information_schema, pg_catalog, mysql, performance_schema, sqlite_master, sys.
  • Không cho phép một số hàm/biểu thức nguy hiểm như sleep, benchmark, load_file, xp_cmdshell.
  • Query dài quá giới hạn sẽ bị từ chối.
  • Query có timeout thực thi.
  • limit bị giới hạn tối đa 1000.
Điểm quan trọng: MCP data fetching là công cụ đọc dữ liệu có kiểm soát, không phải kênh quản trị database tổng quát.

Khi Nào Dùng SQL Và Khi Nào Dùng JPQL

Dùng SQL khi muốn truy vấn trực tiếp theo bảng/cột database.
Ví dụ:
{
  "queryType": "SQL",
  "queryString": "SELECT status, COUNT(*) AS total FROM orders GROUP BY status",
  "skip": 0,
  "limit": 100
}
Dùng JPQL khi muốn truy vấn theo entity JPA và field của entity.
Ví dụ:
{
  "queryType": "JPQL",
  "queryString": "SELECT e.status, COUNT(e.id) FROM Order e GROUP BY e.status",
  "skip": 0,
  "limit": 100
}
Nếu chưa chắc tên bảng/cột hoặc entity/field, không nên đoán quá rộng. Hãy dùng cơ chế SQL scripts bên dưới.

Tra Cứu Schema Bằng SQL Scripts

Hệ thống không khuyến khích AI bắt đầu bằng information_schema, SHOW TABLES hoặc truy vấn metadata database. Những truy vấn đó có thể bị chặn.
Thay vào đó, server cung cấp tool get_sql_scripts. Tool này trả về đường dẫn tải file SQL scripts tổng hợp từ admin và các module đang bật. AI client nên tải file về disk, cache lại, rồi tìm kiếm cục bộ trong file đó để xác định tên bảng/cột.
flowchart TD
    A[Query trực tiếp thất bại vì sai bảng/cột] --> B[Gọi get_sql_scripts]
    B --> C[Tải file SQL scripts về local cache]
    C --> D[Tìm bảng/cột trong file local]
    D --> E[Sửa SELECT]
    E --> F[Gọi lại admin_graphql_data_fetching]
Khi cache SQL scripts, cần lưu kèm serverStartTime. Trước khi tái sử dụng cache ở lần sau, gọi get_server_start_time. Nếu giá trị thay đổi, nên tải lại SQL scripts vì server hoặc module có thể đã được reload.

Hướng Dẫn Viết Prompt

Prompt tốt nên nói rõ mục tiêu dữ liệu, bộ lọc, khoảng thời gian và định dạng trả lời mong muốn.
Ví dụ prompt nên dùng:
Hãy dùng MCP server để thống kê số đơn hàng theo trạng thái trong tháng 7/2026.
Đọc guide admin data fetching nếu cần.
Ưu tiên query SELECT trực tiếp nếu đã biết bảng/cột.
Trả lời kèm query đã dùng, khoảng thời gian lọc và tổng số dòng trả về.
Với câu hỏi có ngày tương đối:
Hãy kiểm tra số user đăng ký hôm qua.
Resolve “hôm qua” thành ngày cụ thể theo timezone hệ thống trước khi query.
Trả lời rõ khoảng thời gian bắt đầu và kết thúc đã dùng.
Với câu hỏi chưa chắc schema:
Hãy lấy danh sách 20 đơn hàng mới nhất gồm id, mã đơn, trạng thái và thời gian tạo.
Nếu query lỗi vì sai bảng hoặc cột, hãy dùng get_sql_scripts, tải/cache file schema, tìm tên bảng/cột đúng rồi thử lại.
Không dùng information_schema hoặc SHOW TABLES.
Prompt nên tránh:
Hãy show toàn bộ database schema.
Chạy thử vài câu SQL cho đến khi ra kết quả.
Dùng information_schema để tìm bảng đơn hàng.

Quy Trình Khuyến Nghị Cho AI Client

Khi nhận câu hỏi truy vấn dữ liệu, AI client nên làm theo thứ tự:
  1. Xác định đối tượng nghiệp vụ: user, order, post, payment, product, v.v.
  2. Xác định filter: trạng thái, loại dữ liệu, ngày tạo, ngày cập nhật, tenant/module nếu có.
  3. Nếu biết query chuẩn, gọi admin_graphql_data_fetching ngay.
  4. Nếu lỗi do sai bảng/cột, đọc structuredContent.error.summarystructuredContent.error.hint.
  5. Chỉ khi cần schema, gọi get_sql_scripts, tải file về cache và tìm local.
  6. Gọi lại tool với query đã sửa.
  7. Trả lời người dùng bằng ngôn ngữ nghiệp vụ, kèm filter, khoảng thời gian và lưu ý nếu dữ liệu bị giới hạn bởi limit.

Ví Dụ Response Mong Muốn

Trong khoảng 2026-07-01 00:00:00 đến 2026-08-01 00:00:00, hệ thống có 245 đơn hàng.

Query đã dùng:
SELECT COUNT(*) AS total FROM orders
WHERE created_at >= '2026-07-01 00:00:00'
  AND created_at < '2026-08-01 00:00:00'

Kết quả trả về 1 dòng.

Giới Hạn Cần Lưu Ý

MCP data fetching không tự hiểu nghiệp vụ nếu prompt thiếu ngữ cảnh. Nếu trạng thái, loại dữ liệu hoặc khoảng thời gian mơ hồ, AI nên hỏi lại hoặc chỉ rõ giả định.
Tool chỉ trả rows theo thứ tự cột, không trả metadata tên cột riêng trong response. Vì vậy query nên chọn cột tường minh và AI cần tự ánh xạ thứ tự cột khi trình bày.
Đây là kênh đọc dữ liệu, không dùng để thay đổi dữ liệu, migrate schema, gọi stored procedure, lock row hoặc khám phá database bằng metadata tables.

Kết Luận

Truy vấn dữ liệu qua MCP server hoạt động theo mô hình: AI client gửi JSON-RPC, MCP server dispatch tới tool đọc dữ liệu, hệ thống kiểm tra quyền và validate query, sau đó trả kết quả có cấu trúc cho AI tổng hợp thành câu trả lời.
Cách dùng hiệu quả nhất là prompt rõ mục tiêu, ưu tiên một câu SELECT ngắn và an toàn, chỉ tra SQL scripts khi thiếu schema, cache schema theo serverStartTime, và luôn trả lời kèm filter/khoảng thời gian đã dùng.