LLMs are weirdly bad at scheduling, in a very specific way. Hand Claude a calendar with twenty events and ask it to find 45 minutes with someone before Thursday, and it will, with total confidence, hand back a slot that collides with your own calendar. Not because it can’t see the 2pm; it’s right there in the context. It’s because reasoning about overlapping intervals, using natural language only, is a task that’s not well suited to current models.
I built Tempo to give the model tooling to help with this problem. It’s a small MCP server, written in Rust, that hands the model a set of scheduling tools and lets a deterministic engine do the calendar reconciliation.
The core function is propose, check, commit. The model never mutates the calendar directly, and it never decides on its own whether two events conflict. It loads calendars (iCal, JSON, or Google Calendar), queries free/busy and asks for open slots, then proposes candidate events. A tool checks each proposal against everything else, and only verified, conflict-free proposals get committed, atomically. There are 22 tools in total, but they all fall into that shape.
The reason this works is that it splits the problem along a natural seam. The model is genuinely good at the fuzzy half: turning “before Thursday, mornings, leave me room to grab lunch” into constraints. Where it struggles is the exact half: does 10:30 to 11:15 overlap anything across four calendars once the RRULEs are expanded. Propose-and-check lets each side do what it’s good at, and forces the model to verify its work before it can act on it.
The evals bear this out.
Each run is scored on a 0-100 composite:
| Dimension | Weight | What it measures |
|---|---|---|
| Correctness | 40% | Zero conflicts with existing events |
| Completeness | 25% | All requested blocks actually scheduled |
| Constraint adherence | 20% | Custom rules satisfied (time windows, buffers, spread) |
| Efficiency | 15% | Bonus for perfect correctness + completeness |
Bare Claude Sonnet 4 vs. Claude Sonnet 4 + Tempo (composite score, 0-100):
| Scenario | Bare | + Tempo | Conflicts (bare → MCP) |
|---|---|---|---|
| 01 - Simple scheduling | 100.0 | 100.0 | 0 → 0 |
| 02 - Dense calendar | 45.0 | 98.4 | 7 → 0 |
| 03 - Recurring event maze | 61.0 | 100.0 | 3 → 0 |
| 04 - Multi-calendar | 52.9 | 98.7 | 4 → 0 |
| 05 - Constraint-heavy | 99.8 | 100.0 | 0 → 0 |
| 06 - Real-world Google Cal | 54.7 | 100.0 | 3 → 0 |
| 07 - Pick from options | 71.5 | 100.0 | 1 → 0 |
| Average | 69.3 | 99.6 | 18 → 0 |
Modern models could certainly build a similar tool JIT (Tempo was mostly built by a model after all), but a prebuilt engine is faster, doesn’t need a debug loop, and is reliable across many calendars.
I built this as a tool for an experimental ClassPass side-project: letting an agent schedule ClassPass classes based on:
- Your actual calendar
- Your stated desires (“I want to take 3 classes this week, in the mornings, never on two consecutive days”)
- The ClassPass schedule
Tempo turned this use case into something that is actually feasible rather than requiring the human to guess-and-check the results.