Commit Graph

5 Commits

Author SHA1 Message Date
marcus e13324e10c Fix deadlock in lazy init: _ensure_initialized calling login via request()
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>
2026-04-13 15:49:26 +02:00
marcus 737c816ee7 Add stderr diagnostics and structured httpx timeout to dsm_client
- 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>
2026-04-13 15:38:37 +02:00
marcus 61cbf41900 Fix Claude Desktop loading: lazy NAS connection on first tool call
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>
2026-04-13 15:13:24 +02:00
marcus 81ff649ab7 Fix stdio startup for Claude Desktop compatibility
- Replace asyncio.run() with anyio.run() in serve command: FastMCP uses
  anyio.create_task_group() internally, and anyio.run() ensures the correct
  backend context. asyncio.run() can misbehave on Windows (ProactorEventLoop).
- Add SERVER STARTING / MCP server ready messages to stderr for diagnostics.
- Replace sys.exit(1) with early return + stderr write inside anyio context;
  sys.exit inside anyio.run() is less predictable than a clean return.
- Eagerly import all modules at serve startup so ImportErrors surface on
  stderr immediately instead of silently killing the process.
- Add __main__.py to allow python -m mcp_synology_container invocation.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:02:29 +02:00
marcus a0c1b6ed93 Initial implementation 2026-04-13 14:22:37 +02:00