diff --git a/client/src/i18n/translations/ar.ts b/client/src/i18n/translations/ar.ts
index cdcac563..96474671 100644
--- a/client/src/i18n/translations/ar.ts
+++ b/client/src/i18n/translations/ar.ts
@@ -233,6 +233,7 @@ const ar: Record = {
'settings.mcp.endpoint': 'نقطة نهاية MCP',
'settings.mcp.clientConfig': 'إعداد العميل',
'settings.mcp.clientConfigHint': 'استبدل برمز API من القائمة أدناه. قد يحتاج مسار npx إلى ضبط وفق نظامك (مثلاً C:\\PROGRA~1\\nodejs\\npx.cmd على Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'نسخ',
'settings.mcp.copied': 'تم النسخ!',
'settings.mcp.apiTokens': 'رموز API',
diff --git a/client/src/i18n/translations/br.ts b/client/src/i18n/translations/br.ts
index d3b11e66..af7af325 100644
--- a/client/src/i18n/translations/br.ts
+++ b/client/src/i18n/translations/br.ts
@@ -295,6 +295,7 @@ const br: Record = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configuração do cliente',
'settings.mcp.clientConfigHint': 'Substitua por um token de API da lista abaixo. O caminho para o npx pode precisar ser ajustado para o seu sistema (ex.: C:\\PROGRA~1\\nodejs\\npx.cmd no Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copiar',
'settings.mcp.copied': 'Copiado!',
'settings.mcp.apiTokens': 'Tokens de API',
diff --git a/client/src/i18n/translations/cs.ts b/client/src/i18n/translations/cs.ts
index 130f9623..f0eca4ca 100644
--- a/client/src/i18n/translations/cs.ts
+++ b/client/src/i18n/translations/cs.ts
@@ -181,6 +181,7 @@ const cs: Record = {
'settings.mcp.endpoint': 'MCP endpoint',
'settings.mcp.clientConfig': 'Konfigurace klienta',
'settings.mcp.clientConfigHint': 'Nahraďte API tokenem ze seznamu níže. Cestu k npx může být nutné upravit pro váš systém (např. C:\\PROGRA~1\\nodejs\\npx.cmd ve Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopírovat',
'settings.mcp.copied': 'Zkopírováno!',
'settings.mcp.apiTokens': 'API tokeny',
diff --git a/client/src/i18n/translations/de.ts b/client/src/i18n/translations/de.ts
index c9ebf453..7018c775 100644
--- a/client/src/i18n/translations/de.ts
+++ b/client/src/i18n/translations/de.ts
@@ -228,6 +228,7 @@ const de: Record = {
'settings.mcp.endpoint': 'MCP-Endpunkt',
'settings.mcp.clientConfig': 'Client-Konfiguration',
'settings.mcp.clientConfigHint': 'Ersetze durch ein API-Token aus der Liste unten. Der Pfad zu npx muss ggf. für dein System angepasst werden (z. B. C:\\PROGRA~1\\nodejs\\npx.cmd unter Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopieren',
'settings.mcp.copied': 'Kopiert!',
'settings.mcp.apiTokens': 'API-Tokens',
diff --git a/client/src/i18n/translations/en.ts b/client/src/i18n/translations/en.ts
index 1bdaeeef..d0b79891 100644
--- a/client/src/i18n/translations/en.ts
+++ b/client/src/i18n/translations/en.ts
@@ -249,6 +249,7 @@ const en: Record = {
'settings.mcp.endpoint': 'MCP Endpoint',
'settings.mcp.clientConfig': 'Client Configuration',
'settings.mcp.clientConfigHint': 'Replace with an API token from the list below. The path to npx may need to be adjusted for your system (e.g. C:\\PROGRA~1\\nodejs\\npx.cmd on Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copy',
'settings.mcp.copied': 'Copied!',
'settings.mcp.apiTokens': 'API Tokens',
diff --git a/client/src/i18n/translations/es.ts b/client/src/i18n/translations/es.ts
index 41219432..8b462f2a 100644
--- a/client/src/i18n/translations/es.ts
+++ b/client/src/i18n/translations/es.ts
@@ -229,6 +229,7 @@ const es: Record = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configuración del cliente',
'settings.mcp.clientConfigHint': 'Reemplaza con un token de la lista de abajo. Es posible que debas ajustar la ruta de npx según tu sistema (p. ej. C:\\PROGRA~1\\nodejs\\npx.cmd en Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copiar',
'settings.mcp.copied': '¡Copiado!',
'settings.mcp.apiTokens': 'Tokens de API',
diff --git a/client/src/i18n/translations/fr.ts b/client/src/i18n/translations/fr.ts
index cbc2e09c..340125f9 100644
--- a/client/src/i18n/translations/fr.ts
+++ b/client/src/i18n/translations/fr.ts
@@ -228,6 +228,7 @@ const fr: Record = {
'settings.mcp.endpoint': 'Point de terminaison MCP',
'settings.mcp.clientConfig': 'Configuration du client',
'settings.mcp.clientConfigHint': 'Remplacez par un token API de la liste ci-dessous. Le chemin vers npx devra peut-être être ajusté selon votre système (ex. C:\\PROGRA~1\\nodejs\\npx.cmd sous Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copier',
'settings.mcp.copied': 'Copié !',
'settings.mcp.apiTokens': 'Tokens API',
diff --git a/client/src/i18n/translations/hu.ts b/client/src/i18n/translations/hu.ts
index 40ce49a2..14982e4f 100644
--- a/client/src/i18n/translations/hu.ts
+++ b/client/src/i18n/translations/hu.ts
@@ -180,6 +180,7 @@ const hu: Record = {
'settings.mcp.endpoint': 'MCP végpont',
'settings.mcp.clientConfig': 'Kliens konfiguráció',
'settings.mcp.clientConfigHint': 'Cserélje ki a részt egy API tokenre az alábbi listából. Az npx elérési útját szükség lehet módosítani a rendszeréhez (pl. C:\\PROGRA~1\\nodejs\\npx.cmd Windows-on).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Másolás',
'settings.mcp.copied': 'Másolva!',
'settings.mcp.apiTokens': 'API tokenek',
diff --git a/client/src/i18n/translations/it.ts b/client/src/i18n/translations/it.ts
index d5449ff8..6ca0c21b 100644
--- a/client/src/i18n/translations/it.ts
+++ b/client/src/i18n/translations/it.ts
@@ -180,6 +180,7 @@ const it: Record = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Configurazione client',
'settings.mcp.clientConfigHint': 'Sostituisci con un token API dalla lista sottostante. Il percorso di npx potrebbe dover essere adattato per il tuo sistema (es. C:\\PROGRA~1\\nodejs\\npx.cmd su Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Copia',
'settings.mcp.copied': 'Copiato!',
'settings.mcp.apiTokens': 'Token API',
diff --git a/client/src/i18n/translations/nl.ts b/client/src/i18n/translations/nl.ts
index 2e7495da..4891b9e9 100644
--- a/client/src/i18n/translations/nl.ts
+++ b/client/src/i18n/translations/nl.ts
@@ -228,6 +228,7 @@ const nl: Record = {
'settings.mcp.endpoint': 'MCP-eindpunt',
'settings.mcp.clientConfig': 'Clientconfiguratie',
'settings.mcp.clientConfigHint': 'Vervang door een API-token uit de onderstaande lijst. Het pad naar npx moet mogelijk worden aangepast voor jouw systeem (bijv. C:\\PROGRA~1\\nodejs\\npx.cmd op Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopiëren',
'settings.mcp.copied': 'Gekopieerd!',
'settings.mcp.apiTokens': 'API-tokens',
diff --git a/client/src/i18n/translations/pl.ts b/client/src/i18n/translations/pl.ts
index 4f60b983..4eb3c345 100644
--- a/client/src/i18n/translations/pl.ts
+++ b/client/src/i18n/translations/pl.ts
@@ -198,6 +198,7 @@ const pl: Record = {
'settings.mcp.endpoint': 'Endpoint MCP',
'settings.mcp.clientConfig': 'Konfiguracja klienta',
'settings.mcp.clientConfigHint': 'Zastąp tokenem API z listy poniżej. Ścieżka do npx może wymagać dostosowania do Twojego systemu (np. C:\\PROGRA~1\\nodejs\\npx.cmd w systemie Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Kopiuj',
'settings.mcp.copied': 'Skopiowano!',
'settings.mcp.apiTokens': 'Tokeny API',
diff --git a/client/src/i18n/translations/ru.ts b/client/src/i18n/translations/ru.ts
index 18001fc9..c3f53588 100644
--- a/client/src/i18n/translations/ru.ts
+++ b/client/src/i18n/translations/ru.ts
@@ -228,6 +228,7 @@ const ru: Record = {
'settings.mcp.endpoint': 'MCP-эндпоинт',
'settings.mcp.clientConfig': 'Конфигурация клиента',
'settings.mcp.clientConfigHint': 'Замените на API-токен из списка ниже. Путь к npx может потребовать настройки для вашей системы (например, C:\\PROGRA~1\\nodejs\\npx.cmd в Windows).',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': 'Копировать',
'settings.mcp.copied': 'Скопировано!',
'settings.mcp.apiTokens': 'API-токены',
diff --git a/client/src/i18n/translations/zh.ts b/client/src/i18n/translations/zh.ts
index d0af81d3..43e95f11 100644
--- a/client/src/i18n/translations/zh.ts
+++ b/client/src/i18n/translations/zh.ts
@@ -228,6 +228,7 @@ const zh: Record = {
'settings.mcp.endpoint': 'MCP 端点',
'settings.mcp.clientConfig': '客户端配置',
'settings.mcp.clientConfigHint': '将 替换为下方列表中的 API 令牌。npx 的路径可能需要根据您的系统进行调整(例如 Windows 上为 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': '复制',
'settings.mcp.copied': '已复制!',
'settings.mcp.apiTokens': 'API 令牌',
diff --git a/client/src/i18n/translations/zhTw.ts b/client/src/i18n/translations/zhTw.ts
index 86fa1418..19a256d5 100644
--- a/client/src/i18n/translations/zhTw.ts
+++ b/client/src/i18n/translations/zhTw.ts
@@ -220,6 +220,7 @@ const zhTw: Record = {
'settings.mcp.endpoint': 'MCP 端點',
'settings.mcp.clientConfig': '客戶端配置',
'settings.mcp.clientConfigHint': '將 替換為下方列表中的 API 令牌。npx 的路徑可能需要根據您的系統進行調整(例如 Windows 上為 C:\\PROGRA~1\\nodejs\\npx.cmd)。',
+ 'settings.mcp.clientConfigHintOAuth': 'Replace and with the credentials shown in the OAuth 2.1 client you created above. mcp-remote will open your browser to complete the authorization the first time you connect. The path to npx may need to be adjusted for your system (e.g. C:\PROGRA~1\nodejs\npx.cmd on Windows).',
'settings.mcp.copy': '複製',
'settings.mcp.copied': '已複製!',
'settings.mcp.apiTokens': 'API 令牌',
diff --git a/client/src/pages/OAuthRegisterPage.tsx b/client/src/pages/OAuthRegisterPage.tsx
new file mode 100644
index 00000000..64bfbd39
--- /dev/null
+++ b/client/src/pages/OAuthRegisterPage.tsx
@@ -0,0 +1,214 @@
+import React, { useEffect, useState } from 'react'
+import { useAuthStore } from '../store/authStore'
+import { oauthApi } from '../api/client'
+import { ALL_SCOPES } from '../api/oauthScopes'
+import ScopeGroupPicker from '../components/OAuth/ScopeGroupPicker'
+import { Lock, ShieldCheck, AlertTriangle, Loader2, LogIn } from 'lucide-react'
+
+interface ValidateResult {
+ valid: boolean
+ error?: string
+ error_description?: string
+ client_name?: string
+ requested_scopes?: string[]
+ loginRequired?: boolean
+}
+
+type PageState = 'loading' | 'login_required' | 'ready' | 'error' | 'done'
+
+export default function OAuthRegisterPage(): React.ReactElement {
+ const { isLoading: authLoading, loadUser } = useAuthStore()
+ const [pageState, setPageState] = useState('loading')
+ const [validation, setValidation] = useState(null)
+ const [selectedScopes, setSelectedScopes] = useState([])
+ const [submitting, setSubmitting] = useState(false)
+ const [errorMsg, setErrorMsg] = useState(null)
+
+ const params = new URLSearchParams(window.location.search)
+ const redirectUri = params.get('redirect_uri') || ''
+ const clientName = params.get('client_name') || ''
+ const scope = params.get('scope') || ''
+ const state = params.get('state') || ''
+
+ useEffect(() => {
+ loadUser({ silent: true }).catch(() => {})
+ }, [loadUser])
+
+ useEffect(() => {
+ if (authLoading) return
+ validateRequest()
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [authLoading])
+
+ async function validateRequest() {
+ setPageState('loading')
+ try {
+ const result: ValidateResult = await oauthApi.register.validate({
+ redirect_uri: redirectUri,
+ client_name: clientName,
+ scope,
+ state,
+ })
+ setValidation(result)
+
+ if (!result.valid) {
+ setPageState('error')
+ setErrorMsg(result.error_description || result.error || 'Invalid registration request')
+ return
+ }
+
+ if (result.loginRequired) {
+ setPageState('login_required')
+ return
+ }
+
+ // Pre-check the scopes the client requested; fall back to read-only defaults
+ const requested = result.requested_scopes ?? []
+ setSelectedScopes(
+ requested.length > 0
+ ? requested
+ : ALL_SCOPES.filter(s => s.endsWith(':read')),
+ )
+ setPageState('ready')
+ } catch {
+ setPageState('error')
+ setErrorMsg('Failed to validate registration request. Please try again.')
+ }
+ }
+
+ function handleLoginRedirect() {
+ const next = '/oauth/register?' + params.toString()
+ window.location.href = '/login?redirect=' + encodeURIComponent(next)
+ }
+
+ async function submitRegistration(approved: boolean) {
+ setSubmitting(true)
+ try {
+ const result = await oauthApi.register.submit({
+ client_name: validation?.client_name || clientName || 'MCP Client',
+ redirect_uri: redirectUri,
+ scopes: approved ? selectedScopes : [],
+ state,
+ approved,
+ })
+ setPageState('done')
+ window.location.href = result.redirect
+ } catch {
+ setPageState('error')
+ setErrorMsg('Registration failed. Please try again.')
+ setSubmitting(false)
+ }
+ }
+
+ // ---- Render states ----
+
+ if (pageState === 'loading' || pageState === 'done') {
+ return (
+