
はじめに
Anthropicの規約変更で、サードパーティのハーネスからClaude系のサブスクOAuth利用がブロックされた。世の中はそこそこ騒いでいたが、正直なところ、俺にはあんまり関係のない話だった。
Claude Code CLIは手元にある。Discordに投げたメッセージをCLIに渡して、返事をDiscordに返す。それだけの橋を架ければいい。
だから作った。
骨組みだけ作った
作ったのはLogBot。Discord上のメッセージをClaude Code CLIに転送して、応答をDiscordに返す。それだけのBot。
Discord ──→ LogBot ──→ Claude Code CLI
↑ │
└── 応答を投稿 ──┘
最低限の骨組みとして、こんな機能を持たせた。
- セッション管理 — UUIDベースでClaude Codeのセッションを維持。VSCodeのセッションとは完全に分離される
- メッセージキュー — Claudeが処理中にメッセージが来てもキューに溜めて順番に処理。取りこぼさない
- 承認フロー — Claudeがファイルを編集しようとしたら、Discordに通知が飛んで、リアクション(✅ / ❌)で承認か拒否を返せる
- MCPサーバー —
tools/ディレクトリにファイルを置けば、Claude側からツールとして使える
ここで大事なのは、MCPツールは最初ゼロだったということ。天気もカレンダーも電車情報も、何もない。ただの骨組み。
でも、この骨組みには一つだけ強烈な特性がある。
Claudeはファイルを書ける。 つまり tools/ にJavaScriptファイルを追加できる。MCPサーバーは tools/ 配下を自動スキャンして登録する。
Claudeが自分で自分の手足を作れる。
「時計が欲しい」から始まった
最初にDiscordからClaudeに頼んだのは些細なことだった。
「今何時?」
Claude Code CLIはシステムの時刻を取れるが、MCPツールとして切り出されていたほうがスマートだ。Claudeに「時刻を返すMCPツールを作ってくれ」と頼んだ。
数秒で tools/current-time.js が生えた。
次は「天気が知りたい」。Open-Meteoという無料の天気APIを使った tools/weather.js が生えた。APIキーすら不要。
「Googleカレンダーの予定を見たい」。OAuth認証のヘルパーごと、tools/gcal-auth.js と tools/gcal-list.js が生えた。
「Gmailも読みたい」。同じ要領で、認証・一覧・本文読み取り・送信・フィルタ・一括削除まで、Gmailツール群が一式生えた。
全部、Discordから「これ欲しい」と言っただけだ。自分はコードを一行も書いていない。
CRONが叩くのはコードじゃない
ツールが揃ってくると、次に欲しくなるのは定期実行だ。
「毎朝7時に天気と電車の運行情報と今日の予定を教えてほしい」
ここで普通なら、天気APIを叩いてカレンダーAPIを叩いて運行情報をスクレイピングして整形して送信する、というスクリプトを書いてCRONに登録する。
でもせっかくClaude使うんだから、コードじゃなくてプロンプト渡した方が面白い。
{
"cron": "0 7 * * *",
"prompt": "朝の定期報告をして。天気(さいたま市北区、今日)・電車の運行情報・今日のカレンダー予定を教えて。おはようの挨拶も添えてね。"
}
朝7時になると、スケジューラーがClaudeを起こす。Claudeは天気ツールを叩き、カレンダーツールを叩き、電車運行情報ツールを叩き、結果をまとめてDiscordに投稿する。
何のツールをどう組み合わせるかはClaudeが判断する。ロジックはコードに書かれていない。プロンプトに書かれている。
つまり、報告のフォーマットを変えたければプロンプトを書き換えるだけ。「明日の天気も追加して」と一言Discordに送るだけで、翌朝から変わる。
出発通知——これが本題
朝の報告は序の口だった。
「今日の予定に合わせて、出発する時間になったら教えてほしい」
この一言から、出発通知の仕組みが生まれた。
やりたいこと
「14時に新宿で打ち合わせ」という予定があったら、移動時間を逆算して、出発の30分前に天気と電車の運行情報付きで通知してほしい。
普通のリマインダーとの違い
Googleカレンダーの通知は「予定の30分前」に鳴る。でも移動時間は考慮してくれない。自宅から新宿まで1時間かかるなら、13時半の通知じゃ遅い。12時半に「そろそろ出ろ」と言ってほしい。
しかも出先にいたら計算が変わる。午前中に大宮で別の用事があって、そこから新宿に向かうなら、移動時間は短くなる。
Claudeがやっていること
CRONで毎時(6時〜22時)、Claudeにこういうプロンプトが飛ぶ。
カレンダーを確認して、場所のある予定について、出発通知が必要なら登録して。
Claudeはこの指示を受けて、自分で判断する。
- カレンダーを見る — 今後の予定を取得。場所が設定されている予定を探す
- 現在地を推定する — 今進行中のカレンダー予定があれば、その場所にいると推定。なければ自宅
- 移動時間を計算する — Google Maps APIで現在地から目的地までの移動時間を算出。2km以内なら徒歩、それ以上は電車。日本ではTransit APIが使えないので、車の所要時間+15分で近似している。泥臭いが意外と実用的だ
- 出発時刻を逆算する — 予定の開始時刻 - 移動時間 = 出発時刻
- 通知ジョブを登録する — 出発の30分前にワンショットジョブをスケジューラーに突っ込む
そして出発30分前になると、ジョブが発火してClaudeが起き、天気と電車の運行情報を取得して通知を組み立てる。
🚨 もうすぐ出発の時間だよ!
📅 打ち合わせ(14:00開始)
📍 目的地: 新宿
🚃 電車(推定): 約55分 → 12:35出発
☁️ 今日(月) 一部曇り
🌡️ 22.3℃ / 14.1℃ ☔ 10%
🟢 現在、異常のある路線はありません!
ロジックはどこにあるか
ここが一番伝えたいところだ。
この一連の判断ロジックは、departure-check.js というMCPツールにまとまっている。でも、このツールを作ったのもClaudeだ。「出発前に通知してほしい」と言ったら、必要なツール(移動時間、現在地推定)がまだなかったので、それらを先に作り、最後にそれらを組み合わせる departure-check.js を作った。
そしてCRONが叩いているのは、相変わらずプロンプトだ。「カレンダーを確認して、出発通知が必要なら登録して」。この一文でClaudeがツールを駆使して判断する。
個々のパーツはシンプルだ。天気を取るツール、カレンダーを見るツール、移動時間を計算するツール、電車の運行情報を取るツール。でもそれをいつ、どう組み合わせるかはClaude側にある。コードにif文を並べたんじゃない。AIが状況を見て判断している。
自己拡張する環境
ここまでの話をまとめると、こういうことだ。
- MCPツール = 手足。個別の能力(天気、カレンダー、移動時間、メール…)
- Claude = 頭。ツールを組み合わせて判断する
- CRON = 目覚まし。Claudeを定期的に起こす。叩くのはプロンプト
- Discord = 窓口。リクエストも通知もここ
そして最大の特徴は、手足が足りなければClaudeがその場で作ること。
「こういう機能欲しい」とDiscordに送れば、Claudeがツールのコードを書いて tools/ に追加する。MCPサーバーが自動で検出して登録する。次の瞬間から使える。
逆に言えば、自分がやったのは骨組みを作っただけだ。Discord-CLI間の橋と、MCPの自動スキャンと、CRONスケジューラー。
おわりに
今は朝7時に天気と予定を教えてくれて、外出前に移動時間を逆算して運行情報付きで通知してくれて、メールの管理もしてくれる。もちろんツールの挙動を手直しした場面もあるが、基本はDiscordから「これ欲しい」と言って増えていった。
こんなAI初心者のアイデアで当たり前かもしれないけど、GitHubで公開しておきます。
OpenCClaw — Discord経由でClaude Code CLIを操作するBotシステム。