From 63c7702027a6170e86d1524271e511cd4a12539b Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Mon, 20 Jul 2026 10:38:42 +0200 Subject: [PATCH 1/8] fix(mcp/condor): honor full WEB_URL instead of hard-coded 127.0.0.1 call_main_api built the URL as `http://127.0.0.1:{WEB_PORT}/...`, ignoring the host and scheme from WEB_URL. When WEB_URL points at a remote or reverse-proxied endpoint (e.g. https://hbot.example.com:8043), the MCP subprocess still hit 127.0.0.1: and failed. Use WEB_URL directly so scheme, host, and port are all respected. Co-Authored-By: Claude Opus 4.7 --- mcp_servers/condor/condor_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index 6d88bbcd..c130cc2a 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -22,9 +22,9 @@ async def call_main_api( Raises APIError on failure instead of returning {"error": ...}. """ from condor.web.auth import create_jwt - from utils.config import WEB_PORT + from utils.config import WEB_URL - url = f"http://127.0.0.1:{WEB_PORT}/api/v1{path}" + url = f"{WEB_URL}/api/v1{path}" token = create_jwt(settings.user_id, role="user") headers = {"Authorization": f"Bearer {token}"} From 3273a80c06c4687a4a199a19aba13e15101182b7 Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Wed, 5 Aug 2026 23:00:49 +0200 Subject: [PATCH 2/8] Revert "fix(mcp/condor): honor full WEB_URL instead of hard-coded 127.0.0.1" This reverts commit 63c7702027a6170e86d1524271e511cd4a12539b. --- mcp_servers/condor/condor_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index c130cc2a..6d88bbcd 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -22,9 +22,9 @@ async def call_main_api( Raises APIError on failure instead of returning {"error": ...}. """ from condor.web.auth import create_jwt - from utils.config import WEB_URL + from utils.config import WEB_PORT - url = f"{WEB_URL}/api/v1{path}" + url = f"http://127.0.0.1:{WEB_PORT}/api/v1{path}" token = create_jwt(settings.user_id, role="user") headers = {"Authorization": f"Bearer {token}"} From 8576f62cc1bb68734249b4042ae6e773ea7658ee Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Wed, 5 Aug 2026 23:53:59 +0200 Subject: [PATCH 3/8] fix(main/mcp): let the user bind condor to specific BIND_HOST and BIND_PORT and honor it in condor_client.py --- main.py | 6 +++--- mcp_servers/condor/condor_client.py | 4 ++-- utils/config.py | 6 ++++++ 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/main.py b/main.py index 0c31d131..bdd3b261 100644 --- a/main.py +++ b/main.py @@ -20,7 +20,7 @@ from condor.persistence import SafePicklePersistence from handlers import cancel_command, clear_all_input_states from utils.auth import restricted -from utils.config import TELEGRAM_TOKEN, WEB_PORT, WEB_URL +from utils.config import TELEGRAM_TOKEN, BIND_HOST, BIND_PORT, WEB_URL, WEB_PORT # Enable logging logging.basicConfig( @@ -777,8 +777,8 @@ async def _run_dual(application: Application) -> None: web_app = create_app() config = uvicorn.Config( web_app, - host="0.0.0.0", - port=WEB_PORT, + host=BIND_HOST, + port=BIND_PORT, log_level="info", access_log=False, ) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index e851a0f5..c781adf7 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -24,11 +24,11 @@ async def call_main_api( """ from condor.runtime.timeouts import TIMEOUTS from condor.web.auth import create_jwt - from utils.config import WEB_PORT + from utils.config import BIND_HOST, BIND_PORT if timeout is None: timeout = TIMEOUTS.mcp_call - url = f"http://127.0.0.1:{WEB_PORT}/api/v1{path}" + url = f"http://{BIND_HOST}:{BIND_PORT}/api/v1{path}" token = create_jwt(settings.user_id, role="user") headers = {"Authorization": f"Bearer {token}"} diff --git a/utils/config.py b/utils/config.py index 14d7631a..e805fcff 100644 --- a/utils/config.py +++ b/utils/config.py @@ -19,6 +19,12 @@ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") +_bind_host_raw = os.environ.get("BIND_HOST", "").strip() +_bind_port_raw = os.environ.get("BIND_PORT", "").strip() + +BIND_HOST = str(_bind_host_raw) if _bind_host_raw else "0.0.0.0" +BIND_PORT = int(_bind_port_raw) if _bind_port_raw else 8088 + # Single WEB_URL param: full URL including port if needed (e.g. http://myserver.com:8088) # Falls back to WEB_PORT for backward compat, then default 8088 _web_url_raw = os.environ.get("WEB_URL", "").strip() From 8f7aa00a437d04a3a583b1d33150f6556562aa34 Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Thu, 6 Aug 2026 00:17:37 +0200 Subject: [PATCH 4/8] fix(mcp/condor): manage ipv6 url format --- mcp_servers/condor/condor_client.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index c781adf7..34679ee8 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -1,8 +1,8 @@ """HTTP client for calling the Condor main-process web API.""" import re - import aiohttp +import ipaddress from mcp_servers.condor.exceptions import APIError from mcp_servers.condor.settings import settings @@ -28,6 +28,14 @@ async def call_main_api( if timeout is None: timeout = TIMEOUTS.mcp_call + + try: + ip = ipaddress.ip_address(host) + if ip.version == 6: + host = f"[{host}]" + except ValueError: + pass + url = f"http://{BIND_HOST}:{BIND_PORT}/api/v1{path}" token = create_jwt(settings.user_id, role="user") headers = {"Authorization": f"Bearer {token}"} From 2c19b54920b9c17b2df0b59b5bddd34f451e7844 Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Thu, 6 Aug 2026 00:23:03 +0200 Subject: [PATCH 5/8] fix(mcp/condor): use BIND_HOST variable --- mcp_servers/condor/condor_client.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index 34679ee8..53a281f0 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -30,9 +30,9 @@ async def call_main_api( timeout = TIMEOUTS.mcp_call try: - ip = ipaddress.ip_address(host) + ip = ipaddress.ip_address(BIND_HOST) if ip.version == 6: - host = f"[{host}]" + BIND_HOST = f"[{BIND_HOST}]" except ValueError: pass From 09f02fc3c4cb68ca5941f40bafe3e967acb16fdc Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Fri, 7 Aug 2026 14:32:26 +0200 Subject: [PATCH 6/8] fix(config): uses WEB_PORT as BIND_PORT if not defined --- utils/config.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/utils/config.py b/utils/config.py index e805fcff..29926ba7 100644 --- a/utils/config.py +++ b/utils/config.py @@ -19,12 +19,6 @@ OPENAI_API_KEY = os.environ.get("OPENAI_API_KEY") -_bind_host_raw = os.environ.get("BIND_HOST", "").strip() -_bind_port_raw = os.environ.get("BIND_PORT", "").strip() - -BIND_HOST = str(_bind_host_raw) if _bind_host_raw else "0.0.0.0" -BIND_PORT = int(_bind_port_raw) if _bind_port_raw else 8088 - # Single WEB_URL param: full URL including port if needed (e.g. http://myserver.com:8088) # Falls back to WEB_PORT for backward compat, then default 8088 _web_url_raw = os.environ.get("WEB_URL", "").strip() @@ -37,3 +31,9 @@ else: WEB_PORT = int(_web_port_raw) if _web_port_raw else 8088 WEB_URL = f"http://localhost:{WEB_PORT}" + +_bind_host_raw = os.environ.get("BIND_HOST", "").strip() +_bind_port_raw = os.environ.get("BIND_PORT", "").strip() + +BIND_HOST = str(_bind_host_raw) if _bind_host_raw else "0.0.0.0" +BIND_PORT = int(_bind_port_raw) if _bind_port_raw else WEB_PORT From f822f0b2ccf500b4b48d5949dbcd82ec1f7e62c2 Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Fri, 7 Aug 2026 14:45:12 +0200 Subject: [PATCH 7/8] fix(config): respect WEB_PORT env var when WEB_URL has no explicit port --- utils/config.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/utils/config.py b/utils/config.py index 29926ba7..f3dbd301 100644 --- a/utils/config.py +++ b/utils/config.py @@ -27,7 +27,13 @@ if _web_url_raw: WEB_URL = _web_url_raw.rstrip("/") _parsed = urlparse(WEB_URL) - WEB_PORT = _parsed.port or (443 if _parsed.scheme == "https" else 80) + + if _parsed.port: + WEB_PORT = _parsed.port + elif _web_port_raw: + WEB_PORT = int(_web_port_raw) + else: + WEB_PORT = 443 if _parsed.scheme == "https" else 80 else: WEB_PORT = int(_web_port_raw) if _web_port_raw else 8088 WEB_URL = f"http://localhost:{WEB_PORT}" From a5ce91ba776f1d8b96d9926efd48b4cf0188e577 Mon Sep 17 00:00:00 2001 From: Laurent Grawet Date: Fri, 7 Aug 2026 15:18:54 +0200 Subject: [PATCH 8/8] fix(mcp): prevent requests to 0.0.0.0 and [::] endpoints --- mcp_servers/condor/condor_client.py | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/mcp_servers/condor/condor_client.py b/mcp_servers/condor/condor_client.py index 53a281f0..1c3e74b1 100644 --- a/mcp_servers/condor/condor_client.py +++ b/mcp_servers/condor/condor_client.py @@ -29,14 +29,20 @@ async def call_main_api( if timeout is None: timeout = TIMEOUTS.mcp_call + host = BIND_HOST + try: - ip = ipaddress.ip_address(BIND_HOST) + ip = ipaddress.ip_address(host) + + if ip.is_unspecified: + host = "::1" if ip.version == 6 else "127.0.0.1" + if ip.version == 6: - BIND_HOST = f"[{BIND_HOST}]" + host = f"[{host}]" except ValueError: pass - url = f"http://{BIND_HOST}:{BIND_PORT}/api/v1{path}" + url = f"http://{host}:{BIND_PORT}/api/v1{path}" token = create_jwt(settings.user_id, role="user") headers = {"Authorization": f"Bearer {token}"}