เปิดใช้งาน auth สำหรับแอปที่ใช้ MCP ของคุณด้วย Logto
คู่มือนี้จะแนะนำวิธีการผสาน Logto เข้ากับเซิร์ฟเวอร์ MCP ของคุณโดยใช้ mcp-auth เพื่อให้คุณสามารถยืนยันตัวตนผู้ใช้และดึงข้อมูลอัตลักษณ์ของพวกเขาอย่างปลอดภัยด้วยกระบวนการมาตรฐาน OpenID Connect
คุณจะได้เรียนรู้วิธี:
- กำหนดค่า Logto เป็นเซิร์ฟเวอร์การอนุญาต (authorization server) สำหรับเซิร์ฟเวอร์ MCP ของคุณ
- ตั้งค่าเครื่องมือ “whoami” ในเซิร์ฟเวอร์ MCP เพื่อส่งคืนการอ้างสิทธิ์ของอัตลักษณ์ผู้ใช้ปัจจุบัน
- ทดสอบกระบวนการด้วย MCP Inspector (MCP client)
หลังจากจบบทเรียนนี้ เซิร์ฟเวอร์ MCP ของคุณจะสามารถ:
- ยืนยันตัวตนผู้ใช้ใน Logto tenant ของคุณ
- ส่งคืนการอ้างสิทธิ์ของอัตลักษณ์ (
sub
,username
,name
,email
ฯลฯ) สำหรับการเรียกใช้เครื่องมือ "whoami"
เมื่อผสานการทำงานเสร็จสมบูรณ์ คุณสามารถแทนที่ MCP Inspector ด้วย MCP client ของคุณเอง เช่น เว็บแอป เพื่อเข้าถึงเครื่องมือและทรัพยากรที่เซิร์ฟเวอร์ MCP ของคุณเปิดเผย
ข้อกำหนดเบื้องต้น
- Logto Cloud (หรือแบบ self-hosted) เทนแนนต์
- สภาพแวดล้อม Node.js หรือ Python
ทำความเข้าใจสถาปัตยกรรม
- เซิร์ฟเวอร์ MCP: เซิร์ฟเวอร์ที่เปิดเผยเครื่องมือและทรัพยากรให้กับไคลเอนต์ MCP
- ไคลเอนต์ MCP: ไคลเอนต์ที่ใช้เริ่มต้นโฟลว์การยืนยันตัวตนและทดสอบการเชื่อมต่อ เราจะใช้ MCP Inspector เป็นไคลเอนต์ในคู่มือนี้
- Logto: ทำหน้าที่เป็นผู้ให้บริการ OpenID Connect (authorization server) และจัดการข้อมูลระบุตัวตนของผู้ใช้
ไดอะแกรมลำดับ (sequence diagram) ที่ไม่เป็นมาตรฐานนี้แสดงภาพรวมของกระบวนการทั้งหมด:
เนื่องจาก MCP มีการพัฒนาอย่างรวดเร็ว ไดอะแกรมข้างต้นอาจไม่อัปเดตล่าสุดเสมอ โปรดดูเอกสาร mcp-auth สำหรับข้อมูลล่าสุด
ตั้งค่าแอปใน Logto
- ลงชื่อเข้าใช้ Logto Console ของคุณ
- ไปที่ Applications → Create application → Create app without framework
- เลือกประเภท: Single-page app
- กรอกชื่อแอปและข้อมูลที่จำเป็นอื่น ๆ จากนั้นคลิก Create application
- บันทึกและคัดลอก App ID และ Issuer endpoint
ตั้งค่าเซิร์ฟเวอร์ 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
-
เริ่ม MCP Inspector
เนื่องจากข้อจำกัดของ MCP Inspector เวอร์ชันปัจจุบัน เราจำเป็นต้องใช้เวอร์ชัน forked จาก mcp-auth:
git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run devจากนั้นเปิด URL ที่แสดงในเทอร์มินัล
-
ใน MCP Inspector:
- Transport Type:
SSE
- URL:
http://localhost:3001/sse
- OAuth Client ID: วาง Logto App ID ของคุณ
- Auth Params:
{"scope": "openid profile email"}
- Redirect URI: URL นี้ควรถูกเติมอัตโนมัติ ให้คัดลอกไว้
- Transport Type:
-
ค้นหาแอปพลิเคชันที่คุณสร้างไว้ใน Logto Console เปิดหน้ารายละเอียด แล้ววาง redirect URI ลงในส่วน Settings / Redirect URIs จากนั้นบันทึกการเปลี่ยนแปลง
-
กลับไปที่ MCP Inspector แล้วคลิก Connect ระบบจะนำคุณไปสู่ประสบการณ์การลงชื่อเข้าใช้ของ Logto
หลังจากลงชื่อเข้าใช้เสร็จ คุณจะถูกนำกลับไปยัง MCP Inspector ไปที่ Tools -> List Tools -> whoami -> Run Tool
คุณควรเห็นการอ้างสิทธิ์ของผู้ใช้ เช่น:
{
"sub": "user_XXXX",
"username": "alice",
"name": "Alice Smith",
"email": "[email protected]"
}
- Python
- Node.js
โค้ดเซิร์ฟเวอร์ MCP แบบเต็มสามารถดูได้ที่ mcp-auth/python
โค้ดเซิร์ฟเวอร์ MCP แบบเต็มสามารถดูได้ที่ mcp-auth/js