ข้ามไปที่เนื้อหา

6. การเชื่อมต่อผ่าน Claude (MCP)#

พนักงานทุกคนมี Claude ใช้อยู่แล้ว จึงให้ Claude เป็น ช่องทางหลักในการส่งข้อมูลเข้าระบบ โดยเชื่อมผ่าน MCP server ที่ https://work.keycake.com/mcp

6.1 หลักการออกแบบ#

Claude คือช่องทางกรอก ไม่ใช่แหล่งความจริง

Claude อาจเข้าใจผิด เดาโครงการผิด หรือตีความวันที่ผิด ระบบจึงต้องออกแบบโดย สมมติว่าข้อมูลที่ส่งเข้ามาอาจผิดเสมอ

กติกา 5 ข้อ

  1. ตรวจสอบฝั่งเซิร์ฟเวอร์เสมอ — ห้ามเชื่อค่าที่ Claude ส่งมาโดยไม่ตรวจ
  2. ทุกการเขียนต้องผ่าน 2 จังหวะpreview (สรุปให้ดู) แล้วจึง commit (บันทึกจริง)
  3. เก็บข้อความดิบraw_input ไว้ตรวจย้อนหลังเมื่อข้อมูลดูผิดปกติ
  4. มีเว็บใช้แทนได้เสมอ — วันที่ Claude ล่ม ทีมต้องยังลงเวลาได้
  5. ผูกตัวตนกับคนจริง — ไม่มี token กลาง ทุกคนใช้ token ของตัวเอง

6.2 การยืนยันตัวตน#

sequenceDiagram
    autonumber
    actor U as พนักงาน
    participant W as work.keycake.com
    participant G as Google Workspace
    participant CL as Claude
    participant M as MCP Server

    U->>W: เข้าเว็บครั้งแรก
    W->>G: OAuth (จำกัดโดเมน buildupclick.com)
    G-->>W: ยืนยันตัวตน
    W-->>U: สร้าง Personal Token (แสดงครั้งเดียว)
    U->>CL: ตั้งค่า MCP connector + วาง token
    CL->>M: เรียก tool พร้อม token
    M->>M: ตรวจ token → รู้ว่าเป็นใคร → ตรวจสิทธิ์
    M-->>CL: ผลลัพธ์เฉพาะที่คนนี้มีสิทธิ์เห็น
  • Token ผูกกับพนักงานรายคน เพิกถอนได้ทันทีจากหน้าเว็บ
  • Token หมดอายุอัตโนมัติทุก 180 วัน
  • ทุกการเรียก tool ถูกบันทึกใน audit log พร้อมชื่อคน

6.3 รายการ Tool#

กลุ่มลงเวลา#

Tool ทำอะไร สิทธิ์
log_time ลงเวลาทำงาน (มี confirm เป็น 2 จังหวะ) ทุกคน
get_my_timesheet ดู timesheet ตัวเองตามช่วงวันที่ ทุกคน
delete_time_entry ลบรายการที่ลงผิด (เฉพาะงวดที่ยังไม่ปิด) เจ้าของรายการ
get_missing_days เช็กว่าตัวเองยังไม่ได้ลงเวลาวันไหนบ้าง ทุกคน

กลุ่มกะ · OT · ลา#

Tool ทำอะไร สิทธิ์
get_my_shifts ดูตารางกะตัวเอง ทุกคน
request_ot ขอ OT ทุกคน
request_leave ขอลา ทุกคน
get_my_requests ดูสถานะคำขอของตัวเอง ทุกคน
list_pending_approvals ดูคำขอที่รออนุมัติ lead, executive
approve_request อนุมัติ / ไม่อนุมัติ lead, executive

กลุ่มโครงการ#

Tool ทำอะไร สิทธิ์
list_projects รายชื่อโครงการที่ตัวเองเกี่ยวข้อง ทุกคน
get_project_status สถานะโครงการ + ชั่วโมงสะสม ทุกคน (ไม่เห็นตัวเงิน)
list_my_work_items งานที่ได้รับมอบหมาย ทุกคน
update_work_item อัปเดตสถานะงาน ผู้รับผิดชอบ, ba
create_work_item สร้างงานใหม่ ba, lead

กลุ่มรายงาน (จำกัดสิทธิ์)#

Tool ทำอะไร สิทธิ์
get_project_cost ต้นทุนโครงการเป็นตัวเงิน executive, lead (เฉพาะทีมตัวเอง)
get_client_pnl กำไร-ขาดทุนรายลูกค้า executive
get_team_hours ชั่วโมงรวมของทีม lead, ba, executive

กลุ่มคลังความรู้ (Phase 3)#

Tool ทำอะไร สิทธิ์
search_kb ค้นหาความรู้เชิงความหมาย ทุกคน
create_kb_note บันทึกความรู้ใหม่ ทุกคน

6.4 ตัวอย่างสัญญาของ tool#

{
  "name": "log_time",
  "description": "บันทึกเวลาทำงานของผู้ใช้ปัจจุบัน ต้องเรียกด้วย confirm=false ก่อนเสมอเพื่อให้ผู้ใช้ตรวจสอบ",
  "input_schema": {
    "type": "object",
    "properties": {
      "entries": {
        "type": "array",
        "items": {
          "type": "object",
          "properties": {
            "work_date":    { "type": "string", "format": "date" },
            "project_code": { "type": "string" },
            "hours":        { "type": "number", "multipleOf": 0.5 },
            "kind":         { "enum": ["shift","ot","support","internal","meeting"] },
            "note":         { "type": "string" }
          },
          "required": ["work_date","project_code","hours","kind"]
        }
      },
      "confirm":   { "type": "boolean", "default": false },
      "raw_input": { "type": "string", "description": "ข้อความต้นฉบับที่ผู้ใช้พิมพ์" }
    },
    "required": ["entries","raw_input"]
  }
}

ผลลัพธ์เมื่อ confirm=false — คืนสรุปที่อ่านง่ายให้ผู้ใช้ตรวจ พร้อมคำเตือนถ้ามี เช่น "ชั่วโมงรวมวันนี้ 11 ชม. เกินเวลากะปกติ 8 ชม. — ต้องมีใบ OT หรือไม่?"

ผลลัพธ์เมื่อ confirm=true — บันทึกจริง คืน id ของแต่ละรายการ

{
  "name": "request_ot",
  "input_schema": {
    "type": "object",
    "properties": {
      "ot_date":      { "type": "string", "format": "date" },
      "hours":        { "type": "number", "multipleOf": 0.5 },
      "project_code": { "type": "string" },
      "reason":       { "type": "string", "minLength": 10 },
      "confirm":      { "type": "boolean", "default": false }
    },
    "required": ["ot_date","hours","project_code","reason"]
  }
}

ระบบตรวจก่อนรับ: ชนกะเดิมหรือไม่ · เกินเพดาน OT ของเดือนหรือไม่ · โครงการมีอยู่จริงหรือไม่ เมื่อสร้างสำเร็จ ระบบส่งแจ้งเตือนหาหัวหน้างานใน Google Chat

6.5 การตรวจสอบที่ต้องทำฝั่งเซิร์ฟเวอร์#

ทุกครั้งที่ log_time ถูกเรียกด้วย confirm=true:

ลำดับ ตรวจอะไร ถ้าไม่ผ่าน
1 Token ใช้ได้และยังไม่หมดอายุ ปฏิเสธ 401
2 project_code มีอยู่จริงและยัง active ปฏิเสธพร้อมรายชื่อโครงการที่ใกล้เคียง
3 work_date ไม่เกิน 7 วันย้อนหลัง และไม่เป็นอนาคต ปฏิเสธ + แนะให้ขออนุมัติจากหัวหน้า
4 งวดของวันนั้นยัง open ปฏิเสธ — งวดปิดแล้ว
5 kind = 'ot' → ต้องมีใบ OT ที่อนุมัติแล้วครอบคลุมวัน+ชั่วโมงนั้น ปฏิเสธ
6 ชั่วโมงรวมของวันนั้น ≤ 16 ปฏิเสธ
7 ไม่ซ้ำกับรายการเดิม คืนรายการเดิม ไม่สร้างซ้ำ

ข้อความ error ต้องบอกวิธีแก้

Claude จะอ่าน error แล้วอธิบายให้ผู้ใช้ต่อ ดังนั้นแทนที่จะคืน "invalid project" ให้คืน "ไม่พบโครงการรหัส LSM-MEM — โครงการที่ใกล้เคียงคือ LSM-MEMBER (ระบบสมาชิก LSM99)"

6.6 สิ่งที่ Claude ห้าม ทำ#

  • ❌ อนุมัติ OT หรือลาแทนหัวหน้างานโดยอัตโนมัติ (ต้องเป็นการกระทำของหัวหน้างานเอง)
  • ❌ แก้ไขข้อมูลของพนักงานคนอื่น
  • ❌ เปิดเผยเงินเดือนหรือ cost_rate ให้บทบาทที่ไม่มีสิทธิ์
  • ❌ ลบข้อมูลถาวร (มีแต่การทำเครื่องหมายยกเลิก)
  • ❌ บันทึกข้อมูลโดยไม่ให้ผู้ใช้ยืนยัน