Khi cần tạo một GraphQL fetcher chỉ dùng trong admin, MCP tool giúp AI agent đi theo một quy trình có kiểm soát: đọc schema, sinh draft, validate, lưu nháp, rồi chỉ publish khi người dùng xác nhận. Fetcher admin chạy trong ngữ cảnh admin panel, có quyền truy cập adminIdadminRoles, và không được xem là fetcher public cho website.

Kiến trúc tổng quát

MCP server của plugin expose endpoint JSON-RPC cho admin. Endpoint này yêu cầu phiên admin đã xác thực, sau đó tự inject thông tin admin vào request trước khi chuyển tiếp tới tool handler.
flowchart TD
    A[AI agent] --> B[MCP JSON-RPC endpoint]
    B --> C[Xác thực admin]
    C --> D[Inject adminId, adminRoles, access token]
    D --> E[tools/list hoặc tools/call]
    E --> F[Tool handler]
    F --> G[Authoring service]
    G --> H[Post-based GraphQL fetcher]
    H --> I[Admin GraphQL runtime]
Điểm quan trọng: agent không tự truyền adminId. MCP server lấy từ phiên admin hiện tại và đưa vào params hoặc arguments.

Fetcher admin khác fetcher public thế nào?

Fetcher admin được lưu bằng post type riêng cho admin và chạy trong admin panel. Nó không được expose qua endpoint GraphQL public của website.
Vì vậy:
  • Dùng create_admin_graphql_fetcher_draft thay vì create_graphql_fetcher_draft.
  • Dùng save_admin_graphql_fetcher thay vì save_graphql_fetcher.
  • Dùng list_admin_graphql_fetchers để kiểm tra trùng slug.
  • Dùng get_admin_graphql_fetcher_by_name khi sửa fetcher admin đã tồn tại.
Fetcher admin nên dùng các service/bean thuộc ngữ cảnh admin. Không trộn bean public vào fetcher admin, vì mỗi ngữ cảnh có rule visibility và quyền khác nhau.

Workflow khuyến nghị

sequenceDiagram
    participant Dev as Người dùng / Agent
    participant MCP as MCP tools
    participant Store as Post storage
    participant GQL as Admin GraphQL runtime

    Dev->>MCP: list_admin_graphql_fetchers
    MCP-->>Dev: Danh sách slug và status
    Dev->>MCP: get_graphql_fetcher_runtime_catalog
    MCP-->>Dev: Runtime globals, bean lookup, quy tắc script
    Dev->>MCP: create_admin_graphql_fetcher_draft
    MCP-->>Dev: summary, content.js, schema preview, example query
    Dev->>MCP: validate_graphql_fetcher
    MCP-->>Dev: errors, warnings, SDL preview
    Dev->>MCP: save_admin_graphql_fetcher publish=false
    MCP->>Store: Lưu draft
    Dev->>MCP: save_admin_graphql_fetcher publish=true
    MCP->>Store: Publish fetcher
    GQL->>Store: Load fetcher đã publish

Các MCP tool cần biết

list_admin_graphql_fetchers
Dùng trước khi tạo fetcher mới. Tool trả về danh sách slug và trạng thái DRAFT hoặc PUBLISHED. Nếu slug đã tồn tại, nên sửa fetcher cũ hoặc đổi slug.
get_graphql_fetcher_runtime_catalog
Trả về contract runtime của JavaScript fetcher: queryArguments, query, requestArguments, queryName, content, getBean(name), properties, logger, cùng các biến riêng theo ngữ cảnh. Với admin fetcher, runtime bổ sung adminIdadminRoles.
get_graphql_fetcher_summary_schema
Cho biết format JSON của phần summary, tức schema mô tả arguments và response của fetcher.
create_admin_graphql_fetcher_draft
Sinh draft gồm slug, group, summary, content, schemaPreview, exampleQuery. Sau khi nhận draft, agent nên lưu local theo cấu trúc:
admin-graphql-fetchers/{slug}/
  content.js
  schema.json
  meta.json
validate_graphql_fetcher
Kiểm tra queryName, summary, content, trả về valid, errors, warnings và SDL preview.
save_admin_graphql_fetcher
Lưu fetcher admin. Dùng publish=false khi còn thử nghiệm. Chỉ dùng publish=true sau khi người dùng xác nhận publish.

Ví dụ tạo draft

Một lời gọi tool có thể truyền ý định nghiệp vụ như sau:
{
  "queryName": "admin_get_order_summary",
  "group": "order",
  "description": "Lấy thông tin tóm tắt đơn hàng cho màn hình admin",
  "arguments": [
    { "name": "orderId", "type": "Long", "description": "ID đơn hàng" }
  ],
  "responseProperties": [
    { "name": "orderId", "type": "Long" },
    { "name": "status", "type": "String" },
    { "name": "totalAmount", "type": "Double" }
  ]
}
Tool sẽ sinh schema JSON, JavaScript skeleton và SDL preview. Agent sau đó chỉnh content.js theo service thật trong admin runtime.

Viết JavaScript fetcher

Trong script, đọc tham số GraphQL bằng queryArguments.get('name'), không dùng dot notation. Runtime dùng Rhino JavaScript và queryArguments là Java Map, nên queryArguments.orderId không đáng tin cậy.
Ví dụ khung xử lý:
var orderId = queryArguments.get('orderId');

if (!adminId || adminId == 0) {
    throw "admin authentication required";
}

if (!adminRoles || !adminRoles.isAccessible("/admin/orders")) {
    throw "permission denied";
}

var orderService = getBean("adminOrderService");
if (!orderService) {
    throw "adminOrderService not found";
}

var order = orderService.getOrderById(orderId.longValue());

({
    orderId: order.getId(),
    status: order.getStatus(),
    totalAmount: order.getTotalAmount()
});

Validate và lưu

Sau khi có summarycontent, gọi validate_graphql_fetcher. Nếu hợp lệ, lưu nháp:
{
  "slug": "admin_get_order_summary",
  "group": "order",
  "summary": "{...}",
  "content": "...",
  "publish": false
}
Khi cần đưa vào runtime GraphQL admin, gọi lại save_admin_graphql_fetcher với publish=true. Chỉ fetcher đã publish mới được provider liệt kê và đăng ký vào GraphQL runtime.
Bổ sung phần này vào bài, nên đặt sau mục Workflow khuyến nghị hoặc trước Ví dụ tạo draft.

Hướng dẫn viết prompt cho AI agent

Khi yêu cầu AI agent tạo GraphQL fetcher admin bằng MCP tool, prompt nên nói rõ 5 nhóm thông tin: fetcher dùng cho admin, mục tiêu nghiệp vụ, input GraphQL, output mong muốn, và quy tắc publish.
Một prompt tốt nên có dạng:
Tạo admin GraphQL fetcher bằng MCP tool.

Fetcher chỉ chạy trong admin panel, không expose ra public /graphql.

Tên query: admin_get_order_summary
Group: order

Mục tiêu:
Lấy thông tin tóm tắt đơn hàng để hiển thị trong màn hình quản trị.

Input:
- orderId: Long, bắt buộc, ID đơn hàng

Output:
- orderId: Long
- status: String
- totalAmount: Double
- customerName: String

Yêu cầu:
- Trước khi tạo, gọi list_admin_graphql_fetchers để kiểm tra trùng slug.
- Gọi get_graphql_fetcher_runtime_catalog trước khi viết JavaScript.
- Nếu cần dùng service/bean, kiểm tra schema trước, không đoán bean name.
- Dùng adminXxx bean, không dùng webXxx bean.
- Trong JavaScript, đọc argument bằng queryArguments.get('orderId').
- Validate bằng validate_graphql_fetcher.
- Lưu bằng save_admin_graphql_fetcher với publish=false.
- Không publish=true nếu chưa hỏi lại tôi.
Với prompt sửa fetcher đã tồn tại:
Sửa admin GraphQL fetcher: admin_get_order_summary.

Yêu cầu:
- Gọi get_admin_graphql_fetcher_by_name để lấy bản hiện tại.
- Giữ nguyên slug và group nếu không cần đổi.
- Bổ sung field response: paymentMethod: String.
- Cập nhật cả schema summary và content.js.
- Validate lại bằng validate_graphql_fetcher.
- Lưu publish=false.
- Không publish nếu chưa có xác nhận.
Với prompt cần truy vấn dữ liệu để hiểu cấu trúc:
Tôi cần tạo admin GraphQL fetcher cho báo cáo đơn hàng.

Trước khi viết fetcher:
- Dùng admin_graphql_data_fetching nếu cần kiểm tra dữ liệu mẫu.
- Chỉ chạy SELECT read-only.
- Giới hạn limit tối đa 20 khi khảo sát.
- Không chạy câu lệnh ghi dữ liệu.

Sau đó tạo draft admin fetcher, validate và lưu draft.
Một prompt nên tránh mơ hồ như:
Tạo fetcher lấy đơn hàng.
Vì agent sẽ không biết fetcher là admin hay public, slug là gì, output gồm những field nào, có được publish hay không, và nên dùng ngữ cảnh service nào.

Bảo mật

MCP endpoint yêu cầu admin đã xác thực. Tool tạo/lưu fetcher admin kiểm tra quyền lưu fetcher trước khi thực thi. Tool query dữ liệu admin cũng kiểm tra quyền riêng trước khi chạy.
Dù vậy, script fetcher vẫn nên tự kiểm tra adminIdadminRoles nếu logic bên trong đụng tới dữ liệu nhạy cảm hoặc chức năng quản trị cụ thể.

Lưu ý

Không dùng admin fetcher cho website public.
Không gọi publish=true như bước mặc định.
Không đoán bean name. Hãy dùng singleton/class schema hoặc runtime catalog để xác minh trước.
Không dùng GraphQL variable declaration kiểu query($id: Long). Custom parser ưu tiên dạng query trực tiếp với biến trong arguments, ví dụ { my_fetcher(id: $id) { * } }.

Kết luận

MCP tool biến việc tạo GraphQL fetcher admin thành một workflow rõ ràng: khám phá runtime, tránh trùng slug, sinh draft, validate schema, lưu nháp và publish có kiểm soát. Thiết kế này đặc biệt hợp với AI agent vì mỗi bước đều có schema đầu vào/đầu ra, có kiểm tra quyền, và có ranh giới rõ giữa fetcher admin nội bộ với fetcher public của website.