Hướng dẫn sử dụng mcp tool để tạo event handler thông qua bài viết
Back to graphqlEvent handler có thể được tạo trực tiếp qua MCP tool mà không cần viết Java class hay restart ứng dụng. Cách này phù hợp khi cần bổ sung nhanh một logic phản ứng theo event, hoặc tạo một
ezy function có thể gọi từ Thymeleaf template.Tổng Quan
Một event handler được định nghĩa bởi ba phần chính:
-
eventName: tên event mà handler sẽ xử lý. Giá trị này cũng chính là slug của bản ghi lưu handler. -
summary: JSON mô tả schema của dữ liệu đầu vào và kết quả trả về. -
content: mã Rhino JavaScript sẽ được thực thi khi event được gọi.
Handler chỉ chạy khi application code gọi event tương ứng. Nó không tự động trở thành HTTP API.
flowchart LR
A[AI đọc guide MCP] --> B[Lấy schema summary]
B --> C[Kiểm tra handler đã tồn tại]
C --> D[Viết summary và Rhino JavaScript]
D --> E[Validate handler]
E --> F{User xác nhận?}
F -->|Lưu nháp| G[save_event_handler publish=false]
F -->|Publish| H[save_event_handler publish=true]
H --> I[Handler sẵn sàng chạy khi event được dispatch]
Các MCP Tool Cần Dùng
guide://event-handler-authoringTài liệu contract chính. AI nên đọc resource này trước khi tạo handler.
get_event_handler_summary_schemaTrả về schema hợp lệ cho trường
summary. Lưu ý: schema dùng dataType, itemType, keyType, valueType là tên Java class đầy đủ, ví dụ java.lang.String, java.lang.Long, java.util.Map.list_event_handlersLiệt kê các handler hiện có, gồm cả
DRAFT và PUBLISHED. Bước này bắt buộc để tránh ghi đè nhầm handler cũ.get_event_handler_by_nameLấy chi tiết handler theo
eventName nếu tên đã tồn tại.validate_event_handlerKiểm tra
eventName, summary, content; trả về valid, errors, warnings, và mô tả đã parse từ summary.save_event_handlerLưu handler. Dùng
publish=false để lưu nháp, chỉ dùng publish=true khi người dùng xác nhận muốn publish.install_ezy_functionDùng khi mục tiêu là tạo function gọi được từ Thymeleaf qua
ezyfunctions.call(...). Tool này tự thêm prefix ezy_function_ vào event name.Quy Trình Tạo Event Handler
Bước đầu tiên là đọc guide:
Read resource guide://event-handler-authoring
Sau đó lấy schema summary:
Call get_event_handler_summary_schema
Trước khi đặt tên mới, luôn kiểm tra danh sách handler:
Call list_event_handlers
Nếu
eventName mong muốn đã tồn tại, gọi:Call get_event_handler_by_name with eventName
Sau khi có tên hợp lệ, AI tạo
summary và content, rồi validate:Call validate_event_handler with eventName, summary, content
Nếu hợp lệ, hỏi người dùng muốn lưu nháp hay publish. Khi lưu:
{
"eventName": "fetch_post_by_slug",
"summary": "{...}",
"content": "var slug = eventData.get('slug'); ...",
"publish": false
}
Viết Summary
summary là JSON mô tả handler. Ví dụ:
{
"description": "Fetch a post by slug from event data.",
"argumentSchema": {
"dataType": "java.util.Map",
"name": "eventData",
"required": true,
"fields": [
{
"dataType": "java.lang.String",
"name": "slug",
"required": true,
"description": "The post slug to fetch."
}
]
},
"resultSchema": {
"dataType": "java.util.Map",
"name": "result",
"required": false
},
"examples": [
"{"eventName":"fetch_post_by_slug","eventData":{"slug":"hello-world"}}"
]
}
Điểm quan trọng: event handler summary không dùng
"type": "string" như JSON Schema thông thường. Nó dùng dataType là Java class name đầy đủ.Viết Rhino JavaScript
Event handler chạy trên Rhino, không phải Node.js. Không dùng:
-
require -
import -
async/await - package npm
- API chỉ có trong browser hoặc Node.js
Các biến có sẵn:
-
eventData: payload của event. -
eventName: tên event đang được xử lý. -
content: nội dung script gốc. -
getBean(name): lấy bean theo tên lower camel. -
properties: application properties. -
console,logger: helper ghi log.
Khi đọc dữ liệu từ
eventData, dùng:
var slug = eventData.get('slug');
Không dùng:
var slug = eventData.slug;
Vì
eventData thường là Java Map, dot notation không hoạt động ổn định trong Rhino.Giá Trị Trả Về
Giá trị
return của script trở thành kết quả của event handler.Nếu có nhiều handler cùng
eventName, chúng được chạy theo thứ tự. Handler đầu tiên trả về giá trị khác null sẽ là kết quả cuối. Nếu muốn nhường cho handler sau, trả về null hoặc undefined.Native JavaScript object sẽ được chuyển thành Map, JavaScript array thành List, còn Java object sẽ đi qua cơ chế chuyển đổi của Rhino.
Tạo Ezy Function
Nếu handler cần gọi từ Thymeleaf template, hãy tạo nó như một
ezy function.Cách khuyến nghị là dùng:
install_ezy_function
Ví dụ input:
{
"functionName": "get_collection_categories",
"summary": "{...}",
"content": "...",
"publish": false
}
Tool sẽ lưu event name thực tế là:
ezy_function_get_collection_categories
Nhưng khi gọi trong Thymeleaf, không truyền prefix:
th:with="categories="
Không gọi như sau:
th:with="categories="
Quy tắc dễ nhớ:
Khi lưu: eventName = ezy_function_ + shortName Khi gọi: ezyfunctions.call(shortName)
Prompt Gợi Ý Cho AI
Có thể dùng prompt sau khi muốn AI tạo handler qua MCP:
Bạn là AI hỗ trợ tạo event handler bằng MCP tool.
Hãy làm đúng quy trình:
1. Đọc resource guide://event-handler-authoring.
2. Gọi get_event_handler_summary_schema.
3. Hỏi hoặc tự suy luận xem handler này có cần gọi từ Thymeleaf template như ezy function không.
4. Gọi list_event_handlers để kiểm tra tên đã tồn tại chưa.
5. Nếu tên đã tồn tại, gọi get_event_handler_by_name và hỏi tôi muốn sửa handler đó hay đổi tên.
6. Viết summary JSON đúng schema, dùng dataType là Java class name đầy đủ.
7. Viết content bằng Rhino JavaScript, không dùng Node.js, async/await, require/import hoặc npm package.
8. Luôn dùng eventData.get('key') khi đọc payload.
9. Gọi validate_event_handler.
10. Nếu hợp lệ, hỏi tôi muốn save draft hay publish.
11. Chỉ gọi save_event_handler với publish=true sau khi tôi xác nhận rõ ràng.
Yêu cầu handler:
[Mô tả nghiệp vụ ở đây]
Tên event mong muốn:
[event_name ở đây]
Nếu là ezy function:
Tên function ngắn, không có prefix ezy_function_:
[function_name ở đây]
Lưu Ý Bảo Mật Và Vận Hành
save_event_handler và install_ezy_function yêu cầu quyền admin phù hợp để lưu nội dung handler.Handler đã publish được runtime đọc theo
eventName, nên thay đổi nội dung published có thể ảnh hưởng ngay tới luồng đang gọi event đó.Nên lưu nháp trước, validate kỹ, rồi mới publish. Với handler có truy cập bean hoặc dữ liệu hệ thống, luôn kiểm tra null khi dùng
getBean(name) và giới hạn dữ liệu trả về ở đúng nhu cầu của template hoặc caller.