Giới thiệu
Keenable SELECT là một MCP server cho phép agent tìm kiếm web bằng câu lệnh SQL. Thay vì trả về một danh sách link để agent tự đọc toàn bộ, server đưa dữ liệu web vào row set, áp dụng filter và extraction, rồi chạy phần SELECT cuối bằng DuckDB.
Sản phẩm tập trung vào research report có cấu trúc. Mỗi report trong showcase đi kèm kết quả cuối, các query đã chạy, tool result và result set, nhờ đó người đọc có thể xem lại trajectory thay vì chỉ nhận một đoạn tổng hợp.
Tính năng chính
MCP server có hai tool chính:
selectnhận một câu lệnh DuckDB SELECT read-only và trả về các row. Mỗi kết quả được lưu với một ID để query sau có thể dùng lại.generate_html_reportnhận brief và danh sách result-set ID, sau đó tạo report HTML có link chia sẻ.
Các toán tử web và semantic được viết bên trong SQL:
WEB_SEARCHchạy nhiều truy vấn song song, gộp kết quả đã xếp hạng và bỏ URL trùng.WEB_FETCHtải các URL được chỉ định thành Markdown, mỗi trang là một row.SEM_EXTRACTtrích một field từ mỗi row; không tìm thấy thì trả về null.SEM_EXTRACT_ALLlấy danh sách mọi giá trị phù hợp.SEM_MATCHdùng model để kiểm tra một predicate theo nghĩa.SEM_SCOREtạo điểm embedding chi phí thấp để sắp xếp và giới hạn kết quả.SEM_NORMgom các giá trị cùng nghĩa về một key để GROUP BY.
Server parse câu SQL, chạy toán tử web và semantic bên ngoài DuckDB, thay chúng bằng các cột dữ liệu thường rồi mới chạy SELECT cuối. Exact SQL filter được áp dụng trước, nên chỉ những row còn lại mới đi qua toán tử dùng LLM. Cách này có thể giảm số lần gọi model khi điều kiện có thể biểu diễn bằng filter xác định.
WEB_SEARCH và WEB_FETCH cũng có thể nhận giá trị từ từng row. Ví dụ, sau khi có cột tên công ty, query tiếp theo có thể ghép tên đó với cụm “founding year” để tìm năm thành lập cho từng row.
Kiến trúc tạo report
Showcase mô tả hai agent:
- Research agent dùng tool
select, tự viết và chạy query cho đến khi đủ dữ liệu trả lời. Câu hỏi follow-up tiếp tục trên transcript đã lưu. - Report agent nhận brief và các result set, rồi dựng trang trong một Python sandbox có dữ liệu dạng dataframe. Sau mỗi lần publish nháp, server render trang, trả screenshot và số lỗi JavaScript để agent sửa trong một budget cố định. Chỉ bản cuối được giữ ở link công khai.
Việc đưa row trực tiếp vào dataframe giúp model không phải gõ lại dữ liệu khi tạo trang. Tuy vậy, nó không tự bảo đảm dữ liệu đúng: WEB_SEARCH phụ thuộc nguồn tìm được, còn các toán tử SEM_* vẫn dùng model để phân loại và trích xuất.
Cách sử dụng
Một query research phù hợp nên tách phần xác định và phần semantic. Chẳng hạn, để lập danh sách nhà nghiên cứu chuyển giữa các AI lab từ năm 2025:
- Dùng nhiều WEB_SEARCH query để thu nguồn đa dạng.
- Áp dụng filter SQL cho ngày, domain hoặc field có thể kiểm tra chính xác.
- Dùng SEM_MATCH để giữ trang thực sự nói về một lần chuyển việc có tên cụ thể.
- Dùng SEM_EXTRACT cho tên, lab cũ, lab mới và tháng chuyển.
- Giữ URL nguồn trong result set và kiểm tra lại các row quan trọng trước khi viết kết luận.
Khi dùng trong workflow agent, dev nên lưu câu SQL, result-set ID, link nguồn và phiên bản prompt mô tả field. Report nên phân biệt giá trị trích nguyên văn, giá trị do model chuẩn hóa và kết luận do report agent viết.
Điểm cần kiểm tra
Read-only SQL giới hạn thao tác với DuckDB, nhưng không biến semantic operator thành hàm xác định. Trước khi dựa vào kết quả, cần kiểm tra:
- SEM_EXTRACT có trả null ổn định khi nguồn thiếu dữ liệu hay không.
- SEM_NORM có gộp nhầm hai thực thể gần tên hay không.
- WEB_SEARCH có bao phủ nguồn sơ cấp và loại bản sao hay không.
- Report cuối có giữ source trail cho từng claim quan trọng hay không.
- Result set và transcript được lưu bao lâu, ai có quyền truy cập và có chứa dữ liệu nhạy cảm hay không.
Keenable SELECT đáng chú ý vì biến research trajectory thành artifact có thể xem lại và cho phép exact filter chạy trước model. Lợi ích đó chỉ giữ được khi report cuối vẫn liên kết đến row và nguồn gốc, thay vì biến SQL thành lớp vỏ chắc chắn cho một câu trả lời semantic chưa được xác minh.