คู่มือการนำระบบรับรองความถูกต้องของเซิร์ฟเวอร์ MCP ไปใช้: ใช้สเปคเวอร์ชันล่าสุด
ให้ประเด็นสำคัญในการนำระบบรับรองความถูกต้องของเซิร์ฟเวอร์ MCP ให้สอดคล้องกับสเปควันที่ 2025-06-18
ไม่กี่วันที่ผ่านมา (18 มิถุนายน 2025) ทีม MCP (Model Context Protocol) ได้ปล่อย MCP Spec (2025-06-18) เวอร์ชันล่าสุด การอัปเดตนี้มีการเปลี่ยนแปลงสำคัญในส่วน auth โดยเซิร์ฟเวอร์ MCP จะไม่ออก access tokens ในฐานะ Authorization Server อีกต่อไป แต่จะทำหน้าที่ตรวจสอบ access token และให้บริการ resource ในฐานะ Resource Server แทน
ในฐานะผู้ดูแลของ MCP Auth (ไลบรารี auth สำหรับ MCP Server ที่พร้อมใช้งาน) ฉันได้อัปเดตโปรเจกต์นี้ให้รองรับสเปค auth ของ MCP เวอร์ชันล่าสุดแล้ว จากประสบการณ์จริง ฉันจะอธิบายขั้นตอนการนำฟีเจอร์รับรองความถูกต้องตามข้อกำหนดของสเปคล่าสุดมาปรับใช้กับ MCP Server ของคุณ
บทความนี้จะช่วยให้คุณ:
- เข้าใจหลักการทำงานของ MCP auth ภายใต้สเปค auth ใหม่
- ชี้แจงสิ่งที่เซิร์ฟเวอร์ MCP ต้องนำไปใช้ในฐานะ Resource Server ตามข้อกำหนดของ MCP auth spec
- มีแนวทางการติดตั้งระบบรับรองความถูกต้องที่สอดคล้องกับสเปค MCP Auth ล่าสุดในฝั่งเซิร์ฟเวอร์ของคุณ
- ระบุจุดที่มักถูกมองข้ามและปัญหาด้านความปลอดภัยเมื่อใช้งาน MCP auth spec
โปรดทราบว่าบทความนี้:
- สมมติว่าผู้อ่านมีพื้นฐานความเข้าใจเกี่ยวกับ JWT (JSON Web Token) อยู่แล้ว จะไม่อธิบายโครงสร้างหรือการตรวจสอบลายเซ็นต์ JWT รวมถึงแนวคิดพื้นฐานอื่น ๆ อย่างล ะเอียด หากต้องการดูรายละเอียดเพิ่มเติม อ่านที่ Auth Wiki - JWT
- ไม่ลงรายละเอียด RFC ต่าง ๆ ที่ MCP auth spec อ้างอิง แต่อธิบายตัวอย่างตามข้อกำหนดของ RFC เหล่านี้เท่านั้น
- ไม่กล่าวถึงการนำไปใช้และรายละเอียดการโต้ตอบในฝั่ง MCP Client และ Authorization Server เพราะส่วนนี้โดยทั่วไปถูกพัฒนาโดย LLM client หรือผู้ให้บริการ authorization server ที่รองรับ MCP ตามข้อกำหนด MCP Server แค่ทำหน้าที่ฝั่งของตนเอง สำหรับข้อมูลเชิงลึกเพิ่มเติมดูที่ OAuth Client และ Authorization Server
- Access tokens ทั้งหมดที่กล่าวถึงในบทความนี้ หมายถึง JWT format ซึ่งเป็นรูปแบบที่นิยมใช้มากที่สุดในตลาด หากเป็น token อื่น โปรดใช้งานตามคู่มือของผู้ให้บริการ authorization server แต่ละราย
MCP auth ทำงานอย่างไร?
ตาม MCP auth spec เวอร์ชันล่าสุด flow การรับรองความถูกต้องของ MCP สรุปได้ใน diagram ต่อไปนี้:
-
MCP Client ส่งคำขอเพื่อเข้าถึง resource บน MCP Server ที่
https://github-tools.com
เพราะผู้ใช้งานยังไม่ได้เข้าสู่ระบบ HTTP authorization header ของ request นี้จึงยังไม่มี access token ที่แทนตัวตนผู้ใช้ -
MCP Server ไม่พบ access token ใน header ของคำขอจาก MCP Client เซิร์ฟเวอร์จึงตอบกลับด้วย HTTP 401 error และใส่ WWW-Authenticate header ซึ่งประกอบด้วย URL ชี้ไปยัง resource metadata (ค่าของฟิลด์
resource_metadata
) -
MCP Client ดึงค่า
resource_metadata
จาก WWW-Authenticate header (เช่นhttps://github-tools.com/.well-known/oauth-protected-resource
) แล้วขอ resource metadata จาก Server ที่อยู่ภายใต้บทบาท Resource Server Metadata นี้จะระบุเช่นauthorization_servers
และscopes_supported
เพื่อให้ MCP Client ทราบว่าจะขอ token จาก authorization server ไหนและต้องมีสิทธิ์อะไร
4-8. MCP Client ขอ metadata ข้อมูล authorization server จาก URL ที่ได้ในขั้นตอนก่อน จากนั้นทำ OAuth 2.1 flow กับ authorization server และได้รับ access token หลัง authorize สำเร็จ
-
MCP Client ถือ access token ที่ได้มา ส่งคำขอ resource ใหม่ไปยัง MCP Server
-
MCP Server ตรวจสอบ token ว่า valid แล้วจึงตอบกลับ resource ที่ร้องขอ หลังจากนั้นการสื่อสารระหว่าง MCP Client กับ MCP Server จะอยู่ภายใต้ token ที่ผ่านการตรวจสอบแล้ว
ต่อไปจะอธิบายวิธีนำกลไก auth ของ MCP server ไปใช้ทีละขั้นตอนตาม workflow ของ MCP auth
จัดการกับคำขอที่ไม่ authorized : คืนค่า 401 และ WWW-Authenticate Header
ใน flow ด้านบน เมื่อ MCP Client ส่ง request โดยไม่แนบ access token ไป MCP Server ต้องตอบกลับด้วย HTTP 401 Unauthorized และระบุ WWW-Authenticate
header ที่มี URL สำหรับรับ resource metadata ของ server นี้
ตามข้อกำหนด MCP auth spec error handling กรณีที่ MCP Server พบ access token ไม่ถูกต้อง ก็ต้องตอบกลับ 401 error พร้อม WWW-Authenticate
header ด้วยเช่นกัน
หลังรู้แล้วว่าต้องคืน 401 error เมื่อใด จะสร้าง WWW-Authenticate
header อย่างไร?
อ้างอิงจาก RFC9728 Section 5.1 WWW-Authenticate
header จะต้องมีพารามิเตอร์ resource_metadata
ชี้ไปยัง URL ข้อมูล metadata ของ resource นี้
รูปแบบตัวอย่าง:
คำว่า Bearer
คือ authentication scheme ที่แปลว่าการเข้าใช้ resource ที่ได้รับการป้องกันด้วย OAuth 2.0 ต้องใช้ bearer token (ดู: MDN documentation) ส่วนค่าพารามิเตอร์ resource_metadata
คือ URL endpoint ของ resource metadata ที่ MCP Server ของคุณให้บริการ
ตัวอย่างโค้ดจริงทำงานดังนี้:
เมื่อ MCP Client ได้รับ 401 error แบบนี้ จะรู้ว่า endpoint ชี้ไปที่ resource metadata ของ MCP Server จาก header resource_metadata
ต่อไป client จะใช้ metadata นี้เพื่อขอ access token ไปยัง authorization server ที่ระบุใน metadata ต่อไป
ตอนนี้เรารู้แล้วว่าคืนค่า 401 เมื่อไหร่และต้องแนบ URL ของ resource metadata ด้วย แต่ยังไม่รู้ว่า endpoint URL นี้ควรเป็นที่ไหนหรือ metadata มีอะไรบ้าง ดูต่อไปหัวข้อต่อไป
นำกลไก resource metadata discovery มาใช้
ตาม flow MCP auth หลัง MCP Client ได้รับ 401 error ต้องร้องขอข้อมูล resource metadata ต่อทันที ดังนั้น MCP Server ซึ่งทำหน้าที่ Resource Server ควรมี endpoint สำหรับ metadata นี้
กำหนดเส้ นทาง URL ของ metadata endpoint
ในระบบ OAuth ใช้ URL ระบุที่อยู่ของ Resource เรียกว่า "resource indicator" ซึ่งตาม RFC9728 endpoint resource metadata ควรอยู่ที่ path เฉพาะ /.well-known
ถ้า MCP Server ของคุณ (เช่น https://github-tools.com
) มีแค่ service เดียว endpoint metadata ก็เป็น:
หากมี service หลายตัวใน host เดียวกัน แต่ละ service ต้องมี endpoint metadata ของตัวเอง ยกตัวอย่าง https://api.acme-corp.com
ให้บริการ:
https://api.acme-corp.com/github
- เซอร์วิสเชื่อมต่อ GitHubhttps://api.acme-corp.com/slack
- เซอร์วิสเชื่อมต่อ Slackhttps://api.acme-corp.com/database
- บริการฐานข้อมูล
metadata endpoint ของแต่ละ service คือ:
https://api.acme-corp.com/.well-known/oauth-protected-resource/github
https://api.acme-corp.com/.well-known/oauth-protected-resource/slack
https://api.acme-corp.com/.well-known/oauth-protected-resource/database
ข้อดีของการแยกแบบนี้คือ แต่ละ service กำหนด permission scope และ authorization server ต่างกันได้ เช่น
- GitHub ใ ช้ OAuth server ของ GitHub ต้องการสิทธิ์
github:read
,github:write
- Slack ใช้ OAuth server ของ Slack ต้องการ
slack:channels:read
,slack:messages:write
- Database ใช้ authorization server ภายใน ต้องการ
db:query
สรุป url pattern ของ metadata endpoint จะเป็นดังนี้:
สามารถสร้าง endpoint URL จาก resource identifier ได้แบบนี้:
สร้าง response ของ resource metadata
เมื่อได้ endpoint URL แล้ว ต้องให้ path นี้ส่งคืน metadata แบบ JSON ตามข้อกำหนด RFC9728
โดยทั่วไปให้เน้น 4 ฟิลด์หลัก ๆ คือ
resource
- resource identifier ต้องตรงกับ resource address ที่ MCP Client จะใช้authorization_servers
- array ของ authorization server ที่ให้ MCP Client ขอ access token ได้ (MCP auth spec บังคับต้องระบุ)scopes_supported
- รายการ permission scopes ที่ Resource Server รองรับbearer_methods_supported
- วิธีส่ง access token มาที่ server นี้ เช่น["header"]
หมายถึง ส่งใน HTTP Authorization header
ตัวอย่าง metadata ของ https://github-tools.com
MCP Server:
metadata นี้บอกกับ MCP Client ว่า ต้องการเข้าถึง resource https://github-tools.com
ควรขอ access token จาก https://auth.github-tools.com
และควรขอ scope ใดได้บ้าง รวมถึงต้องส่ง token ผ่าน HTTP header
กรณีส่วนใหญ่ ระบุ 4 ฟิลด์นี้ก็เพียงพอแล้ว ถ้าต้องการกำหนดฟิลด์อื่นเพิ่มเติม อ่านรายละเอียดทั้งหมดจาก RFC9728
ตรวจสอบความถูกต้อง access tokens
หลัง MCP Client ได้ access token จาก authorization server ก็จะนำ token นั้นมาเข้าใช้งานกับ MCP Server
เวลาตรวจสอบ access token ที่ MCP Server ต้องใส่ใจประเด็นดังนี้:
- ตรวจสอบ token โดยอ้างอิงจากข้อมูลที่ MCP Server config ไว้ ไม่ใช่ค่าจาก JWT token โดยตรง
- ตรวจสอบ audience ของ token ว่าเป็น resource นี้จริง
- ตรวจสอบ scope ว่าตรงกับสิทธิ์ที่ต้องการ
ตรวจสอบ access token ตาม config MCP Server
เมื่อ MCP Server ได้ access token ซึ่งมีข้อมูล issuer (authorization server) อยู่ นักพัฒนาบางคนอาจเลือกข้อมูลสำหรับตรวจสอบ token โดยใช้ค่า issuer
จาก token ทันที โดยเฉพาะหาก resource metadata ของ MCP Server มีหลาย authorization server เช่น
กรณีนี้มีความเสี่ยงด้านความปลอดภัย หากมีผู้ไม่หวังดีสร้าง authorization server หลอกและออก access token ปลอมระบุ issuer เป็น server หลอกนี้ หา ก MCP Server ใช้ issuer ใน token นี้ไปตรวจสอบกับ server ปลอม จะทำให้ credential ปลอมก็ถูกยอมรับ
วิธีตรวจสอบที่ปลอดภัยควรเป็น:
- ถ้ามี authorization server เดียว ให้ยึด config ฝั่ง backend/server เป็นหลัก
- ถ้ามีหลาย authorization server ให้ดู issuer จาก JWT (ที่ยังไม่ verify) แล้ว cross-check ว่า issuer นี้อยู่ใน config MCP Server หรือไม่ ถ้าไม่มีก็ reject token นั้น
- ทุกครั้งที่ตรวจสอบ token ต้องตรวจสอบ issuer อย่างเข้มงวด
ตัวอย่างใช้ไลบรารี jose ตรวจสอบ JWT:
ตรวจสอบ token audience
ในหัวข้อ Token Audience Binding and Validation ของ MCP auth spec ระบุว่า ตอน client ขอ access token จาก authorization server ต้องระบุ resource
ด้วยว่า token จะนำไปใช้ที่ resource server ไหน (เช่น https://github-tools.com
)
เมื่อ authorization server ออก token ให้ ต้องผูก resource นี้ไว้ใน JWT field aud
(audience) ด้วย
เมื่อ MCP Server รับ access token นี้มา ต้องตรวจสอบว่าค่า audience
ใน JWT ตรงกับ resource identifier ของตนเอง
ตัวอย่างเช่น MCP Server https://github-tools.com
:
กระบวนการนี้สำคัญในการป้องกันการนำ token ที่ได้จาก service อื่นมาใช้กับ MCP Server ของเราโดยมิชอบ
ตรวจสอบ scope
หาก MCP Server ของคุณมีระบบกำหนด permission รายผู้ใช้ หลังจาก access token ผ่านการตรวจสอบเบื้องต้น ต้องเช็คว่า token นี้มี scope ตรงกับสิทธิ์ที่ต้องการ เช่น
ตาม MCP auth spec หาก token ไม่มี scope ที่ resource ต้องการ ต้องตอบกลับด้วย 403 Forbidden
สรุป
หลังอ่านบทความนี้ คุณควรนำไปติดตั้งระบบรับรองความถูกต้องตรงตามสเปคล่าสุดของ MCP Server ได้สำเร็จ ประเด็นสำคัญคือ ตรวจสอบ token อย่างเข้มงวด กำหนดค่า metadata ให้ถูกต้อง และตรวจสอบ audience อย่างเคร่งครัด
ถ้าคุณกำลังสร้าง MCP Server แนะนำให้ลองใช้ไลบรารี MCP Auth ซึ่งทำตามฟีเจอร์ทั้งหมดข้างต้น และช่วยให้คุณผสานฟีเจอร์ auth เข้ากับระบบได้รวดเร็ว
หากมีข้อสงสัย พูดคุยกันได้ใน GitHub มาช่วยกันพัฒนา ecosystem ของ MCP ไปด้วยกัน