跳轉到主要內容

教學:我是誰? (Tutorial: Who am I?)

本教學將引導你設定 MCP Auth,以驗證 (Authentication) 使用者並從授權 (Authorization) 伺服器取得其身分資訊。

完成本教學後,你將會:

  • ✅ 基本瞭解如何使用 MCP Auth 進行使用者驗證 (Authentication)。
  • ✅ 擁有一個 MCP 伺服器,並能提供工具來取得使用者身分資訊。

概覽 (Overview)​

本教學將涉及以下元件:

  • MCP 伺服器:一個簡單的 MCP 伺服器,使用 MCP 官方 SDK 處理請求。
  • MCP inspector:MCP 伺服器的視覺化測試工具,同時作為 OAuth / OIDC 用戶端,啟動授權流程並取得存取權杖 (Access token)。
  • 授權伺服器 (Authorization server):一個 OAuth 2.1 或 OpenID Connect 提供者,負責管理使用者身分並簽發存取權杖 (Access token)。

以下是這些元件間互動的高階圖示:

瞭解你的授權伺服器 (Understand your authorization server)​

取得使用者身分資訊 (Retrieving user identity information)​

為完成本教學,你的授權伺服器應提供 API 以取得使用者身分資訊:

Logto 是一個 OpenID Connect 提供者,支援標準的 userinfo endpoint 來取得使用者身分資訊。

要取得可用於 userinfo endpoint 的存取權杖 (Access token),至少需兩個權限範圍 (Scopes):openid 與 profile。你可以繼續閱讀,稍後會介紹權限範圍設定。

動態用戶端註冊 (Dynamic Client Registration)​

本教學不強制需要動態用戶端註冊,但如果你想自動化 MCP 用戶端在授權伺服器的註冊流程,這會很有幫助。詳情請參閱 是否需要動態用戶端註冊?。

設定 MCP 伺服器 (Set up the MCP server)​

我們將使用 MCP 官方 SDK 建立一個 MCP 伺服器,並實作一個 whoami 工具,從授權伺服器取得使用者身分資訊。

建立新專案 (Create a new project)​

mkdir mcp-server
cd mcp-server
uv init # 或使用 `pipenv` 或 `poetry` 建立新虛擬環境

安裝 MCP SDK 與相依套件 (Install the MCP SDK and dependencies)​

pip install "mcp[cli]" starlette uvicorn

或使用你偏好的套件管理工具,如 uv 或 poetry。

建立 MCP 伺服器 (Create the MCP server)​

首先,讓我們建立一個實作 whoami 工具的 MCP 伺服器。

建立名為 whoami.py 的檔案,並加入以下程式碼:

from mcp.server.fastmcp import FastMCP
from starlette.applications import Starlette
from starlette.routing import Mount
from typing import Any

mcp = FastMCP("WhoAmI")

@mcp.tool()
def whoami() -> dict[str, Any]:
    """回傳目前使用者資訊的工具。"""
    return {"error": "Not authenticated"}

app = Starlette(
    routes=[Mount('/', app=mcp.sse_app())]
)

以以下指令啟動伺服器:

uvicorn whoami:app --host 0.0.0.0 --port 3001

檢查 MCP 伺服器 (Inspect the MCP server)​

下載並執行 MCP inspector (Clone and run MCP inspector)​

現在 MCP 伺服器已啟動,我們可以使用 MCP inspector 檢查 whoami 工具是否可用。

由於目前實作上的限制,我們 fork 了 MCP inspector,讓其在驗證 (Authentication) 與授權 (Authorization) 上更靈活且可擴展。我們也已向原始倉庫提交 pull request。

執行 MCP inspector,請使用以下指令(需安裝 Node.js):

git clone https://github.com/mcp-auth/inspector.git
cd inspector
npm install
npm run dev

然後在瀏覽器開啟 http://localhost:6274/(或終端機顯示的其他網址)以進入 MCP inspector。

連接 MCP inspector 與 MCP 伺服器 (Connect MCP inspector to the MCP server)​

在繼續之前,請檢查 MCP inspector 的以下設定:

  • Transport Type:設為 SSE。
  • URL:設為你的 MCP 伺服器網址,本例應為 http://localhost:3001/sse。

現在你可以點擊「Connect」按鈕,檢查 MCP inspector 是否能連接 MCP 伺服器。如果一切正常,應會看到 MCP inspector 顯示「Connected」狀態。

檢查點:執行 whoami 工具 (Checkpoint: Run the whoami tool)​

  1. 在 MCP inspector 上方選單點選「Tools」分頁。
  2. 點擊「List Tools」按鈕。
  3. 你應該會在頁面上看到 whoami 工具,點擊它以開啟工具詳情。
  4. 右側會出現「Run Tool」按鈕,點擊執行工具。
  5. 你應該會看到工具回傳結果為 JSON:{"error": "Not authenticated"}。

MCP inspector 首次執行畫面

與授權伺服器整合 (Integrate with your authorization server)​

完成本節需考慮以下幾點:

你的授權伺服器簽發者 (Issuer) URL

通常是你的授權伺服器基礎網址,例如 https://auth.example.com。有些提供者可能會有路徑,如 https://example.logto.app/oidc,請參閱你的提供者文件。

如何取得授權伺服器中繼資料 (Metadata)
如何將 MCP inspector 註冊為授權伺服器用戶端
如何取得使用者身分資訊,以及如何設定授權請求參數
  • 對於 OpenID Connect 提供者:通常需在授權流程請求至少 openid 與 profile 權限範圍 (Scopes)。這可確保授權伺服器回傳的存取權杖 (Access token) 具備存取 userinfo endpoint 所需權限。

    注意:部分提供者可能不支援 userinfo endpoint。

  • 對於 OAuth 2.0 / OAuth 2.1 提供者:請查閱你的提供者文件,瞭解如何用存取權杖 (Access token) 取得使用者身分資訊,以及啟動授權流程時需帶哪些參數。

雖然每個提供者可能有不同需求,以下步驟將引導你整合 MCP inspector 與 MCP 伺服器,並進行提供者專屬設定。

註冊 MCP inspector 為用戶端 (Register MCP inspector as a client)​

與 Logto 整合非常簡單,因為它是支援標準 userinfo endpoint 的 OpenID Connect 提供者。

由於 Logto 尚未支援動態用戶端註冊,你需手動將 MCP inspector 註冊為 Logto 租戶的用戶端:

  1. 開啟 MCP inspector,點擊「OAuth Configuration」按鈕。複製 Redirect URL (auto-populated),例如 http://localhost:6274/oauth/callback。
  2. 登入 Logto Console(或你的自架 Logto Console)。
  3. 進入「應用程式」分頁,點擊「建立應用程式」。頁面底部點「不使用框架建立應用程式」。
  4. 填寫應用程式資訊,然後點擊「建立應用程式」:
    • 選擇應用程式類型:選「單頁應用程式」。
    • 應用程式名稱:如「MCP Inspector」。
  5. 在「設定 / Redirect URIs」區塊,貼上剛才複製的 Redirect URL (auto-populated),然後點擊底部「儲存變更」。
  6. 頁面上方會看到「App ID」,請複製。
  7. 回到 MCP inspector,將「App ID」貼到「OAuth Configuration」的「Client ID」欄位。
  8. 在「Auth Params」欄位輸入 {"scope": "openid profile email"},確保 Logto 回傳的存取權杖 (Access token) 具備存取 userinfo endpoint 所需權限。

設定 MCP Auth (Set up MCP auth)​

在你的 MCP 伺服器專案中,需安裝 MCP Auth SDK 並設定使用你的授權伺服器中繼資料。

首先安裝 mcpauth 套件:

pip install mcpauth

或使用你偏好的套件管理工具,如 uv 或 poetry。

MCP Auth 需要授權伺服器中繼資料才能初始化。根據你的提供者:

簽發者 (Issuer) URL 可在 Logto Console 的應用程式詳情頁「Endpoints & Credentials / Issuer endpoint」區塊找到,格式類似 https://my-project.logto.app/oidc。

將 whoami.py 更新,加入 MCP Auth 設定:

from mcpauth import MCPAuth
from mcpauth.config import AuthServerType
from mcpauth.utils import fetch_server_config

auth_issuer = '<issuer-endpoint>'  # 請替換為你的簽發者 (Issuer) 端點
auth_server_config = fetch_server_config(auth_issuer, type=AuthServerType.OIDC)
mcp_auth = MCPAuth(server=auth_server_config)

接下來,我們需要建立一個自訂的存取權杖 (Access token) 驗證器,該驗證器會使用 MCP inspector 提供的存取權杖,從授權伺服器 (Authorization server) 取得使用者身分資訊。

import pydantic
import requests
from mcpauth.exceptions import (
    MCPAuthTokenVerificationException,
    MCPAuthTokenVerificationExceptionCode,
)
from mcpauth.types import AuthInfo

def verify_access_token(token: str) -> AuthInfo:
    """
    透過從授權伺服器 (Authorization server) 取得使用者資訊,驗證所提供的 Bearer 權杖 (Token)。
    若權杖有效,將回傳包含使用者資訊的 `AuthInfo` 物件。

    :param token: 從 MCP inspector 接收到的 Bearer 權杖 (Token)。
    """

    issuer = auth_server_config.metadata.issuer
    endpoint = auth_server_config.metadata.userinfo_endpoint # 提供者應支援 userinfo endpoint
    if not endpoint:
        raise ValueError(
            "auth server metadata 中未設定 userinfo endpoint。"
        )

    try:
        response = requests.get(
            endpoint,
            headers={"Authorization": f"Bearer {token}"}, # 標準 Bearer 權杖標頭
        )
        response.raise_for_status() # 確保 HTTP 錯誤時會拋出例外
        json = response.json() # 解析 JSON 回應
        return AuthInfo(
            token=token,
            subject=json.get("sub"), # 'sub' 是主體 (Subject, 使用者 ID) 的標準宣告 (Claim)
            issuer=issuer, # 使用 metadata 中的簽發者 (Issuer)
            claims=json, # 包含 userinfo endpoint 回傳的所有宣告 (Claims)
        )
    # `AuthInfo` 是 Pydantic 模型,驗證錯誤通常代表回應結構不符預期
    except pydantic.ValidationError as e:
        raise MCPAuthTokenVerificationException(
            MCPAuthTokenVerificationExceptionCode.INVALID_TOKEN,
            cause=e,
        )
    # 處理請求過程中可能發生的其他例外
    except Exception as e:
        raise MCPAuthTokenVerificationException(
            MCPAuthTokenVerificationExceptionCode.TOKEN_VERIFICATION_FAILED,
            cause=e,
        )

更新 MCP 伺服器 (Update MCP server)​

快完成了!現在要更新 MCP 伺服器,套用 MCP Auth 路由與中介軟體,並讓 whoami 工具回傳實際的使用者身分資訊。

@mcp.tool()
def whoami() -> dict[str, Any]:
    """回傳目前使用者資訊的工具。"""
    return (
        mcp_auth.auth_info.claims
        if mcp_auth.auth_info # 由 Bearer auth middleware 填入
        else {"error": "Not authenticated"}
    )

# ...

bearer_auth = Middleware(mcp_auth.bearer_auth_middleware(verify_access_token))
app = Starlette(
    routes=[
        # 加入 metadata 路由 (`/.well-known/oauth-authorization-server`)
        mcp_auth.metadata_route(),
        # 以 Bearer auth middleware 保護 MCP 伺服器
        Mount('/', app=mcp.sse_app(), middleware=[bearer_auth]),
    ],
)

檢查點:以驗證 (Authentication) 執行 whoami 工具 (Checkpoint: Run the whoami tool with authentication)​

重新啟動 MCP 伺服器,並在瀏覽器開啟 MCP inspector。當你點擊「Connect」按鈕時,應會被導向授權伺服器的登入頁面。

登入後回到 MCP inspector,重複前述步驟執行 whoami 工具。這次你應該會看到授權伺服器回傳的使用者身分資訊。

MCP inspector whoami 工具結果

資訊

完整 MCP 伺服器(OIDC 版本)程式碼請參考 MCP Auth Python SDK repository。

結語 (Closing notes)​

🎊 恭喜你!已成功完成本教學。讓我們回顧一下:

  • 建立具備 whoami 工具的基本 MCP 伺服器
  • 透過 MCP Auth 將 MCP 伺服器與授權伺服器整合
  • 設定 MCP Inspector 以驗證 (Authentication) 使用者並取得其身分資訊

你也可以進一步探索進階主題,包括:

歡迎參閱其他教學與文件,充分發揮 MCP Auth 的效能。