diff --git a/src/clj/auto_ap/server.clj b/src/clj/auto_ap/server.clj index c2252e15..0b38c555 100644 --- a/src/clj/auto_ap/server.clj +++ b/src/clj/auto_ap/server.clj @@ -62,7 +62,15 @@ (.setHandler server stats-handler)) (.setStopAtShutdown server true)) -(def ^:dynamic *http-port-override* nil) +(def ^:dynamic *http-port-override* + ;; In dev, `lein mcp-repl` records the chosen HTTP port in `.http-port` so it + ;; stays stable across reloads. `refresh` re-evaluates this def, so reading the + ;; file here (rather than relying solely on an alter-var-root override that gets + ;; reset) keeps the port from falling back to (env :port). Absent in prod. + (let [f (java.io.File. ".http-port")] + (when (.exists f) + (let [p (.trim ^String (slurp f))] + (when (seq p) p))))) (mount/defstate port :start (Integer/parseInt (str (or *http-port-override* (env :port) "3000")))) diff --git a/src/clj/dev_mcp.clj b/src/clj/dev_mcp.clj index 7e9f6b06..4bc94ce2 100644 --- a/src/clj/dev_mcp.clj +++ b/src/clj/dev_mcp.clj @@ -9,15 +9,29 @@ (with-open [s (ServerSocket. 0)] (.getLocalPort s))) -(defn- mcp-repl-task [& _args] - "Start nREPL server and HTTP server on random ports. +(defn- read-port [path] + "Read a previously-recorded port from `path`, or nil if missing/unparseable." + (let [f (io/file path)] + (when (.exists f) + (try (Integer/parseInt (.trim ^String (slurp f))) + (catch Exception _ nil))))) - Writes ports to nrepl-port and .http-port files. - Connect with: clj-nrepl-eval -p $(cat nrepl-port)" - (let [nrepl-port (available-port) - http-port (available-port)] - (spit "nrepl-port" (str nrepl-port)) - (spit ".http-port" (str http-port)) +(defn- stable-port [path] + "Reuse the port recorded in `path` if present, otherwise pick a random + available one. Always (re)writes the file so the port stays stable for this + worktree across REPL restarts and reloads." + (let [port (or (read-port path) (available-port))] + (spit path (str port)) + port)) + +(defn- mcp-repl-task [& _args] + "Start nREPL server and HTTP server. + + Reuses the ports recorded in nrepl-port and .http-port if present (keeping + them stable per worktree), otherwise picks random available ports and records + them. Connect with: clj-nrepl-eval -p $(cat nrepl-port)" + (let [nrepl-port (stable-port "nrepl-port") + http-port (stable-port ".http-port")] (println (format "nREPL port: %d (nrepl-port)" nrepl-port)) (println (format "HTTP port: %d (.http-port)" http-port)) (nrepl/start-server :port nrepl-port)