upstash/context7 · warning

Port ${port} is in use, trying port ${port + 1}...

Error message

Port ${port} is in use, trying port ${port + 1}...

What it means

Emitted by the context7 MCP server's HTTP transport when app.listen(port) fails with EADDRINUSE. The server then retries port+1, up to maxAttempts=10 consecutive ports above initialPort (CLI_PORT ?? DEFAULT_PORT=3000). If attempts are exhausted or the error is not EADDRINUSE, it logs 'Failed to start server' and exits 1. The 'listening' callback prints the port actually bound.

Source

Thrown at packages/mcp/src/index.ts:540

        }
        res.type("text/plain").send(OPENAI_APPS_CHALLENGE_TOKEN);
      }
    );

    // Catch-all 404 handler - must be after all other routes
    app.use((_req: express.Request, res: express.Response) => {
      res.status(404).json({
        error: "not_found",
        message: "Endpoint not found. Use /mcp for MCP protocol communication.",
      });
    });

    const startServer = (port: number, maxAttempts = 10) => {
      const httpServer = app.listen(port);

      httpServer.once("error", (err: NodeJS.ErrnoException) => {
        if (err.code === "EADDRINUSE" && port < initialPort + maxAttempts) {
          console.warn(`Port ${port} is in use, trying port ${port + 1}...`);
          startServer(port + 1, maxAttempts);
        } else {
          console.error(`Failed to start server: ${err.message}`);
          process.exit(1);
        }
      });

      httpServer.once("listening", () => {
        console.error(
          `Context7 Documentation MCP Server v${SERVER_VERSION} running on HTTP at http://localhost:${port}/mcp`
        );
      });
    };

    startServer(initialPort);
  } else {
    stdioApiKey = cliOptions.apiKey || process.env.CONTEXT7_API_KEY;
    stdioSessionId = randomUUID();

View on GitHub (pinned to c3248289c2)

Solutions

  1. Let it self-heal: it retries and the startup line 'running on HTTP at http://localhost:<port>/mcp' shows the final port — use that port in the client config
  2. Free the occupied port: lsof -ti :3000 | xargs kill -9, or stop the dev server using it
  3. Pass a known-free port explicitly: context7-mcp --http --port 3900
  4. If you need a fixed port (a client config already points at it), ensure nothing else binds it before launch

Example fix

# before — port 3000 busy, server drifts to 3001+ while client still targets 3000
context7-mcp --http

# after — free the port or pin a free one
lsof -ti :3000 | xargs kill -9
context7-mcp --http --port 3000
Defensive patterns

Strategy: fallback

Validate before calling

import net from "node:net";
function isFree(port: number, host = "127.0.0.1"): Promise<boolean> {
  return new Promise((resolve) => {
    const srv = net.createServer();
    srv.once("error", () => resolve(false));
    srv.once("listening", () => srv.close(() => resolve(true)));
    srv.listen(port, host);
  });
}
// before start: if (!(await isFree(3000))) port = await findFree(3001);

Type guard

function isAddrInUse(err: unknown): err is NodeJS.ErrnoException {
  return typeof err === "object" && err !== null && (err as NodeJS.ErrnoException).code === "EADDRINUSE";
}

Try / catch

server.once("error", (err) => {
  if (isAddrInUse(err) && attemptsLeft) start(port + 1);
  else { console.error(`Failed to start server: ${(err as Error).message}`); process.exit(1); }
});

Prevention

When it happens

Trigger: Starting the server with --http (or a client spawning it) while ports 3000..3009 are occupied — another context7-mcp instance, a dev server that defaults to 3000 (React/Next/Vite), Docker port mappings, or two MCP clients each launching their own copy.

Common situations: Local web dev on port 3000 while an MCP client also starts context7-mcp; a previous server process not terminated after a crash; concurrent CI jobs sharing a host network.

Related errors


AI-assisted analysis of upstash/context7@c3248289c2 (2026-08-18). Data as JSON: /api/errors/9dbf5dcc9424ffc1. Report an issue: GitHub.