Skip to content

feat: agents can hold and book several calendars together (MCP 0.2.0, client 0.4.1) - #66

Merged
simonorzel26 merged 1 commit into
mainfrom
feat/kit-tools
Oct 4, 2026
Merged

simonorzel26 merged 1 commit into
mainfrom
feat/kit-tools

Conversation

@simonorzel26

Copy link
Copy Markdown
Member

Why

deltat 0.4.0 holds several resources at once and books them all or none (deltat#44). No agent could reach that: every MCP tool took one calendar_id or one hold_id, and the SDK had only single place / commit. The shape follows the decision to widen the existing tools rather than add *_joint ones: same three tools, same find, hold, commit story, and one calendar is a one-item list.

What agents see

find_slots({ calendar_ids: [body, lens, crew], from, to })   -> times when ALL are free
hold_slot({ calendar_ids: [body, lens, crew], start, end })  -> { hold_ids }   all or none
commit_hold({ hold_ids, label })                             -> { booking_ids } all or none
release_hold({ hold_ids })

A refused kit is not a dead end (PRINCIPLES.md §4). deltat offers no alternatives for several calendars, because its per-calendar sweep cannot answer a joint question. The MCP asks the question find_slots already answers: the earliest times within the next week when every calendar is free for the same length. It never offers the time just refused, nothing is held, and it uses deltat's own limits (7 days, 3 alternatives). retry_same_time is false when the refusal was "outside opening hours" (23514), since waiting won't change that.

SDK (client 0.4.1)

  • holds.placeMany and holds.commitMany each send one statement and are never chunked. The server makes a statement all-or-nothing; a sequence of statements is not.
  • holds.place is now placeMany of one. It sends the same single row as before, so it still works on every deltat.
  • holds.commit keeps its UPDATE for the same reason.

Breaking, deliberately (MCP 0.1.0 → 0.2.0)

  • Tool arguments are now calendar_ids / hold_ids, and hold_slot returns hold_ids.
  • The MCP needs deltat ≥ 0.4.0. The README says so.
  • delt.at's hosted /mcp is the meeting-requests server: the demo only imports OidcAdapter and VerifiedPrincipal from this package, so delt.at's tools are unchanged.

Release plumbing

  • check-published-deps.sh now holds each adapter's client range to the APIs that adapter calls. Without that, the MCP needing client 0.4.1 would fail the CLI, whose ^0.4.0 is fine.
  • Until client 0.4.1 is on npm, the MCP line reports PENDING, which the script treats as "publish the client first", not a merge blocker.
  • The MCP's live suite joins the integration job.

Verified

Locally, against a deltat 0.4.0 build:

  • Unit tests: 406 pass.
  • Live suites (client, examples, cli, mcp): 62 pass. That includes every kit alternative fed back into hold_slot and accepted, and a parity test showing getCombined over one calendar (capacity 1 and 2) answers exactly what get does, which is why find_slots uses one path.
  • npm publish --dry-run packs MCP 0.2.0.

Mutation-checked. Each of these turns a test red:

  • one statement per hold, unit and live;
  • alternatives from one calendar only, live;
  • offering the refused time;
  • asking the joint question for a single calendar.

Not in this PR

Publishing to npm: client 0.4.1 first, then MCP 0.2.0 and the MCP registry entry, per RELEASING.md.

🤖 Generated with Claude Code

https://claude.ai/code/session_01Vaz5XtKxcGVsLe9GeX186M

… client 0.4.1)

deltat 0.4.0 holds several resources at once and books them all or
none, but no agent could reach it: every MCP tool took one calendar_id
or one hold_id. Now the same three tools take lists, and one calendar
is the one-item case.

- find_slots(calendar_ids) lists only times when every calendar is free.
- hold_slot(calendar_ids) holds every calendar for the same time, or
  none, and returns hold_ids; commit_hold(hold_ids) books every hold or
  none; release_hold(hold_ids) gives them back.
- A refused kit is not a dead end (PRINCIPLES.md 4). deltat offers no
  alternatives for several calendars, so the MCP asks find_slots' own
  question: the earliest times in the next week when every calendar is
  free for the same length, never the time just refused, none held.
- SDK: holds.placeMany and holds.commitMany, each one statement and
  never chunked, since the server makes a statement all-or-nothing and a
  sequence of them is not. holds.place is placeMany of one.

check-published-deps.sh now holds each adapter's client range to the
APIs that adapter calls, so the MCP needing client 0.4.1 does not fail
the CLI. The MCP's live suite joins the integration job.

Verified against deltat 0.4.0: unit 406 pass; live suites 62 pass,
including every kit alternative fed back into hold_slot and accepted.
Mutation-checked: one statement per hold, alternatives from one calendar
only, offering the refused time, and asking the joint question for a
single calendar each turn a test red.

Claude-Session: https://claude.ai/code/session_01Vaz5XtKxcGVsLe9GeX186M
@simonorzel26
simonorzel26 merged commit 9750c8f into main Oct 4, 2026
4 checks passed
@simonorzel26
simonorzel26 deleted the feat/kit-tools branch October 4, 2026 12:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant