サードパーティ AI エージェントによる MCP サーバーアクセスの有効化
このガイドでは、 mcp-auth を使用して Logto を MCP サーバーと統合し、標準の OpenID Connect フローを利用してユーザーを認証し、アイデンティティ情報を安全に取得する方法を説明します。
このガイドで学べること:
- MCP サーバーの認可 (Authorization) サーバーとして Logto を設定する方法
- MCP サーバーに「whoami」ツールをセットアップし、現在のユーザーのクレーム (Claims) を返す方法
- サードパーティ AI エージェント (MCP クライアント) でフローをテストする方法
このチュートリアルの完了後、MCP サーバーは以下のことが可能になります:
- Logto テナントでユーザーを認証 (Authentication) する
- 「whoami」ツールの呼び出し時に、
sub
、username
、name
、email
などのクレーム (Claims) を返す
サードパーティ AI エージェント (MCP クライアント) と自社 MCP クライアントの違い
例を見てみましょう。あなたが MCP サーバーを運用し、メールアクセスと自動化を管理している開発者だとします。
公式メールアプリ(自社 MCP クライアント)
- ユーザーがメールを閲覧・管理できる公式メールアプリを提供します。
- 動作:公式メールアプリは Logto を使って MCP サーバーに接続し、ユーザーを認証 (Authentication) します。Alice がサインインすると、自動的にメールへアクセスでき、追加の同意画面は不要です(信頼されたアプリのため)。
サードパーティ AI エージェント(サードパーティ MCP クライアント)
- MCP サーバーを中心にエコシステムを構築している場合、他の開発者が「SmartMail AI」(メールを要約し、会議を自動でスケジューリングする AI アシスタント)をサードパーティクライアントとして統合します。
- 動作:SmartMail AI(サードパーティ MCP クライアント)は、MCP サーバー経由でユーザーのメールにアクセスしたいと考えています。Alice が自分のアカウントで SmartMail AI にサインインすると:
- SmartMail AI がメールやカレンダーの閲覧許可を求める同意画面が表示されます。
- Alice はこのアクセスを許可または拒否できます。
- Alice が同意したデータのみが SmartMail AI と共有され、明示的な再同意なしに追加データへアクセスすることはできません。
このアクセス(権限)コントロールにより、MCP サーバーがすべてのデータを管理していても、SmartMail AI のようなサードパーティアプリはユーザーが明示的に許可した範囲のみアクセスできます。このプロセスは MCP サーバーのアクセス制御実装によって強制され、回避できません。
まとめ
クライアント種別 | 例 | 同意画面が必要? | 管理者 |
---|---|---|---|
公式メールアプリ | 自社メールアプリケーション | いいえ | 開発者(あなた) |
サードパーティ AI エージェント | SmartMail AI アシスタント | はい | 他の開発者 |
自社の AI エージェントやアプリと MCP サーバーを統合したい場合は、 Logto で MCP ベースのアプリに認証 (Authentication) を有効化する ガイドを参照してください。
前提条件
- Logto Cloud (またはセルフホスト型)テナント
- Node.js または Python 環境
アーキテクチャの理解
- MCP サーバー:MCP クライアントにツールやリソースを提供するサーバー。
- MCP クライアント:認証 (Authentication) フローを開始し、統合をテストするために使用されるクライアント。このガイドではサードパーティ AI エージェントをクライアントとして使用します。
- Logto:OpenID Connect プロバイダー(認可 (Authorization) サーバー)として機能し、ユーザーアイデンティティを管理します。
規範的でないシーケンス図でプロセス全体の流れを示します:
MCP は急速に進化しているため、上記の図は最新の状態ではない場合があります。最新情報は mcp-auth ドキュメントを参照してください。
サードパーティ AI エージェントのセットアップ
サードパーティ AI エージェントが MCP サーバーへアクセスできるようにするには、以下の設定が必要です:
- クライアントが MCP サーバーで公開されているツールを呼び出す MCP リクエストを送信できること。
- クライアントが 401 Unauthorized レスポンスを処理できること。詳細は 認可 (Authorization) フローステップ を参照してください。
- 認証 (Authentication) に成功した後、Logto から取得したアクセス トークン (Access token) で MCP サーバーにリクエストできること。
Logto で AI エージェントをセットアップ
サードパーティ AI エージェントが MCP サーバーへアクセスできるようにするには、Logto で サードパーティアプリ をセットアップする必要があります。このアプリは AI エージェントを表し、認証 (Authentication) および認可 (Authorization) に必要なクレデンシャルを取得するために使用されます。
Logto で開発者がサードパーティアプリを作成できるようにする
マーケットプレイスを構築したり、開発者が Logto でサードパーティアプリを作成できるようにしたい場合は、 Logto Management API を活用してプログラム的にサードパーティアプリを作成できます。これにより、開発者は自分のアプリケーションを登録し、認証 (Authentication) に必要なクレデンシャルを取得できます。
クライアント登録プロセスを処理する独自サービスをホストする必要があります。このサービスが Logto Management API と連携し、開発者の代わりにサードパーティアプリを作成します。
または、Logto コンソールで手動でサードパーティアプリを作成し、プロセスに慣れることもできます。
Logto でサードパーティアプリを手動作成する
テストやアドホックな統合の場合、Logto コンソールでサードパーティアプリを手動で作成できます。クライアント登録フローを実装せずに統合を素早くテストしたい場合に便利です。
- Logto コンソールにサインインします。
- アプリケーション → アプリケーション作成 → サードパーティアプリ -> OIDC を選択します。
- アプリ名など必要事項を入力し、アプリケーション作成 をクリックします。
- 権限 タブをクリックし、ユーザー セクションで「追加」をクリックします。
- 開いたダイアログで -> ユーザーデータ ->
profile
、email
権限を選択し、保存 をクリックします。 - サードパーティアプリで
openid profile email
権限をリクエストするようスコープを設定します。 - サードパーティアプリの リダイレクト URI を適切に設定します。Logto 側のリダイレクト URI も忘れずに更新してください。

内部的には、サードパーティアプリは標準的な OAuth 2.0 / OIDC クライアントにすぎません。つまり、Logto との統合には、任意の OAuth 2.0 / OIDC ライブラリやフレームワークを利用できます(開発者自身またはサードパーティ開発者が選択可能です)。
OAuth 2.0 や OIDC に慣れていない場合は、「従来型 Web」クイックスタートガイドのいずれかから始めることをおすすめします。
注意すべき点は以下の通りです:
- Logto では現在、サードパーティアプリは「従来型 Web」アプリである必要があります。つまり、クライアントシークレットを安全に保存するためにバックエンドサーバー(またはバックエンド・フォー・フロントエンド)が必要です。
- クイックスタートガイドの多くはファーストパーティアプリ向けに書かれていますが、サードパーティアプリ統合の参考としても利用できます。
- 主な違いは、サードパーティアプリでは同意画面が表示され、ユーザーにデータアクセスの明示的な許可を求める点です。
詳細は クイックスタートガイド で確認できます。
MCP サーバーのセットアップ
プロジェクトの作成と依存関係のインストール
- 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 # または任意のパッケージマネージャーを使用
Logto で MCP 認証 (Authentication) を構成する
先ほどコピーした発行者 (Issuer) エンドポイント <your-logto-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) を検証しユーザー情報を取得するため、次のようにアクセス トークン (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" ツールの実装
次に、クライアントから送信されたアクセス トークン (Access token) を使用して userinfo エンドポイントにリクエストし、現在のユーザーのアイデンティティ クレーム (Claims) を返す "whoami" ツールを実装します。
現時点の SDK バージョンでは Streamable HTTP トランスポートの公式サポートがないため、例として SSE トランスポートを使用しています。理論的には、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 メタデータを提供
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 サーバーを作成し、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 アプリ & MCP Auth ミドルウェア
const app = express();
app.use(mcpAuth.delegatedRouter());
app.use(mcpAuth.bearerAuth(verifyToken));
// SSE トランスポート(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 エージェントを起動します。
- クライアントで
whoami
ツールを呼び出し、現在のユーザーのクレーム (Claims) を取得します。 - クライアントは 401 Unauthorized レスポンスを処理し、ユーザーを Logto へリダイレクトして認証 (Authentication) します。
- 認証 (Authentication) に成功すると、クライアントはアクセス トークン (Access token) を受け取り、それを使って MCP サーバーにリクエストします。
- クライアントはアクセス トークン (Access token) を使って MCP サーバーからクレーム (Claims) を取得できるようになります。
- Python
- Node.js
完全な MCP サーバーコードは mcp-auth/python リポジトリで確認できます。
完全な MCP サーバーコードは mcp-auth/js リポジトリで確認できます。