Client Interaction
server ไม่ได้มีคำตอบเสมอไป
หัวข้อที่มีชื่อว่า “server ไม่ได้มีคำตอบเสมอไป”MCP ส่วนใหญ่ไหลทางเดียว: client ถาม server ตอบ tools/list, tools/call, resources/read — request เข้า result ออก แต่ tool ของจริงบางทีก็ไปเจอทางตันกลางทาง:
- ต้องให้คนตัดสินใจ “จองโต๊ะ 4 หรือ 6 ที่?” “จะ deploy ไป region ไหน?” มีแค่ผู้ใช้เท่านั้นที่ตอบได้
- ต้องใช้ secret ที่ server ไม่ควรเห็นแบบ plain text API key ของ service ภายนอก, การอนุมัติจ่ายเงิน, OAuth consent
- ใช้เวลานานเกินกว่าที่ HTTP request เดียวจะเปิดค้างไว้ได้ CI pipeline, bulk import, งานที่ต้องรอ approval
ทุกกรณีข้างต้น server ต้องการอะไรบางอย่างจาก client — แต่ MCP เป็น protocol ที่ stateless และขับเคลื่อนโดย client การตัดสินใจออกแบบข้อเดียวนี้กำหนดรูปร่างของทุกอย่างใน module นี้
ข้อจำกัด: ไม่มี request ที่ server เป็นฝ่ายเริ่ม
หัวข้อที่มีชื่อว่า “ข้อจำกัด: ไม่มี request ที่ server เป็นฝ่ายเริ่ม”ใน revision 2026-07-28 MCP เป็น stateless: ทุก request แบกทุกอย่างที่ server ต้องใช้ไว้ใน _meta และ server ห้ามอนุมานอะไรจาก request ก่อนหน้าบน connection เดียวกัน ผลข้างเคียงที่ทำให้คนที่มาจากยุคเก่า (2025-11-25 และก่อนหน้า) แปลกใจคือ server ส่ง JSON-RPC request ของตัวเองไปหา client ไม่ได้อีกแล้ว ไม่มี channel เปิดค้างที่ elicitation/create หรือ sampling/createMessage จะวิ่งย้อนขึ้นไปได้
sequenceDiagram participant U as User participant C as Client participant S as Server C->>S: tools/call (id 1) Note over S: ต้องให้ผู้ใช้เลือก region S-->>C: InputRequiredResult (inputRequests, requestState) C->>U: form: เลือก region U-->>C: eu-west-1 C->>S: tools/call (id 2, args เดิม + inputResponses + requestState) S-->>C: final result
ดังนั้นแทนที่จะ ส่ง request server จะ return result ที่ขอ input client ไปรวบรวมคำตอบมาแล้ว retry request เดิม พร้อมแนบคำตอบไปด้วย นี่คือ pattern Multi Round-Trip Requests (MRTR) และเป็นกระดูกสันหลังของทุกอย่างด้านล่าง
module นี้ครอบคลุมอะไร
หัวข้อที่มีชื่อว่า “module นี้ครอบคลุมอะไร”| บทเรียน | กลไก | แก้ปัญหา |
|---|---|---|
| MRTR | InputRequiredResult → retry พร้อม inputResponses | คำถามจาก server ไป client แบบใดก็ได้ โดยไม่ต้องมี state ฝั่ง server |
| Elicitation | elicitation/create แบบ form หรือ URL | ขอข้อมูลหรือ consent จากผู้ใช้ |
| Progress & cancellation | notifications/progress, notifications/cancelled, ปิด stream | ให้ call ที่ยาวยังมีชีวิตอยู่และหยุดได้ |
| Tasks extension | resultType: "task", tasks/get, tasks/update | งานที่อยู่นานกว่า request |
| Deprecated features | sampling, roots, logging | ควรใช้อะไรแทน |
”รอ” มีสองแบบ
หัวข้อที่มีชื่อว่า “”รอ” มีสองแบบ”จะเข้าใจง่ายขึ้นถ้าแยกตาม ใคร ที่ server กำลังรอ:
- รอผู้ใช้ — elicitation คำตอบมาจากคน ผ่าน UI ของ client ภายใต้ MRTR server ไม่ได้รอเลย: มัน return ออกไป แล้ว retry จะพาคำตอบกลับมา
- รอเวลา — operation ที่รันนาน ส่วนที่เปราะบางคือ connection progress notification ช่วยให้ request เดียวยังมีชีวิตและซื่อสัตย์ ส่วน Tasks extension เปลี่ยนงานให้เป็น handle ที่คงทน poll ได้แม้หลัง reconnect
ทั้งสองแบบทำให้ server ไม่ต้องเก็บ state ต่อ connection state จะเดินทางไปกับ request (requestState) หรือไม่ก็เป็น identifier ชัด ๆ (taskId) ที่ client ส่งมาทุก call
อะไรถูกปลดระวาง
หัวข้อที่มีชื่อว่า “อะไรถูกปลดระวาง”feature ฝั่ง client สามตัวถูก deprecate ใน 2026-07-28 (SEP-2577): sampling (server ขอ completion จาก LLM ของ host), roots (server ถามว่าแตะ directory ไหนได้บ้าง) และ logging (server push log line) ยังใช้ได้ระหว่างช่วง deprecation แต่ server ใหม่ไม่ควรเอามาใช้ บทเรียนสุดท้ายอธิบายว่าทำไมและอะไรมาแทนแต่ละตัว