login() called client.request() which called _ensure_initialized() which
tried to re-acquire _init_lock — deadlocking forever. Fix: set
_initializing=True while inside the init critical section so request()
skips the _ensure_initialized() guard when called from within init
(safe because query_api_info() already populated the API cache).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Write progress markers to stderr at each lazy-init step so Claude
Desktop logs show exactly where a timeout occurs
- Replace flat timeout=30 integer with httpx.Timeout(connect=10,
read=30, write=10, pool=5) to fail fast on connection issues
instead of waiting up to 90 s across three sequential requests
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously the server blocked at startup waiting for query_api_info()
and login() before starting the MCP protocol. Claude Desktop has a short
initialization timeout and dropped the server before the handshake started.
Changes:
- DsmClient: add _ensure_initialized() with asyncio.Lock for thread-safe
lazy init; called automatically at the start of request(), upload_text(),
and download_text() on the first use.
- cli.py serve: remove upfront query_api_info() and auth.login() calls;
the server now starts immediately ("MCP server ready" on stderr) and
connects to the NAS on the first tool invocation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>