macOS Calendar & Reminders について
che-ical-mcp は macOS の EventKit 上に構築された Swift 製 MCP サーバーで、Claude からカレンダーとリマインダーを操作できます。スケジュールやタスクを AI アシスタントで管理したい macOS ユーザー向けで、競合検出、一括操作、取り消し・やり直しに対応します。
主な機能
- 01カレンダーイベントの作成・検索・更新・削除
- 02タグとキーワード検索に対応したリマインダー
- 03競合検出と重複イベントの検索
- 04一括作成・移動・削除
- 05変更の取り消しとやり直し履歴
活用シーン
- 01今日や今週の予定を確認し、イベントを追加
- 02新しい予定と既存の予定の重複を確認
- 03タグ単位でリマインダーを整理し一括処理
MCP 対応
MCP サーバーとして 29 のツールを公開し、クライアントから macOS のカレンダーとリマインダーの読み書きを可能にします。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
ローカルサーバーのツールはマシン上で起動して初めて取得できます。メンテナーはまだツール一覧を提供していません。
詳細
che-ical-mcp
Claude に macOS のカレンダーとリマインダーをネイティブに操作させます。 EventKit を直接利用して構築された Swift 製 MCP サーバーです。イベント、リマインダー、タグ、一括操作、競合検出、取り消し/やり直しに対応する 29 個のツールを備えています。カレンダーイベントだけでなく、リマインダーやタスクも操作できます。
インストール
Claude Code — このリポジトリをマーケットプレイスとして登録し、プラグインをインストールします。プラグインには /today、/week、/quick-event、/remind スラッシュコマンドと、イベントの書き込みごとに曜日を確認する PreToolUse フックが含まれています。
claude plugin marketplace add PsychQuant/che-ical-mcp
claude plugin install che-ical-mcp@che-ical-mcp
Claude Desktop — Releases から最新の .mcpb をダウンロードし、ダブルクリックしてインストールします。
スタンドアロン MCP — プラグインの追加機能なしで、29 個のツールを備えたサーバーのみを使用します。
mkdir -p ~/bin
curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP && chmod +x ~/bin/CheICalMCP
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
初回使用時、macOS はカレンダーとリマインダーへのアクセスを求めます。許可をクリックしてください。ソースからのビルド、既存環境への上書きアップグレード、SSH/launchd/VS Code での実行については、詳細なガイドをインストールでご確認ください。
che-ical-mcp を選ぶ理由
| 機能 | その他のカレンダー MCP | che-ical-mcp |
|---|---|---|
| カレンダーイベント | あり | あり |
| リマインダー/タスク | なし | あり |
| リマインダーの #タグ | なし | あり(MCP レベル) |
| 複数キーワード検索 | なし | あり |
| 重複検出 | なし | あり |
| 競合検出 | なし | あり |
| 一括操作 | なし | あり |
| ローカルタイムゾーン | なし | あり |
| ソースの判別 | なし | あり |
| カレンダーの作成 | 一部 | あり |
| カレンダーの削除 | 一部 | あり |
| イベントのリマインダー | 一部 | あり |
| 場所と URL | 一部 | あり |
| 言語 | Python | Swift(ネイティブ) |
全 29 個のツール
カレンダー(4)
| ツール | 説明 |
|---|---|
list_calendars | すべてのカレンダーとリマインダーリストを一覧表示します(source_type を含む) |
create_calendar | 新しいカレンダーを作成します |
delete_calendar | カレンダーを削除します |
update_calendar | カレンダーの名前を変更するか、色を変更します(v0.9.0) |
イベント(4)
| ツール | 説明 |
|---|---|
list_events | フィルター/並べ替え/件数制限を指定してイベントを一覧表示します(v1.0.0) |
create_event | イベントを作成します(リマインダー、場所、URL、イベントごとのタイムゾーン、除外日を指定した繰り返しに対応) |
update_event | イベントを更新します(タイムゾーン、繰り返し、繰り返しイベントの span を含む) |
delete_event | イベントを削除します(繰り返しイベントの発生回に対応) |
繰り返しの除外(#182):
create_event(およびcreate_events_batchの各項目)では、作成時に繰り返しシリーズ内の特定の日付をスキップするため、recurrence.excluded_occurrence_datesを指定できます。ベストエフォートの全件成功または全件取り消しのセマンティクスで適用されます(失敗があれば、補償削除によって新しいシリーズ全体を削除します。ロールバックに失敗した場合はその旨を報告し、黙って処理することはありません。最初の発生回は除外できません)。undoを 1 回実行すると、除外設定を含めてシリーズ全体が取り消されます。除外された日付は編集された発生回ではなく、削除された発生回です(iCloud のみで確認済み、2026-10-05。他のストアは未確認)。そのため、この取り消しを妨げません。ただし、シリーズ作成後に個別に編集された発生回は妨げます(#236)。既知の制限:冪等な再試行では、指定された日付がすべてすでに存在しない重複繰り返しシリーズはskippedになりますが、既存シリーズにすでに設定されている、要求内容を超える追加の除外は検出されません。
リマインダー(8)
| ツール | 説明 | |------|-------------| | `list_reminders` | リマインダーをフィルター、並べ替え、件数制限付きで一覧表示し、タグを抽出します(v1.0.0) | | `create_reminder` | 期限日とタグを指定してリマインダーを作成します(v1.3.0)。単独の `YYYY-MM-DD` の期限日は日付のみとして扱われます(#267)。その場合、レスポンスに `date_sync` が含まれ、`aligned` は保存されたリマインダーに基づいて判定されます(#301) | | `update_reminder` | リマインダーを更新します(タグ、`clear_due_date` を含む)(v1.3.0) | | `complete_reminder` | 完了/未完了としてマークします | | `delete_reminder` | リマインダーを削除します | | `search_reminders` | キーワードまたはタグでリマインダーを検索します(v1.3.0) | | `list_reminder_tags` | 使用回数とともに一意なタグをすべて一覧表示します(v1.3.0) | | `cleanup_completed_reminders` | 完了したリマインダーを1回の呼び出しですべて削除します。デフォルトでは `dry_run` によるプレビューを行います(v1.7.2)。`undo` で削除した項目を再作成します(#243) |繰り返しリマインダー(#194): 一覧表示/検索では has_recurrence、完全な公開用 recurrence_rules、精度を考慮した due が含まれます。完了時には、書き込み結果を示す operation と、確認済み/不明/該当なしを示す next_occurrence が追加されます。従来の is_completed ではなく operation.status を使用してください。正常に完了しても、次の発生分が未完了のままの場合があります。後続の発生情報が不明でも、2回目の書き込みを行ってはいけません。IDが異なる後続分、または確認できない後続分は、シリーズが終了したとは見なさず、unknown として報告されます。繰り返し項目の完了を取り消す際は、IDで対象を確認します(#204)。識別子が記録された発生分を指さなくなった場合は、明示的に拒否し、履歴項目を削除してスタックが詰まらないようにします。破壊的変更(#205): complete_reminder/list_reminders/search_reminders の completed は、JSON のブール値である必要があります。文字列と数値は拒否されます。省略または null の場合は従来どおりの意味になります。破壊的変更(#207、未リリース): 同じ仕様が、すべてのブール型ツール引数(all_day、clear_*、include_completed、dry_run、delete_original)にも適用されるようになりました。レスポンスの仕様と制限を参照してください。
リマインダーの日程変更(#227/#235/#237): Reminders.app は、リマインダーに設定された最も早い絶対日付アラームの日付を表示します。そのため、時刻付きの due_date を指定して update_reminder を実行すると、開始日とすべての絶対日付アラームも期限日に合わせて移動します(単独の日付を指定すると、後述のとおりリマインダーは日付のみになります。以前の期限日に時刻がない場合は暦日単位で、そうでない場合は正確な時間差に基づいて移動します)。clear_due_date を指定すると、開始日もクリアされ、絶対日付アラームも削除されます。移動時には既存のオフセットが維持されます。そのため、アラームがすでに期限日と一致していないリマインダーを修正するには、realign_to_due: true を指定してください(due_date とともに指定するか、現在の期限日に対して単独で指定できます)。最も早い絶対日付アラームは期限日に設定され、それ以降のアラームは期限日からの間隔を維持します。開始日は、すでに期限日と一致している場合を除き、期限日に設定されます(日付のみの期限日では、その日の任意の時刻。時刻付きの期限日では、期限時刻、またはその日の午前0時、または時刻なし)。レスポンスの date_sync には移動した内容が示され、date_sync.aligned は、保存されたリマインダーで開始日と最も早い絶対日付アラームが期限日と一致しているかどうかを示します(意図的に別の日時に設定されたアラームがある場合も false になります)。Reminders.app で作成した日付のみのリマインダーなど、フローティングリマインダーに時刻付きの期限日を設定すると、明示的に指定されたタイムゾーンが維持されます。取り消すと、場所アラームを含む開始日とアラームが復元されます(#228)。
日付のみのリマインダー(#267): create_reminder、create_reminders_batch、または update_reminder に日付のみ(2026-10-18)を指定した due_date を渡すと、Reminders.app と同様に、時刻を含まない日付のみのリマインダーが作成されます。読み戻したとき、due.time は null です。update_reminder では、開始日もその日に設定されます。これは、開始日と期限日が異なる日付に設定されていた場合も同様です。また、絶対日時アラームは削除されます。Reminders.app では最も早いアラームが表示され、その時刻が表示され続けるためです(デバイスで確認済み)。相対アラームと場所アラームは維持され、date_sync.absolute_alarms_removed に削除された数が記録されます。時刻付きのリマインダーに日付のみを指定すると、時刻が削除されます。時刻付きの期限日は、これまでどおり機能します。日付のみを指定した create_reminder(および create_reminders_batch で作成された各行)は、保存したリマインダーを読み戻して date_sync を返します。これは update_reminder と同様です。期限日が時刻付きで返された場合、見つからなかった場合、またはリマインダーを再読み込みできなかった場合、date_sync.aligned は false になります(#301)。書き込んだ期限日が読み戻し時に見つからなかった場合も、以前は aligned が省略されていた update_reminder で aligned: false が返されます。list_reminders では、日付のみのリマインダーはホストのタイムゾーンでその日が終わった後にのみ期限切れになります。また、list_reminders と search_reminders では、due_date / due_date_local はホストのタイムゾーンでその日の00:00として読み取られます(#297)。
高度な機能(10) ✨ v0.3.0+ で新登場
| ツール | 説明 |
|---|---|
search_events | AND/OR 条件でキーワードを指定してイベントを検索します |
list_events_quick | today、tomorrow、this_week、next_7_days などのクイックショートカットを提供します |
create_events_batch | 複数のイベントを一度に作成します(イベントごとにタイムゾーンを指定可能) |
check_conflicts | 指定した時間範囲内で重複するイベントを確認します |
copy_event | イベントを別のカレンダーにコピーします。delete_original を指定すると、move_events_batch のように元のイベントを削除します(繰り返しイベントは不可) |
move_events_batch | 繰り返し設定と参加者を維持したまま、イベントを別のカレンダーにその場で移動します。繰り返しイベントには span / occurrence_dates を指定します(#226) |
delete_events_batch | ドライランでのプレビュー付きで、ID または日付範囲を指定してイベントを削除します(v1.0.0) |
find_duplicate_events | カレンダー間で重複するイベントを検索します(v0.5.0) |
create_reminders_batch | 複数のリマインダーを一度に作成します(v0.9.0) |
delete_reminders_batch | 複数のリマインダーを一度に削除します(v0.9.0)。undo で削除したリマインダーを再作成します(#243) |
イベントの移動(#226): 移動ではイベントのカレンダーが変更されるため、繰り返し設定、参加者、その他すべてのフィールドが維持されます。同一アカウント内では識別子は変わらず、アカウント間では変わります(各結果に id_changed と new_event_id が記録されます)。繰り返しイベントの場合、span: this(デフォルト)では occurrence_dates で指定された回のみを移動し、その回は単発イベントになります。span: all ではシリーズ全体を移動します。日付を指定していない繰り返しイベントは移動できません。その場での移動に失敗した場合、繰り返し設定も参加者もないイベントに限り、イベントをコピーして元のイベントを削除します。各結果には method(in_place / copied / split / unchanged)と、引き継がれなかったフィールドがあればその内容が記録されます。
元に戻す/やり直す(3) ✨ v1.4.0 で新登場
| ツール | 説明 |
|---|---|
undo | 直近のカレンダー/リマインダー操作を元に戻します |
redo | 最後に元に戻した操作をやり直します。完了操作のみ再度書き込まれます。作成、削除、更新、移動の場合、やり直しでは何も書き込まず、使用するツールを示して success: false を返し、その項目をやり直し履歴から削除します(#247) |
undo_history | 元に戻せる操作をタイムスタンプとともに一覧表示します |
delete_events_batch、シリーズの削除、delete_reminders_batch、cleanup_completed_reminders は、それぞれの呼び出しで実際に削除された項目を保持する取り消しエントリを1つ記録し、それが最新のエントリになります。1回の undo で、その1回の呼び出し内で、項目を1つずつ保存して再作成します。各項目には新しい識別子が付与され、取り消しスナップショットに記録された内容が反映されます。クリーンアップでは、最大で limit(デフォルトは1000)件、またはすべての reminder_ids エントリが保持されます。リマインダーのサブタスクは記録されません。最初の書き込みの前に、各項目が戻されるカレンダーまたはリストを、復元時に参照する記録済みの識別子で確認します(別のアカウントにある同名のリストは該当しません)。1つでも見つからない、または読み取り専用の場合(更新を要求した後に再確認します)、何も書き込まず、エントリ全体を保持します。また、エラーには、カレンダーまたはリストが存在する項目数が示されます。discard_id で破棄すると、すべての項目が破棄されます(一部だけ復元される場合については #287)。保存に失敗した場合、エントリにはまだ復元されていない項目だけが同じIDで残り、失敗した項目は最後に処理されるよう移動されます。そのため、次の undo では他の項目が先に復元されます。ただし、失敗した項目のカレンダーまたはリストがその時点で見つからない、または読み取り専用の場合は、前述のチェックで拒否されます。このような呼び出しのたびにやり直し履歴が消去され、保持される取り消しエントリは最新の50件だけです。
インストール
手早くインストールする方法は、このREADMEの冒頭にあります。こちらは完全なリファレンスです。手動設定、ソースからのビルド、権限に関する特殊なケース、既存インストールのアップグレード、CLI モードを説明します。
要件
- macOS 14.0 以降(Sonoma 以降。v1.11.0 以降では、TCC の権限 API を完全に利用するために必要です)
- Xcode Command Line Tools(ソースからビルドする場合のみ)
Claude Desktop
ワンクリック(推奨): Releasesから最新のche-ical-mcp-<version>.mcpbをダウンロードし、ダブルクリックして Claude Desktop を再起動します。
手動設定: バイナリをダウンロードし、claude_desktop_config.jsonからそのバイナリを指定します。
curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o /usr/local/bin/che-ical-mcp
chmod +x /usr/local/bin/che-ical-mcp
~/Library/Application Support/Claude/claude_desktop_config.jsonを編集してから、Claude Desktop を再起動します。
{
"mcpServers": {
"che-ical-mcp": {
"command": "/usr/local/bin/che-ical-mcp"
}
}
}
Claude Code — プラグイン(推奨)
claude plugin marketplace add PsychQuant/che-ical-mcp
claude plugin install che-ical-mcp@che-ical-mcp
- Claude Code 内では、スラッシュコマンドの
/plugin marketplace add PsychQuant/che-ical-mcpと/plugin install che-ical-mcp@che-ical-mcpも同じように使えます。 - マーケットプレイスは
marketplace.jsonのURLを直接指定するのではなく、Git リポジトリ(owner/repo)経由で追加してください。プラグインのsourceは同一リポジトリ内の相対パス(./plugin)であり、Git 経由で追加した場合にのみ解決されます。 psychquant-claude-pluginsアグリゲーターにも含まれています(claude plugin install che-ical-mcp@psychquant-claude-plugins)。どちらも同じバージョンのバイナリを提供します。- 初回使用時にバイナリがまだ存在しない場合、ラッパーが
~/bin/CheICalMCPに自動ダウンロードします。
Claude Code — スタンドアロン MCP
mkdir -p ~/bin
# If upgrading, remove the old binary first. On macOS 26 the kernel can kill a
# fresh binary that inherits a stale code-signature cache from the old inode —
# one a running MCP process may still be holding open.
rm -f ~/bin/CheICalMCP
curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP
chmod +x ~/bin/CheICalMCP
# --scope user: available in all projects · --transport stdio: local stdin/stdout
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
💡 ヒント: バイナリは
~/bin/のようなローカルディレクトリに置いてください。Dropbox、iCloud、OneDrive などのクラウド同期フォルダーでは、ファイルの同期時に MCP 接続がタイムアウトすることがあります。
ソースからビルド(任意)
git clone https://github.com/PsychQuant/che-ical-mcp.git
cd che-ical-mcp
make release && make install
claude mcp add --scope user --transport stdio che-ical-mcp -- ~/bin/CheICalMCP
⚠️ Swift 6/Xcode 18 をお使いの場合:
swift buildを直接実行しないでください。上流の MCP SDK に並行処理に関するエラーがあります(swift-sdk#214)。Makefile がこれを自動検出し、Swift 5 言語モードに切り替えます。
権限の付与
初回使用時に、macOS からカレンダーとリマインダーへのアクセス許可を求められます。両方で許可をクリックしてください。
⚠️ macOS Sequoia(15.x)に関する注意: 権限ダイアログの表示先はバイナリ自体ではなく、MCP サーバーを起動した親アプリケーションです。つまり、次のようになります。
環境 権限の表示先 Claude Desktop Claude Desktop.app ✅(自動的に動作します) Terminal.app内の Claude Code Terminal.app ✅(自動的に動作します) VS Code内の Claude Code VS Code ❌(ダイアログが表示されない場合があります) iTerm2内の Claude Code iTerm2 ✅(自動的に動作します) 権限ダイアログが表示されない場合(VS Code でよく発生します)、VS Code の Info.plist に
NSCalendarsFullAccessUsageDescriptionを追加する必要があります。# VS Code にカレンダーの使用目的を追加 /usr/libexec/PlistBuddy -c "Add :NSCalendarsFullAccessUsageDescription string 'VS Code needs calendar access for MCP extensions.'" \ "/Applications/Visual Studio Code.app/Contents/Info.plist" /usr/libexec/PlistBuddy -c "Add :NSRemindersFullAccessUsageDescription string 'VS Code needs reminders access for MCP extensions.'" \ "/Applications/Visual Studio Code.app/Contents/Info.plist" # VS Code に再署名(Info.plist の変更後に必要) codesign -s - -f --deep "/Applications/Visual Studio Code.app" # VS Code を再起動すると、権限ダイアログが表示されます注意: この変更は、VS Code のアップデート時に上書きされます。アップデートのたびに再適用する必要があります。
既存のインストールをアップグレードする
プラグインラッパーは新規インストールでは自動的にダウンロードしますが、既存のバイナリは置き換えません。インストール済みの状態でアップグレードするには、次のコマンドを実行してください。
~/bin/CheICalMCP --self-update
このコマンドは GitHub Releases から最新のタグを取得し、新しいバイナリをダウンロードします。公開されている SHA-256、メンテナーの Developer ID 署名、Apple による公証を検証し、すべてのチェックに合格した場合にのみ、現在のバイナリをアトミックに置き換えます(チェックに失敗した場合、インストール済みのファイルは変更されません)。MCP サーバーとして実行中の場合は、新しいバージョンを適用するため、実行後に MCP ホスト(Claude Desktop / Claude Code)を再起動してください。手動での代替手順:rm -f ~/bin/CheICalMCP && curl -L https://github.com/PsychQuant/che-ical-mcp/releases/latest/download/CheICalMCP -o ~/bin/CheICalMCP && chmod +x ~/bin/CheICalMCP。
CLI モード(MCP サーバーなし)
29 個すべてのツールは、MCP サーバーなしでコマンドラインから直接呼び出せます。
# Flag-based: --key value pairs
CheICalMCP --cli list_events --start_date 2026-03-29 --end_date 2026-03-30
# JSON via stdin
echo '{"tool":"list_calendars","arguments":{}}' | CheICalMCP --cli
# From Claude Code via shell
claude -p "Run: ~/bin/CheICalMCP --cli list_events_quick --range today"
launchd ジョブ、シェルスクリプト、CI パイプライン、MCP プロトコルよりサブプロセスを好むエージェントに便利です。TCC の権限は引き続き適用されます。必要に応じて、最初に CheICalMCP --setup を実行してください。
v1.0.0 の機能
柔軟な日付の解析
すべての日付パラメーターで、次の 4 つの形式を使用できるようになりました。
| 形式 | 例 | 解釈 |
|---|---|---|
| ISO8601 完全形式 | "2026-02-06T14:00:00+08:00" | 正確な日付と時刻(オフセットを保持) |
| タイムゾーンなし | "2026-02-06T14:00:00" | timezone が指定されていればイベントの timezone を使用し、指定されていなければシステムのタイムゾーンを使用 |
| 日付のみ | "2026-02-06" | イベントの timezone またはシステムのタイムゾーンでの午前 0 時。リマインダーの due_date の場合は、時刻のない日付のみのリマインダー(#267。「日付のみのリマインダー」を参照) |
| 時刻のみ | "14:00" | 今日のその時刻 |
イベントごとのタイムゾーン(v1.5.0)
イベントごとに表示するタイムゾーンを設定できます。複数のタイムゾーンをまたぐ旅行の予定には不可欠です。
"Create a flight departure at 09:14 Berlin time"
→ create_event(title: "Flight LH123", start_time: "2026-04-08T09:14:00", timezone: "Europe/Berlin", ...)
"Update the hotel check-in to Dubai time"
→ update_event(event_id: "...", timezone: "Asia/Dubai")
"Remove the custom timezone from an event"
→ update_event(event_id: "...", clear_timezone: true)
timezoneパラメーターでは、IANA 識別子(例:Europe/Berlin、America/New_York、Asia/Taipei)を指定できますtimezoneを指定すると、タイムゾーンオフセットのない日時はそのタイムゾーンの日時として解釈されます- イベントの出力では、
timezoneフィールドにイベント固有のタイムゾーンが含まれ、start_date_local/end_date_localはそれに応じてフォーマットされます create_event、update_event、create_events_batchで使用できます- 元に戻す/やり直す操作では、イベントごとのタイムゾーンが保持されます
参加者と主催者(読み取り専用)
イベントのレスポンスには、利用可能な場合に参加者の情報が含まれます。EventKit の制約により、これらのフィールドは読み取り専用であり、MCP を通じて設定または変更することはできません。
利用可能なツール:list_events、search_events、list_events_quick、check_conflicts
attendees(配列、省略可)— イベントに参加者がいる場合に含まれます。各参加者オブジェクトには次の項目が含まれます。
| フィールド | 型 | 説明 |
|---|---|---|
name | string または null | 表示名。アドレスブックに登録されていない場合は null |
email | string | 参加者の URL から抽出したメールアドレス |
role | string | 次のいずれか:unknown、required、optional、chair、non_participant |
status | string | 次のいずれか:unknown、pending、accepted、declined、tentative、delegated、completed、in_process |
type | string | 次のいずれか:unknown、person、room、resource、group |
is_current_user | boolean | この参加者が現在のユーザーかどうか |
organizer(オブジェクト、省略可)— イベントに主催者がいる場合に含まれます。次の項目が含まれます。
| フィールド | 型 | 説明 |
|---|---|---|
name | string または null | 表示名 |
email | string | メールアドレス |
is_current_user | boolean | 主催者が現在のユーザーかどうか |
注: イベントに参加者も主催者もいない場合(例:招待者なしで作成されたローカルカレンダーのイベント)、どちらのフィールドも省略されます。
あいまいなカレンダー名の照合
カレンダー名は大文字と小文字を区別せずに照合されるようになりました。見つからない場合は、エラーメッセージに利用可能なすべてのカレンダーが表示されます。
拡張されたリスト/削除ツール
list_events:filter(all/past/future/all_day)、sort(asc/desc)、limitlist_reminders:filter(all/incomplete/completed/overdue)、sort(due_date/creation_date/priority/title)、limitdelete_events_batch:日付範囲モード(before_date/after_date)+dry_runによるプレビュー
破壊的変更:
list_eventsとlist_remindersは、単純な配列ではなく{events/reminders: [...], metadata: {...}}を返すようになりました。
使用例
カレンダー管理
"List all my calendars"
"What's on my schedule next week?"
"Create a meeting tomorrow at 2 PM titled 'Team Sync'"
"Add a dentist appointment on Friday at 10 AM with location '123 Main St'"
"Delete the meeting called 'Cancelled Meeting'"
リマインダー管理
"List my incomplete reminders"
"Show all reminders in my Shopping list"
"Add a reminder: Buy milk"
"Create a reminder to call mom tomorrow at 5 PM"
"Mark 'Buy milk' as completed"
"Delete the reminder about groceries"
リマインダー管理(v1.5.0)
"Remove the due date from 'Buy groceries'"
→ update_reminder(reminder_id: "...", clear_due_date: true)
高度な機能(v0.3.0+)
"Search for events containing 'meeting'"
"Search for events with both 'project' AND 'review'"
"What do I have today?"
"Show me this week's schedule"
"Are there any conflicts if I schedule a meeting from 2-3 PM?"
"Create 3 weekly team meetings for the next 3 weeks"
"Copy the dentist appointment to my Work calendar"
"Move all events from 'Old Calendar' to 'New Calendar'"
"Delete all the cancelled events"
"Find duplicate events between 'IDOL' and 'Idol' calendars"
DX の改善(v1.0.0)
"Show my next 5 upcoming events"
→ list_events(start_date: "2026-02-06", end_date: "2026-12-31", filter: "future", sort: "asc", limit: 5)
"Show my overdue reminders"
→ list_reminders(filter: "overdue")
"Preview which events would be deleted from 'Old Calendar' before 2025"
→ delete_events_batch(calendar_name: "Old Calendar", before_date: "2025-01-01", dry_run: true)
"Create an event at 2 PM" (no need for full ISO8601!)
→ create_event(start_time: "14:00", end_time: "15:00", ...)
対応するカレンダーソース
macOS のカレンダーアプリと同期されたカレンダーであれば、どれでも使用できます。
- iCloud Calendar
- Google Calendar
- Microsoft Outlook/Exchange
- CalDAV カレンダー
- ローカルカレンダー
同じ名前のカレンダーの識別(v0.6.0+)
異なるソースに同じ名前のカレンダーがある場合(例:iCloud と Google の両方に「Work」がある場合)は、calendar_source パラメーターを使用してください。
"Create an event in my iCloud Work calendar"
→ create_event(calendar_name: "Work", calendar_source: "iCloud", ...)
"Show events from my Google Work calendar"
→ list_events(calendar_name: "Work", calendar_source: "Google", ...)
曖昧さが検出されると、エラーメッセージに利用可能なすべてのソースが表示されます。
トラブルシューティング
| 問題 | 解決策 |
|---|---|
| サーバーが切断される | make release && make install で再ビルドします |
| アクセスが拒否される | 「システム設定」>「プライバシーとセキュリティ」でカレンダー/リマインダーへのアクセスを許可します |
| アクセス許可ダイアログが表示されない | macOS Sequoia での回避策については、アクセス許可の付与を参照してください |
| SSH 経由でアクセスが拒否される | 下記のSSH アクセスを参照してください |
| launchd の実行時にアクセスが拒否される | 下記のlaunchd /自動化を参照してください |
| すべての診断で正常と報告されるのに、一方のサービスだけアクセスが拒否される | 下記のアップグレード後に発生する、通知のない恒久的な拒否を参照してください |
| Claude Code の更新後に毎回、カレンダー/リマインダーが再び動作しなくなる | 下記のClaude Code の更新によってホスト側の許可がローテーションされるを参照してください |
| カレンダーが見つからない | macOS のカレンダーアプリでカレンダーが表示されていることを確認してください |
| リマインダーが同期されない | 「システム設定」で iCloud の同期を確認してください |
アップグレード後にアクセスが永続的に拒否される場合(#154)
あるサービス(通常は Calendar)が access denied を返す一方で、ほかのサービスは動作し、かつ --print-tcc-path とシステム設定で権限が許可済みと表示される場合、#154 のケースに該当している可能性があります。v1.7.1 より前のビルド(アドホック署名)によって作成された TCC 行が、その古いビルドのコードハッシュに固定されています。アップグレード後の Developer ID バイナリはそのハッシュと一致できず、macOS 26.5 以降では、バイナリに一致する com.apple.security.personal-information.* エンタイトルメントがない限り、OS は修復のための再プロンプトを許可しません。
v1.14.0 以降では、起動バナーにこの問題が直接表示されます。Security フレームワークのチェックで csreq の不一致を確認できる場合、[drift] TCC.db <service> entry pins a code requirement this binary no longer satisfies という行が表示されます(#155)。これより前は、バナーを含むすべてのステータス API 診断で問題なしと報告されており、これがこの種の問題を見えにくくしていた原因です。Claude Desktop の .mcpb インストール経由でアクセスが拒否された場合、拒否メッセージには行き止まりとなる --setup ではなく、実際の原因と有効な対処方法が表示されるようになりました(#158)。
修正方法:v1.11.0 以降にアップグレードし(バイナリに両方のエンタイトルメントが含まれるようになりました)、ホストアプリを再起動して(Claude Desktop の場合は完全に Cmd+Q で終了)、Calendar/Reminders に初めてアクセスしたときに表示される権限ダイアログで許可します。許可すると、Developer ID の要件をキーとする TCC 行が書き換えられ、以降のアップグレード後も維持されます。誤ってダイアログで拒否した場合は、システム設定 → プライバシーとセキュリティ → カレンダーまたはリマインダーで、該当するトグルを再度有効にしてください。
⚠️ #108 当時の回避策に関する訂正:
tccutil reset Calendar com.checheng.CheICalMCPは、単独の(バンドルされていない)バイナリでは機能しません。バイナリが LaunchServices に登録されていないため、OSStatus error -10814で失敗します。また、バンドル ID を指定せずに単独でtccutil reset Calendarを実行しないでください。マシン上のすべてのアプリに対する Calendar の許可が消去され、エンタイトルメント導入前のバイナリでは、CheICalMCP が再プロンプトを永続的に表示できなくなります。
Claude Code の更新によりホスト側の許可が切り替わる (#170)
v1.22.0 で変更(#343):macOS が報告する責任プロセスが Claude Code(
~/.local/share/claude/versions/<ver>配下のネイティブ実行ファイル、またはClaudeCode.app)の場合、バイナリは自身を責任プロセスとしてその場で再実行されるため、macOS はCheICalMCPの許可を確認し、Claude Code の更新による影響を受けなくなります。これは MCP サーバー、--cli、--print-tcc-path、--setupに適用されます。--setupはどのホストでも再実行されます。それ以外のすべてのホスト(Terminal、VS Code、Ghostty、ssh、cron、CI)では、v1.22.0 より前の動作が維持されます。ホストの許可が確認され、再実行は行われません。Claude Code では、アップグレード後に CheICalMCP のプロンプトで一度許可するか、フォアグラウンドで~/bin/CheICalMCP --setupを実行してください。GUI のないバックグラウンドセッションではプロンプトを表示できません。トレードオフ:再実行が行われる場合、macOS は CheICalMCP の許可を確認します。そのため、一度許可すると、Claude Code が起動するこのバイナリを実行するすべてのプロセス(
--cliを含む)は、別途同意を得ることなく、その許可のもとでカレンダーとリマインダーを読み取ります。これは、disclaimerを通じて Claude Desktop の.mcpbが持つものと同じ特性です。CHE_ICAL_MCP_NO_DISCLAIM=1を設定するとホストの識別情報に戻り、CHE_ICAL_MCP_FORCE_DISCLAIM=1を設定するとすべてのホストで再実行されます(オプトアウトが優先されます)。未検証:CI では新しい経路を通じたカレンダーの読み取りをカバーしておらず、プロンプトが表示されることを確認できているのは
--setupのみです。サーバーモードと--cliについては未確認です。このセクションの残りは、v1.21.0 以前、Claude Code 以外のホスト、および
CHE_ICAL_MCP_NO_DISCLAIM=1を設定した場合に適用されます。
Claude Code のネイティブインストールでは、実際の実行ファイルはバージョン付きのパス(~/.local/share/claude/versions/<version>。~/.local/bin/claude はシンボリックリンクにすぎません)にあり、macOS TCC はホスト側のカレンダー/リマインダーへの許可をそのパスに紐付けます。Claude Code が自動更新されるたびにパスが変わり、許可が通知なく無効になります。典型的な症状は「昨日は動いていたのに、更新直後に動かなくなった」で、システム設定には古いバージョン番号のみの項目(2.1.202、2.1.203、…)が蓄積していきます。
修正方法:Claude Code からカレンダーツールを呼び出して macOS の再確認を促す(または項目を再作成する)か、システム設定 → プライバシーとセキュリティ → カレンダー/リマインダーで最新のバージョン番号の項目をオンにします。詳しいチェックリストは troubleshoot-tcc スキル(/che-ical-mcp:check-tcc)を参照してください。根本原因は上流にあります(#170 で追跡中。Claude Code 側で安定した TCC ID が必要です)。このリポジトリでできるのは、問題を検出して説明することだけです。
SSH アクセス
macOS TCC(Transparency, Consent, and Control)のプライバシー権限は、アプリケーションごとに付与されます。SSH セッションは別のセキュリティコンテキストである sshd のもとで実行されるため、ローカルの Terminal や Claude Code に付与した権限は SSH には引き継がれません。
回避策 A — まずローカルで実行する(推奨):
- 対象の Mac で
CheICalMCPをローカルで(SSH 経由ではなく)一度実行します - TCC ダイアログが表示されたら、カレンダーとリマインダーへのアクセスを許可します
- その後、SSH セッションでは
CheICalMCPバイナリへの許可が引き継がれるはずです
回避策 B — sshd にフルディスクアクセスを許可する:
- システム設定 → プライバシーとセキュリティ → フルディスクアクセスを開きます
- + をクリックし、⌘⇧G を押して
/usr/sbin/sshdと入力し、追加します - SSH セッションを再起動します
⚠️ 回避策 B では
sshdに広範なファイルアクセスを許可します。完全に管理できるマシンでのみ使用してください。
launchd/自動化
launchd、cron、またはその他の非対話型自動化から CheICalMCP を実行する場合、macOS TCC は権限ダイアログを表示できません。--setup を使用して、あらかじめ権限を付与してください。
# Step 1: Run once from Terminal (triggers TCC permission dialog)
CheICalMCP --setup
# Step 2: Grant Calendar & Reminders access in the dialog that appears
# Step 3: The binary now has permission — launchd jobs can use it
検出:CheICalMCP は非対話型セッション(
TERM環境変数がない、またはlaunchdの直接の子プロセス)を自動的に検出し、--setupの手順を含む、状況に応じたエラーメッセージを表示します。これは間接的な起動チェーン(launchd → Claude Code → CheICalMCP)でも機能します。非対話型セッションでの
--setup(#143):非対話型セッション(TERMがない、またはlaunchdの直接の子プロセス)から--setup自体を実行し、権限がまだ未確定の場合、--setupは要求をスキップして、ハングせずにゼロ以外の終了コードで終了するようになりました。TCC ダイアログはその環境では表示できないため、処理をブロックする代わりに、手動で権限を付与する手順を表示します。ダイアログを表示するには、通常のターミナルから--setupを実行してください。(権限がすでに付与されているバイナリは、非対話型で再実行しても成功を報告します。)注:
--setupで権限を付与しても、launchdから実行したときに MCP が失敗する場合、TCC が権限を親プロセスに関連付けた可能性があります。その場合は、システム設定 → プライバシーとセキュリティ → カレンダー/リマインダーで CheICalMCP を手動で追加してください。
技術詳細
- 現在のバージョン:v1.22.0
- フレームワーク:MCP Swift SDK v0.12.0
- カレンダー API:EventKit(macOS ネイティブフレームワーク)
- トランスポート:stdio
- プラットフォーム:macOS 14.0 以降(Sonoma 以降 — #119 に従い、1.10 以降のクラスターで 13.0 から引き上げ)
- ツール:カレンダー、イベント、リマインダー、タグ、元に戻す/やり直し、クリーンアップ、高度な操作に対応する 29 個のツール
バージョン履歴
| バージョン | 変更内容 |
|---|---|
| v1.22.0 | Claude Code では、CheICalMCP が独自の責任プロセスになります (#343):macOS が報告する責任プロセスが Claude Code の場合、バイナリは disclaim 属性を付けてその場で再実行され、確認される許可は CheICalMCP のものになります(Claude Code のアップデートで無効にならなくなります)。--setup はすべてのホスト上で再実行します。それ以外のホストでは、それぞれのホスト固有の許可が引き続き使われます。--print-tcc-path、起動時バナー、アクセス拒否メッセージには、macOS が確認するプロセス名が表示されます。未検証事項:Claude Code ホスト経由で再実行した際のカレンダー読み取り。移行手順と同一ユーザーに関するトレードオフについては CHANGELOG を参照してください。 |
| v1.21.0 | 長期間の一覧取得、内容が分かるシリーズ ID、会議モジュール、フォルダーごとのルーティング (#285/#310/#325/#326/#335/#337/#338):4 年を超える期間のイベント一覧が約 1461 日で途切れなくなりました。最初の発生が削除されたシリーズも、再び移動、コピー、削除でき、発生項目が更新されます。使用できない単独のシリーズ ID には、その理由(以前の発生項目が編集された、または残っているすべての発生項目が個別に編集された)が表示されます。シリーズ全体の削除を元に戻すと、スキャン範囲内の例外が復元されます。make verify-release-ready は最新のリリースタグと比較します。プラグインシェル:会議プログラムは、終日イベントの総括イベント 1 件と、各項目の時刻指定イベント 1 件ずつに変換されます。また、フォルダーの calendar_routing ルールでカレンダーを選択します。 |
| v1.20.0 | 日付のみのリマインダー、上書きを拒否する取り消し、開始日とアラームの読み取り (#231/#235/#236/#243/#247/#262/#267/#297/#299/#301/#311):単独の YYYY-MM-DD due_date は日付のみのリマインダーを作成し、日付のみのリマインダーはその日が終わってから期限超過になります。create_reminder/update_reminder は date_sync(aligned を含む)を返し、update_reminder に realign_to_due が追加されました。list_reminders/search_reminders は start と alarms を返します。リマインダーの日付は、地域設定にかかわらずグレゴリオ暦で読み書きされます。操作後に別の場所で変更が行われている場合、undo/redo は上書きを拒否します。繰り返しイベントに触れた update_event は取り消されず、発生項目が個別に編集された(時刻の変更を含む)作成済みシリーズは削除されません。取り消しでは場所/メール/絶対時刻アラーム、繰り返し、URL、空き状況、リストが保持されます。バッチ削除は取り消し情報を記録します。破壊的変更(動作):単独の日付形式の due_date、期限超過の判定ルール、undo/redo による拒否、完了以外の対象に対する redo は何も書き込みません。 |
| v1.19.0 | イベントのその場での移動、リマインダーの日付同期、検証済みの自己アップデート (#223/#225/#226/#227):move_events_batch はコピー+削除ではなくカレンダーを再割り当てするため、繰り返し、参加者、すべてのフィールドが保持されます(アカウント間の移動時のみ識別子が変わります。繰り返しイベントでは span/occurrence_dates を保持し、イベントごとの method/id_changed/not_carried_over を返します。コピー+削除は、保護されたフォールバックとしてのみ使用します)。update_reminder は期限日とともに開始日と絶対日付アラームを移動します(Reminders.app ではアラームの日付が表示されます)。date_sync を返し、clear_due_date はそれらをクリアし、undo で復元します。--self-update は Developer ID 署名と公証を受けたバイナリのみをインストールします。共通のスケルトンは che-mcp-kit-swift 0.2.x です。破壊的変更(動作):occurrence_date のない繰り返しイベントは拒否されます。copy_event は繰り返しイベントの移動を拒否します。文字列以外の event_ids 要素は拒否されます。 |
| v1.18.0 | リマインダーの undo/redo 完全性、明示的な discard_id、すべての箇所で厳格なブール値 (#196/#197/#198/#199/#202/#203/#206/#207/#208/#209/#211/#212/#214/#215/#216):undo は記録された completion_date を書き戻し、redo は状態を再推論せず保存された時刻を復元します。繰り返し完了しても元の時刻が保持されます。undo(discard_id) は、安定した undo_history ID を使ってブロック中の先頭レコードを明示的に削除します(削除済みリマインダーや無効なイベントを対象とする見つからないレコードが、スタックを詰まらせなくなりました)。イベントの移動では移動元の発生項目を記録し、undo で元のカレンダーに復元します。event_recurrence_rules/reminder_recurrence_rules は 2 つの形式を区別します(従来のエイリアスも維持)。すべてのツール注釈に、明示的にテスト済みの方針が設定されました。complete_reminder、更新ツール、移動が任意のツールは destructiveHint: true になりました。破壊的変更:すべてのブール型ツール引数は厳密な JSON ブール値である必要があります(文字列/数値は拒否され、<key> must be a boolean が返されます)。内部処理:リマインダーの一覧/検索では、アクターの事前スナップショット内でフィルター/ソート/件数制限を行います。スナップショットの境界に list_reminder_tags を配置し、タグの走査を線形化(指数的なバックトラッキングを排除)しました。イミュータブルで Sendable なリマインダー書き込み結果、専用のアクター拡張に完了/繰り返し履歴メソッドを追加しました。 |
| v1.17.0 | 読み取り時のリマインダー繰り返し、明示的な完了結果、ID で保護された undo、厳密なブール型 completed (#194/#204/#205):list_reminders/search_reminders は has_recurrence、完全な recurrence_rules(frequency_raw_value を含む)、due オブジェクトを公開します。complete_reminder は書き込み結果(operation)と保存されたオブジェクト(observed)を分離し、保存後に一度だけ同期的に確認した後続項目を next_occurrence として返します(デバイス上の iCloud では、同じ ID がその場で進み、完了した発生項目には新しい ID が割り当てられます)。メッセージはリマインダー固有の現地時刻で表示されます。繰り返し完了の undo/redo は ID によって保護されます。ID が記録された発生項目を指さなくなった場合は明示的に拒否し、古い操作を undo できるようエントリを破棄します。見つからない状態は一時的なままです (#191)。破壊的変更:3 つのリマインダーツールでは、completed は JSON ブール値である必要があります(文字列/数値は読み取りまたは書き込みの前に拒否されます。省略/null は従来の意味を維持します。--cli では JSON null が省略扱いになります)。PR #195 で 6 つの AI による検証を 3 回実施し、#200/#201 でも検証を実施しました。デバイス上の stdio プローブを 2 回実施。582 件のテスト。 |
| v1.16.1 | 型安全性とデバイス上の検証に関する修正 (#184/#190/#191):オブジェクト以外の recurrence を拒否するようになりました(以前は黙って破棄していました)。all_day と timezone の組み合わせを拒否するようになりました(以前は終日フラグを黙って削除し、日付変更線をまたぐ除外を無効にしていました)。繰り返しシリーズの削除を undo する際、値のスナップショットからルールを再構築します(EKCADErrorDomain 1010 を修正)。undo/redo が失敗しても、エントリを消費しなくなりました。529 件のテスト。 |
| v1.16.0 | 繰り返しの除外、undo の完全性、イベントアーカイブスキル (#182/#185/#180):create_event/バッチに excluded_occurrence_dates を追加(2 段階の作成後削除、補償削除、最初の発生項目は除外不可)。バッチ/シリーズの削除が undo エントリを記録するようになりました(.batch 単位 1 件)。繰り返しイベントの作成を undo すると、シリーズ全体が削除されるようになりました。新しい archive-event スキルを追加しました。訂正履歴の追跡と .claude/.ical/ プロジェクト設定を含む、ソースからイベントへのアーカイブ機能です。514 件のテスト。 |
| v1.15.0 | --print-tcc-path の実行コンテキストと、バージョン管理されたホストを示すバナーシグナル。 TCC 診断に、親プロセスのチェーン(self → … → launchd)とコンテキスト依存の警告が表示されるようになりました。認証状態は責任プロセスのコンテキストに従うため (#168)、どのホスト上でクエリが実行されたかが重要です (#169)。親チェーン診断を改善しました。目視可能な切り詰め/循環マーカー、空の comm の関連付け、ps -ww、デコード/終了失敗の報告、NOTE の精度向上を含みます (#173)。ドリフト検出器に、「バージョン管理された Claude Code ホスト+未許可の EventKit」という新しいシグナルを追加しました。起動時に #170 のアップデート切り替えによる問題を事前に説明し、この状況では矛盾する --setup のヒントを抑制します (#175)。3 項目すべてを 6 つの AI によるモデル横断アンサンブルで検証しました。検証で見つかった CWE-150 の端末エスケープの不備は、マージ前に修正しました。v1.14.2 のプラグインリリースとのバージョン差異を、5 つすべてのバージョン記述箇所で調整しました (#172)。490 件のテスト。 |
| v1.14.2 | ドキュメント/スキルレイヤーのリリース — 2 層の TCC 認証モデル (#168):troubleshoot-tcc スキル、/check-tcc、mcpb/README.md、plugin/CLAUDE.md に、ホストアプリ(責任プロセス)の TCC レイヤー、バージョン番号のみの System Settings 項目(2.1.202 = Claude Code のバージョン管理されたバイナリ)、切り替えて状態を確認する検証手順を記載しました。リリース時点のバイナリは v1.14.1 とバイト単位で同一です(プラグインシェルのみ。ソースのバージョン記述箇所は後に #172 で調整)。 |
| v1.14.1 | メタデータの修正 — ツール数の整合性。 server.json の description は「24 tools」、PROMOTION.md は「20 tools」と記載していましたが、サーバーが実際に公開するのは 29 tools です(mcpb/manifest.json の long_description および ManifestParityTests のツール整合性ガードと一致)。レジストリ向けの server.json、docs/COMPETITIVE_ANALYSIS.md、PROMOTION.md を 29 に修正しました。コードやツールの公開範囲に変更はなく、機能的には v1.14.0 と同一です。このリリースは、修正済みのレジストリメタデータを公開することだけを目的としています(レジストリのバージョンは変更できません)。 |
| v1.14.0 | Claude Desktop のツール注入が失敗する問題を修正 (#166):mcpb/manifest.json の display_name にリテラルの & が含まれていると、Desktop 1.18286.0 では会話ごとに 29 ツールのサーバー全体が黙って除外されていました(Claude Code には影響なし)。& を and に変更し、問題のあるインストール環境で単一変数の介入を行い、ManifestParityTests に回帰ガードを追加して確認しました。また、serverInfo.name を kebab 形式のマニフェスト ID に合わせました(整備目的。原因ではないことを実証済み)。#154 の関連バッチ:csreq 不一致による TCC ドリフトシグナル (#155。サイレント拒否クラスを検出する SecCodeCheckValidity の自己チェック)、.mcpb の拒否メッセージが、すでに .denied の署名に対して --setup を案内して行き詰まる問題を修正 (#158)、macOS バッジを 13.0 から 14.0 に変更 (#157)、swift-nio を 2.96 から 2.101 に更新 (#159)。454 件のテスト。 |
| v1.13.0 | SwiftUI SetupWindow (#164):対話型の --setup で、#163 のフォアグラウンド NSApplication 内にライブステータスウィンドウ(エンティティごとの Grant ボタンと解決済みバイナリパス)が表示されるようになりました。Desktop でカレンダーへのアクセスが拒否される問題を修正 (#165):GUI アプリから起動されたサーバーでは TERM == nil によって isNonInteractive が誤判定され、requestFullAccess の前に高速で失敗していたため、Claude Desktop 経由では初回許可ダイアログが表示されませんでした。現在は CGSession の GUI セッションシグナルを使います。429 件のテスト。 |
| v1.12.0 | フォアグラウンドでの --setup (#163):対話型の --setup がフォアグラウンドの NSApplication 内で実行されるようになり、EventKit のカレンダー TCC モーダルが実際に表示されます(以前は、単独の CLI 非同期コンテキストからは黙って拒否されていました)。拒否メッセージと起動時バナーに、解決済みバイナリパスと、埋め込まれた .mcpb バイナリ用のコピー&ペースト可能な "<path>" --setup コマンドが表示されます。 |
| v1.11.1 | create_event の時間範囲検証 (#160):update_event と同じく、共通の validateTimeRange ガードで、時刻が逆転したイベントや所要時間がゼロの時刻指定イベントを拒否します。405 件のテスト。 |
| v1.11.0 | TCC の修復再プロンプトを有効化 (#154):Entitlements.plist に personal-information.calendars と .reminders が含まれるようになりました。v1.7.1 より前から長期間使用しているインストール環境では、macOS 26.5 でカレンダーへのアクセスが恒久的に黙って拒否されることがありました(TCC 行が古い cdhash に固定され、バイナリに権限が含まれていないため修復再プロンプトがポリシーでブロックされ、すべての診断は正常を報告)。署名済みバイナリのリリースゲートで両方のキーを検証します。非対話型 EventKit の堅牢化 (#131/#143/#144 と #146–#150)。破壊的変更:デプロイ下限を macOS 14.0 に引き上げました (#119)。401 件のテスト。 |
| v1.10.0 | TCC ドリフト検出器と起動時バナー (#122):MCP サーバー起動時に、バージョン/パス/PID とドリフトシグナル(サービスごとの TCC.db パス不一致、古いプロセス)を含む一度限りの stderr バナーを表示します。CHE_ICAL_MCP_NO_BANNER=1 でオプトアウトできます。サブプロセスヘルパーのパイプデッドロックを修正し、補間されるすべてのバナー値に CWE-117 の stderr インジェクション対策を適用しました。 |
| v1.9.0 | TCC アクセスゲートのリファクタリング (#108 フェーズ 2、#109 を解決):プロセスの存続期間中 has*Access をキャッシュするアンチパターンを削除しました。新しい AuthorizationGate と AuthorizationStatusSource の境界を介して、呼び出しごとに EKEventStore.authorizationStatus(for:) を確認します(Apple TN3153 のパターン)。状態変更がすぐに反映され、許可状態の古いキャッシュによる黙った失敗がなくなります。診断フラグ --print-tcc-path を追加しました。 |
| v1.8.1 | ドキュメント:インストール後/アップグレード後の TCC 権限設定ガイドを mcpb/README.md に追加しました (#108 フェーズ 1)。 |
| v1.8.0 | ワイヤーフォーマットの一貫性向上とレスポンス形状パラメーター (#101 クラスター — 3 日間で 5 件の問題を解決。すべて Refs #N IDD と 6-AI アンサンブルで検証)。イベント一覧レスポンス形状のパラメーター (#47/#101):detail_level(summary/standard)、fields の許可リスト、display_timezone(厳密な IANA 形式)、limit(上限 10000)を追加し、LLM の冗長さを調整できるようになりました。エンベロープの統一 (#102/#107、ワイヤーフォーマットの破壊的変更) :list_events.metadata.returned と list_reminders.metadata.returned を削除しました。5 つすべての一覧/検索エンベロープで、事前制限の意味を持つトップレベルの <entity>_count を使用します。search_reminders.result_count は reminder_count に変更しました。search_reminders に limit パラメーターを追加しました(search_events と同様)。metadata.returned または result_count を読み取る MCP クライアントは更新が必要です。バリデーターの堅牢化 (#101 F1–F3):requireOptionalInt で Int(exactly:) を使用し、Int.max による DoS のトラップを解消しました。detail_level/display_timezone のバリデーターが、未指定と文字列以外を区別するようになりました(暗黙の型変換なし)。ランタイムを基準にしたドリフト検出 (#103、#101 M3 を強化):formatEventDict と validEventFields の不一致テストを、EventFormattingSource の境界と FakeFormattableEvent を介して行うようになりました。CHANGELOG の分類を修正 (#106):ワイヤーフォーマットの名称変更を Fixed から Changed に移動しました(Keep a Changelog 1.1.0)。リリースパイプラインの修正:パッケージ化前の防御チェックが、DEVELOPER_ID 証明書から Team ID を取得するようになりました(以前は SHA ハッシュを、人間が読める Authority= 文字列と比較していました)。 |
| v1.7.2 | 堅牢化と機能追加の波(v1.7.1 以降 30 件以上のコミット。すべて Refs #N IDD と 6-AI 検証を実施)。--self-update (#49) と SHA-256 バイナリ検証 (#98):暗号技術によるリリース破損防止を備えた、既存インストール環境のアップグレード経路。make install-signed (#50):macOS 26 でメンテナーが開発用 TCC を扱うフロー。Developer ID がない場合は即時失敗し、codesign 検証を強制します。CI テストワークフロー (#51):PR 時に macos-latest で swift build と swift test を実行します。サニタイザー堅牢化クラスター:escapeForStderr で C0 と DEL を完全にカバー (#73)、executeUndo/executeRedo のタイトル補間に sanitizeForInterpolation を追加 (#74)、CLIRunner の stderr を writeFailureLog に委譲して信頼済み分岐を適用 (#80)、writeFailureLog に 1024 文字の DoS 上限を追加 (#86)、CLIError.invalidJSON に作成者管理データのみを対象とする契約ドキュメントを追加 (#85)、FileHandle.standardError.write のスレッド安全性と macOS の PIPE_BUF=512 を文書化 (#70/#94)。配布の仕上げ:古い codesign キャッシュがあるインストール手順に rm -f の前置処理を追加しました (#90。#62 の zh-TW との整合性)。v1.7.1 以降の仕上げ (#46 #57 #58 #60):redo エラー補間の整合性、build-mcpb.sh の手順番号付け直し、Entitlements.plist のドキュメント、Makefile release-signed: の作業ディレクトリに関する注記。cleanup_completed_reminders ツール (#21):完了済みのリマインダーすべてを 1 回の呼び出しで削除します。既定では dry_run=true です。 |
| v1.7.1 | セキュリティの堅牢化 (#20 #26):すべてのイベント/リマインダーのエントリーポイントで入力を検証(長さ制限と URL スキーム許可リスト)、MCP の読み取りレスポンスにプロンプトインジェクション対策のラッパーを追加、days_of_week/days_of_month/alarms_minutes_offsets の解析境界で検証(無効値を黙って破棄せずエラーを送出)、Info.plist の不足分を補完、回帰テストを 42 件追加。 |
| v1.7.0 | 参加者と主催者の情報 (#17):イベントレスポンスに読み取り専用の attendees 配列と organizer オブジェクトを追加しました。共有の formatEventDict メソッドをリファクタリングしました。 |
| v1.6.0 | --setup フラグ (#13):launchd/自動化向けに TCC 権限を事前承認します。非対話型セッションを検出します(TERM+ppid)。SSH+launchd の複合エラーメッセージを追加しました。--cli モード (#14):MCP サーバーを介さず、コマンドラインから 28 の全ツールを直接実行できます。フラグ方式(--key value)と JSON 標準入力方式に対応します。bool/int/double/array 型パラメーターを自動推論します。MCP Swift SDK 0.12.0(Swift 6.3 互換)。 |
| v1.5.0 | イベントごとのタイムゾーン (#12):create_event/update_event/create_events_batch に timezone パラメーターを追加。イベント出力ではイベント固有のタイムゾーンを使い、タイムゾーンのない日時はイベントのタイムゾーンで解析します。期限日のクリア (#9):update_reminder に clear_due_date を追加。曜日の検証 (#5):create_event/update_event で start_time の曜日を days_of_week と照合します。Undo/redo (#8):新しいツールを 3 つ追加(undo、redo、undo_history)。繰り返しイベントの修正 (#7):occurrence_date を使った発生単位の削除/更新。Swift 6 ビルド (#11):make release ワークフローに合わせて README を更新 |
| v1.4.0 | LLM の信頼性:既定の検索範囲を修正(distantPast/Future ではなく前後 2 年)、search_events レスポンスに searched_range メタデータを追加、create_events_batch に similar_events のヒントを追加、ツールの説明に LLM 向けのヒントを追加 |
| v1.3.1 | ドキュメントの修正:タグは Reminders.app のネイティブタグではなく、MCP レベルの機能であることを明確化しました。Apple はネイティブタグ用の公開 API を提供していません。 |
| v1.3.0 | リマインダーのタグ(MCP レベル):create_reminder/update_reminder/create_reminders_batch 用に、#hashtag 形式のテキストをメモに保存します。search_reminders でタグによるフィルタリングを行い、新しい list_reminder_tags ツールを追加しました。MCP SDK 0.11.0。注:タグは MCP 経由で検索できますが、Reminders.app のネイティブタグとしては表示されません(Apple はそのための公開 API を提供していません)。 |
| v1.2.0 | 冪等な書き込み:create_event、create_events_batch、create_reminder、create_reminders_batch、create_calendar は、再試行時の重複を防ぐため、書き込み前に既存項目を確認するようになりました。レスポンスには skipped 件数が含まれます。 |
| v1.1.0 | 繰り返しと場所:イベント/リマインダーの繰り返し(日次/週次/月次/年次)、座標を含む構造化された場所、場所に基づくリマインダーのトリガー(ジオフェンスへの進入/退出)、詳細な繰り返し情報の出力 |
| v1.0.0 | DX の改善:柔軟な日付解析(4 つの形式)、あいまい検索によるカレンダー照合、list_events/list_reminders のフィルター/ソート/件数制限、delete_events_batch のドライランと日付範囲モード |
| v0.9.0 | 新しいツールを 4 つ追加(20→24):update_calendar、search_reminders、create_reminders_batch、delete_reminders_batch |
| v0.8.2 | 多言語対応の週サポート:list_events_quick に week_starts_on パラメーターを追加(monday/sunday/saturday/system) |
| v0.8.1 | 修正:update_event の時刻検証のバグ、イベント移動時に所要時間が保持されない問題 |
| v0.8.0 | 破壊的変更:作成操作では calendar_name が必須になりました(暗黙の既定値は使われません) |
| v0.7.0 | Anthropic Connectors Directory 向けのツール注釈、自動更新機構、バッチツールの説明を改善 |
| v0.6.0 | ソースの曖昧さの解消:同名カレンダー向けに calendar_source パラメーターを追加 |
| v0.5.0 | バッチ削除、重複検出、複数キーワード検索、権限エラーの改善、PRIVACY.md |
| v0.4.0 | イベントのコピー/移動:copy_event、move_events_batch |
| v0.3.0 | 高度な機能:検索、クイック範囲指定、バッチ作成、競合チェック、タイムゾーン表示 |
| v0.2.0 | Swift に書き換え、Reminders を完全サポート |
| v0.1.x | Python 版(非推奨) |
コントリビューション
コントリビューションを歓迎します!お気軽にプルリクエストを送信してください。
リリースプロセス(メンテナー向け)
バージョン番号は、意味合いの異なる次の3か所にあります。
| ファイル | 役割 | 更新するタイミング |
|---|---|---|
Sources/CheICalMCP/Version.swift — AppVersion.current | 信頼できる唯一の情報源。--version、help、MCP の serverInfo.version に表示されます | リリースごと |
Sources/CheICalMCP/Info.plist — CFBundleVersion | macOS バンドルのバージョン | リリースごと。AppVersion.current と一致させる必要があります |
mcpb/manifest.json — version | .mcpb に同梱される Claude Desktop バンドルマニフェスト | リリースごと。AppVersion.current と一致させる必要があります |
server.json — version + packages[].identifier + fileSha256 | MCP Registry への登録用スナップショット | 新しい .mcpb を MCP Registry に再提出する場合のみ(独立したサイクル) |
scripts/build-mcpb.sh は最初の3つが一致するかを確認し、いずれかにずれがあればビルドを失敗させます。server.json は意図的に切り離されています。更新には .mcpb の再ビルド、新しい SHA256 の取得、再提出が必要ですが、これらの手順はソースのリリースごとに行うものではないためです。
署名と公証(macOS 26 以降で必須)
v1.7.1 以降、リリースバイナリは Developer ID Application 証明書で署名し、Apple の notarytool を使って公証しています。macOS 26 ではこれが必須です。アドホック署名されたバイナリでは、カレンダー/リマインダーの TCC 権限ダイアログを表示できません。
前提条件(初回のみの設定):
- Apple Developer Program への登録。
- Developer ID Application 証明書をログインキーチェーンにインストールします。
- 次のコマンドで確認します:
security find-identity -p codesigning -v(Developer ID Application: <Your Name> (<TeamID>)が表示される必要があります)。 - Team ID はご自身のものを使用します。https://developer.apple.com/account → Membership Details で確認してください。(このリポジトリ内に記載されているメンテナーの
6W377FS7BSは、参考情報にすぎません。)
- 次のコマンドで確認します:
notarytoolのキーチェーンプロファイル(名前は任意。ビルドスクリプトが既定で探す名前はche-ical-mcpです)。- 対話形式で作成します(推奨。パスワードがシェルの履歴に残りません)。
xcrun notarytool store-credentials che-ical-mcp --apple-id <your-apple-id> --team-id <your-team-id> # notarytool がアプリ用パスワードの入力を求めます - アプリ用パスワードは、https://account.apple.com → Sign-In and Security → App-Specific Passwords で生成します。用途を限定したパスワード(例:
che-ical-mcpという名前)を使用してください。漏えいした場合は失効させて再生成します。コマンドラインで--passwordを使って渡すことは絶対に避けてください。~/.zsh_historyに記録されます。
- 対話形式で作成します(推奨。パスワードがシェルの履歴に残りません)。
- ビルドスクリプトで使用する認証情報を環境変数に設定します。
export DEVELOPER_ID='Developer ID Application: <Your Name> (<TeamID>)' export NOTARY_PROFILE='che-ical-mcp' # match what you set up in step 3
これらは ~/.zshrc またはプロジェクトローカルの .envrc(gitignore 対象)に設定してください。スクリプトには意図的に既定値がありません。そのため、新しくフォークした場合にメンテナーの認証情報に関するエラーが発生することはありません。
リリースごとの手順:
make release-signed # builds universal binary → signs + notarizes → packages .mcpb
gh release create vX.Y.Z mcpb/server/CheICalMCP mcpb/server/CheICalMCP.sha256 mcpb/che-ical-mcp-X.Y.Z.mcpb mcpb/che-ical-mcp-X.Y.Z.mcpb.sha256 --notes "..."
make release-signed は scripts/build-mcpb.sh を実行します。このスクリプトはユニバーサルバイナリの作成後に scripts/sign-and-notarize.sh を呼び出します。署名スクリプトは事前チェック(証明書と notarytool プロファイル)を行い、不足があればわかりやすいメッセージを表示してすぐに失敗します。公証には通常1~15分かかります(notarytool submit --wait は Apple の処理が終わるまで待機します)。
ビルド後の検証(エンドツーエンドで確認するため、3つすべて実行してください):
# 1. Signature properties (cert + hardened runtime + team ID)
codesign -dv --verbose=2 mcpb/server/CheICalMCP
# Expected:
# Authority=Developer ID Application: <Your Name> (<TeamID>)
# TeamIdentifier=<TeamID>
# flags=0x10000(runtime)
# Signature size in the few thousand bytes range (varies by cert chain)
# 2. Signature integrity
codesign --verify --deep --strict --verbose=2 mcpb/server/CheICalMCP
# Expected: exit 0, no warnings
# 3. Notarization end-to-end (this is the real "Gatekeeper would accept" gate)
spctl -a -vvv -t install mcpb/server/CheICalMCP
# Expected: <binary>: accepted; source=Notarized Developer ID
#
# Note on flag choice (verified empirically on macOS 26.4.1, 2026-05-04):
# -t execute → rejected "code is valid but does not seem to be an app"
# (Apple's "execute" type expects a .app bundle structure,
# not raw Mach-O CLI binaries)
# -t install → accepted; source=Notarized Developer ID ← use this
# -t open → rejected "Insufficient Context"
#
# Apple's Code Signing Guide describes -t execute as the assessment type for
# "applications and tools", but on macOS 26 raw Mach-O binaries fall through
# the .app bundle check. -t install is the documented assessment type for
# software being installed (which describes how a CLI binary lands in ~/bin),
# and is the type that returns the actual notarization verdict in practice.
# Re-test if Apple changes this behavior in a future macOS update.
署名による遅延を避けたローカル開発時の反復作業:
SKIP_CODESIGN=1 ./scripts/build-mcpb.sh # ad-hoc signed; do NOT ship the result
make install # installs ad-hoc to ~/bin (dev only)
build-mcpb.sh スクリプトは、DEVELOPER_ID が未設定の場合、または証明書がキーチェーンにない場合、署名を自動的にスキップします。そのため、コントリビューター/CI/フォークでは、SKIP_CODESIGN を手動で設定せずにテスト用の動作する署名なし .mcpb をビルドできます。この場合は「Skipping codesign」という警告が表示されます。
署名 ID の環境変数:
| 環境変数 | デフォルト | 必須となる用途 |
|---|---|---|
DEVELOPER_ID | (未設定 — 署名を自動的にスキップ) | 署名付きリリース |
NOTARY_PROFILE | (未設定 — sign-and-notarize.sh で即時終了) | 署名付きリリース |
ENTITLEMENTS | Sources/CheICalMCP/Entitlements.plist | カスタムのエンタイトルメントファイル |
SKIP_CODESIGN | (未設定) | 証明書があっても署名を強制的にスキップする(1 または true を設定) |
REQUIRE_CODESIGN | (未設定) | 署名の前提条件が満たされていない場合に即時終了する(make release-signed によって 1 に設定されます — 正規のリリース手順では、署名されていない成果物を黙って生成してはいけません。フォークでの開発ビルドとして ./scripts/build-mcpb.sh を直接実行する場合は設定しないでください) |
既知の制限 — ステープリング非対応:stapler staple は生の Mach-O バイナリに対応していません(.app/.pkg/.dmg バンドルのみ対応)。公証後、Gatekeeper はステープルされたチケットを読み取るのではなく、初回起動時にオンラインでバイナリを確認します。エアギャップ環境のネットワークを利用するエンドユーザーには、「開発元を検証できません」という警告が表示されることがあります。ネットワーク接続中に一度起動すれば解決します(Apple が判定結果をキャッシュします)。対処法:必要に応じて、将来 .pkg ラッパーに対して xcrun stapler staple を実行してください。
トラブルシューティング:
- 公証が却下されましたか?
xcrun notarytool log <submission-id> --keychain-profile $NOTARY_PROFILEで Apple による却下理由を確認できます。署名スクリプトは毎回、送信 ID を出力します。 codesignで ID が見つからないというエラーが表示されますか?security find-identity -p codesigning -vで証明書が存在し、有効であることを確認してください。xcrun notarytool history --keychain-profile $NOTARY_PROFILEでプロファイルが機能することを確認してください。- 証明書の有効期限が切れていますか? https://developer.apple.com/account/resources/certificates で再発行し、インストールして、
DEVELOPER_IDを再エクスポートしてください。 - セキュリティに関する警告:共有マシンや信頼できないマシンでは、署名用キーチェーンのロックを解除しないでください。証明書と秘密鍵による署名は、サプライチェーンの安全性にとって重要です。
ライセンス
MIT ライセンス — 詳細は LICENSE を参照してください。
作成者
Che Cheng(@kiki830621)が作成しました。
役に立った場合は、ぜひスターを付けてください!
繰り返し予定の読み取り名(#198、未リリース):イベントには event_recurrence_rules を、リマインダーには reminder_recurrence_rules を使用してください。どちらもルール配列ですが、セレクターが欠落している場合の扱いと終了日の表示は異なります。従来の recurrence_rules エイリアスも引き続き利用できます。不明なフィールドを拒否するクライアントでは、デコーダーの更新が必要です。形式の比較を参照してください。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。