はじめに
Claude のトークン使用量には上限があり、一定時間ごとにリセットされます。
現時点では、5時間間隔でリセットが発生します。
毎朝9時(JST)にセッションを開始すると、リセットのタイミングが次のように並びます。
09:00 → 14:00 → 19:00 → 00:00(翌日)→ 05:00 → ...
日中の主要な作業時間帯(9時・14時・19時)に新鮮なトークン枠が確保されます。
これは Claude を使い倒す上でかなり有利なサイクルです。
問題は、「毎朝9時にセッションを開始する」という行為を自動化したい点です。
そこで Claude Code の /schedule スキルを使います。
Anthropic のクラウド上でエージェントが毎朝9時に自動起動するため、ローカルマシンは起動していなくてかまいません。
この記事では、毎朝9時のセッション起動を自動化する手段として /schedule を活用し、ClaudeのコネクタからGoogle Calendar連携して、イベント登録してもらいます。
最終成果物として、毎朝このようなイベントが Google Calendar に自動追加されます。
今回は RemoteTrigger APIなどでmcp設定を見るので Claude Code(プロンプト)から作成してもらいます。
Web UI では https://claude.ai/code/routines で確認できますが、より詳細なものは現時点ではClaudeCodeからRemoteTriggerを実行してもらうのが良いです。
/schedule スキルとは何か
Claude Code の /schedule は、RemoteTrigger API を通じて Anthropic のサンドボックス環境でエージェントを cron 定期起動できる仕組みです。
重要な特徴を整理しておきます。
- ローカルの Claude Code セッションが落ちていても動く
- 設定した MCP コネクターをそのまま利用できる
- 実行ログが
claude.ai/code/routinesに残る
ルーティン定義の主要な構成要素は次のとおりです。
| フィールド | 役割 |
|---|---|
cron_expression |
起動タイミング(UTC 基準) |
allowed_tools |
エージェントが使えるツールの許可リスト |
mcp_connections |
接続する MCP サーバーの定義 |
events[].message.content |
エージェントに渡すプロンプト |
サンドボックス環境はネットワーク制限があります。
任意の外部 API を curl や WebFetch で叩ける保証はありません。
この制限が後ほど天気取得で大きな障壁になります。
全体設計: 毎朝9時 JST に何をさせるか
処理の流れは次のとおりです。
- JST 基準で明日の日付を取得する
- 東京の明日の天気データを取得する
- 天気情報を日本語に整形する
- Google Calendar に終日イベントを登録する
Step 1: Google Calendar MCP コネクターを接続する
まずブラウザで次の URL にアクセスして、Google Calendar コネクターを追加します。
「Google Calendar」を選択して OAuth 認証を完了させてください。
Step 2: コネクター UUID を取得する
mcp_connections フィールドには connector_uuid を指定する必要があります。
ところが、公式ドキュメントにはこの UUID をどこから取るかが明記されていません。
コネクターを設定ページで表示すると、URL が次の形式になっています。
https://claude.ai/settings/connectors/{uuid}
この {uuid} 部分がそのまま connector_uuid として使える値です。
ブラウザのアドレスバーをコピーして UUID を取り出してください。
UUID は小文字のハイフン区切り(v4 形式)です。
例: a1b2c3d4-e5f6-7890-abcd-ef1234567890
Step 3: MCP サーバー URL を特定する
mcp_connections には connector_uuid だけでなく url フィールドも必要です。
これを省略すると HTTP 400 エラーが返ります。
では URL はどこから取るのか。
これも公式ドキュメントには明記されていません。
Google Calendar MCP ツール(mcp__claude_ai_Google_Calendar__authenticate など)のスキーマを ToolSearch で読み込むと、description の中に MCP サーバー URL が書かれていることがわかります。
Google Calendar の MCP サーバー URL は次のとおりです。
https://calendarmcp.googleapis.com/mcp/v1
最終的な mcp_connections の記述例はこちらです。
"mcp_connections": [{
"connector_uuid": "<コネクターUUID>",
"name": "Google-Calendar",
"url": "https://calendarmcp.googleapis.com/mcp/v1"
}]
url フィールドを省略すると HTTP 400 が返ります。
必ず指定してください。
Step 4: 天気データ取得でひたすらハマった話
ここが今回の最大のクライマックスです。
試行錯誤の全記録を書きます。
(a) wttr.in を curl → 403
最初に試みたのは、天気 API として定番の wttr.in を Bash の curl で叩く方法です。
curl "https://wttr.in/Tokyo?format=j1"
結果: 403 Forbidden。
サンドボックスのアウトバウンド制限に引っかかりました。
(b) open-meteo.com に切り替え → 同じく 403
次に、オープンソースで無料の気象 API である open-meteo.com を試しました。
curl "https://api.open-meteo.com/v1/forecast?latitude=35.69&longitude=139.69&daily=temperature_2m_max&timezone=Asia/Tokyo"
結果: 同じく 403。
(c) Bash の curl 自体がホスト許可リスト制限でブロック
2 つ試して同じ結果になったので、curl そのものの問題を疑いました。
サンドボックスには許可された外部ホストのリストがあり、任意のホストには接続できないようになっています。
(d) WebFetch も制限に当たる
WebFetch ツールを使って同じ URL にアクセスしてみました。
これも同様にブロックされました。
(e) WebSearch で「東京 明日の天気」を検索 → 安定して取得できる
試行錯誤の末、WebSearch ツールで検索する方法が安定して動くことがわかりました。
WebSearch: "東京 明日の天気"
tenki.jp や Weather.com などの検索結果から天気情報を抽出できます。
最高気温・最低気温・天気概況・降水確率が揃ったデータを取得できます。
得られた知見
リモートサンドボックスでは任意の外部 API を curl や WebFetch で叩けません。
外部データを取得する場合は、MCP コネクター経由か WebSearch を使う設計にする必要があるみたいです。
Step 5: allowed_tools に WebSearch を追加する
デフォルトの allowed_tools には WebSearch が含まれていません。
明示的に追加しなければ、エージェントは WebSearch を使えません。
最終的に採用した allowed_tools セットはこちらです。
"allowed_tools": ["Bash", "Read", "Write", "Edit", "Glob", "Grep", "WebFetch", "WebSearch"]
WebSearch だけでなく WebFetch も入れているのは、エージェントが URL から詳細情報を取得しようとする場合に備えるためです。
サンドボックスの制限で実際には動かないケースもありますが、ツールとして使える状態にしておくことで、エージェントが代替手段を選択しやすくなります。
Step 6: 日付ズレ問題 — UTC と JST の境界で事故る
エージェントが Bash の date コマンドを実行すると、UTC 時刻が返ります。
date -d "tomorrow" +%Y-%m-%d
# UTC 00:05 に実行すると UTC 翌日 = JST 同日 になる
JST 09:00 に起動するルーティンの場合、UTC では 00:00 です。
date -d "tomorrow" を UTC で実行すると、JST の「明日」より1日ずれた日付が返ることがあります。
対策として、TZ 環境変数を指定して JST 基準で日付を取得します。
TZ=Asia/Tokyo date -d "tomorrow" +%Y-%m-%d
プロンプトにこのコマンドを明示的に書いておくことで、エージェントが正しい日付を取得できます。
date コマンドを素のまま使うと UTC 基準になります。
JST で「明日」を取得するには必ず TZ=Asia/Tokyo を付けてください。
完成したルーティン定義
エージェントに渡すプロンプト全文
You are a weather assistant. Follow these steps carefully:
## Step 1: Get tomorrow's date in JST
Run this bash command:
TZ=Asia/Tokyo date -d "tomorrow" +%Y-%m-%d
Save the result as TOMORROW_DATE (format: YYYY-MM-DD).
## Step 2: Fetch tomorrow's Tokyo weather via WebSearch
Use the WebSearch tool with this query:
"東京 明日の天気"
From the search results, extract:
- max temperature (C)
- min temperature (C)
- weather condition (text in Japanese)
- precipitation probability (%)
Use whichever result contains the most complete data for TOMORROW_DATE.
## Step 3: Convert weather condition to Japanese if needed
If the condition is already in Japanese, keep it as-is.
If it is in English, map it:
- Clear / Sunny -> "快晴"
- Mostly Sunny / Partly Cloudy -> "おおむね晴れ"
- Mostly Cloudy -> "一部曇り"
- Cloudy / Overcast -> "曇り"
- Rain / Showers -> "雨"
- Snow -> "雪"
- Thunderstorm -> "雷雨"
- Other -> "不明"
## Step 4: Create Google Calendar event
Use the Google Calendar MCP tools to create an all-day event:
- calendarId: "primary"
- Date: TOMORROW_DATE
- Title: "東京の天気: [condition] [max_temp]C"
- Description: "最高: [max_temp]C / 最低: [min_temp]C / 降水確率: [precip]% / Source: [source name]"
- Reminders: useDefault=false, overrides=[{"method": "popup", "minutes": 120}]
(120 minutes before midnight UTC = 07:00 JST on the event day)
First check if an event with '東京の天気' already exists for TOMORROW_DATE.
If yes, update it. If no, create a new one.
## Step 5: Confirm
Report the final event title, date, description, and reminder setting to confirm success.
RemoteTrigger API create body
{
"name": "東京明日の天気 to Google Calendar",
"cron_expression": "0 0 * * *",
"enabled": true,
"job_config": {
"ccr": {
"environment_id": "<environment_id>",
"session_context": {
"model": "claude-sonnet-4-6",
"sources": [],
"allowed_tools": [
"Bash",
"Read",
"Write",
"Edit",
"Glob",
"Grep",
"WebFetch",
"WebSearch"
]
},
"events": [{
"data": {
"uuid": "<lowercase-v4-uuid>",
"session_id": "",
"type": "user",
"parent_tool_use_id": null,
"message": {
"role": "user",
"content": "<上記プロンプト全文>"
}
}
}]
}
},
"mcp_connections": [{
"connector_uuid": "<コネクターUUID>",
"name": "Google-Calendar",
"url": "https://calendarmcp.googleapis.com/mcp/v1"
}]
}
<environment_id> は Claude Code の設定画面から確認できます。
<lowercase-v4-uuid> は任意の v4 UUID を小文字で生成してください。
python3 -c "import uuid; print(uuid.uuid4())"
運用してみてわかったこと・落とし穴まとめ
実際に数日間運用して気づいたことを整理します。
- コネクターを追加後は Claude Code を再起動しないと /schedule に反映されない
- MCP サーバー URL は省略不可。
urlフィールドを必ず指定する - サンドボックスでは任意の外部 API を curl できない。WebSearch か MCP を使う
- 日付は
TZ=Asia/Tokyo date -d "tomorrow"で JST 基準を明示する - 終日イベントのリマインダー分数は UTC midnight からの逆算になる
- 実行ログは
https://claude.ai/code/routinesで確認できる - 同日に重複して実行された場合のために、プロンプトに「既存イベントがあれば更新する」ロジックを入れておく
- WebSearch の結果は検索エンジンの仕様変更に依存するため、稀にデータ取得が失敗することがある
実行ログページでは、各ルーティンの実行結果(成功・失敗・エラーメッセージ)を確認できます。
初期設定後は必ずログを確認して、期待どおりに動いているかチェックしてください。
発展: 他のルーティンにも応用するには
「WebSearch で情報取得 → 整形 → MCP で書き込み」というパターンは、他のルーティンにもそのまま応用できます。
朝のニュースダイジェスト
WebSearch でその日のニュース検索 → 要約 → Google Calendar や Slack に投稿
GitHub 通知サマリ
GitHub MCP コネクターで通知を取得 → 重要度でフィルタ → Slack MCP で送信
週次レビューの自動作成
毎週月曜に先週の Google Calendar イベントを一覧取得 → GPT で要約 → Google Docs に保存
共通のパターンとして意識しておくべき点があります。
- 外部データ取得は WebSearch か MCP コネクター経由にする
- 日付・時刻操作は必ずタイムゾーンを明示する
- 重複実行に備えて「既存があれば更新」ロジックを入れる
- allowed_tools は必要なものを明示的に列挙する
おわりに
/schedule は Claude Code を「クラウド常駐エージェント」として機能させられる強力な仕組みです。
設定さえ済めば、ローカルマシンを起動しなくても毎日決まった時刻にエージェントが動き続けます。
一方で、次の3点を押さえていないとほぼ確実に詰まります。
- サンドボックスのネットワーク制限
- UTC と JST のズレ
- MCP 接続設定の細かい仕様
これらのハマりどころを先に知っておけば、設定自体は難しくありません。
ぜひ天気以外のルーティンにも応用してみてください。
