Merge pull request #504 from modelcontextprotocol/jerome/fix/linting

Fixing linting issues from previous bug fix
This commit is contained in:
Jerome 2025-06-13 18:22:19 +01:00 • committed by GitHub
commit 5bc0eed36f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 304 additions and 257 deletions

0
.git-blame-ignore-revs Normal file
View file

View file

@ -349,7 +349,7 @@ const App = () => {
const headers: HeadersInit = {}; const headers: HeadersInit = {};
const proxyAuthToken = getMCPProxyAuthToken(config); const proxyAuthToken = getMCPProxyAuthToken(config);
if (proxyAuthToken) { if (proxyAuthToken) {
headers['Authorization'] = `Bearer ${proxyAuthToken}`; headers["Authorization"] = `Bearer ${proxyAuthToken}`;
} }
fetch(`${getMCPProxyAddress(config)}/config`, { headers }) fetch(`${getMCPProxyAddress(config)}/config`, { headers })

View file

@ -84,12 +84,6 @@ Object.defineProperty(window, "sessionStorage", {
value: sessionStorageMock, value: sessionStorageMock,
}); });
Object.defineProperty(window, "location", {
value: {
origin: "http://localhost:3000",
},
});
describe("AuthDebugger", () => { describe("AuthDebugger", () => {
const defaultAuthState = EMPTY_DEBUGGER_STATE; const defaultAuthState = EMPTY_DEBUGGER_STATE;
@ -104,7 +98,7 @@ describe("AuthDebugger", () => {
jest.clearAllMocks(); jest.clearAllMocks();
sessionStorageMock.getItem.mockReturnValue(null); sessionStorageMock.getItem.mockReturnValue(null);
// Supress // Suppress console errors in tests to avoid JSDOM navigation noise
jest.spyOn(console, "error").mockImplementation(() => {}); jest.spyOn(console, "error").mockImplementation(() => {});
mockDiscoverOAuthMetadata.mockResolvedValue(mockOAuthMetadata); mockDiscoverOAuthMetadata.mockResolvedValue(mockOAuthMetadata);
@ -447,18 +441,6 @@ describe("AuthDebugger", () => {
it("should store auth state to sessionStorage before redirect in Quick OAuth Flow", async () => { it("should store auth state to sessionStorage before redirect in Quick OAuth Flow", async () => {
const updateAuthState = jest.fn(); const updateAuthState = jest.fn();
// Mock window.location.href setter
const originalLocation = window.location;
const locationMock = {
...originalLocation,
href: "",
origin: "http://localhost:3000",
};
Object.defineProperty(window, "location", {
writable: true,
value: locationMock,
});
// Setup mocks for OAuth flow // Setup mocks for OAuth flow
mockStartAuthorization.mockResolvedValue({ mockStartAuthorization.mockResolvedValue({
authorizationUrl: new URL( authorizationUrl: new URL(

View file

@ -519,6 +519,7 @@ describe("Sidebar Environment Variables", () => {
label: "Request Timeout", label: "Request Timeout",
description: "Timeout for requests to the MCP server (ms)", description: "Timeout for requests to the MCP server (ms)",
value: 5000, value: 5000,
is_session_item: false,
}, },
}), }),
); );
@ -544,6 +545,7 @@ describe("Sidebar Environment Variables", () => {
description: description:
"Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577", "Set this if you are running the MCP Inspector Proxy on a non-default address. Example: http://10.1.1.22:5577",
value: "http://localhost:8080", value: "http://localhost:8080",
is_session_item: false,
}, },
}), }),
); );
@ -569,6 +571,7 @@ describe("Sidebar Environment Variables", () => {
description: description:
"Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications)", "Maximum total timeout for requests sent to the MCP server (ms) (Use with progress notifications)",
value: 10000, value: 10000,
is_session_item: false,
}, },
}), }),
); );
@ -591,6 +594,7 @@ describe("Sidebar Environment Variables", () => {
label: "Request Timeout", label: "Request Timeout",
description: "Timeout for requests to the MCP server (ms)", description: "Timeout for requests to the MCP server (ms)",
value: 0, value: 0,
is_session_item: false,
}, },
}), }),
); );
@ -637,6 +641,7 @@ describe("Sidebar Environment Variables", () => {
label: "Request Timeout", label: "Request Timeout",
description: "Timeout for requests to the MCP server (ms)", description: "Timeout for requests to the MCP server (ms)",
value: 3000, value: 3000,
is_session_item: false,
}, },
}), }),
); );

View file

@ -246,7 +246,7 @@ export function useConnection({
const proxyAuthToken = getMCPProxyAuthToken(config); const proxyAuthToken = getMCPProxyAuthToken(config);
const headers: HeadersInit = {}; const headers: HeadersInit = {};
if (proxyAuthToken) { if (proxyAuthToken) {
headers['Authorization'] = `Bearer ${proxyAuthToken}`; headers["Authorization"] = `Bearer ${proxyAuthToken}`;
} }
const proxyHealthResponse = await fetch(proxyHealthUrl, { headers }); const proxyHealthResponse = await fetch(proxyHealthUrl, { headers });
const proxyHealth = await proxyHealthResponse.json(); const proxyHealth = await proxyHealthResponse.json();
@ -335,7 +335,7 @@ export function useConnection({
const proxyAuthToken = getMCPProxyAuthToken(config); const proxyAuthToken = getMCPProxyAuthToken(config);
const proxyHeaders: HeadersInit = {}; const proxyHeaders: HeadersInit = {};
if (proxyAuthToken) { if (proxyAuthToken) {
proxyHeaders['Authorization'] = `Bearer ${proxyAuthToken}`; proxyHeaders["Authorization"] = `Bearer ${proxyAuthToken}`;
} }
// Create appropriate transport // Create appropriate transport
@ -356,7 +356,11 @@ export function useConnection({
fetch: ( fetch: (
url: string | URL | globalThis.Request, url: string | URL | globalThis.Request,
init: RequestInit | undefined, init: RequestInit | undefined,
) => fetch(url, { ...init, headers: { ...headers, ...proxyHeaders } }), ) =>
fetch(url, {
...init,
headers: { ...headers, ...proxyHeaders },
}),
}, },
requestInit: { requestInit: {
headers: { ...headers, ...proxyHeaders }, headers: { ...headers, ...proxyHeaders },
@ -372,7 +376,11 @@ export function useConnection({
fetch: ( fetch: (
url: string | URL | globalThis.Request, url: string | URL | globalThis.Request,
init: RequestInit | undefined, init: RequestInit | undefined,
) => fetch(url, { ...init, headers: { ...headers, ...proxyHeaders } }), ) =>
fetch(url, {
...init,
headers: { ...headers, ...proxyHeaders },
}),
}, },
requestInit: { requestInit: {
headers: { ...headers, ...proxyHeaders }, headers: { ...headers, ...proxyHeaders },
@ -388,7 +396,11 @@ export function useConnection({
fetch: ( fetch: (
url: string | URL | globalThis.Request, url: string | URL | globalThis.Request,
init: RequestInit | undefined, init: RequestInit | undefined,
) => fetch(url, { ...init, headers: { ...headers, ...proxyHeaders } }), ) =>
fetch(url, {
...init,
headers: { ...headers, ...proxyHeaders },
}),
}, },
requestInit: { requestInit: {
headers: { ...headers, ...proxyHeaders }, headers: { ...headers, ...proxyHeaders },
@ -471,7 +483,8 @@ export function useConnection({
if (isProxyAuthError(error)) { if (isProxyAuthError(error)) {
toast({ toast({
title: "Proxy Authentication Required", title: "Proxy Authentication Required",
description: "Please enter the session token from the proxy server console in the Configuration settings.", description:
"Please enter the session token from the proxy server console in the Configuration settings.",
variant: "destructive", variant: "destructive",
}); });
setConnectionStatus("error"); setConnectionStatus("error");

4
package-lock.json generated
View file

@ -1,12 +1,12 @@
{ {
"name": "@modelcontextprotocol/inspector", "name": "@modelcontextprotocol/inspector",
"version": "0.14.0", "version": "0.14.1",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "@modelcontextprotocol/inspector", "name": "@modelcontextprotocol/inspector",
"version": "0.14.0", "version": "0.14.1",
"license": "MIT", "license": "MIT",
"workspaces": [ "workspaces": [
"client", "client",

View file

@ -89,33 +89,43 @@ app.use((req, res, next) => {
const webAppTransports: Map<string, Transport> = new Map<string, Transport>(); // Web app transports by web app sessionId const webAppTransports: Map<string, Transport> = new Map<string, Transport>(); // Web app transports by web app sessionId
const serverTransports: Map<string, Transport> = new Map<string, Transport>(); // Server Transports by web app sessionId const serverTransports: Map<string, Transport> = new Map<string, Transport>(); // Server Transports by web app sessionId
const sessionToken = randomBytes(32).toString('hex'); const sessionToken = randomBytes(32).toString("hex");
const authDisabled = !!process.env.DANGEROUSLY_OMIT_AUTH; const authDisabled = !!process.env.DANGEROUSLY_OMIT_AUTH;
// Origin validation middleware to prevent DNS rebinding attacks // Origin validation middleware to prevent DNS rebinding attacks
const originValidationMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => { const originValidationMiddleware = (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
const origin = req.headers.origin; const origin = req.headers.origin;
// Default origins based on CLIENT_PORT or use environment variable // Default origins based on CLIENT_PORT or use environment variable
const clientPort = process.env.CLIENT_PORT || '6274'; const clientPort = process.env.CLIENT_PORT || "6274";
const defaultOrigins = [ const defaultOrigins = [
`http://localhost:${clientPort}`, `http://localhost:${clientPort}`,
`http://127.0.0.1:${clientPort}` `http://127.0.0.1:${clientPort}`,
]; ];
const allowedOrigins = process.env.ALLOWED_ORIGINS?.split(',') || defaultOrigins; const allowedOrigins =
process.env.ALLOWED_ORIGINS?.split(",") || defaultOrigins;
if (origin && !allowedOrigins.includes(origin)) { if (origin && !allowedOrigins.includes(origin)) {
console.error(`Invalid origin: ${origin}`); console.error(`Invalid origin: ${origin}`);
res.status(403).json({ res.status(403).json({
error: 'Forbidden - invalid origin', error: "Forbidden - invalid origin",
message: 'Request blocked to prevent DNS rebinding attacks. Configure allowed origins via environment variable.' message:
"Request blocked to prevent DNS rebinding attacks. Configure allowed origins via environment variable.",
}); });
return; return;
} }
next(); next();
}; };
const authMiddleware = (req: express.Request, res: express.Response, next: express.NextFunction) => { const authMiddleware = (
req: express.Request,
res: express.Response,
next: express.NextFunction,
) => {
if (authDisabled) { if (authDisabled) {
return next(); return next();
} }
@ -123,12 +133,13 @@ const authMiddleware = (req: express.Request, res: express.Response, next: expre
const sendUnauthorized = () => { const sendUnauthorized = () => {
res.status(401).json({ res.status(401).json({
error: "Unauthorized", error: "Unauthorized",
message: "Authentication required. Use the session token shown in the console when starting the server." message:
"Authentication required. Use the session token shown in the console when starting the server.",
}); });
}; };
const authHeader = req.headers.authorization; const authHeader = req.headers.authorization;
if (!authHeader || !authHeader.startsWith('Bearer ')) { if (!authHeader || !authHeader.startsWith("Bearer ")) {
sendUnauthorized(); sendUnauthorized();
return; return;
} }
@ -216,38 +227,152 @@ const createTransport = async (req: express.Request): Promise<Transport> => {
} }
}; };
app.get("/mcp", originValidationMiddleware, authMiddleware, async (req, res) => { app.get(
const sessionId = req.headers["mcp-session-id"] as string; "/mcp",
console.log(`Received GET message for sessionId ${sessionId}`); originValidationMiddleware,
try { authMiddleware,
const transport = webAppTransports.get( async (req, res) => {
sessionId, const sessionId = req.headers["mcp-session-id"] as string;
) as StreamableHTTPServerTransport; console.log(`Received GET message for sessionId ${sessionId}`);
if (!transport) {
res.status(404).end("Session not found");
return;
} else {
await transport.handleRequest(req, res);
}
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
});
app.post("/mcp", originValidationMiddleware, authMiddleware, async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string | undefined;
let serverTransport: Transport | undefined;
if (!sessionId) {
try { try {
console.log("New StreamableHttp connection request"); const transport = webAppTransports.get(
sessionId,
) as StreamableHTTPServerTransport;
if (!transport) {
res.status(404).end("Session not found");
return;
} else {
await transport.handleRequest(req, res);
}
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
},
);
app.post(
"/mcp",
originValidationMiddleware,
authMiddleware,
async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string | undefined;
let serverTransport: Transport | undefined;
if (!sessionId) {
try {
console.log("New StreamableHttp connection request");
try {
serverTransport = await createTransport(req);
} catch (error) {
if (error instanceof SseError && error.code === 401) {
console.error(
"Received 401 Unauthorized from MCP server:",
error.message,
);
res.status(401).json(error);
return;
}
throw error;
}
console.log("Created StreamableHttp server transport");
const webAppTransport = new StreamableHTTPServerTransport({
sessionIdGenerator: randomUUID,
onsessioninitialized: (sessionId) => {
webAppTransports.set(sessionId, webAppTransport);
serverTransports.set(sessionId, serverTransport!);
console.log("Client <-> Proxy sessionId: " + sessionId);
},
});
console.log("Created StreamableHttp client transport");
await webAppTransport.start();
mcpProxy({
transportToClient: webAppTransport,
transportToServer: serverTransport,
});
await (webAppTransport as StreamableHTTPServerTransport).handleRequest(
req,
res,
req.body,
);
} catch (error) {
console.error("Error in /mcp POST route:", error);
res.status(500).json(error);
}
} else {
console.log(`Received POST message for sessionId ${sessionId}`);
try {
const transport = webAppTransports.get(
sessionId,
) as StreamableHTTPServerTransport;
if (!transport) {
res.status(404).end("Transport not found for sessionId " + sessionId);
} else {
await (transport as StreamableHTTPServerTransport).handleRequest(
req,
res,
);
}
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
}
},
);
app.delete(
"/mcp",
originValidationMiddleware,
authMiddleware,
async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string | undefined;
console.log(`Received DELETE message for sessionId ${sessionId}`);
let serverTransport: Transport | undefined;
if (sessionId) {
try {
serverTransport = serverTransports.get(
sessionId,
) as StreamableHTTPClientTransport;
if (!serverTransport) {
res.status(404).end("Transport not found for sessionId " + sessionId);
} else {
await (
serverTransport as StreamableHTTPClientTransport
).terminateSession();
webAppTransports.delete(sessionId);
serverTransports.delete(sessionId);
console.log(`Transports removed for sessionId ${sessionId}`);
}
res.status(200).end();
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
}
},
);
app.get(
"/stdio",
originValidationMiddleware,
authMiddleware,
async (req, res) => {
try {
console.log("New STDIO connection request");
let serverTransport: Transport | undefined;
try { try {
serverTransport = await createTransport(req); serverTransport = await createTransport(req);
console.log("Created server transport");
} catch (error) { } catch (error) {
if (error instanceof SseError && error.code === 401) { if (error instanceof SseError && error.code === 401) {
console.error( console.error(
"Received 401 Unauthorized from MCP server:", "Received 401 Unauthorized from MCP server. Authentication failure.",
error.message,
); );
res.status(401).json(error); res.status(401).json(error);
return; return;
@ -256,211 +381,127 @@ app.post("/mcp", originValidationMiddleware, authMiddleware, async (req, res) =>
throw error; throw error;
} }
console.log("Created StreamableHttp server transport");
const webAppTransport = new StreamableHTTPServerTransport({
sessionIdGenerator: randomUUID,
onsessioninitialized: (sessionId) => {
webAppTransports.set(sessionId, webAppTransport);
serverTransports.set(sessionId, serverTransport!);
console.log("Client <-> Proxy sessionId: " + sessionId);
},
});
console.log("Created StreamableHttp client transport");
await webAppTransport.start();
mcpProxy({
transportToClient: webAppTransport,
transportToServer: serverTransport,
});
await (webAppTransport as StreamableHTTPServerTransport).handleRequest(
req,
res,
req.body,
);
} catch (error) {
console.error("Error in /mcp POST route:", error);
res.status(500).json(error);
}
} else {
console.log(`Received POST message for sessionId ${sessionId}`);
try {
const transport = webAppTransports.get(
sessionId,
) as StreamableHTTPServerTransport;
if (!transport) {
res.status(404).end("Transport not found for sessionId " + sessionId);
} else {
await (transport as StreamableHTTPServerTransport).handleRequest(
req,
res,
);
}
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
}
});
app.delete("/mcp", originValidationMiddleware, authMiddleware, async (req, res) => {
const sessionId = req.headers["mcp-session-id"] as string | undefined;
console.log(`Received DELETE message for sessionId ${sessionId}`);
let serverTransport: Transport | undefined;
if (sessionId) {
try {
serverTransport = serverTransports.get(
sessionId,
) as StreamableHTTPClientTransport;
if (!serverTransport) {
res.status(404).end("Transport not found for sessionId " + sessionId);
} else {
await (
serverTransport as StreamableHTTPClientTransport
).terminateSession();
webAppTransports.delete(sessionId);
serverTransports.delete(sessionId);
console.log(`Transports removed for sessionId ${sessionId}`);
}
res.status(200).end();
} catch (error) {
console.error("Error in /mcp route:", error);
res.status(500).json(error);
}
}
});
app.get("/stdio", originValidationMiddleware, authMiddleware, async (req, res) => {
try {
console.log("New STDIO connection request");
let serverTransport: Transport | undefined;
try {
serverTransport = await createTransport(req);
console.log("Created server transport");
} catch (error) {
if (error instanceof SseError && error.code === 401) {
console.error(
"Received 401 Unauthorized from MCP server. Authentication failure.",
);
res.status(401).json(error);
return;
}
throw error;
}
const webAppTransport = new SSEServerTransport("/message", res);
console.log("Created client transport");
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
serverTransports.set(webAppTransport.sessionId, serverTransport);
await webAppTransport.start();
(serverTransport as StdioClientTransport).stderr!.on("data", (chunk) => {
if (chunk.toString().includes("MODULE_NOT_FOUND")) {
webAppTransport.send({
jsonrpc: "2.0",
method: "notifications/stderr",
params: {
content: "Command not found, transports removed",
},
});
webAppTransport.close();
serverTransport.close();
webAppTransports.delete(webAppTransport.sessionId);
serverTransports.delete(webAppTransport.sessionId);
console.error("Command not found, transports removed");
} else {
webAppTransport.send({
jsonrpc: "2.0",
method: "notifications/stderr",
params: {
content: chunk.toString(),
},
});
}
});
mcpProxy({
transportToClient: webAppTransport,
transportToServer: serverTransport,
});
} catch (error) {
console.error("Error in /stdio route:", error);
res.status(500).json(error);
}
});
app.get("/sse", originValidationMiddleware, authMiddleware, async (req, res) => {
try {
console.log(
"New SSE connection request. NOTE: The sse transport is deprecated and has been replaced by StreamableHttp",
);
let serverTransport: Transport | undefined;
try {
serverTransport = await createTransport(req);
} catch (error) {
if (error instanceof SseError && error.code === 401) {
console.error(
"Received 401 Unauthorized from MCP server. Authentication failure.",
);
res.status(401).json(error);
return;
} else if (error instanceof SseError && error.code === 404) {
console.error(
"Received 404 not found from MCP server. Does the MCP server support SSE?",
);
res.status(404).json(error);
return;
} else if (JSON.stringify(error).includes("ECONNREFUSED")) {
console.error("Connection refused. Is the MCP server running?");
res.status(500).json(error);
} else {
throw error;
}
}
if (serverTransport) {
const webAppTransport = new SSEServerTransport("/message", res); const webAppTransport = new SSEServerTransport("/message", res);
webAppTransports.set(webAppTransport.sessionId, webAppTransport);
console.log("Created client transport"); console.log("Created client transport");
serverTransports.set(webAppTransport.sessionId, serverTransport!);
console.log("Created server transport"); webAppTransports.set(webAppTransport.sessionId, webAppTransport);
serverTransports.set(webAppTransport.sessionId, serverTransport);
await webAppTransport.start(); await webAppTransport.start();
(serverTransport as StdioClientTransport).stderr!.on("data", (chunk) => {
if (chunk.toString().includes("MODULE_NOT_FOUND")) {
webAppTransport.send({
jsonrpc: "2.0",
method: "notifications/stderr",
params: {
content: "Command not found, transports removed",
},
});
webAppTransport.close();
serverTransport.close();
webAppTransports.delete(webAppTransport.sessionId);
serverTransports.delete(webAppTransport.sessionId);
console.error("Command not found, transports removed");
} else {
webAppTransport.send({
jsonrpc: "2.0",
method: "notifications/stderr",
params: {
content: chunk.toString(),
},
});
}
});
mcpProxy({ mcpProxy({
transportToClient: webAppTransport, transportToClient: webAppTransport,
transportToServer: serverTransport, transportToServer: serverTransport,
}); });
} catch (error) {
console.error("Error in /stdio route:", error);
res.status(500).json(error);
} }
} catch (error) { },
console.error("Error in /sse route:", error); );
res.status(500).json(error);
}
});
app.post("/message", originValidationMiddleware, authMiddleware, async (req, res) => { app.get(
try { "/sse",
const sessionId = req.query.sessionId; originValidationMiddleware,
console.log(`Received POST message for sessionId ${sessionId}`); authMiddleware,
async (req, res) => {
try {
console.log(
"New SSE connection request. NOTE: The sse transport is deprecated and has been replaced by StreamableHttp",
);
let serverTransport: Transport | undefined;
try {
serverTransport = await createTransport(req);
} catch (error) {
if (error instanceof SseError && error.code === 401) {
console.error(
"Received 401 Unauthorized from MCP server. Authentication failure.",
);
res.status(401).json(error);
return;
} else if (error instanceof SseError && error.code === 404) {
console.error(
"Received 404 not found from MCP server. Does the MCP server support SSE?",
);
res.status(404).json(error);
return;
} else if (JSON.stringify(error).includes("ECONNREFUSED")) {
console.error("Connection refused. Is the MCP server running?");
res.status(500).json(error);
} else {
throw error;
}
}
const transport = webAppTransports.get( if (serverTransport) {
sessionId as string, const webAppTransport = new SSEServerTransport("/message", res);
) as SSEServerTransport; webAppTransports.set(webAppTransport.sessionId, webAppTransport);
if (!transport) { console.log("Created client transport");
res.status(404).end("Session not found"); serverTransports.set(webAppTransport.sessionId, serverTransport!);
return; console.log("Created server transport");
await webAppTransport.start();
mcpProxy({
transportToClient: webAppTransport,
transportToServer: serverTransport,
});
}
} catch (error) {
console.error("Error in /sse route:", error);
res.status(500).json(error);
} }
await transport.handlePostMessage(req, res); },
} catch (error) { );
console.error("Error in /message route:", error);
res.status(500).json(error); app.post(
} "/message",
}); originValidationMiddleware,
authMiddleware,
async (req, res) => {
try {
const sessionId = req.query.sessionId;
console.log(`Received POST message for sessionId ${sessionId}`);
const transport = webAppTransports.get(
sessionId as string,
) as SSEServerTransport;
if (!transport) {
res.status(404).end("Session not found");
return;
}
await transport.handlePostMessage(req, res);
} catch (error) {
console.error("Error in /message route:", error);
res.status(500).json(error);
}
},
);
app.get("/health", (req, res) => { app.get("/health", (req, res) => {
res.json({ res.json({
@ -481,22 +522,28 @@ app.get("/config", originValidationMiddleware, authMiddleware, (req, res) => {
} }
}); });
const PORT = parseInt(process.env.PORT || '6277', 10); const PORT = parseInt(process.env.PORT || "6277", 10);
const HOST = process.env.HOST || '127.0.0.1'; const HOST = process.env.HOST || "127.0.0.1";
const server = app.listen(PORT, HOST); const server = app.listen(PORT, HOST);
server.on("listening", () => { server.on("listening", () => {
console.log(`⚙️ Proxy server listening on ${HOST}:${PORT}`); console.log(`⚙️ Proxy server listening on ${HOST}:${PORT}`);
if (!authDisabled) { if (!authDisabled) {
console.log(`🔑 Session token: ${sessionToken}`); console.log(`🔑 Session token: ${sessionToken}`);
console.log(`Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth`); console.log(
`Use this token to authenticate requests or set DANGEROUSLY_OMIT_AUTH=true to disable auth`,
);
// Display clickable URL with pre-filled token // Display clickable URL with pre-filled token
const clientPort = process.env.CLIENT_PORT || '6274'; const clientPort = process.env.CLIENT_PORT || "6274";
const clientUrl = `http://localhost:${clientPort}/?MCP_PROXY_AUTH_TOKEN=${sessionToken}`; const clientUrl = `http://localhost:${clientPort}/?MCP_PROXY_AUTH_TOKEN=${sessionToken}`;
console.log(`\n🔗 Open inspector with token pre-filled:\n ${clientUrl}\n (Auto-open is disabled when authentication is enabled)\n`); console.log(
`\n🔗 Open inspector with token pre-filled:\n ${clientUrl}\n (Auto-open is disabled when authentication is enabled)\n`,
);
} else { } else {
console.log(`⚠️ WARNING: Authentication is disabled. This is not recommended.`); console.log(
`⚠️ WARNING: Authentication is disabled. This is not recommended.`,
);
} }
}); });
server.on("error", (err) => { server.on("error", (err) => {