/**
 * @license
 * Copyright 2025 Google LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import './polyfill.js';
import { ensureBrowserConnected, ensureBrowserLaunched } from './browser.js';
import { parseArguments } from './cli.js';
import { setServer, setBrowser, watchClose } from './closeChrome.js';
import { loadIssueDescriptions } from './issue-descriptions.js';
import { logger, saveLogsToFile } from './logger.js';
import { McpContext } from './McpContext.js';
import { McpResponse } from './McpResponse.js';
import { Mutex } from './Mutex.js';
import { McpServer, StdioServerTransport, SetLevelRequestSchema, } from './third_party/index.js';
import { ToolCategory } from './tools/categories.js';
import { tools } from './tools/tools.js';
// If moved update release-please config
// x-release-please-start-version
const VERSION = '0.11.0';
// x-release-please-end
export const args = parseArguments(VERSION);
const logFile = args.logFile ? saveLogsToFile(args.logFile) : undefined;
logger(`Starting Chrome DevTools MCP Server v${VERSION}`);
const server = new McpServer({
    name: 'chrome_devtools',
    title: 'Chrome DevTools MCP server',
    version: VERSION,
}, { capabilities: { logging: {} } });
server.server.setRequestHandler(SetLevelRequestSchema, () => {
    return {};
});
let context;
async function getContext() {
    const extraArgs = (args.chromeArg ?? []).map(String);
    if (args.proxyServer) {
        extraArgs.push(`--proxy-server=${args.proxyServer}`);
    }
    const devtools = args.experimentalDevtools ?? false;
    const browser = args.browserUrl || args.wsEndpoint
        ? await ensureBrowserConnected({
            browserURL: args.browserUrl,
            wsEndpoint: args.wsEndpoint,
            wsHeaders: args.wsHeaders,
            devtools,
        })
        : await ensureBrowserLaunched({
            headless: args.headless,
            executablePath: args.executablePath,
            channel: args.channel,
            isolated: args.isolated ?? false,
            userDataDir: args.userDataDir,
            logFile,
            viewport: args.viewport,
            args: extraArgs,
            acceptInsecureCerts: args.acceptInsecureCerts,
            devtools,
        });
    if (context?.browser !== browser) {
        context = await McpContext.from(browser, logger, {
            experimentalDevToolsDebugging: devtools,
            experimentalIncludeAllPages: args.experimentalIncludeAllPages,
        }, undefined, {
            responseLimitArraySize: args.responseLimitArraySize,
            responseLimitArrayUrl: args.responseLimitArrayUrl,
            clickWait: args.clickWait,
        });
    }
    return context;
}
const logDisclaimers = () => {
    console.error(`chrome-devtools-mcp exposes content of the browser instance to the MCP clients allowing them to inspect,
debug, and modify any data in the browser or DevTools.
Avoid sharing sensitive or personal information that you do not want to share with MCP clients.`);
};
const toolMutex = new Mutex();
function registerTool(tool) {
    if (tool.annotations.category === ToolCategory.EMULATION &&
        args.categoryEmulation === false) {
        return;
    }
    if (tool.annotations.category === ToolCategory.PERFORMANCE &&
        args.categoryPerformance === false) {
        return;
    }
    if (tool.annotations.category === ToolCategory.NETWORK &&
        args.categoryNetwork === false) {
        return;
    }
    server.registerTool(tool.name, {
        description: tool.description,
        inputSchema: tool.schema,
        annotations: tool.annotations,
    }, async (params) => {
        const guard = await toolMutex.acquire();
        try {
            logger(`${tool.name} request: ${JSON.stringify(params, null, '  ')}`);
            const context = await getContext();
            logger(`${tool.name} context: resolved`);
            await context.detectOpenDevToolsWindows();
            setBrowser(context.browser);
            const response = new McpResponse();
            await tool.handler({
                params,
            }, response, context);
            const content = await response.handle(tool.name, context);
            return {
                content,
            };
        }
        catch (err) {
            logger(`${tool.name} error:`, err, err?.stack);
            const errorText = err && 'message' in err ? err.message : String(err);
            return {
                content: [
                    {
                        type: 'text',
                        text: errorText,
                    },
                ],
                isError: true,
            };
        }
        finally {
            guard.dispose();
        }
    });
}
for (const tool of tools) {
    registerTool(tool);
}
await loadIssueDescriptions();
const transport = new StdioServerTransport();
await server.connect(transport);
setServer(server);
watchClose();
logger('Chrome DevTools MCP Server connected');
logDisclaimers();
