Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 61 additions & 15 deletions mcpjam-inspector/bin/start.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import { resolve, dirname } from "path";
import { spawn } from "child_process";
import { fileURLToPath } from "url";
import { createServer } from "net";
import { createServer, createConnection } from "net";
import { execSync } from "child_process";
import { existsSync, readFileSync } from "fs";
import open from "open";
Expand Down Expand Up @@ -137,6 +137,48 @@ function isPortAvailable(port) {
});
}

function waitForServerReady(port, host, timeoutMs = 30000) {
const intervalMs = 200;
const startTime = Date.now();

return new Promise((resolve) => {
function attempt() {
if (Date.now() - startTime >= timeoutMs) {
resolve(false);
return;
}

const socket = createConnection({ port, host });
let settled = false;

function cleanup() {
if (settled) return;
settled = true;
socket.removeAllListeners();
socket.destroy();
}

socket.once("connect", () => {
cleanup();
resolve(true);
});

socket.once("error", () => {
cleanup();
setTimeout(attempt, intervalMs);
});

socket.setTimeout(1000);
socket.once("timeout", () => {
cleanup();
setTimeout(attempt, intervalMs);
});
}

attempt();
});
}

function spawnPromise(command, args, options) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
Expand Down Expand Up @@ -737,30 +779,34 @@ async function main() {
serverProcess.kill("SIGTERM");
});

// Wait a bit for the server to start up
await delay(2000);

if (!cancelled) {
// Open the browser automatically
// Use BASE_URL if set, otherwise construct from HOST and PORT
// Default: localhost in development, 127.0.0.1 in production
const defaultHost =
process.env.ENVIRONMENT === "dev" ? "localhost" : "127.0.0.1";
const host = process.env.HOST || defaultHost;
let url = process.env.BASE_URL || `http://${host}:${PORT}`;

// Append initial tab hash if specified
if (initialTab) {
url = `${url}#${initialTab}`;
}
// Wait until the server is actually accepting connections
const ready = await waitForServerReady(parseInt(PORT, 10), host, 30000);

try {
await open(url);
logSuccess(`🌐 Browser opened at ${url}`);
} catch (error) {
if (!ready) {
logWarning(
`Could not open browser automatically. Please visit ${url} manually.`,
`Server did not become ready within 30s. Please visit ${url} manually.`,
);
} else if (!cancelled) {
// Append initial tab hash if specified
if (initialTab) {
url = `${url}#${initialTab}`;
}

try {
await open(url);
logSuccess(`🌐 Browser opened at ${url}`);
} catch (error) {
logWarning(
`Could not open browser automatically. Please visit ${url} manually.`,
);
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,9 @@ describe("useChatSession minimal mode parity", () => {
const latestTransport = mockTransportInstances.at(-1)!;
expect(latestTransport.options.api).toBe("/api/mcp/chat-v2");
expect(latestTransport.options.fetch).toBeUndefined();
expect(await resolveConfig(latestTransport.options.headers)).toBeUndefined();
expect(
await resolveConfig(latestTransport.options.headers),
).toBeUndefined();

act(() => {
result.current.sendMessage({ text: "hello" });
Expand Down Expand Up @@ -353,9 +355,9 @@ describe("useChatSession minimal mode parity", () => {
expect(await resolveConfig(latestTransport.options.headers)).toEqual({
Authorization: "Bearer convex-token",
});
expect(await resolveConfig(latestTransport.options.headers)).not.toHaveProperty(
"X-MCP-Session-Auth",
);
expect(
await resolveConfig(latestTransport.options.headers),
).not.toHaveProperty("X-MCP-Session-Auth");
expect(mockAuthFetch).not.toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ describe("web routes — chat-v2 guest mode", () => {

beforeEach(() => {
vi.clearAllMocks();
testGuestKeyDir = mkdtempSync(path.join(os.tmpdir(), "chat-v2-guest-test-"));
testGuestKeyDir = mkdtempSync(
path.join(os.tmpdir(), "chat-v2-guest-test-"),
);
process.env.GUEST_JWT_KEY_DIR = testGuestKeyDir;
initGuestTokenSecret();
process.env.CONVEX_HTTP_URL = "https://example.convex.site";
Expand Down
Loading