บันทึกการพัฒนา: MCP, การติดตามอีเมล และโครงสร้างเมนู
วันนี้ผมใช้เวลาไปกับการสร้าง MCP servers, ระบบติดตามอีเมลอัตโนมัติ และเมนูผู้ดูแลระบบที่รองรับการขยายตัว (scalable admin menus)
นี่คือบทเรียนสำคัญที่ได้รับจากการทำงาน
ความปลอดภัยของ MCP Server
ผมได้ปล่อยชุดเครื่องมือ MCP แบบทั่วไป (generic MCP toolbox) และติดตั้งเซิร์ฟเวอร์ในแอปพลิเคชันระดับองค์กรหลายแห่ง เมื่อคุณสร้างเอเจนต์ (agents) ที่สามารถโต้ตอบกับระบบของคุณได้ ให้ปฏิบัติตามกฎเหล่านี้:
- ให้เครื่องมือสำหรับอ่าน (read tools) แก่เอเจนต์ได้อย่างอิสระ
- ให้เครื่องมือสำหรับเขียน (write tools) อย่างจำกัด
- บังคับให้ทุกการดำเนินการเขียนต้องผ่าน runbook ที่มีการตรวจสอบโดยมนุษย์ (human-gated)
- ทำการ Hash รหัสผ่านในเครื่องมือสร้างผู้ใช้ (create-user tools) ห้ามเก็บเป็นข้อความธรรมดา (plaintext) โดยเด็ดขาด
- ใช้ public UUID สำหรับบันทึกการตรวจสอบ (audit logs) ห้ามเปิดเผย ID ภายในฐานข้อมูลโดยเด็ดขาด
- ใช้ fallback สำหรับบริบทของผู้ใช้ (user context) เนื่องจากเอเจนต์อาจใช้ HTTP หรือ STDIO ตรวจสอบให้แน่ใจว่าโค้ดของคุณรองรับทั้งสองแบบ
การติดตามอีเมลโดยไม่ต้องทำงานด้วยตัวเอง
ผมได้สร้างระบบที่ติดตามการเปิดและการคลิกอีเมลโดยอัตโนมัติ อย่าให้เหล่านักพัฒนาต้องมาคอยเพิ่ม tracking pixels ลงในทุกอีเมล แต่ให้ใช้ mail-sending listener แทน
- listener จะดักจับข้อความ
- มันจะฉีด (inject) tracking pixel เข้าไปใน HTML
- มันจะครอบลิงก์ทั้งหมดเพื่อติดตามการคลิก
- มันจะเพิ่ม metadata hash เพื่อให้ง่ายต่อการเชื่อมโยงข้อมูล
หมายเหตุสำคัญสองประการ:
- หลีกเลี่ยง
Mail::raw()เพราะมันจะข้ามขั้นตอนการเขียน HTML ใหม่ (HTML rewriting path) ให้ใช้ HTML Mailables ที่เหมาะสมเพื่อให้แน่ใจว่าการติดตามทำงานได้ - ตั้งค่าการติดตามเป็น "on" โดยค่าเริ่มต้น หากผู้ใช้ต้องเป็นคนเปิดใช้งานเอง พวกเขาก็จะลืม
เมนูผู้ดูแลระบบที่รองรับการขยายตัว
เมื่อคุณต้องจัดการเมนูในหลายแอปพลิเคชัน อย่าใช้ไฟล์ขนาดใหญ่เพียงไฟล์เดียว แต่ให้ใช้ builder classes ขนาดเล็กสำหรับแต่ละกลุ่มแทน
- สร้างหนึ่งคลาสต่อหนึ่งกลุ่ม (เช่น Settings, User Management)
- แต่ละคลาสจะประกาศรายการ (items) และสิทธิ์ที่จำเป็น (required permissions) ของตัวเอง
- วิธีนี้จะทำให้การนำทาง (navigation) ของคุณเป็นแบบ declarative
- ตัดข้อความ (truncate) ป้ายกำกับที่ยาวเกินไปภายในคอมโพเนนต์ ไม่ใช่ตัดแยกตามแต่ละรายการ
- จำกัดการเข้าถึงเครื่องมือด้วยการตรวจสอบสองชั้น: สิทธิ์ของผู้ใช้ และเวอร์ชันของแอปพลิเคชัน (app edition) ที่ใช้งานอยู่
ภาพรวมที่ใหญ่กว่า
เป้าหมายคือการทำให้ "ตาข่ายนิรภัย" (safety net) ทำงานโดยอัตโนมัติ
หากเครื่องมือวินิจฉัย (diagnostic tool) มีประโยชน์ ให้เปิดใช้งานมันเป็นค่าเริ่มต้น หากคุณต้องคอยจำว่าต้องเปิดใช้งานมันเมื่อไหร่ คุณจะไม่มีมันใช้งานในตอนที่ระบบล่มตอนตี 2 จงใส่บทเรียนของคุณลงไปในเครื่องมือ เพื่อที่คุณจะได้ไม่ต้องเสียเวลาเรียนรู้มันใหม่อีกครั้ง