From 49963ca58fb22c226b200a3d41a882e92dffeded Mon Sep 17 00:00:00 2001
From: gpt-5-codex <elope@esus.name>
Date: Sat, 11 Oct 2025 07:37:42 +0200
Subject: [PATCH] fix: harden ngrok helper defaults

---
 docs/NGROK.md            | 11 +++---
 scripts/run_mcp_ngrok.sh | 74 ++++++++++++++++++++++++++--------------
 2 files changed, 54 insertions(+), 31 deletions(-)

diff --git a/docs/NGROK.md b/docs/NGROK.md
index 5b97fb1..fc9c9ad 100644
--- a/docs/NGROK.md
+++ b/docs/NGROK.md
@@ -1,9 +1,10 @@
 # Publishing mcp-browser with ngrok
 
 The `scripts/run_mcp_ngrok.sh` helper launches `mcp-browser` in
-streamable-http mode and exposes it through an ngrok tunnel. By default it uses
-whatever server is marked as default in your configuration (or you can specify
-one explicitly with `--server`).
+streamable-http mode and exposes it through an ngrok tunnel. If you do not
+provide `--config`, the script spins up an ephemeral config that exposes only
+the built-in tools. Otherwise it will respect your chosen server (or the
+default entry in your config).
 
 ```bash
 ./scripts/run_mcp_ngrok.sh \
@@ -23,8 +24,8 @@ tunnel is ready.
 
 Useful options:
 
-- `--server chrome` – publish a different server entry from your config.
-- `--config ~/.claude/mcp-browser/config.yaml` – point at a custom config file.
+- `--config ~/.claude/mcp-browser/config.yaml` – point at your own config file
+  (often combined with `--server <name>`).
 - `--ngrok-region eu` or `--ngrok-domain your-name.ngrok.app` – choose a region
   or reserved domain.
 - `--ngrok-oauth-provider google --ngrok-oauth-allow-email you@example.com` –
diff --git a/scripts/run_mcp_ngrok.sh b/scripts/run_mcp_ngrok.sh
index 46a581f..51f8b05 100755
--- a/scripts/run_mcp_ngrok.sh
+++ b/scripts/run_mcp_ngrok.sh
@@ -6,8 +6,9 @@ usage() {
 Usage: run_mcp_ngrok.sh [options] [-- additional mcp-browser args]
 
 Launch mcp-browser in streamable-http mode and expose it via an ngrok HTTPS
-endpoint. By default it uses the configured default MCP server, but you can
-override that with --server if needed.
+endpoint. By default the script uses a minimal temporary configuration that
+only exposes the built-in tools; pass --config/--server if you want something
+else.
 
 Options:
   --config PATH            Path to mcp-browser config file.
@@ -53,6 +54,7 @@ NGROK_OAUTH_SCOPES=()
 NGROK_INSPECT="false"
 MCP_EXTRA_ARGS=()
 NGROK_EXTRA_ARGS=()
+TEMP_CONFIG=""
 
 while [[ $# -gt 0 ]]; do
   case "$1" in
@@ -103,6 +105,21 @@ while [[ $# -gt 0 ]]; do
   esac
 done
 
+if [[ -z "$CONFIG_PATH" ]]; then
+  TEMP_CONFIG=$(mktemp -t mcp-ngrok-config.XXXXXX.yaml)
+  cat <<'EOF' > "$TEMP_CONFIG"
+servers:
+  builtin-only:
+    name: builtin-only
+    command: null
+default_server: builtin-only
+sparse_mode: true
+enable_builtin_servers: true
+EOF
+  CONFIG_PATH="$TEMP_CONFIG"
+  [[ -z "$SERVER_NAME" ]] && SERVER_NAME="builtin-only"
+fi
+
 if ! command -v "$MCP_BIN" >/dev/null 2>&1; then
   echo "Error: mcp-browser binary '$MCP_BIN' not found" >&2
   exit 1
@@ -113,15 +130,20 @@ if ! command -v "$NGROK_BIN" >/dev/null 2>&1; then
 fi
 
 if [[ -z "$HTTP_PORT" ]]; then
-  HTTP_PORT=$(python3 - <<'PY'
+  if ! HTTP_PORT=$(python3 - <<'PY'
 import socket
-s = socket.socket()
-s.bind(('127.0.0.1', 0))
-port = s.getsockname()[1]
-s.close()
-print(port)
+try:
+    s = socket.socket()
+    s.bind(('127.0.0.1', 0))
+    port = s.getsockname()[1]
+    s.close()
+    print(port)
+except Exception:
+    raise SystemExit(1)
 PY
-)
+  ); then
+    HTTP_PORT=39129
+  fi
 fi
 
 HTTP_PATH="/${HTTP_PATH#/}"
@@ -143,29 +165,28 @@ NGROK_LOG=$(mktemp -t ngrok-mcp.XXXXXX.log)
 cleanup() {
   [[ -n "${NGROK_PID:-}" ]] && kill "$NGROK_PID" >/dev/null 2>&1 || true
   [[ -n "${MCP_PID:-}" ]] && kill "$MCP_PID" >/dev/null 2>&1 || true
+  [[ -n "$TEMP_CONFIG" && -f "$TEMP_CONFIG" ]] && rm -f "$TEMP_CONFIG"
 }
 trap cleanup EXIT INT TERM
 
 "${MCP_CMD[@]}" >"$MCP_LOG" 2>&1 &
 MCP_PID=$!
 
-python3 - "$HTTP_HOST" "$HTTP_PORT" <<'PY'
-import socket, time, sys
-host, port = sys.argv[1], int(sys.argv[2])
-for _ in range(200):
-    sock = socket.socket()
-    try:
-        sock.connect((host, port))
-        sock.close()
-        sys.exit(0)
-    except OSError:
-        sock.close()
-        time.sleep(0.05)
-print('Port not ready', file=sys.stderr)
-sys.exit(1)
-PY
-if [[ $? -ne 0 ]]; then
-  echo "Failed to start mcp-browser gateway. See $MCP_LOG" >&2
+ready=0
+for _ in {1..60}; do
+  if ! kill -0 "$MCP_PID" >/dev/null 2>&1; then
+    echo "mcp-browser exited early. See $MCP_LOG" >&2
+    exit 1
+  fi
+  if grep -q "Streamable HTTP gateway listening" "$MCP_LOG"; then
+    ready=1
+    break
+  fi
+  sleep 0.5
+done
+
+if [[ $ready -ne 1 ]]; then
+  echo "Gateway did not become ready. See $MCP_LOG" >&2
   exit 1
 fi
 
@@ -234,3 +255,4 @@ Local logs:
   ngrok:       $NGROK_LOG
 
 Press Ctrl+C to stop.
+EOF
