deltat について
deltatは、人の確認前に候補時間を提示するエージェント向けのカレンダー予約MCPサーバーです。検索、仮押さえ、確定の手順で空き枠を一時予約し、複数カレンダーの予約も原子的に確定します。
主な機能
- 01複数カレンダーの空き枠検索
- 02確認前の枠の仮押さえ
- 03仮押さえの確定または解除
- 04複数カレンダーの一括予約
- 05競合時の代替時間提示
- 06予約の一覧表示とキャンセル
活用シーン
- 01返答を待つ間、候補時間を確保
- 02会場と機材をまとめて予約
- 03枠が埋まった際に代替案を提示
- 04予約とキャンセルの管理
MCP 対応
deltatデータベースを利用し、MCPクライアントにカレンダーツールを提供します。予約はfind_slots、hold_slot、commit_holdの順で行い、現在のパッケージはstdioサーバーを提供します。
設定
ローカルサーバーの設定はどのクライアントでも共通です。コピーしてクライアントの MCP 設定ファイルに貼り付けてください。
npx -y @open-deltat/mcpDELTAT_PASSWORDシークレットPassword for the deltat server. Required; there is no default.DELTAT_HOSTHostname of the deltat server.DELTAT_PORTPort deltat listens on.DELTAT_DATABASETenant to connect to. Each database name is an isolated tenant.DELTAT_USERUsername presented at connect time.DELTAT_TLSon to encrypt the connection and verify deltat's certificate. Unset means off unless DELTAT_TLS_CA is set; without TLS the password is sent in the clear, so use it for any deltat that is not on this machine.DELTAT_TLS_CAPath to a PEM certificate to trust instead of the system's authorities, for a deltat with a self-signed certificate. Implies DELTAT_TLS=on.ローカルサーバーにはマシン上の実行環境(Node.js 18 以上など)が必要です。設定ファイルの場所はクライアントごとに異なります。
ツール
9掲載時のツール一覧 · 2 週間前に更新
| パラメーター | 型 | 必須 | 説明 |
|---|---|---|---|
| name | string | はい | |
| hours | array | いいえ | 週間の営業時間。空の場合は利用不可を意味します |
| timezone | string | いいえ | IANA タイムゾーン(例:Europe/Berlin) |
| slot_minutes | integer | いいえ |
詳細
@open-deltat/mcp
二重予約を決して起こさず、エージェントが実際に予約できるカレンダーを提供します。
npx @open-deltat/mcp
ほとんどのスケジュール管理 API がエージェントに提供する動詞は、book だけです。フォームの送信なら問題ありませんが、エージェントには適していません。エージェントの判断には数秒かかるためです。14:30 が空いていることを確認し、「14:30 はどうですか?」と尋ね、人間の返事を待つうちに、別の人がその枠を予約してしまいます。空き状況の確認と予約は別々のタイミングで行われ、その間はすべてが競争になります。
このサーバーには、1 ステップで予約する動詞はありません。予約の手順は次のとおりです。
find_slots → hold_slot → commit_hold
要となるのはホールドです。数分間、枠を確保しておくため、時間を提案してから確定するまで、その時間はあなたのものであり、ほかの人が予約することはできません。ホールドは自動的に期限切れになるため、会話が途中で終わっても後片付けは不要で、ホールドに費用もかかりません。
その基盤となるのはdeltatです。同じ時間帯に 2 件の予約が入ることはない、という不変条件を持つデータベースです。拒否は、事前に確認してうまくいくことを期待するアプリケーションコードではなく、ストレージエンジンによって行われます。
ツール
| ツール | 使用するタイミング |
|---|---|
find_slots | 相手に時間を提案する前です。指定したすべてのカレンダーで、実際に空いている枠を一覧表示します。 |
hold_slot | 人間に特定の時間を伝えようとするタイミングです。hold_idsを返します。 |
commit_hold | 予約が確定したときです。すべてのホールドを、アトミックに予約へ変換します。 |
release_hold | ホールドした時間が不要だとわかったときです。すぐに空き枠に戻します。 |
create_calendar | 新しい予約可能なカレンダーが必要なときです。calendar_idを返します。 |
set_availability | 営業時間を変更するとき、またはfind_slotsで空き枠が返されないときです。週全体を置き換えます。 |
list_bookings | 予定を尋ねられたとき、またはキャンセルするためにbooking_idが必要なときです。 |
cancel_booking | 確定済みの予約をキャンセルするよう人間から依頼されたときです。 |
book_slot | 使用しません。hold_slot + commit_holdを案内して拒否するためだけに存在します。 |
最後の行は意図的なものです。ほかのカレンダー API にはすべて 1 ステップで予約する動詞があるため、モデルはここでも同じものを使おうとしますが、見つかりません。幻覚によるツール呼び出しや会話の中断につながらないよう、この動詞は登録され、拒否するとともに、応答で実際に必要な 2 つの手順を説明します。予約が行われることはありません。
時刻は RFC 3339 形式の文字列で、必ずオフセットを含めて受け渡します。エポックミリ秒だけの値は使用できません。タイムゾーンのないタイムスタンプは、プロセスが実行されているタイムゾーンで暗黙に解釈されるのではなく、拒否されます。エラーには分岐に使える型付きプレフィックスが付いています。CONFLICT(別の枠を選択)、EXPIRED(再度ホールド)、INVALID、NOT_FOUNDです。
拒否時に代替時間を示す
枠が埋まっている場合や営業時間外の場合、拒否応答には、代わりに予約できた時間が含まれます。これにより、エージェントは最初からやり直さずに、同じターンで別の時間を提案できます。
{
"error": "CONFLICT",
"booked": false, "held": false, "reserved": false,
"retry_same_time": true,
"alternatives": [
{ "start": "2026-06-01T12:00:00.000Z", "end": "2026-06-01T13:00:00.000Z",
"start_local": "1 Jun 2026, 2:00 pm" }
],
"next": "These times were free a moment ago but are NOT reserved. Offer one, then call hold_slot on it before you tell anyone it is theirs."
}
リアルタイムの通話では、通常なら沈黙になってしまうモデルのターンを丸ごと省けます。
reservedは常にfalseです。代替案だけに目を通したモデルが、何かが確保されたと誤解しないよう、暗示ではなく明示されています。代替時間は、その時点では空いていた時間です。選ぶ場合も、hold_slotを呼び出す必要があります。
提案できる時間がない場合、拒否応答は従来どおり単純なCODE: message形式になります。そのため、代替案の提示が無効になっているカーネル(DELTAT_COUNTER_OFFER=0)や、この機能より前のバージョンでも、以前とまったく同じ動作をします。
複数のカレンダーをまとめて予約する
カメラ本体、レンズ、撮影スタッフ。外科医と手術室。予約と、そこまでの移動時間。次の 3 つのツールすべてに、すべてのカレンダーを渡します。
find_slots({ calendar_ids: [body, lens, crew], from, to }) times when ALL are free
hold_slot({ calendar_ids: [body, lens, crew], start, end }) holds every one, or none
commit_hold({ hold_ids, label }) books every one, or none
カレンダーが 1 つの場合も、リストに 1 項目を指定すれば同じ呼び出しで済みます。確定処理はdeltat内の単一レコードとして行われるため、別の予約者との競合やクラッシュが起きても、本体だけ予約されてレンズは空いたままになることはありません。
セットの予約が拒否された場合、代替時間は、拒否された時間を除き、すべてのカレンダーが同じ長さで空いている時間です。上記と同じ形式で返されます。
設定する
deltat サーバーが必要です。バージョンは 0.4.0 以降です。Docker でセルフホストします。
docker run -p 5433:5433 -e DELTAT_PASSWORD=<your-password> ghcr.io/open-deltat/deltat
次に、MCP サーバーを追加します。Claude Code の場合:
claude mcp add deltat \
--env DELTAT_HOST=localhost \
--env DELTAT_PORT=5433 \
--env DELTAT_DATABASE=public \
--env DELTAT_PASSWORD=<your-password> \
-- npx -y @open-deltat/mcp
Claude Desktop では、claude_desktop_config.json を編集して再起動します。
{
"mcpServers": {
"deltat": {
"command": "npx",
"args": ["-y", "@open-deltat/mcp"],
"env": {
"DELTAT_HOST": "localhost",
"DELTAT_PORT": "5433",
"DELTAT_DATABASE": "public",
"DELTAT_PASSWORD": "<your-password>"
}
}
}
}
DELTAT_PASSWORD は必須で、デフォルト値はありません。推測されやすいパスワードを試すのではなく、設定されていない場合はサーバーの起動を拒否します。それ以外はすべて、localhost:5433 のローカル deltat とデータベース public をデフォルトとして使用します。各データベース名は、独立したテナントになります。
あとは、次のように依頼するだけです。「平日の午後に利用できる『ヘアカット』というカレンダーを作成して、明日の最初の空いている30分枠を予約してください。」
認証について、率直に
この stdio サーバーにログイン機能はありません。 設定ファイルにある deltat のパスワードが認証情報で、サーバーはユーザーの権限で実行されます。これが単一オペレーター向けのセルフホストモデルです。deltat とエージェントはユーザーが所有するため、OAuth は必要ありません。
ホスト型のマルチテナントサーバーは、別の問題です。 その場合、エージェントは OAuth 2.1 で認証します。サーバーは未認証の呼び出しに対し、保護されたリソースのメタデータ(RFC 9728)とともに 401 を返します。対応クライアントは、ワンタイムの人間による同意を得て Client ID Metadata Document を使って登録し、認可コード + PKCE を実行します。このパッケージの OidcAdapter はそのうちリソースサーバー側を担い、リクエストごとにネットワーク呼び出しを行うことなく、発行者の JWKS に基づいてベアラー JWT をオフラインで検証します。
このホスト型トランスポートは、まだこのパッケージに含まれていません。現在実行できるのは、上記の stdio サーバーです。
組み込む
import { createDeltatMcpServer } from "@open-deltat/mcp";
import { DeltaT } from "@open-deltat/client";
const server = createDeltatMcpServer(new DeltaT({ /* ... */ }));
await server.connect(yourTransport);
エンドツーエンドで検証する
deltat を起動した状態で:
bun scripts/smoke.ts
インメモリ MCP クライアントを通じて一連の処理を実行し、往復処理(作成 → 空き状況の確認 → 検索 → 仮押さえ → 確定 → 一覧表示 → キャンセル)を検証します。
ライセンス
MIT
コメント
AI アプリケーションが外部のツールやデータソースに統一的な方法で接続するためのオープンなプロトコルです。クライアントはモデルとの対話を担い、MCP サーバーはツール・リソース・プロンプトテンプレートを提供します。標準メッセージでやり取りするため、1 つのサーバーを複数のクライアントで再利用できます。