mcpField
E
Easy!Appointments

Easy!Appointments

リモート
ea-mcp-demo.qiyuanlabs.ai生産性01 週間前に更新
リポジトリ公式サイト

Easy!Appointments について

Easy!Appointmentsは、予約システムのスタッフがAIアシスタントを通じてサービス、顧客、空き時間を調べ、予約を管理するリモートMCPサーバーです。OAuthのアクセス権は読み取り専用と受付担当に分かれ、変更には事前確認が必要です。

主な機能

  1. 01サービス、顧客、予約の検索
  2. 02サービスや時間帯で空き枠を絞り込み
  3. 03予約の作成、変更、キャンセル
  4. 04接続ごとに読み取り専用または受付権限を設定
  5. 05変更時にプレビュー、署名トークン、冪等キーを要求
  6. 06マスキング済みの呼び出しログを記録・出力

活用シーン

  1. 01顧客に合う予約時間を探す
  2. 02予約の登録や既存予約の変更
  3. 03顧客の予約履歴を確認
  4. 04受付操作のログを監査・出力

MCP 対応

OAuth認証を介して、Easy!Appointmentsの検索および予約管理ツールをAIクライアントに提供するリモートMCPサーバーです。書き込みには同じ利用者とクライアントによるプレビューに一致する確認トークンが必要です。

設定

リモートサーバーはインストール不要です。クライアントを選んで設定をコピーするか、ワンクリックで導入できます。

エンドポイントhttps://ea-mcp-demo.qiyuanlabs.ai/mcp
インストールコマンドをコピー
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

コマンドはターミナルで実行し、JSON は各クライアントの MCP 設定に貼り付けて再起動します。認可が必要なサーバーは初回接続時にログインを求めます。

ツール

詳細

Easy!Appointments MCP サーバー

Claude、ChatGPT、その他の AI アシスタントが Easy!Appointments の予約システムで受付業務を行えるリモート MCP サーバーです。空き枠の検索、顧客情報の照会、予約、日時変更、キャンセルができます。

開発者だけでなく、予約システムを運用する方のために作られています。

  • OAuth でサインイン。 スタッフは各自のログイン情報を使って AI アシスタントを接続します。Easy!Appointments API トークンがサーバーの外に出ることはありません。
  • 接続ごとに 2 つのアクセスレベル。 閲覧のみでは、サービス、空き時間、顧客、予約を確認できます。受付では、予約、日時変更、キャンセルも可能です。各ユーザーの上限は管理者が設定します。
  • プレビューなしで変更されることはありません。 変更はすべて 2 段階の呼び出しで行います。まずアシスタントがユーザーに表示するプレビューを行い、次にプレビューの署名付き confirmation_token と冪等性キーを含む確定呼び出しを行います。プレビューと一致しない確定要求は拒否され、再試行された要求で予約が重複することもありません。
  • 呼び出しログ。 すべてのツール呼び出しについて、マスキングされた個人情報、実行した Easy!Appointments へのリクエスト、所要時間を記録します。スタッフはログを確認し、CSV としてエクスポートできるほか、任意のアシスタントを切断できます。
  • Easy!Appointments に負荷をかけません。 API は IP ごとに 2 分間で 100 件のリクエストを許可しています。このサーバーはサービス一覧と空き時間をキャッシュし、1 回の検索で対象となる日数に上限を設けます。また、予約システムごとに共通のリクエスト予算(デフォルトでは 2 分間に 90 件、EA_REQUEST_BUDGET)を設け、複数のアシスタントが同時に利用してもアクセスが遮断されないようにします。

Easy!Appointments とは提携関係になく、同社からの推奨も受けていません。Easy!Appointments はその所有者の商標です。

ツール

ツールアクセス機能
list_services閲覧のみ所要時間、料金、提供者、および各提供者のタイムゾーンを含むサービス一覧
find_open_slots閲覧のみサービスの空き開始時刻を最長 14 日間分検索します。特定の提供者または全員を対象にでき、午前、午後、夕方で絞り込めます
find_customer閲覧のみ名前、メールアドレス、電話番号から顧客を検索します
list_appointments閲覧のみ顧客、提供者、または日付範囲を指定して予約を検索します
book_appointment受付既存または新規の顧客の予約を行います
reschedule_appointment受付予約の日時または提供者を変更します
cancel_appointment受付今後の予約をキャンセルします

API 経由で変更を行うたびに、Easy!Appointments は通常の確認メール、変更メール、キャンセルメールを送信します。

必要条件

  • API が有効になっている Easy!Appointments 1.5 以降(Settings > Integrations > API で API トークンを設定してください)。1.6.1 でテスト済みです。
  • PHP 8.3 以降、または Docker。
  • 本番環境では HTTPS が必要です。AI クライアントはインターネット上の HTTP のみのサーバーには接続しません。

デモをローカルで実行する

compose ファイルを使うと、Easy!Appointments 1.6.1、メールキャッチャー、このサーバーが起動し、架空の理学療法クリニックにサービス、提供者、顧客、2 週間分の予約データが登録されます。

cp .env.docker.example .env.docker
# Set APP_KEY (see the comment in the file) and EA_API_TOKEN (any long random string)
docker compose up -d --build
sh demo/setup.sh

その後、次の URL にアクセスします。

AI クライアントを使わずに一連の流れを確認するには、エンドツーエンドスクリプトを実行します。OAuth クライアントを登録してサインインし、アクセスレベルを選択して、すべてのツールを呼び出します。実際に予約を行い、その予約の日時変更とキャンセルも行います。

php demo/e2e.php http://localhost:8000 [email protected] demo-password-1 front_desk
php demo/e2e.php http://localhost:8000 [email protected] demo-password-1 read

HTTPS 対応の公開サーバーにデモを配置するには、docs/deploy-demo.md を参照してください。

実際の予約システムにインストールする

Docker を使用する場合:

docker run -d --name ea-mcp \
  -e APP_KEY=base64:... \
  -e APP_URL=https://mcp.example.com \
  -e TRUSTED_PROXIES=10.0.0.5 \
  -v ea-mcp-data:/data/app \
  -p 127.0.0.1:8080:8080 \
  ea-mcp-server

HTTPS ロードバランサーまたはリバースプロキシの背後に配置するか、SERVER_NAME=mcp.example.com を設定してポート 80 と 443 を公開し、組み込みの Caddy が証明書を取得できるようにします。

TRUSTED_PROXIES は、どの送信元の X-Forwarded-For ヘッダーを信頼するかを決定します。また、レート制限はクライアント IP ごとに適用されます。プロキシのアドレスのみを設定し、ポート 8080 はそのプロキシにのみ公開してください(プロキシが同じホスト上で動作する場合は 127.0.0.1 にのみ公開します)。ポートに直接アクセスできる状態で * を使用してはいけません。誰でも自分の IP を指定してレート制限を回避できてしまいます。組み込みの Caddy が HTTPS を処理する場合は、設定しないでください。同じイメージを使用する 2 つ目のコンテナで php artisan schedule:work を実行し、古いログと期限切れトークンを毎日削除してください。

Docker を使用しない場合は、標準的な Laravel 13 アプリです。composer install --no-dev を実行し、.env.example を .env にコピーして、php artisan key:generate、php artisan passport:keys、php artisan migrate を実行し、ウェブサーバーが public/ を参照するように設定します。

次に、予約システムを連携し、スタッフを追加します。

php artisan ea:connect "Maple Street Physio" https://booking.example.com   # asks for the API token
php artisan ea:user [email protected] --name="Anna" --level=front_desk       # asks for a password

--level は、その人がアシスタントに付与できる権限の上限です。各アシスタントに付与する権限は、同意画面で個別に選択します。

有効なトークンで ea:connect が 401 を返す場合、ウェブサーバーから PHP に Authorization ヘッダーが渡されていません。PHP-FPM を使用する Apache では、Easy!Appointments の仮想ホストに SetEnvIf Authorization "(.*)" HTTP_AUTHORIZATION=$1 を追加してください。

AI アシスタントを接続する

カスタムコネクターとして https://your-server/mcp を追加します(Claude:Settings > Connectors、ChatGPT:開発者モードのワークスペースコネクター)。クライアントが自身を登録してサインインページを開き、利用者が 閲覧のみ または 受付 を選択します。利用者は /dashboard でいつでも設定を変更または削除できます。

セキュリティモデル

  • Easy!Appointments API トークンは管理者レベルのため、このサーバー上で暗号化して保存され、クライアントに送信されることはありません。各利用者は自分のアカウントでサインインし、このサーバーでのみ有効な短期間のトークンを取得します(有効期間は1時間で、30日間更新可能です)。
  • サインイン前は、initialize と tools/list がトークンなしで応答するため、クライアントはサーバーが提供する内容を表示できます。有効なトークンなしで tools/call(およびその他すべて)を実行すると、OAuth メタデータを示す WWW-Authenticate ヘッダーとともに 401 が返されます。これにより、Claude やその他のクライアントでサインインが開始されます。サインイン後、接続で使用できないツールは一覧に表示されず、呼び出されても拒否されます。
  • 書き込みには、確認のための2回目の呼び出しが必要です。確認には、まったく同じ引数でのプレビューから得た confirmation_token、同じ利用者とアシスタントによる呼び出し(MCP_CONFIRMATION_MINUTES で設定された10分以内)、および冪等性キーを含める必要があります。書き込みが行われる前にキーが確保されるため、同じキーによる並行再試行でも予約は1件だけ作成されます。
  • Easy!Appointments は、API による予約の作成や移動の際に空き状況を確認しません。そのため確認処理では、プロバイダーと日付ごとにロックを取得し、ロック内でキャッシュを使わずに予約枠を再確認してから書き込みます。同じ予約枠に対する異なるキーの確認処理が2件あっても、予約は1件だけ作成され、もう一方は最も近い空き時間とともに拒否されます。
  • Easy!Appointments からの応答が失われた場合や、サーバーエラーが返された場合、キーは確保されたままになり、アシスタントにはむやみに再試行せず list_appointments で確認するよう伝えられます。Easy!Appointments が書き込みを確認した後は、その後に起きたこと(名前の読み戻しなど)によってエラーになったり、書き込みが取り消されたりすることはありません。
  • 時刻は、Easy!Appointments が保存しているとおり、各プロバイダー固有のタイムゾーンで読み書きされ、すべての結果に使用するタイムゾーンが示されます。
  • クライアント登録は MCP の想定どおりオープンですが、制限されています。リダイレクト URI はフラグメントやユーザー情報を含まない https(ループバックアドレスでは http)である必要があります。登録は IP ごとにレート制限され(MCP_REGISTRATIONS_PER_HOUR、10件)、一度も使用されないクライアントは1日後、未使用のクライアントは90日後に削除されます。
  • 同意画面では、クライアント名は未検証であること(どのアプリも独自の名前を指定できること)が示され、利用者がリダイレクトされるホストが表示されます。また、そのホストが既知の AI アシスタントではない場合(MCP_KNOWN_CLIENT_HOSTS)に警告が表示されます。
  • 名前、メールアドレス、電話番号、住所、メモ、検索テキストは呼び出しログでマスキングされます。Easy!Appointments のエラーメッセージに顧客レコードの内容が含まれている場合は削除され、エラーに残ったメールアドレスも、アシスタント、呼び出しログ、アプリケーションログに届く前にマスキングされます。
  • サインインの試行は IP ごとに、またそれとは別にアカウントごとに制限されるため、多数の IP に分散した推測も制限に達します(MCP_LOGIN_ATTEMPTS_PER_ACCOUNT、10分間に10回)。DEMO_EMAIL で設定された公開デモアカウントは、パスワードが公開されており、制限を設けると第三者によってロックされるだけなので、アカウントごとの制限の対象外です。APP_URL が https の場合、セッション Cookie は HTTPS でのみ使用されます。
  • 新規顧客の予約では、処理開始前にすべてのリクエスト分の予算が確保されます。その後 Easy!Appointments が予約を明確に拒否した場合(4xx)、作成した顧客は削除されます。応答がない場合やサーバーエラーが発生した場合は予約が存在する可能性があるため、顧客は残され、アシスタントには list_appointments で確認するよう伝えられます。
  • .env.example では APP_ENV=production と APP_DEBUG=false が設定されています。ea:connect はプロンプトまたは EA_API_TOKEN から API トークンを読み取るため、シェル履歴やプロセス一覧に残りません。
  • ログの保存期間は、デフォルトで90日です(MCP_LOG_RETENTION_DAYS)。

既知の制限事項

  • Easy!Appointments API では、移動対象の予約を無視して空き状況を確認できないため、現在の予約時間と重なる日時への変更は、説明を表示して拒否されます。その場合は、キャンセルして再予約してください。
  • キャンセルすると、Easy!Appointments では予約が削除されます。API にはソフトキャンセル機能がありません。
  • スロットロックが対象とするのは、このサーバーを通じて行われる変更です。同じタイミングで Easy!Appointments 自体から同じ時間枠に予約する人がいると、API では時間枠を予約できないため、二重予約が発生する可能性があります。
  • Easy!Appointments にはリクエストのタイムゾーンが保存されないため、プロバイダーのタイムゾーンが後で変更されても、既存の予約は同じ壁時計時刻のままです。
  • 1 つのサーバーに、アカウントごとに 1 つ、複数の Easy!Appointments インスタンスをリンクできます。セルフサービスのサインアップ機能はありません。管理者が ea:user を使ってユーザーを追加します。

開発

composer install
cp .env.example .env && sed -i 's/^APP_ENV=production/APP_ENV=local/' .env
php artisan key:generate && php artisan passport:keys && php artisan migrate
php artisan test
vendor/bin/pint

テストは Easy!Appointments API のインメモリフェイク(tests/Support/FakeEasyAppointments.php)に対して実行されます。demo/e2e.php は実際のインスタンスに対して実行されます。

ライセンス

MIT

コメント

MCP は初めてですか?

プロトコルの概要から最初のサーバーの導入まで、よくある疑問にまとめて答えます。

AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。