clerk-nextjs-skills について
Next.js 開発者向けの Clerk 統合スキルで、認証、ルート保護、ユーザーデータの取得、Next.js バージョン間の移行を解説します。Vercel アダプターと Clerk ツールを使った OAuth 検証付き MCP サーバーの構築方法も扱います。
主な機能
- 01Clerk 認証の設定
- 02Next.js ルートの保護
- 03クライアントとサーバーでのユーザーデータ取得
- 04middleware.ts から proxy.ts への移行
- 05OAuth 検証付き MCP サーバーの設定
活用シーン
- 01Next.js アプリへのサインインと登録の追加
- 02選択したルートへの認証必須化
- 03Next.js 15 プロジェクトの 16 への移行
- 04MCP ツール向け Clerk OAuth トークンの検証
MCP 対応
@vercel/mcp-adapter と @clerk/mcp-tools を使った Next.js での MCP サーバー構築を説明し、Clerk OAuth トークン検証と動的クライアント登録を扱います。
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ gocallum/ nextjs16-agent-skills --skill clerk-nextjs-skillsインストール後、Claude Code で/clerk-nextjs-skillsを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
CREATION_SUMMARY.mdQUICK_REFERENCE.mdREADME.mdreferences/CLERK_ENV_SETUP.mdCLERK_MCP_SERVER_SETUP.mdEXAMPLES.mdPROXY_MIGRATION.mdscripts/setup-clerk-nextjs.sh詳細
リンク
- Clerk Next.js クイックスタート
- Clerk MCP サーバーガイド
- Clerk Next.js SDK リファレンス
- clerkMiddleware() リファレンス
- ユーザーデータの読み取り
- ルートの保護
- OAuth トークンの検証
- Clerk ダッシュボード
- @vercel/mcp-adapter
- @clerk/mcp-tools
- MCP サンプルリポジトリ
クイックスタート
1. 依存関係をインストールする(pnpm を使用)
pnpm add @clerk/nextjs
# For MCP server integration, also install:
pnpm add @vercel/mcp-adapter @clerk/mcp-tools
2. proxy.ts を作成する(Next.js 16)
proxy.ts ファイルは、Next.js 15 の middleware.ts に代わるものです。ルートまたは /src に作成します。
// proxy.ts (or src/proxy.ts)
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware()
export const config = {
matcher: [
'/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
'/(api|trpc)(.*)',
],
}
3. 環境変数を設定する
プロジェクトのルートに .env.local を作成します。
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY=your_publishable_key_here
CLERK_SECRET_KEY=your_secret_key_here
NEXT_PUBLIC_CLERK_SIGN_IN_URL=/sign-in
NEXT_PUBLIC_CLERK_SIGN_UP_URL=/sign-up
NEXT_PUBLIC_CLERK_AFTER_SIGN_IN_URL=/
NEXT_PUBLIC_CLERK_AFTER_SIGN_UP_URL=/
4. ClerkProvider をレイアウトに追加する
// app/layout.tsx
import {
ClerkProvider,
SignInButton,
SignUpButton,
SignedIn,
SignedOut,
UserButton,
} from '@clerk/nextjs'
import type { Metadata } from 'next'
export const metadata: Metadata = {
title: 'My App',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<ClerkProvider>
<html lang="en">
<body>
<header className="flex justify-end items-center p-4 gap-4 h-16">
<SignedOut>
<SignInButton />
<SignUpButton />
</SignedOut>
<SignedIn>
<UserButton />
</SignedIn>
</header>
{children}
</body>
</html>
</ClerkProvider>
)
}
5. アプリを実行する
pnpm dev
http://localhost:3000 にアクセスし、「Sign Up」をクリックして最初のユーザーを作成します。
主要な概念
proxy.ts と middleware.ts の違い
- Next.js 16(App Router):Clerk ミドルウェアには
proxy.tsを使用します - Next.js ≤15:同じコードで
middleware.tsを使用します(異なるのはファイル名のみです) - Clerk の
clerkMiddleware()関数は、ファイル名に関係なく同じです matcherの設定により、適切なルート処理とパフォーマンスが確保されます
ルートの保護
デフォルトでは、clerkMiddleware() はルートを保護しません。すべてのルートが公開されています。認証を必須にするには、auth.protect() を使用します。
// Protect specific route
import { auth } from '@clerk/nextjs/server'
export default async function Page() {
const { userId } = await auth()
if (!userId) {
// Redirect handled by clerkMiddleware
}
return <div>Protected content for {userId}</div>
}
または、proxy.ts ですべてのルートを保護します。
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware(async (auth, req) => {
await auth.protect()
})
環境変数の検証
実行時の前に、必要な Clerk キーが設定されていることを確認します。
// lib/clerk-config.ts
export function validateClerkEnv() {
const required = [
'NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY',
'CLERK_SECRET_KEY',
]
const missing = required.filter(key => !process.env[key])
if (missing.length > 0) {
throw new Error(`Missing required Clerk environment variables: ${missing.join(', ')}`)
}
}
ユーザーデータへのアクセス
クライアントコンポーネントでは Clerk フックを使用します。
// app/components/user-profile.tsx
'use client'
import { useUser } from '@clerk/nextjs'
export function UserProfile() {
const { user, isLoaded } = useUser()
if (!isLoaded) return <div>Loading...</div>
if (!user) return <div>Not signed in</div>
return (
<div>
<h1>{user.fullName}</h1>
<p>{user.primaryEmailAddress?.emailAddress}</p>
</div>
)
}
または、サーバーコンポーネント/アクションでは次のようにします。
// app/actions.ts
'use server'
import { auth, clerkClient } from '@clerk/nextjs/server'
export async function getUserData() {
const { userId } = await auth()
if (!userId) {
throw new Error('Unauthorized')
}
const clerk = await clerkClient()
const user = await clerk.users.getUser(userId)
return user
}
middleware.ts(Next.js 15)から proxy.ts(Next.js 16)への移行
移行手順
-
ファイル名を変更する:
middleware.tsからproxy.tsに変更します(場所はルートまたは/srcのままです) -
コードはそのままにする — 機能上の変更は不要です:
// Before (middleware.ts) import { clerkMiddleware } from '@clerk/nextjs/server' export default clerkMiddleware() export const config = { ... } // After (proxy.ts) - Same code import { clerkMiddleware } from '@clerk/nextjs/server' export default clerkMiddleware() export const config = { ... } -
Next.js のバージョンを更新する:
pnpm add next@latest -
環境変数を確認する:引き続き
.env.localに設定されていることを確認します(変更は不要です) -
移行をテストする:
pnpm dev
移行時のトラブルシューティング
- ルートが保護されない場合は、
proxy.tsが正しい場所(ルートまたは/src)にあることを確認します .env.localに必要な Clerk キーがすべて設定されていることを確認します- ミドルウェアの変更が反映されない場合は、
.nextキャッシュを消去します:rm -rf .next && pnpm dev - Next.js のバージョンが 16.0 以降であることを確認します:
pnpm list next
Clerk を使用した MCP サーバーの構築
MCP サーバーの統合については、CLERK_MCP_SERVER_SETUP.md を参照してください。
MCP セットアップの概要
-
MCP の依存関係をインストールする:
pnpm add @vercel/mcp-adapter @clerk/mcp-tools -
MCP ルートを作成する:
app/[transport]/route.tsに作成します。import { verifyClerkToken } from '@clerk/mcp-tools/next' import { createMcpHandler, withMcpAuth } from '@vercel/mcp-adapter' import { auth, clerkClient } from '@clerk/nextjs/server' const clerk = await clerkClient() const handler = createMcpHandler((server) => { server.tool( 'get-clerk-user-data', 'Gets data about the Clerk user that authorized this request', {}, async (_, { authInfo }) => { const userId = authInfo!.extra!.userId! as string const userData = await clerk.users.getUser(userId) return { content: [{ type: 'text', text: JSON.stringify(userData) }], } }, ) }) const authHandler = withMcpAuth( handler, async (_, token) => { const clerkAuth = await auth({ acceptsToken: 'oauth_token' }) return verifyClerkToken(clerkAuth, token) }, { required: true, resourceMetadataPath: '/.well-known/oauth-protected-resource/mcp', }, ) export { authHandler as GET, authHandler as POST } -
OAuth メタデータのエンドポイントを公開する(完全なセットアップについてはリファレンスを参照してください)
-
proxy.ts を更新する:
.well-knownエンドポイントを除外します。import { clerkMiddleware, createRouteMatcher } from '@clerk/nextjs/server' const isPublicRoute = createRouteMatcher([ '/.well-known/oauth-authorization-server(.*)', '/.well-known/oauth-protected-resource(.*)', ]) export default clerkMiddleware(async (auth, req) => { if (isPublicRoute(req)) return await auth.protect() }) -
Clerk ダッシュボード で Dynamic Client Registration を有効にする
ベストプラクティス
1. 環境変数の管理
- 開発には必ず
.env.localを使用します(機密キーは絶対にコミットしないでください) - アプリケーションの起動時に環境変数を検証します
- 安全に公開できる機密性のないキーに限り、
NEXT_PUBLIC_接頭辞を使用します - 本番環境では、デプロイプラットフォーム(Vercel など)で環境変数を設定します
2. ルート保護の戦略
// Option A: Protect all routes
export default clerkMiddleware(async (auth, req) => {
await auth.protect()
})
// Option B: Protect specific routes
import { createRouteMatcher } from '@clerk/nextjs/server'
const isProtectedRoute = createRouteMatcher(['/dashboard(.*)', '/api/user(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (isProtectedRoute(req)) {
await auth.protect()
}
})
// Option C: Public routes with opt-in protection
const isPublicRoute = createRouteMatcher(['/sign-in(.*)', '/sign-up(.*)'])
export default clerkMiddleware(async (auth, req) => {
if (!isPublicRoute(req)) {
await auth.protect()
}
})
3. MCP サーバーのセキュリティ
- Clerk Dashboard で動的クライアント登録を有効にします
.well-knownエンドポイントは公開したまま、すべての MCP ツールを OAuth で保護します- マシントークンを必須にするには、
auth()でacceptsToken: 'oauth_token'を使用します - パブリックベータ期間中、OAuth トークンは無料です(料金は未定)
- ユーザーデータを公開する前に、必ず
verifyClerkToken()でトークンを検証します
4. パフォーマンスとキャッシュ
- サーバー側のユーザークエリには
clerkClient()を使用します(自動的にキャッシュされます) - React Server Components を活用して、ユーザーデータに安全にアクセスします
- API 呼び出しを減らすため、可能な場合はユーザーデータをキャッシュします
@clerk/nextjsのフックはクライアントコンポーネント('use client')でのみ使用します
5. 本番環境へのデプロイ
- デプロイ先のプラットフォームにすべての環境変数を設定します
- Clerk の本番インスタンスキー(開発用キーではなく)を使用します
- 本番環境にデプロイする前に、ステージング環境で認証フローをテストします
- Clerk Dashboard で認証エラーを監視します
@clerk/nextjsを最新の状態に保ちます:pnpm update @clerk/nextjs
トラブルシューティング
問題と解決策
| 問題 | 解決策 |
|---|---|
| "Missing environment variables" | .env.local に NEXT_PUBLIC_CLERK_PUBLISHABLE_KEY と CLERK_SECRET_KEY が設定されていることを確認します |
| ミドルウェアでルートが保護されない | proxy.ts が app/ ではなく、ルートまたは /src ディレクトリにあることを確認します |
| サインイン/サインアップページが機能しない | .env.local の NEXT_PUBLIC_CLERK_SIGN_IN_URL と NEXT_PUBLIC_CLERK_SIGN_UP_URL を確認します |
| ユーザーデータが null を返す | ユーザーが認証済みであることを確認します:getUser() を呼び出す前に userId が null でないことを確認します |
| MCP サーバーの OAuth が失敗する | Clerk Dashboard の OAuth Applications で動的クライアント登録を有効にします |
| 変更が反映されない | .next キャッシュをクリアします:rm -rf .next を実行してから pnpm dev を再起動します |
| "proxy.ts" が認識されない | Next.js のバージョンが 16.0 以上であることを確認します:pnpm list next |
Next.js 16 でよくある注意点
- ファイル名:Next.js 16 では
middleware.tsではなく、proxy.tsにする必要があります - 配置場所:
proxy.tsはプロジェクトのルートまたは/srcディレクトリに配置します。app/には配置しないでください - 再エクスポート:matcher を機能させるには、設定オブジェクトを
proxy.tsからエクスポートする必要があります - 非同期処理:
clerkMiddleware()は非同期処理に対応しています。ルートを保護するにはawait auth.protect()を使用します
デバッグモード
デバッグログを有効にします:
// proxy.ts
import { clerkMiddleware } from '@clerk/nextjs/server'
export default clerkMiddleware((auth, req) => {
if (process.env.DEBUG_CLERK) {
console.log('Request URL:', req.nextUrl.pathname)
console.log('User ID:', auth.sessionClaims?.sub)
}
})
デバッグを有効にして実行します:
DEBUG_CLERK=1 pnpm dev
関連スキル
- mcp-server-skills:Vercel アダプターを使用した一般的な MCP サーバーのパターン
- nextjs16-skills:Next.js 16 の機能、破壊的変更、ベストプラクティス
- authjs-skills:Auth.js(Auth0、GitHub など)を使用した代替の認証方法