Make long-running tools fire-and-return to fix intermittent timeouts

redeploy_project, create_project and pull_image used to block the tool
call while polling DSM until the project reached RUNNING / the image
appeared - up to 300s and 240s respectively. On large images this
regularly ran past Claude Desktop's ~4 min tool-call ceiling (the live
MCP log shows redeploy_project calls up to 260s), which the client
reported as a timeout even though the server kept working. Whether a
call crossed the ceiling depended on image size and NAS load, which is
why the failure was intermittent.

These tools now fire-and-return: they trigger the operation, consume
build_stream only for a short early-error window (20s, to catch fast
daemon errors like "manifest unknown"), then return a "running in the
background - check get_project_status / check_image_updates" hint.
Completion is observed via the existing fast status tools.

- DsmClient.trigger_build_stream gains a `budget` parameter
- remove _wait_for_project_running and the _POLL_*/_BUILD_POLL_TIMEOUT
  constants (projects.py) and _PULL_POLL_* constants (registry.py)
- update tests, CLAUDE.md DSM quirks and CHANGELOG; bump 0.7.0 -> 0.8.0

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-06-16 05:56:42 +02:00
parent 7bb9b00dcc
commit 4a49407883
9 changed files with 208 additions and 302 deletions
+32
View File
@@ -2,6 +2,38 @@
All notable changes to this project will be documented in this file.
## [0.8.0] - 2026-06-16
### Changed (fixes intermittent "MCP not responding" timeouts)
The long-running tools no longer block the tool call until the operation
finishes. They now **fire-and-return**: trigger the work, surface any fast
failure, then return immediately so Claude can poll status with the existing
fast tools. This removes the root cause of the intermittent timeouts —
analysis of the live MCP log showed `redeploy_project` calls running up to
**260 s**, which crosses Claude Desktop's ~4 min tool-call ceiling. Whether a
call crossed it depended on image size and NAS load, which is exactly why the
failure was intermittent ("works fine for a while, then suddenly times out").
- **`redeploy_project` / `create_project`** — `build_stream` is now consumed
only for a short early-error window (`_BUILD_EARLY_BUDGET`, 20 s) to catch
fast daemon errors (e.g. `manifest unknown`). If the build is still running
after that window (large image), the tool returns a "redeploy/create
started — check `get_project_status`" hint instead of polling for up to
300 s. The pull and container start continue on the NAS.
- **`pull_image`** — calls `pull_start` and returns immediately with a
"pull started in the background — verify with `check_image_updates` /
`list_images`" hint, instead of polling `Image/list` for up to 240 s.
- **`DsmClient.trigger_build_stream`** — gained a `budget` parameter so
callers can cap how long the streamed log is consumed.
### Removed
- `_wait_for_project_running` and the `_POLL_INTERVAL` / `_POLL_TIMEOUT` /
`_BUILD_POLL_TIMEOUT` constants in `projects.py`, and the
`_PULL_POLL_TIMEOUT` / `_PULL_POLL_INTERVALS` constants in `registry.py`
the minutes-long polling loops they drove are gone.
## [0.7.0] - 2026-05-18
### Added