はじめに
第1章では、エージェントAIの概念と、**Model Context Protocol(MCP)**がどのようにAIを外部データやツールと接続し、自律的なタスク実行を可能にするかを学びました。簡単なメールサーバーを構築し、MCPの基本的な動作を体験しました。今回は、実際にエージェントAIを強化する第一歩として、Google CalendarとMCPを統合する方法を解説します。
この第2章では、Google Calendar APIを利用して予定を取得・作成するMCPサーバーを構築し、Claude Desktopと連携させます。これにより、「来週の空き時間を教えて」や「新しいミーティングを追加して」といったリクエストを処理できるエージェントAIの基盤を作ります。コード例とステップごとのガイドで、初心者でも実装できる内容を目指します。さっそく始めましょう!
Google Calendar APIの準備
Google Calendarと連携するには、Google Cloud Platform(GCP)でAPIを有効化し、認証情報を設定する必要があります。以下の手順で準備します:
-
Google Cloud Consoleでプロジェクトを作成:
- Google Cloud Consoleにアクセス。
- 新しいプロジェクトを作成(例:
mcp-calendar-agent
)。 - 「APIとサービス」→「ライブラリ」で「Google Calendar API」を検索し、有効化。
-
OAuth 2.0認証情報の設定:
- 「APIとサービス」→「認証情報」→「認証情報を作成」→「OAuthクライアントID」。
- アプリケーションの種類を「デスクトップアプリ」に設定。
- クライアントIDとクライアントシークレットをダウンロード(
credentials.json
)。
-
必要なライブラリのインストール:
PythonでGoogle Calendar APIを利用するため、以下のライブラリをインストール:pip install google-auth-oauthlib google-auth-httplib2 google-api-python-client
-
トークンの生成:
初回実行時に、ブラウザでGoogleアカウントにログインし、アクセスを許可。トークンがtoken.json
に保存されます。
MCPサーバーの構築:Google Calendarとの統合
Google Calendarから予定を取得し、新しい予定を作成するMCPサーバーを構築します。以下のコードは、予定リストの取得と予定作成のリソースを提供します:
from mcp import MCPServer
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from datetime import datetime, timedelta
import os
class CalendarServer(MCPServer):
def __init__(self, host, port, credentials_file, token_file):
super().__init__(host, port)
self.credentials_file = credentials_file
self.token_file = token_file
self.service = self._init_calendar_service()
self.register_resource("get_events", self.get_events)
self.register_resource("create_event", self.create_event)
def _init_calendar_service(self):
SCOPES = ['https://www.googleapis.com/auth/calendar']
creds = None
if os.path.exists(self.token_file):
creds = Credentials.from_authorized_user_file(self.token_file, SCOPES)
if not creds or not creds.valid:
flow = InstalledAppFlow.from_client_secrets_file(self.credentials_file, SCOPES)
creds = flow.run_local_server(port=0)
with open(self.token_file, 'w') as token:
token.write(creds.to_json())
return build('calendar', 'v3', credentials=creds)
def get_events(self, params):
try:
time_min = datetime.utcnow().isoformat() + 'Z'
time_max = (datetime.utcnow() + timedelta(days=7)).isoformat() + 'Z'
events_result = self.service.events().list(
calendarId='primary',
timeMin=time_min,
timeMax=time_max,
maxResults=10,
singleEvents=True,
orderBy='startTime'
).execute()
events = events_result.get('items', [])
formatted_events = [
{
'summary': event.get('summary', 'No title'),
'start': event['start'].get('dateTime', event['start'].get('date')),
'end': event['end'].get('dateTime', event['end'].get('date'))
}
for event in events
]
return {"status": "success", "events": formatted_events}
except Exception as e:
return {"status": "error", "message": str(e)}
def create_event(self, params):
try:
summary = params.get("summary", "New Meeting")
start_time = params.get("start_time", (datetime.utcnow() + timedelta(hours=1)).isoformat())
duration = params.get("duration", 60) # 分単位
event = {
'summary': summary,
'start': {'dateTime': start_time, 'timeZone': 'UTC'},
'end': {'dateTime': (datetime.fromisoformat(start_time) + timedelta(minutes=duration)).isoformat(), 'timeZone': 'UTC'}
}
event = self.service.events().insert(calendarId='primary', body=event).execute()
return {"status": "success", "event_id": event.get('id'), "link": event.get('htmlLink')}
except Exception as e:
return {"status": "error", "message": str(e)}
if __name__ == "__main__":
server = CalendarServer(
host="localhost",
port=8088,
credentials_file="credentials.json",
token_file="token.json"
)
print("カレンダーMCPサーバーを起動中: http://localhost:8088")
server.start()
コードの説明
- _init_calendar_service:Google Calendar APIの認証を設定。初回はブラウザで認証し、トークンを保存。
- get_events:今後7日間の予定を取得し、タイトル、開始・終了時間を返す。
- create_event:新しい予定を作成。タイトル、開始時間、期間をパラメータとして受け取る。
- register_resource:リソースを登録し、AIがアクセス可能に。
前提条件
-
credentials.json
をプロジェクトフォルダに配置。 - 初回実行時に、ブラウザでGoogleアカウントにログインし、アクセスを許可。
サーバーのテスト
サーバーが正しく動作するか確認します:
-
サーバー起動:
python calendar_server.py
コンソールに「カレンダーMCPサーバーを起動中: http://localhost:8088」と表示。
-
JSON-RPCリクエストの送信:
Pythonでテストリクエストを送信:import requests import json url = "http://localhost:8088" payload = { "jsonrpc": "2.0", "method": "get_events", "params": {}, "id": 1 } response = requests.post(url, json=payload) print(json.dumps(response.json(), indent=2, ensure_ascii=False))
期待されるレスポンス:
{ "jsonrpc": "2.0", "result": { "status": "success", "events": [ { "summary": "チームミーティング", "start": "2025-04-16T10:00:00Z", "end": "2025-04-16T11:00:00Z" } ] }, "id": 1 }
-
予定作成のテスト:
payload = { "jsonrpc": "2.0", "method": "create_event", "params": {"summary": "テストミーティング", "duration": 30}, "id": 2 } response = requests.post(url, json=payload) print(json.dumps(response.json(), indent=2, ensure_ascii=False))
Claude Desktopとの統合
サーバーをClaude Desktopに接続します:
-
設定ファイルの編集:
Claude Desktopの設定ファイル(例:claude_desktop_config.json
)に以下を追加:{ "mcp_servers": [ { "name": "CalendarServer", "url": "http://localhost:8088", "auth": "none" } ] }
-
Claudeでテスト:
Claude Desktopを起動し、プロンプトを入力:来週の予定を教えてください。
レスポンス例:
来週の予定: - 2025-04-16 10:00: チームミーティング(1時間)
予定作成のプロンプト:
明日の14時に30分のミーティングを追加してください。
レスポンス例:
ミーティングを追加しました: - タイトル:テストミーティング - 時間:2025-04-16 14:00(30分) - リンク:https://calendar.google.com/...
セキュリティの考慮
本番環境では、以下の対策を講じます:
-
OAuth 2.1の使用:
auth
を"none"
から適切なトークン認証に変更。 -
アクセス制限:カレンダーの読み取り専用スコープ(
https://www.googleapis.com/auth/calendar.readonly
)を検討。 - エラーハンドリング:ユーザー向けにわかりやすいエラーメッセージを返す。
- ログ記録:リクエストとレスポンスを記録し、問題を追跡。
実装のコツ
- キャッシュ:頻繁にアクセスする予定データをキャッシュして、API呼び出しを削減。
- タイムゾーン対応:ユーザーのタイムゾーンを考慮し、適切に変換。
- テストデータ:本番前に、テスト用カレンダーを作成して動作確認。
- コミュニティリソース:GitHubで公開されているGoogle Calendar用MCPサーバーを参考に。
まとめと次のステップ
この第2章では、Google CalendarとMCPを統合し、スケジュール管理の基盤となるサーバーを構築しました。これにより、エージェントAIがユーザーの予定を把握し、新しい予定を追加する能力を獲得しました。
次の第3章では、NotionとSlackを統合し、プロジェクト管理を自動化するエージェントAIを構築します。たとえば、SlackのメッセージからNotionにタスクを自動追加する機能を実装します。実用的なエージェントAIに興味がある方は、ぜひお楽しみに!
役に立ったと思ったら、「いいね」や「ストック」をしていただけると嬉しいです!次の章でまたお会いしましょう!