เปิดใช้งานการเข้าถึงเซิร์ฟเวอร์ MCP ของคุณด้วย AI agent ของบุคคลที่สาม
คู่มือนี้จะแนะนำวิธีผสาน Logto เข้ากับเซิร์ฟเวอร์ MCP ของคุณโดยใช้ mcp-auth เพื่อให้คุณสามารถยืนยันตัวตนผู้ใช้และดึงข้อมูลเอกลักษณ์ของผู้ใช้อย่างปลอดภัยผ่านกระบวนการ OpenID Connect มาตรฐาน
คุณจะได้เรียนรู้วิธี:
- กำหนดค่า Logto เป็นเซิร์ฟเวอร์การอนุญาต (Authorization server) สำหรับเซิร์ฟเวอร์ MCP ของคุณ
- ตั้งค่าเครื่องมือ “whoami” ในเซิร์ฟเวอร์ MCP เพื่อส่งคืนการอ้างสิทธิ์เอกลักษณ์ (identity claims) ของผู้ใช้ปัจจุบัน
- ทดสอบกระบวนการกับ AI agent ของบุคคลที่สาม (MCP client)
หลังจากจบบทเรียนนี้ เซิร์ฟเวอร์ MCP ของคุณจะสามารถ:
- ยืนยันตัวตนผู้ใช้ใน Logto tenant ของคุณ
- ส่งคืนการอ้างสิทธิ์เอกลักษณ์ (
sub,username,name,emailฯลฯ) สำหรับการเรียกใช้เครื่องมือ "whoami"
ความแตกต่างระหว่าง AI agent ของบุคคลที่สาม (MCP client) กับ MCP client ของคุณเอง
ลองดูตัวอย่าง สมมติว่าคุณเป็นนักพัฒนาที่รันเซิร์ฟเวอร์ MCP เพื่อจัดการการเข้าถึงและระบบอีเมลอัตโนมัติ
แอปอีเมลทางการ (MCP client ของคุณเอง)
- คุณมีแอปอีเมลทางการให้ผู้ใช้สำหรับอ่านและจัดการอีเมลของตนเอง
- วิธีการทำงาน: แอปอีเมลทางการเชื่อมต่อกับเซิร์ฟเวอร์ MCP ของคุณโดยใช้ Logto เพื่อยืนยันตัวตนผู้ใช้ เมื่อ Alice ลงชื่อเข้าใช้ เธอจะเข้าถึงอีเมลของตนเองได้ทันทีโดยไม่ต้องมีหน้าขออนุญาตเพิ่มเติม เพราะเป็นแอปที่คุณไว้วางใจ
AI agent ของบุคคลที่สาม (Third-party MCP client)
- คุณกำลังสร้าง ecosystem รอบเซิร์ฟเวอร์ MCP ของคุณ นักพัฒนาคนอื่นจึงสร้าง “SmartMail AI” (ผู้ช่วย AI ที่สรุปอีเมลและนัดหมายอัตโนมัติ) โดยผสานเป็น client ของบุคคลที่สาม
- วิธีการทำงาน: SmartMail AI (third-party MCP client) ต้องการเข้าถึงอีเมลผู้ใช้ผ่านเซิร์ฟเวอร์ MCP ของคุณ เมื่อ Alice ลงชื่อเข้าใช้ SmartMail AI ด้วยบัญชีของเธอ:
- เธอจะเห็นหน้าขอความยินยอม (consent screen) เพื่อขออนุญาตให้ SmartMail AI อ่านอีเมลและปฏิทินของเธอ
- Alice สามารถอนุญาตหรือปฏิเสธการเข้าถึงนี้ได้
- เฉพาะข้อมูลที่ Alice อนุญาตเท่านั้นที่จะถูกแชร์กับ SmartMail AI และ SmartMail AI จะไม่สามารถเข้าถึงข้อมูลอื่นเพิ่มเติมได้หากไม่ได้รับความยินยอมใหม่อย่างชัดเจน
การควบคุมการเข้าถึง (permission) นี้ช่วยให้ข้อมูลผู้ใช้ปลอดภัย แม้เซิร์ฟเวอร์ MCP ของคุณจะจัดการข้อมูลทั้งหมด แต่แอปของบุคคลที่สามอย่าง SmartMail AI จะเข้าถึงได้เฉพาะสิ่งที่ผู้ใช้อนุญาตเท่านั้น ไม่สามารถข้ามขั้นตอนนี้ได้ เพราะถูกบังคับใช้โดยการควบคุมการเข้าถึงของคุณในเซิร์ฟเวอร์ MCP
สรุป
| ประเภท client | ตัวอย่าง | ต้องขอความยินยอม? | ใครควบคุม? |
|---|---|---|---|
| แอปอีเมลทางการ | แอปอีเมลของคุณเอง | ไม่ต้อง | คุณ (นักพัฒนา) |
| AI agent ของบุคคลที่สาม | SmartMail AI assistant | ต้อง | นักพัฒนาคนอื่น |
หากคุณต้องการผสานเซิร์ฟเวอร์ MCP ของคุณกับ AI agent หรือแอปของคุณเอง โปรดดูคู่มือ เปิดใช้งาน auth สำหรับแอปที่ใช้ MCP ของคุณด้วย Logto
ข้อกำหนดเบื้องต้น
- Logto Cloud (หรือแบบ self-hosted) เทนแนนต์
- สภาพแวดล้อม Node.js หรือ Python
ทำความเข้าใจสถาปัตยกรรม
- เซิร์ฟเวอร์ MCP: เซิร์ฟเวอร์ที่เปิดเผยเครื่องมือและทรัพยากรให้กับไคลเอนต์ MCP
- ไคลเอนต์ MCP: ไคลเอนต์ที่ใช้เริ่มต้นโฟลว์การยืนยันตัวตนและทดสอบการเชื่อมต่อ AI agent ของบุคคลที่สามจะถูกใช้เป็นไคลเอนต์ในคู่มือนี้
- Logto: ทำหน้าที่เป็นผู้ให้บริการ OpenID Connect (authorization server) และจัดการข้อมูลระบุตัวตนของผู้ใช้
ไดอะแกรมลำดับ (sequence diagram) ที่ไม่เป็นมาตรฐานนี้แสดงภาพรวมของกระบวนการทั้งหมด:
เนื่องจาก MCP มีการพัฒนาอย่างรวดเร็ว ไดอะแกรมข้างต้นอาจไม่อัปเดตล่าสุดเสมอ โปรดดูเอกสาร mcp-auth สำหรับข้อมูลล่าสุด
กำหนดค่า AI agent ของบุคคลที่สามใน Logto
เพื่อให้ AI agent ของบุคคลที่สามสามารถเข้าถึง เซิร์ฟเวอร์ MCP ได้ คุณต้องตั้งค่า แอปของบุคคลที่สาม ใน Logto แอปนี้จะใช้แทน AI agent และรับข้อมูลประจำตัวที่จำเป็นสำหรับการยืนยันตัวตน (Authentication) และการอนุญาต (Authorization)
แอปของบุคคลที่สาม คือแอปพลิเคชันที่สร้างโดยนักพัฒนาภายนอก (ไม่ใช่เจ้าของทรัพยากร) ซึ่งต้องได้รับความยินยอมจากผู้ใช้เพื่อเข้าถึงทรัพยากรที่ได้รับการปกป้อง แตกต่างจากแอปของเจ้าของ (first-party apps; แอปของคุณเอง) แอปของบุคคลที่สามจะแสดงหน้าขอความยินยอม (consent screen) เพื่อขออนุมัติสิทธิ์เฉพาะก่อนเข้าถึงข้อมูลของผู้ใช้ เพื่อให้แน่ใจว่าผู้ใช้สามารถควบคุมข้อมูลที่จะแชร์กับบริการภายนอกได้
ดูเพิ่มเติมที่ แอปพลิเคชันของบุคคลที่สาม
อนุญาตให้นักพัฒนาสร้างแอปของบุคคลที่สามใน Logto
หากคุณกำลังสร้าง marketplace หรืออยากให้นักพัฒนาสามารถสร้างแอปของบุคคลที่สามใน Logto ได้ คุณสามารถใช้ Logto Management API เพื่อสร้างแอปของบุคคลที่สามแบบโปรแกรมมิ่ง วิธีนี้จะช่วยให้นักพัฒนาสามารถลงทะเบียนแอปพลิเคชันของตนเองและรับข้อมูลประจำตัวที่จำเป็นสำหรับการยืนยันตัวตน
คุณจะต้องโฮสต์บริการของคุณเองเพื่อจัดการกระบวนการลงทะเบียน client โดยบริการนี้จะติดต่อกับ Logto Management API เพื่อสร้างแอปของบุคคลที่สามแทนนักพัฒนา
หรือ คุณสามารถสร้างแอปของบุคคลที่สามใน Logto Console ด้วยตนเองเพื่อทำความคุ้นเคยกับกระบวนการนี้
สร้างแอปของบุคคลที่สามใน Logto ด้วยตนเอง
คุณสามารถสร้างแอปของบุคคลที่สามใน Logto Console ด้วยตนเองเพื่อทดสอบหรือเชื่อมต่อแบบเฉพาะกิจ วิธีนี้เหมาะสำหรับการทดสอบการเชื่อมต่ออย่างรวดเร็วโดยไม่ต้องพัฒนากระบวนการลงทะเบียน client แบบเต็มรูปแบบ
-
ลงชื่อเข้าใช้ Logto Console ของคุณ
-
ไปที่ แอปพลิเคชัน → สร้างแอปพลิเคชัน → แอปของบุคคลที่สาม -> OIDC
-
กรอกชื่อแอปและข้อมูลที่จำเป็นอื่น ๆ จากนั้นคลิก สร้างแอปพลิเคชัน
-
คลิกแท็บ สิทธิ์ (Permissions) ในส่วน ผู้ใช้ (User) คลิก "เพิ่ม"
-
ในกล่องโต้ตอบที่เปิดขึ้น -> ข้อมูลผู้ใช้ (User data) -> เลือกสิทธิ์
profile,emailจากนั้นคลิก บันทึก -
ในแอปของบุคคลที่สาม ให้กำหนดค่า scopes เพื่อขอสิทธิ์
openid profile email(scopes)หมายเหตุ:
openidจำเป็นสำหรับ OIDC และprofileกับemailคือสิทธิ์ที่คุณเพิ่มในขั้นตอนก่อนหน้า -
กำหนดค่า redirect URI ของแอปของบุคคลที่สามของคุณให้ถูกต้อง และอย่าลืมอัปเดต redirect URI ใน Logto ด้วย
เบื้องหลังแล้ว แอปของบุคคลที่สามคือไคลเอนต์มาตรฐานของ OAuth 2.0 / OIDC ซึ่งหมายความว่าคุณ (หรือผู้พัฒนาแอปบุคคลที่สาม) สามารถใช้ไลบรารีหรือเฟรมเวิร์ก OAuth 2.0 / OIDC ใดก็ได้ในการเชื่อมต่อกับ Logto
ข้อควรคำนึงถึง:
- เมื่อสร้างแอปบุคคลที่สาม ให้เลือกประเภทแอปพลิเคชันที่เหมาะสมตามสถาปัตยกรรมของแอป:
- เว็บแบบดั้งเดิม: ใช้ client secret สำหรับการยืนยันตัวตน
- Single page app / Native: ใช้ PKCE เพื่อความปลอดภัยในการอนุญาตโดยไม่ต้องใช้ client secret
- คู่มือเริ่มต้นอย่างรวดเร็วส่วนใหญ่ของเราเขียนสำหรับแอป first-party แต่คุณยังสามารถใช้เป็นข้อมูลอ้างอิงสำหรับการเชื่อมต่อแอปบุคคลที่สามได้
- ความแตกต่างหลักคือแอปบุคคลที่สามจะแสดงหน้าขอความยินยอม (consent screen) เพื่อขออนุญาตจากผู้ใช้ในการเข้าถึงข้อมูลของพวกเขาโดยชัดแจ้ง
ดู แอปพลิเคชันบุคคลที่สาม สำหรับคู่มือการเชื่อมต่อฉบับสมบูรณ์
ตั้งค่าเซิร์ฟเวอร์ MCP
สร้างโปรเจกต์และติดตั้ง dependencies
- Python
- Node.js
mkdir mcp-server
cd mcp-server
uv init # หรือใช้โครงสร้างโปรเจกต์ของคุณเอง
uv add "mcp[cli]" starlette uvicorn mcpauth # หรือใช้ตัวจัดการแพ็กเกจที่คุณต้องการ
mkdir mcp-server
cd mcp-server
npm init -y
npm install @modelcontextprotocol/sdk express mcp-auth # หรือใช้ตัวจัดการแพ็กเกจที่คุณต้องการ
ตั้งค่า MCP auth กับ Logto
อย่าลืมแทนที่ <your-logto-issuer-endpoint> ด้วย issuer endpoint ที่คุณคัดลอกมาก่อนหน้านี้
- Python
- Node.js
ใน whoami.py:
from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config
auth_issuer = '<your-logto-issuer-endpoint>'
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)
ใน whoami.js:
import { MCPAuth, fetchServerConfig } from 'mcp-auth';
const authIssuer = '<your-logto-issuer-endpoint>';
const mcpAuth = new MCPAuth({
server: await fetchServerConfig(authIssuer, { type: 'oidc' }),
});
ดำเนินการตรวจสอบโทเค็น
เนื่องจากเราจะตรวจสอบโทเค็นการเข้าถึง (Access token) และดึงข้อมูลผู้ใช้ เราจึงต้องดำเนินการตรวจสอบโทเค็นการเข้าถึงดังนี้:
- Python
- Node.js
import requests
from mcpauth.types import AuthInfo
def verify_access_token(token: str) -> AuthInfo:
endpoint = auth_server_config.metadata.userinfo_endpoint
response = requests.get(
endpoint,
headers={"Authorization": f"Bearer {token}"},
)
response.raise_for_status()
data = response.json()
return AuthInfo(
token=token,
subject=data.get("sub"),
issuer=auth_server_config.metadata.issuer,
claims=data,
)
const verifyToken = async (token) => {
const { userinfoEndpoint, issuer } = mcpAuth.config.server.metadata;
const response = await fetch(userinfoEndpoint, {
headers: { Authorization: `Bearer ${token}` },
});
if (!response.ok) throw new Error('Token verification failed');
const userInfo = await response.json();
return {
token,
issuer,
subject: userInfo.sub,
claims: userInfo,
};
};
สร้างเครื่องมือ "whoami"
ต่อไป มาสร้างเครื่องมือ "whoami" ที่จะคืนค่าการอ้างสิทธิ์ (claims) ของตัวตนผู้ใช้ปัจจุบัน โดยร้องขอไปยัง userinfo endpoint พร้อมโทเค็นการเข้าถึงที่ส่งมาจาก client
ตัวอย่างนี้ใช้การส่งข้อมูลแบบ SSE เนื่องจาก SDK เวอร์ชันปัจจุบันยังไม่รองรับ Streamable HTTP transport อย่างเป็นทางการ ในทางทฤษฎี คุณสามารถใช้ transport ที่รองรับ HTTP ใดก็ได้
- Python
- Node.js
from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from starlette.middleware import Middleware
mcp = FastMCP("WhoAmI")
@mcp.tool()
def whoami() -> dict:
"""
คืนค่าข้อมูลตัวตนของผู้ใช้ปัจจุบัน
"""
return (
mcp_auth.auth_info.claims
if mcp_auth.auth_info
else {"error": "Not authenticated"}
)
bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
routes=[
mcp_auth.metadata_route(), # ให้บริการ OIDC metadata สำหรับ discovery
Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
],
)
รันเซิร์ฟเวอร์ด้วย:
uvicorn whoami:app --host 0.0.0.0 --port 3001
import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
import express from 'express';
// สร้าง MCP server และลงทะเบียนเครื่องมือ whoami
const server = new McpServer({ name: 'WhoAmI', version: '0.0.0' });
server.tool('whoami', ({ authInfo }) => ({
content: [
{ type: 'text', text: JSON.stringify(authInfo?.claims ?? { error: 'Not authenticated' }) },
],
}));
// Express app & MCP Auth middleware
const app = express();
app.use(mcpAuth.delegatedRouter());
app.use(mcpAuth.bearerAuth(verifyToken));
// SSE transport (ตามเอกสาร SDK)
const transports = {};
app.get('/sse', async (_req, res) => {
const transport = new SSEServerTransport('/messages', res);
transports[transport.sessionId] = transport;
res.on('close', () => delete transports[transport.sessionId]);
await server.connect(transport);
});
app.post('/messages', async (req, res) => {
const sessionId = String(req.query.sessionId);
const transport = transports[sessionId];
if (transport) await transport.handlePostMessage(req, res, req.body);
else res.status(400).send('No transport found for sessionId');
});
app.listen(3001);
รันเซิร์ฟเวอร์ด้วย:
node whoami.js
ทดสอบการผสานระบบ
- เริ่มเซิร์ฟเวอร์ MCP
- เริ่ม AI agent
- ใน client เรียกใช้เครื่องมือ
whoamiเพื่อดึงการอ้างสิทธิ์เอกลักษณ์ของผู้ใช้ปัจจุบัน - client ควรจัดการกับการตอบกลับ 401 Unauthorized และเปลี่ยนเส้นทางผู้ใช้ไปที่ Logto เพื่อยืนยันตัวตน
- หลังจากยืนยันตัวตนสำเร็จ client จะได้รับโทเค็นการเข้าถึง (access token) และใช้สำหรับส่งคำขอไปยังเซิร์ฟเวอร์ MCP
- client ควรสามารถดึงการอ้างสิทธิ์เอกลักษณ์จากเซิร์ฟเวอร์ MCP โดยใช้ access token ได้
- Python
- Node.js
โค้ดเซิร์ฟเวอร์ MCP แบบเต็มสามารถดูได้ที่ mcp-auth/python
โค้ดเซิร์ฟเวอร์ MCP แบบเต็มสามารถดูได้ที่ mcp-auth/js