|
1 | | -import { exec } from "child_process" |
2 | | -import { promisify } from "util" |
3 | | - |
4 | | -const execAsync = promisify(exec) |
| 1 | +import find from "find-process" |
5 | 2 |
|
6 | 3 | interface NextJsServerInfo { |
7 | 4 | port: number |
@@ -30,52 +27,35 @@ interface NextJsMCPResponse { |
30 | 27 |
|
31 | 28 | async function findNextJsServers(): Promise<NextJsServerInfo[]> { |
32 | 29 | try { |
33 | | - const { stdout } = await execAsync("ps aux") |
34 | | - const lines = stdout.split("\n") |
| 30 | + const nodeProcesses = await find("name", "node", true) |
35 | 31 | const servers: NextJsServerInfo[] = [] |
36 | 32 | const seenPorts = new Set<number>() |
37 | 33 |
|
38 | | - for (const line of lines) { |
39 | | - // Enhanced detection patterns for Next.js servers |
| 34 | + for (const proc of nodeProcesses) { |
| 35 | + const command = proc.cmd || "" |
| 36 | + |
40 | 37 | const isNextJsProcess = |
41 | | - line.includes("next dev") || |
42 | | - line.includes("next-server") || |
43 | | - line.includes("next/dist/bin/next") || |
44 | | - (line.includes("node") && line.includes("next") && line.includes("dev")) |
| 38 | + command.includes("next dev") || |
| 39 | + command.includes("next-server") || |
| 40 | + command.includes("next/dist/bin/next") || |
| 41 | + (command.includes("next") && command.includes("dev")) |
45 | 42 |
|
46 | 43 | if (isNextJsProcess) { |
47 | | - const parts = line.trim().split(/\s+/) |
48 | | - const pid = parseInt(parts[1], 10) |
49 | | - const command = parts.slice(10).join(" ") |
50 | | - |
51 | | - // Try multiple methods to detect port |
52 | 44 | const portMatch = |
53 | 45 | command.match(/--port[=\s]+(\d+)/) || |
54 | 46 | command.match(/-p[=\s]+(\d+)/) || |
| 47 | + command.match(/--port\s+["'](\d+)["']/) || |
| 48 | + command.match(/["']--port["']\s+["']?(\d+)["']?/) || |
| 49 | + command.match(/["'](\d+)["']\s*$/) || |
55 | 50 | command.match(/:(\d+)/) |
56 | 51 |
|
57 | | - let port = 3000 // Default Next.js port |
58 | | - |
59 | 52 | if (portMatch) { |
60 | | - port = parseInt(portMatch[1], 10) |
61 | | - } else { |
62 | | - // Fallback: use lsof to find the listening port |
63 | | - try { |
64 | | - const processInfo = await execAsync(`lsof -Pan -p ${pid} -i 2>/dev/null || true`) |
65 | | - const portFromLsof = processInfo.stdout.match(/:(\d+).*LISTEN/) |
66 | | - if (portFromLsof) { |
67 | | - port = parseInt(portFromLsof[1], 10) |
68 | | - } |
69 | | - } catch { |
70 | | - // If lsof fails, continue with default port |
| 53 | + const port = parseInt(portMatch[1], 10) |
| 54 | + if (!seenPorts.has(port)) { |
| 55 | + seenPorts.add(port) |
| 56 | + servers.push({ port, pid: proc.pid, command }) |
71 | 57 | } |
72 | 58 | } |
73 | | - |
74 | | - // Avoid duplicate ports (in case multiple processes are detected) |
75 | | - if (!seenPorts.has(port)) { |
76 | | - seenPorts.add(port) |
77 | | - servers.push({ port, pid, command }) |
78 | | - } |
79 | 59 | } |
80 | 60 | } |
81 | 61 |
|
@@ -159,22 +139,13 @@ async function makeNextJsMCPRequest( |
159 | 139 | } |
160 | 140 | } |
161 | 141 |
|
162 | | -export async function discoverNextJsServer( |
163 | | - preferredPort?: number |
164 | | -): Promise<NextJsServerInfo | null> { |
| 142 | +export async function discoverNextJsServer(): Promise<NextJsServerInfo | null> { |
165 | 143 | const servers = await findNextJsServers() |
166 | 144 |
|
167 | 145 | if (servers.length === 0) { |
168 | 146 | return null |
169 | 147 | } |
170 | 148 |
|
171 | | - if (preferredPort) { |
172 | | - const server = servers.find((s) => s.port === preferredPort) |
173 | | - if (server) { |
174 | | - return server |
175 | | - } |
176 | | - } |
177 | | - |
178 | 149 | if (servers.length === 1) { |
179 | 150 | return servers[0] |
180 | 151 | } |
|
0 commit comments