From 662db5c5930bd4d8b5a7ca0f79ff7b22d0a79ae9 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 27 Mar 2026 22:32:51 +0100 Subject: [PATCH] fix(state-hub): fix mcp-http startup crash and remove legacy tunnel targets MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add `Optional` to typing imports in mcp_server/server.py — it was used in 13 annotations but never imported, crashing FastMCP v3 at startup - Remove legacy tunnel/tunnel-daemon/tunnel-loop/tunnel-status/tunnel-stop targets from Makefile; ops-bridge (tunnels-up/status/check) supersedes them Co-Authored-By: Claude Sonnet 4.6 --- state-hub/Makefile | 64 ++-------------------------------- state-hub/mcp_server/server.py | 2 +- 2 files changed, 3 insertions(+), 63 deletions(-) diff --git a/state-hub/Makefile b/state-hub/Makefile index 58d3af2..a561d91 100644 --- a/state-hub/Makefile +++ b/state-hub/Makefile @@ -1,4 +1,4 @@ -.PHONY: install install-cli db db-tools migrate seed api dashboard check test clean register-project validate-adr add-domain rename-domain add-repo list-repos register-path cleanup-stale tunnel tunnel-daemon tunnel-loop tunnel-status tunnel-stop tunnels-up tunnels-status tunnels-check install-hooks install-hooks-all gitea-inventory +.PHONY: install install-cli db db-tools migrate seed api dashboard check test clean register-project validate-adr add-domain rename-domain add-repo list-repos register-path cleanup-stale tunnels-up tunnels-status tunnels-check install-hooks install-hooks-all gitea-inventory COMPOSE = docker compose -f infra/docker-compose.yml --env-file .env @@ -43,67 +43,7 @@ test: TEST_DATABASE_URL=postgresql+asyncpg://custodian:changeme@127.0.0.1:5432/custodian_test \ uv run pytest -x -q -## COULOMBCORE host (default target for tunnel targets) -COULOMBCORE ?= tegwick@92.205.130.254 -TUNNEL_PORT ?= 8000 - -## Foreground reverse tunnel — good for debugging. Ctrl-C to stop. -## Usage: make tunnel HOST=tegwick@92.205.130.254 -tunnel: - @test -n "$(HOST)" || (echo "ERROR: HOST is required. Usage: make tunnel HOST=user@hostname"; exit 1) - @echo "Opening reverse tunnel → $(HOST) (remote :$(TUNNEL_PORT) → local :$(TUNNEL_PORT))" - @echo "Keep this terminal open. Ctrl-C to close the tunnel." - ssh -N -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \ - -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(HOST) - -## Background tunnel to COULOMBCORE with auto-reconnect. -## Uses autossh if available; prints install hint and exits if not. -## After running, COULOMBCORE can reach the State Hub at http://127.0.0.1:8000 -tunnel-daemon: - @if command -v autossh >/dev/null 2>&1; then \ - echo "Starting autossh tunnel → $(COULOMBCORE)"; \ - autossh -f -N -M 0 \ - -o "ServerAliveInterval=30" \ - -o "ServerAliveCountMax=3" \ - -o "ExitOnForwardFailure=yes" \ - -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(COULOMBCORE); \ - echo "Tunnel running in background. Use 'make tunnel-status' to check."; \ - else \ - echo "autossh not found — install it: sudo apt-get install autossh"; \ - echo "Fallback: run 'make tunnel-loop HOST=$(COULOMBCORE)' in a dedicated terminal."; \ - exit 1; \ - fi - -## Reconnect loop — works without autossh. Run in a terminal you can leave open. -## Usage: make tunnel-loop HOST=tegwick@92.205.130.254 -tunnel-loop: - @test -n "$(HOST)" || (echo "ERROR: HOST is required. Usage: make tunnel-loop HOST=user@hostname"; exit 1) - @echo "Reconnect loop → $(HOST). Ctrl-C to stop." - @while true; do \ - echo "[$(shell date -u +%Y-%m-%dT%H:%M:%SZ)] Connecting..."; \ - ssh -N -o "ServerAliveInterval=30" -o "ServerAliveCountMax=3" \ - -o "ExitOnForwardFailure=yes" \ - -R $(TUNNEL_PORT):127.0.0.1:$(TUNNEL_PORT) $(HOST) || true; \ - echo "[$(shell date -u +%Y-%m-%dT%H:%M:%SZ)] Connection lost — retrying in 5s..."; \ - sleep 5; \ - done - -## Check whether a tunnel is currently active -tunnel-status: - @if command -v autossh >/dev/null 2>&1 && pgrep -f "autossh.*$(TUNNEL_PORT)" > /dev/null 2>&1; then \ - echo "autossh tunnel: RUNNING (PIDs: $$(pgrep -f 'autossh.*$(TUNNEL_PORT)' | tr '\n' ' '))"; \ - elif pgrep -f "ssh.*-R $(TUNNEL_PORT)" > /dev/null 2>&1; then \ - echo "ssh tunnel: RUNNING (PIDs: $$(pgrep -f 'ssh.*-R $(TUNNEL_PORT)' | tr '\n' ' '))"; \ - else \ - echo "Tunnel: NOT running"; \ - fi - -## Stop any active tunnel (autossh or plain ssh) -tunnel-stop: - @pkill -f "autossh.*$(TUNNEL_PORT)" 2>/dev/null && echo "autossh stopped" || true - @pkill -f "ssh.*-R $(TUNNEL_PORT)" 2>/dev/null && echo "ssh loop stopped" || true - -## ops-bridge managed tunnels (preferred over tunnel-*/tunnel-daemon) +## ops-bridge managed tunnels ## Requires ops-bridge: bridge is at /home/worsch/.local/bin/bridge tunnels-up: bridge up diff --git a/state-hub/mcp_server/server.py b/state-hub/mcp_server/server.py index 575413c..8f17672 100644 --- a/state-hub/mcp_server/server.py +++ b/state-hub/mcp_server/server.py @@ -11,7 +11,7 @@ import re import sys from datetime import datetime, timezone from pathlib import Path -from typing import Any +from typing import Any, Optional from uuid import UUID import httpx