1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

claude mcp login/logout でMCPのOAuth認証を管理する ― launchd無人実行で「認証切れ」に気づく仕組みまで

1
Posted at

はじめに

当社(合同会社ジョインクラス)は、Claude Code を launchd で17個以上のジョブとして回し、記事公開・朝ダイジェスト・売上集計などをほぼ無人で動かしています。

その中で地味に痛かったのが リモートMCPサーバーのOAuth認証切れ です。無人実行(claude -p)のセッションでは OAuth のブラウザフローを開けないため、認証が切れたMCPサーバーは「要認証」のまま黙ってツールが消えます。ジョブ自体は成功扱いで終わるので、ログを見るまで誰も気づきません。

実際、この記事を書いている時点の無人セッションでも、Atlassian / Google Calendar / Linear / Windsor.ai / Vercel の5つが「requires authentication」状態でした。

この記事では次の3つを扱います。

  1. claude mcp login / claude mcp logout で認証を張り直す手順
  2. 無人ジョブの前に認証状態をチェックするシェル関数(当社の実装ベース)
  3. ハマりどころと検証方法

前提

  • Claude Code CLI(2026年10月時点の版)
  • リモートMCPサーバー(HTTP/SSE、OAuth 2.1対応)を claude mcp add 済み
  • macOS + launchd で claude -p を定期実行している

サブコマンドの細かいオプションはバージョンで変わります。作業前に必ず claude mcp --help で手元の版を確認してください。

1. 認証の張り直し: login / logout

まず状態を確認します。

# 登録済みMCPサーバーと接続状態の一覧
claude mcp list

# 出力例(抜粋)
# github: npx -y @modelcontextprotocol/server-github - ✓ Connected
# linear: https://mcp.linear.app/sse (SSE) - ⚠ Needs authentication
# vercel: https://mcp.vercel.com (HTTP) - ⚠ Needs authentication

Needs authentication になっているサーバーに対して、対話できるターミナルで ログインします。

# ブラウザが開き、OAuth同意画面 → コールバックでトークン保存
claude mcp login linear

# トークンを破棄したいとき(アカウント切替・退職者の端末整理など)
claude mcp logout linear

# 張り直し後に再確認
claude mcp list | grep linear

ポイントは以下です。

  • ログインは人間のいるターミナルでしか完了しない。claude -p や launchd 配下ではブラウザを開けません
  • トークンは macOS ではキーチェーンに保存されるため、.mcp.json をgitに入れても秘密情報は漏れません(逆に言えば、別マシンには引き継がれません)
  • アカウントを切り替えたいときは logout → login の順。login を重ねても古いトークンが使われ続けるケースがありました
  • 対話セッション内なら /mcp からも同じ操作ができます

なお claude.ai 側で追加したコネクタ(claude.ai Linear のように表示されるもの)は、CLIではなく claude.ai のコネクタ設定画面 で認可します。CLIの login 対象ではないので混同しないように注意してください。

2. 無人ジョブの前に認証切れを検知する

当社では無人実行を lib/claude-run.sh の claude_run という共通ラッパーに統一しています(コスト記録用)。実物はこうです。

.company/scripts/lib/claude-run.sh
#!/bin/bash
# claude を無人実行するときの共通ラッパー。実コストを記録する。
# 注意: --bare は認証を読まないため "Not logged in" で失敗する。使わない。

_CLAUDE_RUN_LIB="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

claude_run() {
  local label="$1"; shift
  claude --output-format json \
         --fallback-model claude-sonnet-5 \
         --max-budget-usd 3 \
         "$@" 2>/dev/null \
    | python3 "$_CLAUDE_RUN_LIB/record-cost.py" "$label"
}

ここに「必要なMCPが認証済みか」を確認する関数を足します。認証切れなら claude を呼ばずに終了し、通知だけ出します(呼ぶと1回 $0.3 前後かかるうえ、結果も欠けるため)。

.company/scripts/lib/mcp-auth-check.sh
#!/bin/bash
# 使い方: require_mcp_auth linear github || exit 0

require_mcp_auth() {
  local list missing=()
  list="$(claude mcp list 2>/dev/null)" || {
    echo "[mcp-auth] claude mcp list 失敗" >&2
    return 1
  }

  for server in "$@"; do
    local line
    line="$(grep -E "^${server}:" <<<"$list")"
    if [[ -z "$line" ]]; then
      missing+=("${server}(未登録)")
    elif ! grep -q "Connected" <<<"$line"; then
      missing+=("$server")
    fi
  done

  [[ ${#missing[@]} -eq 0 ]] && return 0

  local msg="MCP認証切れ: ${missing[*]} → ターミナルで claude mcp login <name>"
  echo "[mcp-auth] $msg" >&2
  osascript -e "display notification \"$msg\" with title \"AI-CEO\"" 2>/dev/null
  return 1
}

ジョブ側の呼び出しはこうなります。

source "$HOME/workspace/one-ceo/.company/scripts/lib/claude-run.sh"
source "$HOME/workspace/one-ceo/.company/scripts/lib/mcp-auth-check.sh"

# Linear を使うジョブなので、認証が無ければスキップ
require_mcp_auth linear || exit 0

RESULT=$(claude_run dept-dev --effort low -p "Linearの今週のIssueを要約して")

exit 0 にしているのは、launchd に失敗として再起動させないためです。認証は人間が login しない限り直らないので、リトライしても無駄にコストが積まれるだけです。

3. 落とし穴

--bare を付けると全部「未ログイン」になる

起動を軽くしようと --bare を付けたところ、認証情報を読まずに Not logged in で落ちました。上のラッパーのコメントはこの事故の名残です。MCPのOAuthトークンも同じく読まれないので、無人実行では付けないでください。

launchd 配下はキーチェーンにアクセスできないことがある

ログイン済みのはずなのにlaunchdからだけ Needs authentication になる場合は、ジョブが GUI セッション外(LaunchDaemons)で動いている可能性があります。当社はユーザーの ~/Library/LaunchAgents に置き、ログイン中のユーザーコンテキストで動かすことで解消しました。以前 cron がフルディスクアクセス問題で全滅し、launchd に全面移行したときと同じ系統のハマり方です。

claude mcp list 自体が遅い

list は各サーバーに実際に接続して確認するため、サーバーが多いと数秒かかります。ジョブごとに毎回呼ぶより、朝ダイジェストの前に1回だけ実行して結果をファイルに残し、他のジョブはそのファイルを見る、という形のほうが軽く済みます。

4. 検証方法

導入後は、わざと認証を切って検知されるか確かめてください。

claude mcp logout linear
bash -c 'source .company/scripts/lib/mcp-auth-check.sh; require_mcp_auth linear; echo "exit=$?"'
# [mcp-auth] MCP認証切れ: linear → ターミナルで claude mcp login <name>
# exit=1

claude mcp login linear
bash -c 'source .company/scripts/lib/mcp-auth-check.sh; require_mcp_auth linear; echo "exit=$?"'
# exit=0

macOS の通知が出て、exit が 1 → 0 に変われば完成です。

おわりに

自動化率を上げるほど「静かに壊れる箇所」が怖くなります。当社でも、AIが出したメールを確認なしで送って敬語の崩れたメールが取引先に届いたり、git push --force でブランチが消えたりしたことがあり、そのたびに「実行前に止まる仕組み」を足してきました。MCPの認証切れも同じで、login/logoutは人間がやり、切れていることの検知は機械にやらせる、という分担にしてからは無駄な実行がなくなりました。

MCPサーバーそのものの作り方や、OAuth対応のリモートMCPサーバーの設計については、書籍にまとめています。

📘 『Claude Code × MCP サーバー開発入門』
書籍一覧: https://zenn.dev/joinclass?tab=books

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?