# WebServer + DevelopmentService Collision Debugging Session: 2026-07-11 — Dashboard server started but MCP tools 404, dev service blocked. ## Symptoms - Dashboard (port 80) loads, but POST /api/mcp returns 404 even with mcpEnabled=true - Development service (6666 /info) not reachable - MCP screen not appearing on RLCD board (Waveshare 4.2" monochrome ST7305) ## Root Causes Found ### 1. httpd ctrl_port collision `HttpServer::startInternal()` used `HTTPD_DEFAULT_CONFIG()` → ctrl_port 32768 fixed for all instances. When WebServer (80) + DevServer (6666) start near-simultaneously (service manager dispatches), second bind fails → `httpd_start` returns error → `httpServer` stays null → handlers never registered. Fix: unique ctrl_port per server: `32768 + (port % 1000)` → 80→32848, 6666→33434. Src: `Tactility/Source/network/HttpServer.cpp` ### 2. max URI handlers too low ESP-IDF default CONFIG_HTTPD_MAX_URI_HANDLERS=8. WebServer registers 7 handlers: `/`, `/filebrowser`, `/fs/*` GET, `/fs/*` POST, `/admin/*`, `/api/*` GET, `/api/*` POST, `/api/*` PUT, `/*` = 7, plus 2 internal slots → config.max_uri_handlers = 9. If Kconfig max 8 < 9, `httpd_start` fails or later `httpd_register_uri_handler` fails → "no slots left". Fix: `Buildscripts/sdkconfig/default.properties` → `CONFIG_HTTPD_MAX_URI_HANDLERS=20`. ### 3. DisplayIdle early return killed MCP on RLCD `D3919344` added: ```cpp if (!supportsBacklightDuty()) return true; ``` in `onStart()` — disables timer + settings load for ST7305 (no backlight fn). `startMcpScreensaver()` depends on settings + timer for update/auto-off. Fix: always load settings + start timer; only skip auto-backlight logic via existing `if (supportsBacklightDuty())` guard in `tick()`. Files: `Tactility/Source/service/displayidle/DisplayIdle.cpp:235-250`, `303-353` ### 4. Video stream task overflow Stack 4096 + SPIRAM allocs + LVGL lock + socket loops → stack overflow → heap corruption blocking other tasks. Also tight loop `vTaskDelay(5)` even idle. Fix: 8192 + idle delay 50ms, busy 5ms. ## Verification Commands ```bash source ~/esp/esp-idf/export.sh cd firmware python device.py waveshare-esp32-s3-rlcd --dev idf.py build idf.py -p /dev/cu.usbmodem101 flash monitor # Monitor logs: # - Started on port 80 (ctrl_port 32848) # - Started on port 6666 (ctrl_port 33434) # - Mono TCP Video stream server started on port 8081 # - Color TCP Video stream server started on port 8083 # - Monochrome/RLCD detected: idle timer will run but auto-backlight off disabled curl http:///api/sysinfo # public curl -X POST http:///api/mcp -d '{"jsonrpc":"2.0","id":1,"method":"tools/list"}' curl http://:6666/info ``` ## Related Incidents - Upstream #547 merged 2026-07-04 changed settings load to check isFile first — more correct but didn't cause this. - Board mis-ID: user has both ES3C28P color (240x320) and Waveshare RLCD mono (400x300). Wrong sdkconfig → wrong display driver → blank screen misattributed to MCP bug. Always verify `grep CONFIG_TT_DEVICE_ID sdkconfig`.