Apple Calendar について
Apple Calendar は、EventKit を通じて macOS のカレンダーと予定を操作する MCP サーバーです。安全モードやカレンダーの許可リストを備え、対応環境では自動化による読み取りにも切り替えます。
主な機能
- 01カレンダーの検出と一覧表示
- 02予定の作成、読み取り、更新、削除
- 03今日のリソースと計画プロンプト
- 04カレンダーの状態確認と権限の復旧
- 05安全モードとカレンダー許可リスト
活用シーン
- 01会議や予約の予定確認
- 02カレンダー予定の作成や変更
- 03Agent がアクセス・編集できるカレンダーの制限
MCP 対応
MCP クライアントにカレンダー、予定、リソース、プロンプトを提供します。既定の stdio に加え、Streamable HTTP も設定できます。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
このサーバーのパッケージやリモートエンドポイントはまだ取得できていません。プロジェクトの README の手順に従ってください。
ツール
13掲載時のツール一覧 · 1 日前に更新
このツールにパラメーターはありません。
詳細
Apple Calendar
macOS 向けの Apple Calendar MCP サーバーです。
EventKit を通じて、カレンダーとイベントにアクセスできます。Calendar をシステム上の記録元として維持しながら、エージェントによるイベントの読み取り、作成、更新、削除を可能にします。
使用する場面
- カレンダーのみを扱うワークフロー
- オールインワンサーバーを使わずに、EventKit 経由でカレンダーにアクセスする場合
- スケジュール管理をアプリレベルでより明確に分離する場合
機能
- カレンダーの検出と一覧表示
- イベントの作成、読み取り、更新、削除
- コンテキストに制約のあるクライアント向けのツール検出ヘルパー
search_toolsとget_tool_info - 今日のリソースと計画用プロンプト
- 結果が空の場合とアクセスがブロックされている場合を区別するヘルスチェック
- 対応するローカル環境でネイティブの EventKit による読み取りがブロックされている場合に、Calendar.app の自動化を使った読み取りのフォールバック
- 権限の復旧:
calendar_permission_guide、calendar_recheck_permissions
この Mac にインストール
クローンから
git clone https://github.com/JonathanRReed/Apple-MCPs.git
cd Apple-MCPs
uv sync --all-packages
これにより、各サーバーのエントリーポイントが .venv/bin に配置された、すべてのサーバーを含む単一のワークスペース環境が構築されます(例:.venv/bin/apple-calendar-mcp)。MCP クライアントから Apple-Calendar-MCP/start.sh を指定することもできます。このスクリプトは uv run を優先し、利用できない場合は通常の venv のブートストラップにフォールバックします(Python 3.11 以降が必要です)。
AI エージェントにインストール
汎用 MCP クライアントの設定
{
"mcpServers": {
"apple-calendar": {
"command": "uvx",
"args": ["apple-calendar-mcp"],
"env": {
"APPLE_CALENDAR_MCP_SAFETY_MODE": "safe_manage"
}
}
}
}
クローンから実行する場合は、コマンドとして /path/to/Apple-MCPs/Apple-Calendar-MCP/start.sh を指定し、args は空にしてください。
Claude Code の例
claude mcp add --transport stdio --scope user apple-calendar -- uvx apple-calendar-mcp
--scope user を指定すると、すべてのプロジェクトでサーバーを利用できます。代わりに .mcp.json を通じて特定のリポジトリと共有するには、--scope project を指定してください。
カレンダーとイベントの識別子の選択
calendar_list_calendars を呼び出し、表示名とソースを基準に目的のカレンダーを選択します。返された calendar_id は変更せずに、calendar_list_events、calendar_create_event、または calendar_update_event の移動先に渡してください。ネイティブの EventKit による一覧ではネイティブの識別子が返され、自動化による一覧ではカレンダー名が識別子として使われます。EventKit でカレンダーを読み取れる場合、calendar_create_event または calendar_update_event に渡されたカレンダー名は、ネイティブのカレンダーに解決されます。このとき、大文字と小文字の違いや余分な空白は無視されるため、書き込み時にアラームを完全にサポートできます。複数のカレンダーで同じ名前が使われている場合は、候補を含む AMBIGUOUS_CALENDAR が返されます。その場合は、目的の calendar_id を渡してください。名前が見つからない場合は CALENDAR_NOT_FOUND が返され、読み取り専用カレンダーの場合は CALENDAR_READ_ONLY が返されます。ネイティブのカレンダー読み取りアクセスがない場合も、名前は引き続き自動化で処理されます。
Calendar の権限を変更した後は、MCP サーバーを再起動し、calendar_list_calendars を再度呼び出して識別子を更新してください。アラームを完全に置き換える、または消去するには、ネイティブの calendar_id を使ってイベントを一覧表示し、返されたネイティブの event_id を calendar_update_event に渡してください。既存の applescript:: イベント ID は、権限変更後も引き続き自動化で処理されます。イベント ID は不透明な値として扱い、既存のトークンを書き換えるのではなく、再度一覧表示してネイティブ ID を取得してください。カレンダーの書き込み可否、安全モード、許可リストは引き続き適用されます。
ブリッジ一括検索
内部の Python CalendarBridge.get_events(event_ids) メソッドは、MCP ツールを追加することなくネイティブ検索を一括処理します。空でない文字列のシーケンスを渡し、入力 ID は最大 10000 件です。重複する入力 ID は一度だけ解決されます。リクエストは、JSON エスケープを含め、正確に 32768 バイトの UTF-8 JSON argv 予算にチャンク分割されます。個々の ID が大きすぎる場合は、検索の前に拒否されます。
返されるマッピングは以下を区別します。
- イベント値: 要求された ID に対する検証済みの応答
- None: 既存の単一取得/JXA フォールバックを通じて確認された明示的なネイティブミス、またはそのフォールバック経路での決定的なミス
- 存在しないキー: 不明。未応答、不正な形式、矛盾、重複応答、不一致、または未サポートのエントリを含みます
JXA が発行する ID は、Automation バックエンド、カレンダースコープ、および正確な UID または id() 名前空間/値を識別する、不透明なバージョン付きトークンです。これらを解析したり構築したりしないでください。UID を持たないイベントは、実際の型付き id() 値を保持します。同一のメタデータを持つ異なるイベントが、もはや統合されることはありません。使用可能な識別子を持たない行、または重複するプロバイダー ID には、表示専用の弱いトークンが付与されます。弱いトークンは、不在を証明したり、書き込みを承認したりすることはできません。
バージョン付きトークンは、検証済みのサーバーフィルタリングされた JXA 検索を通じて直接解決されます。一致する単一のカレンダーとイベントが必要です。曖昧、利用不可、不正な形式、または不一致の検索は不明のままです。フィルタリングされていないイベントディレクトリのスキャンは使用されません。検索スナップショットは、クエリごとに 1000 カレンダーおよび 1000 件の返された一致に制限され、識別子は 32768 文字に制限されます。レガシーのベア UID/id 値は、その名前空間が同じイベントを曖昧さなく識別する場合には引き続き解決されます。レガシーの calendar/start/title 複合値は、一意である場合には引き続き読み取り可能ですが、変更や決定的な一括不在を承認することはできません。バージョン付きトークンに似たレガシー値は、その意味が矛盾する場合には拒否されます。
レガシーのフォールバック識別子は、リテラルのプロバイダー UID でもあり得るエンコードされた識別子を含め、カレンダー間での衝突チェックを必要とします。これらの正確なクエリは、大規模なカレンダーストアでは 30 秒のフォールバック期限を超える可能性があります。タイムアウトは明示的なエラーであり、不在を確定したり、変更を許可したりしません。完全なネイティブ EventKit アクセスは、ネイティブ識別子に対するそのフォールバック検索を回避します。ホストアプリに完全なカレンダーアクセスを許可し、イベントを再度リストしてネイティブ ID を取得し、再試行してください。既存のフォールバック識別子は、厳格な衝突チェックを維持します。
ネイティブミスは、単一取得/JXA 経路を再試行します。ネイティブバッチ全体が応答できない場合、不透明なネイティブ ID に対するフォールバックミスは、JXA が異なる識別子形式を使用する可能性があるため、不明のままです。検証済みのバージョン付き JXA ミスは、不在を確定できます。権限または ID ごとの確認の失敗は不明のままです。フォールバック以外のヘルパー全体のトランスポート失敗は、明示的なエラーのままです。異なる正規 ID を持つ有効なネイティブ応答には、その正規 ID を確認する別個の単一取得検索が必要です。矛盾するまたは未確認のエイリアスは不明のままです。未サポートのレガシー uid: ID は、検索なしでは不明のままです。呼び出し元は、存在しないキーのマッピングを削除してはなりません。
JXA のインプレース更新と削除には、強力で一意の ID が必要であり、書き込みの前に古いカレンダー名を拒否します。JXA フォールバックを介したカレンダーの移動は、クローン作成がすべてのイベントフィールドを安全に保持できないため、明示的に未サポートです。ネイティブのカレンダー移動は引き続き利用可能です。バージョン付き JXA ID を介した繰り返しの更新も未サポートです。
ネイティブバッチコマンド自体は、EventKit のみの検索結果を報告します。合成 ID は UNSUPPORTED_IDENTIFIER を生成します。ネイティブの EVENT_NOT_FOUND だけでは、両方のバックエンドにわたる確認済みの不在とはなりません。
セーフティモード
safe_readonlysafe_managefull_access
カレンダーの許可リスト
MCP クライアントの設定で次の環境変数を設定し、サーバーを再起動してください。
| 変数 | 効果 |
|---|---|
APPLE_CALENDAR_MCP_ALLOWED_CALENDARS | サーバーによる読み取りまたは変更を許可するカレンダー名を、カンマ区切りで指定します。カレンダー一覧、イベント一覧、イベント詳細、Calendar リソースには、この範囲が適用されます。 |
APPLE_CALENDAR_MCP_WRITE_ALLOWED_CALENDARS | サーバーによるイベントの作成、更新、削除を許可するカレンダー名を、追加でカンマ区切りで指定します。他の読み取り可能なカレンダーが非表示になることはありません。 |
スケジュールの読み取りは許可し、専用カレンダーへの書き込みのみ許可するアシスタントの場合:
{
"APPLE_CALENDAR_MCP_SAFETY_MODE": "safe_manage",
"APPLE_CALENDAR_MCP_WRITE_ALLOWED_CALENDARS": "AI Planning"
}
どちらかの許可リストが未設定または空の場合、そのリストによる制限は適用されません。両方を設定した場合、書き込みは両方の条件を満たす必要があります。safe_readonly は、どちらのリストに関係なくすべての書き込みを禁止します。イベントの移動では、移動元と移動先の両方のカレンダーが確認されます。許可リストが設定されている場合、対象を特定できない書き込みは拒否されます。
名前は設定の空白を取り除いた後、大文字と小文字を区別して完全一致で照合されます。一致する名前のカレンダーはすべて対象となるため、セキュリティ上重要な範囲を設定する場合は、カレンダー名が重複しないようにしてください。calendar_health は、設定されている書き込み許可リストを報告します。
これらは Python MCP サーバーが適用するポリシーであり、macOS のサンドボックスではありません。ネイティブヘルパーやブリッジライブラリを直接使用した場合、これらのポリシーは適用されません。macOS の権限は引き続き適用されます。また、MCP クライアントが返されたデータをモデルプロバイダーに送信する場合があります。
トランスポート
デフォルトで推奨されるトランスポートは stdio です。APPLE_CALENDAR_MCP_TRANSPORT=streamable-http を設定すると(必要に応じて APPLE_CALENDAR_MCP_HOST と APPLE_CALENDAR_MCP_PORT も設定できます)、代わりに Streamable HTTP で提供されます。
macOS の権限
- カレンダーへのアクセスが必要です
calendar_healthは、AppleScript のフォールバックを試したり権限を要求したりせずに、ネイティブのaccess_status、読み取りアクセス、書き込みアクセスを報告します。明示的なカレンダーの読み取りでは、既存の自動化フォールバックを引き続き使用できます。
起動チェックリスト
- MCP クライアントに
uvx apple-calendar-mcp(またはクローンのApple-Calendar-MCP/start.sh)を追加します - カレンダーツール一式がコンテキストに読み込まれるよう、クライアントを再読み込みするか再接続します
- 最初に
calendar_healthを呼び出します - アクセスがブロックされている場合、または
access_statusがnot_determinedの場合は、calendar_permission_guideを呼び出します - macOS の権限を変更した後、
calendar_recheck_permissionsを呼び出します
プロンプト作成時の注意点
tools/listはカレンダーツール一式を返します。コンテキストに制約のあるクライアントは、最初にsearch_toolsを使用し、その後必要なカレンダーツールについてget_tool_infoを呼び出せます。- イベントを作成する前に、日付、時刻、所要時間、タイトルをユーザーに確認します
- 予定された時間枠、会議、予約には Calendar を使用します
関連項目
イベントの通知
calendar_create_event と calendar_update_event は、{ "minutes_before": 15 } または { "absolute_iso": "2030-10-11T10:00:00Z" } オブジェクトの配列である alarms を受け付けます。絶対日時には、明示的な Z または UTC オフセットが必要です。タイムゾーンのない日時は拒否されます。相対オフセットは、0〜525600 の整数分である必要があります。各イベントに設定できるアラームは最大100件です。更新時に既存の通知を保持するには alarms を省略し、消去するには [] を渡します。
イベントの詳細と一覧のレスポンスには、アラームのメタデータが含まれます。EventKit は相対、絶対、場所に基づく通知を報告します。アラームの完全な置き換えと消去には、ネイティブの EventKit へのアクセスが必要です。Calendar のスクリプティングへのフォールバックでは、最初の表示通知を作成し、Calendar のスクリプティング辞書で公開されている通知タイプを読み取ることができます。アラームの編集で既存の通知を削除する必要がある場合、または既存の通知コレクションを読み取れない場合は、イベントのフィールドを変更する前に ALARM_EDIT_REQUIRES_NATIVE を返します。他のフィールドを更新する際に既存の通知を保持するには、alarms を省略してください。フォールバックでの更新では、明示的な alarms([] を含む)と、null 以外のタイトル、時刻、場所、メモ、または終日フィールドを組み合わせる場合、そのフィールドに指定値がすでに設定されていても、ネイティブの EventKit が必要です。変更のない calendar_id はフィールドの書き込みには該当しません。移動は引き続きサポートされません。アラームのみの更新では、4つの通知コレクションすべてを読み取れて、かつ空の場合、最初の表示通知を追加できます。この場合、[] は何もしません。失敗する可能性のあるイベントレコードの読み取りは、挿入前に完了します。挿入に失敗した場合、または変更処理がタイムアウトした場合、結果が不明なことがあります。個々の通知は削除されないため、再試行する前にイベントを確認する必要があります。フォールバックの同等性については、引き続き issue #41 で追跡されています。
calendar_health は、ネイティブの読み取り/書き込み権限に基づき、alarm_edit_backend: "native_eventkit" と can_edit_existing_alarms を報告します。各編集には、Calendar の書き込み可能性とサーバーの安全規則も引き続き適用されます。
元のイベント通知に関する貢献をいただいた LightSpeedSpirit に感謝します(PR #26)。
繰り返しイベント
繰り返しイベントのすべての回は同じ event_id を共有するため、calendar_update_event と calendar_delete_event は、書き込み対象となる回を指定する2つの任意引数を受け付けます。calendar_list_events は、これらのイベントに recurring: true を付けます。
scope:1回分を対象とする"occurrence"、その回とそれ以降のすべてを対象とする"following"、またはすべての回を対象とする"series"を指定します。occurrence_start_iso:"occurrence"と"following"の場合に指定します。calendar_list_eventsが返したとおりの、その回のstartです。
scope を指定せずに繰り返しイベントを書き込んでも、何も変更されません。クライアントが MCP フォーム(エリシテーション)をサポートし、呼び出しで特定の回が指定されている場合、サーバーはユーザーに、今回のみ、今回以降のすべて、シリーズ全体のいずれかを選ぶよう求めます。それ以外の場合は RECURRING_EVENT_SCOPE_REQUIRED を返し、エージェントにユーザーへ確認してから再度呼び出すよう伝えます。選択するのはモデルではなくユーザーであるため、エージェントが推測でシリーズ全体を削除することはできません。ユーザーが質問を拒否すると、CANCELLED_BY_USER が返されます。繰り返しのないイベントは、これまでどおり動作します。
単独で編集された回には独自の event_id が割り当てられ、その event_id を使った書き込みでも同じ scope を指定できます。"series" を指定すると、新しい start_iso/end_iso によって、すべての回が同じ差分だけ移動します。レスポンスの deleted は、対象の回が実際に削除されたかどうかを示します。スコープの指定にはネイティブの EventKit へのアクセスが必要です。Calendar オートメーションでは UNSUPPORTED_OPERATION が返されます。
詳細な報告と根本原因の分析をいただいた vlasovpe-sg に感謝します(issue #79)。
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。