feat: list_recent_activity + request_room_keys + auto-backup-pull (PR-A from real-usage findings) #72

Merged
jlxq0 merged 1 commit from feat/recent-activity-and-key-requests into main 2026-05-19 03:04:10 +00:00
Owner

Summary

Closes the two ergonomic gaps Julian hit in actual v0.3.6 use today:

  1. Activity sort — no way to ask "which rooms had action in the last N days" without enumerating 400 rooms. New list_recent_activity tool returns all joined rooms sorted by latest_origin_server_ts desc, with optional since_unix_ms + encrypted_only filters. Mirrors get_unread_summary's envelope shape minus the unread filter.
  2. Undecryptable history — when a read tool returned unable_to_decrypt the AI had to walk the user through Element settings. New request_room_keys tool wraps Encryption::backups().download_room_keys_for_room at per-room granularity, and read_recent_messages/read_thread auto-fire the same call in the background whenever they surface undecryptable events. Sessions in backup self-heal on the next read.

Tool count 41 → 43.

Verification

  • cargo fmt --check: clean
  • cargo clippy --all-targets -- -D warnings: clean
  • cargo test --all-targets: 126/126

Compat

Additive at the MCP surface. No reconnect required.

## Summary Closes the two ergonomic gaps Julian hit in actual v0.3.6 use today: 1. **Activity sort** — no way to ask "which rooms had action in the last N days" without enumerating 400 rooms. New `list_recent_activity` tool returns all joined rooms sorted by `latest_origin_server_ts` desc, with optional `since_unix_ms` + `encrypted_only` filters. Mirrors `get_unread_summary`'s envelope shape minus the unread filter. 2. **Undecryptable history** — when a read tool returned `unable_to_decrypt` the AI had to walk the user through Element settings. New `request_room_keys` tool wraps `Encryption::backups().download_room_keys_for_room` at per-room granularity, **and** `read_recent_messages`/`read_thread` auto-fire the same call in the background whenever they surface undecryptable events. Sessions in backup self-heal on the next read. Tool count 41 → 43. ## Verification - `cargo fmt --check`: clean - `cargo clippy --all-targets -- -D warnings`: clean - `cargo test --all-targets`: 126/126 ## Compat Additive at the MCP surface. No reconnect required.
feat: list_recent_activity + request_room_keys + auto-backup-pull
All checks were successful
CI / cargo (pull_request) Successful in 56s
CI / docker (pull_request) Successful in 1m10s
34c3224a95
Closes two ergonomic gaps surfaced by Julian's real-world v0.3.6
session ("Check matrix if I have any messages…" — 400-room enumeration,
plus undecryptable Ethan/Pier Household sessions).

list_recent_activity
====================

New tool. Returns every joined room sorted by `latest_origin_server_ts`
descending, with optional `since_unix_ms` filter and `encrypted_only`
flag. Companion to `get_unread_summary` (which only returns the
unread slice). Mirrors that tool's envelope-only metadata shape:
room_id, display_name, encrypted, latest_event_id, latest_sender,
latest_origin_server_ts, plus unread_notifications / unread_mentions
for ergonomic mixing of activity sort with unread filter.

Solves the "I read the message and forgot to reply" use case
without walking every joined room one at a time.

request_room_keys
=================

New tool. Wraps `Encryption::backups().download_room_keys_for_room`
— the same call /setup/recover fires once across all encrypted
rooms post-recovery — at per-room granularity. Used on demand when
a previous read returned unable_to_decrypt events.

Backup downloads are best-effort: sessions actually in backup
self-heal on the next read; sessions never uploaded to backup (rare,
usually rotation-or-opt-out edge cases) stay opaque to this device.
Response field backup_requested reports whether the pull was kicked
off, not whether it recovered anything specific.

Read-path auto-trigger
======================

read_recent_messages + read_thread now call a new
spawn_key_backup_pull_if_needed helper at the end of their happy
path. If any returned event has status=unable_to_decrypt, a
download_room_keys_for_room is fire-and-forget'd in a spawned task.
Subsequent reads of the same room will surface the now-decrypted
events.

This automates the recovery the AI previously had to walk users
through (Element → Settings → Sessions → verify, then re-pull key
backup). For most cases this is the difference between "matrix-mcp
can't read your history" and "matrix-mcp transparently catches up
within a sync cycle".

Tool count
==========

41 → 43.

Tests: 126/126 still green. cargo fmt + clippy strict clean.
jlxq0 merged commit 88e191e3e1 into main 2026-05-19 03:04:10 +00:00
jlxq0 referenced this pull request from a commit 2026-05-19 11:18:59 +00:00
Sign in to join this conversation.
No description provided.