"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.CockpitMcpServer = void 0;
const node_crypto_1 = require("node:crypto");
const node_fs_1 = require("node:fs");
const node_http_1 = require("node:http");
const node_path_1 = require("node:path");
const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
const streamableHttp_js_1 = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
const defaults_1 = require("../../server/defaults");
const job_storage_1 = require("../../server/job-storage");
const notification_settings_1 = require("../../server/notification-settings");
const paths_1 = require("../../server/paths");
const providers_1 = require("../../server/providers");
const singleton_1 = require("../../server/singleton");
const run_context_1 = require("./run-context");
const TOOL_DEFINITIONS = [
    {
        name: "list_jobs",
        description: "List all scheduled jobs",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "get_job",
        description: "Get a scheduled job by ID",
        inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
    },
    {
        name: "create_job",
        description: "Create a new scheduled job",
        inputSchema: {
            type: "object",
            properties: {
                name: { type: "string" },
                schedule: { type: "object", properties: { type: { type: "string", enum: ["simple", "cron"] } }, required: ["type"] },
                schedules: {
                    type: "array",
                    items: { type: "object" },
                    description: "Multiple schedules (use instead of schedule for multi-schedule jobs)",
                },
                prompt: { type: "string" },
                cwd: { type: "string" },
                enabled: { type: "boolean" },
                model: { type: "string" },
                contextSize: { type: "string" },
                thinkingLevel: { type: "string" },
                bypassPermissions: { type: "boolean" },
                maxDurationMinutes: { type: "number" },
                retentionDays: { type: "number" },
                skipIfMissed: { type: "boolean" },
                inboxOutput: { type: "boolean" },
                runtime: { type: "string", enum: ["stream", "pty"], description: "Execution runtime: stream (default) or pty" },
                allowedTools: { type: "array", items: { type: "string" }, description: "Tool names the job is allowed to use" },
                mcpServers: { type: "array", items: { type: "string" }, description: "MCP server names to enable for this job" },
                mcpToolFilters: { type: "object", description: 'Per-MCP-server tool filter: { serverName: ["tool1", "tool2"] }' },
                notifyProviders: { type: "array", items: { type: "string" }, description: "Notification provider IDs to alert on job completion" },
            },
            required: ["name", "schedule", "prompt", "cwd"],
        },
    },
    {
        name: "update_job",
        description: "Update an existing scheduled job",
        inputSchema: {
            type: "object",
            properties: {
                id: { type: "string" },
                name: { type: "string" },
                schedule: { type: "object", properties: { type: { type: "string", enum: ["simple", "cron"] } }, required: ["type"] },
                schedules: { type: "array", items: { type: "object" } },
                prompt: { type: "string" },
                cwd: { type: "string" },
                enabled: { type: "boolean" },
                model: { type: "string" },
                contextSize: { type: "string" },
                thinkingLevel: { type: "string" },
                bypassPermissions: { type: "boolean" },
                maxDurationMinutes: { type: "number" },
                retentionDays: { type: "number" },
                skipIfMissed: { type: "boolean" },
                inboxOutput: { type: "boolean" },
                runtime: { type: "string", enum: ["stream", "pty"] },
                allowedTools: { type: "array", items: { type: "string" } },
                mcpServers: { type: "array", items: { type: "string" } },
                mcpToolFilters: { type: "object" },
                notifyProviders: { type: "array", items: { type: "string" } },
                updates: { type: "array", items: { type: "object" } },
            },
        },
    },
    {
        name: "delete_job",
        description: "Delete a scheduled job by ID",
        inputSchema: {
            type: "object",
            properties: { id: { type: "string" }, ids: { type: "array", items: { type: "string" } } },
        },
    },
    {
        name: "get_settings",
        description: "Get current application settings",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "update_settings",
        description: "Update application settings",
        inputSchema: {
            type: "object",
            properties: {
                thinkingLevel: { type: "string", enum: ["low", "medium", "high", "xhigh", "max"] },
                diffStyle: { type: "string", enum: ["split", "unified"] },
                dismissKeyboardOnSend: { type: "boolean" },
                thinkingExpanded: { type: "boolean" },
                readExpanded: { type: "boolean" },
                editExpanded: { type: "boolean" },
                toolCallsExpanded: { type: "boolean" },
                messageStitching: { type: "boolean" },
                reviewsEnabled: { type: "boolean" },
                bypassAllPermissions: { type: "boolean" },
                modelSlots: {
                    type: "object",
                    properties: {
                        main: { type: "string", description: "Model ID (e.g. claude-sonnet-4-5, claude-opus-4-5, claude-haiku-4-5)" },
                        mainContext: { type: "string", enum: ["50k", "100k", "200k"], description: "Context window size" },
                    },
                },
            },
        },
    },
    {
        name: "list_providers",
        description: "List all model providers",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "add_provider",
        description: "Add a new model provider",
        inputSchema: { type: "object", properties: { name: { type: "string" }, envVars: { type: "object" } }, required: ["name", "envVars"] },
    },
    {
        name: "update_provider",
        description: "Update an existing model provider",
        inputSchema: {
            type: "object",
            properties: {
                id: { type: "string" },
                name: { type: "string" },
                envVars: { type: "object" },
            },
            required: ["id"],
        },
    },
    {
        name: "delete_provider",
        description: "Delete a model provider by ID",
        inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
    },
    {
        name: "list_mcp_servers",
        description: "List all configured MCP servers from ~/.claude.json",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "get_mcp_server",
        description: "Get an MCP server configuration by name",
        inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
    },
    {
        name: "save_mcp_server",
        description: "Create or update an MCP server configuration",
        inputSchema: {
            type: "object",
            properties: { name: { type: "string" }, command: { type: "string" }, args: { type: "array", items: { type: "string" } } },
            required: ["name", "command", "args"],
        },
    },
    {
        name: "delete_mcp_server",
        description: "Delete an MCP server configuration by name",
        inputSchema: { type: "object", properties: { name: { type: "string" } }, required: ["name"] },
    },
    {
        name: "get_notification_settings",
        description: "Get current notification settings",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "update_notification_settings",
        description: "Update notification settings",
        inputSchema: {
            type: "object",
            properties: {
                baseUrl: { type: "string", description: "Webhook URL for notifications" },
            },
        },
    },
    {
        name: "list_notification_providers",
        description: "List all notification providers",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
    {
        name: "add_notification_provider",
        description: "Add a notification provider (telegram or ntfy)",
        inputSchema: {
            type: "object",
            properties: {
                type: { type: "string", enum: ["telegram", "ntfy"] },
                name: { type: "string" },
                enabled: { type: "boolean" },
                config: { type: "object", description: "For telegram: {botToken, chatId}. For ntfy: {serverUrl, topic, token?}" },
                filterPriorities: { type: "array", items: { type: "string", enum: ["info", "warning", "error"] } },
            },
            required: ["type", "name", "config"],
        },
    },
    {
        name: "update_notification_provider",
        description: "Update an existing notification provider by ID",
        inputSchema: {
            type: "object",
            properties: {
                id: { type: "string" },
                name: { type: "string" },
                enabled: { type: "boolean" },
                config: { type: "object" },
                filterPriorities: { type: "array", items: { type: "string", enum: ["info", "warning", "error"] } },
            },
            required: ["id"],
        },
    },
    {
        name: "delete_notification_provider",
        description: "Delete a notification provider by ID",
        inputSchema: { type: "object", properties: { id: { type: "string" } }, required: ["id"] },
    },
    {
        name: "run_job",
        description: "Trigger one or more scheduled jobs to run immediately, regardless of their enabled state; returns as soon as the run is queued and does not wait for completion",
        inputSchema: { type: "object", properties: { id: { type: "string" }, ids: { type: "array", items: { type: "string" } } } },
    },
    {
        name: "stop_job",
        description: "Stop a currently running scheduled job by ID",
        inputSchema: {
            type: "object",
            properties: { id: { type: "string" } },
            required: ["id"],
        },
    },
    {
        name: "list_running_jobs",
        description: "List scheduled jobs that are currently running",
        inputSchema: { type: "object", properties: {}, required: [] },
    },
];
function readClaudeConfig() {
    try {
        return JSON.parse((0, node_fs_1.readFileSync)((0, paths_1.getClaudeUserConfigFile)(), "utf-8"));
    }
    catch {
        return { mcpServers: {} };
    }
}
function writeClaudeConfig(data) {
    const file = (0, paths_1.getClaudeUserConfigFile)();
    (0, node_fs_1.mkdirSync)((0, node_path_1.dirname)(file), { recursive: true });
    (0, node_fs_1.writeFileSync)(file, JSON.stringify(data, null, 2) + "\n");
}
function handleToolCall(name, args, _token) {
    try {
        switch (name) {
            case "list_jobs":
                return { content: [{ type: "text", text: JSON.stringify((0, job_storage_1.loadJobs)(), null, 2) }] };
            case "get_job": {
                const job = (0, job_storage_1.getJob)(args.id);
                if (!job)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Job not found: ${args.id}` }) }], isError: true };
                return { content: [{ type: "text", text: JSON.stringify(job, null, 2) }] };
            }
            case "create_job": {
                const now = Date.now();
                const job = {
                    id: (0, node_crypto_1.randomUUID)(),
                    name: args.name,
                    schedule: args.schedule,
                    prompt: args.prompt,
                    cwd: args.cwd,
                    enabled: args.enabled ?? true,
                    createdAt: now,
                    updatedAt: now,
                };
                (0, job_storage_1.saveJob)(job);
                return { content: [{ type: "text", text: JSON.stringify({ created: job }, null, 2) }] };
            }
            case "update_job": {
                if (Array.isArray(args.updates)) {
                    const results = args.updates.map((entry) => {
                        const id = entry.id;
                        const existing = (0, job_storage_1.getJob)(id);
                        if (!existing)
                            return { id, error: `Job not found: ${id}` };
                        const before = { ...existing };
                        const update = { ...entry };
                        delete update.id;
                        const updated = { ...existing, ...update, updatedAt: Date.now() };
                        (0, job_storage_1.saveJob)(updated);
                        return { id, before, after: updated };
                    });
                    return { content: [{ type: "text", text: JSON.stringify({ results }, null, 2) }] };
                }
                if (!args.id) {
                    return { content: [{ type: "text", text: JSON.stringify({ error: "missing id or updates" }) }], isError: true };
                }
                const existing = (0, job_storage_1.getJob)(args.id);
                if (!existing)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Job not found: ${args.id}` }) }], isError: true };
                const before = { ...existing };
                const update = { ...args };
                delete update.id;
                const updated = { ...existing, ...update, updatedAt: Date.now() };
                (0, job_storage_1.saveJob)(updated);
                return { content: [{ type: "text", text: JSON.stringify({ before, after: updated }, null, 2) }] };
            }
            case "delete_job": {
                if (Array.isArray(args.ids)) {
                    const results = args.ids.map((id) => {
                        const job = (0, job_storage_1.getJob)(id);
                        if (!job)
                            return { id, error: `Job not found: ${id}` };
                        (0, job_storage_1.deleteJob)(id);
                        return { id, deleted: true };
                    });
                    return { content: [{ type: "text", text: JSON.stringify({ results }, null, 2) }] };
                }
                const job = (0, job_storage_1.getJob)(args.id);
                if (!job)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Job not found: ${args.id}` }) }], isError: true };
                (0, job_storage_1.deleteJob)(args.id);
                return { content: [{ type: "text", text: JSON.stringify({ deleted: job }, null, 2) }] };
            }
            case "get_settings":
                return { content: [{ type: "text", text: JSON.stringify((0, defaults_1.getDefaults)(), null, 2) }] };
            case "update_settings": {
                const before = (0, defaults_1.getDefaults)();
                const allowed = [
                    "thinkingLevel",
                    "diffStyle",
                    "dismissKeyboardOnSend",
                    "thinkingExpanded",
                    "readExpanded",
                    "editExpanded",
                    "toolCallsExpanded",
                    "messageStitching",
                    "reviewsEnabled",
                    "bypassAllPermissions",
                    "modelSlots",
                ];
                const safe = Object.fromEntries(Object.entries(args).filter(([k]) => allowed.includes(k)));
                const after = (0, defaults_1.setDefaults)(safe);
                return { content: [{ type: "text", text: JSON.stringify({ before, after }, null, 2) }] };
            }
            case "list_providers":
                return { content: [{ type: "text", text: JSON.stringify((0, providers_1.getProviders)(), null, 2) }] };
            case "add_provider": {
                const provider = (0, providers_1.addProvider)({
                    name: args.name,
                    envVars: args.envVars,
                    models: [],
                });
                return { content: [{ type: "text", text: JSON.stringify({ created: provider }, null, 2) }] };
            }
            case "update_provider": {
                const { id, ...rest } = args;
                const before = (0, providers_1.getProviders)().find((p) => p.id === id);
                if (!before)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Provider not found: ${id}` }) }], isError: true };
                const after = (0, providers_1.updateProvider)(id, rest);
                return { content: [{ type: "text", text: JSON.stringify({ before, after }, null, 2) }] };
            }
            case "delete_provider": {
                const provider = (0, providers_1.getProviders)().find((p) => p.id === args.id);
                if (!provider)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Provider not found: ${args.id}` }) }], isError: true };
                (0, providers_1.deleteProvider)(args.id);
                return { content: [{ type: "text", text: JSON.stringify({ deleted: provider }, null, 2) }] };
            }
            case "list_mcp_servers": {
                const config = readClaudeConfig();
                const entries = Object.entries(config.mcpServers ?? {}).map(([n, c]) => ({ name: n, ...c }));
                return { content: [{ type: "text", text: JSON.stringify(entries, null, 2) }] };
            }
            case "get_mcp_server": {
                const config = readClaudeConfig();
                const entry = config.mcpServers?.[args.name];
                if (!entry)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `MCP server not found: ${args.name}` }) }], isError: true };
                return { content: [{ type: "text", text: JSON.stringify({ name: args.name, ...entry }, null, 2) }] };
            }
            case "save_mcp_server": {
                const config = readClaudeConfig();
                const servers = config.mcpServers ?? {};
                const before = servers[args.name] ? { ...servers[args.name] } : null;
                servers[args.name] = {
                    command: args.command,
                    args: args.args,
                    env: args.env,
                };
                writeClaudeConfig({ ...config, mcpServers: servers });
                return { content: [{ type: "text", text: JSON.stringify({ before, after: servers[args.name] }, null, 2) }] };
            }
            case "delete_mcp_server": {
                const config = readClaudeConfig();
                const servers = config.mcpServers ?? {};
                if (!servers[args.name])
                    return { content: [{ type: "text", text: JSON.stringify({ error: `MCP server not found: ${args.name}` }) }], isError: true };
                const deleted = servers[args.name];
                delete servers[args.name];
                writeClaudeConfig({ ...config, mcpServers: servers });
                return { content: [{ type: "text", text: JSON.stringify({ deleted }, null, 2) }] };
            }
            case "get_notification_settings":
                return { content: [{ type: "text", text: JSON.stringify((0, notification_settings_1.getNotificationSettings)(), null, 2) }] };
            case "update_notification_settings": {
                const before = (0, notification_settings_1.getNotificationSettings)();
                const after = (0, notification_settings_1.updateNotificationSettings)(args);
                return { content: [{ type: "text", text: JSON.stringify({ before, after }, null, 2) }] };
            }
            case "list_notification_providers": {
                const settings = (0, notification_settings_1.getNotificationSettings)();
                return { content: [{ type: "text", text: JSON.stringify(settings.providers, null, 2) }] };
            }
            case "add_notification_provider": {
                const settings = (0, notification_settings_1.getNotificationSettings)();
                const entry = {
                    id: (0, node_crypto_1.randomUUID)(),
                    type: args.type,
                    name: args.name,
                    enabled: args.enabled ?? true,
                    config: args.config,
                    filter: Array.isArray(args.filterPriorities) && args.filterPriorities.length > 0
                        ? { priorities: args.filterPriorities }
                        : undefined,
                };
                const after = (0, notification_settings_1.setNotificationSettings)({ ...settings, providers: [...settings.providers, entry] });
                return { content: [{ type: "text", text: JSON.stringify({ created: entry, providers: after.providers }, null, 2) }] };
            }
            case "update_notification_provider": {
                const settings = (0, notification_settings_1.getNotificationSettings)();
                const idx = settings.providers.findIndex((p) => p.id === args.id);
                if (idx === -1)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Provider not found: ${args.id}` }) }], isError: true };
                const before = settings.providers[idx];
                const updated = {
                    ...before,
                    ...(args.name !== undefined ? { name: args.name } : {}),
                    ...(args.enabled !== undefined ? { enabled: args.enabled } : {}),
                    ...(args.config !== undefined ? { config: args.config } : {}),
                    ...(Array.isArray(args.filterPriorities)
                        ? {
                            filter: args.filterPriorities.length > 0
                                ? { ...before.filter, priorities: args.filterPriorities }
                                : before.filter?.sources?.length
                                    ? { ...before.filter, priorities: undefined }
                                    : undefined,
                        }
                        : {}),
                };
                const providers = [...settings.providers];
                providers[idx] = updated;
                const after = (0, notification_settings_1.setNotificationSettings)({ ...settings, providers });
                return { content: [{ type: "text", text: JSON.stringify({ before, after: after.providers[idx] }, null, 2) }] };
            }
            case "delete_notification_provider": {
                const settings = (0, notification_settings_1.getNotificationSettings)();
                const provider = settings.providers.find((p) => p.id === args.id);
                if (!provider)
                    return { content: [{ type: "text", text: JSON.stringify({ error: `Provider not found: ${args.id}` }) }], isError: true };
                const after = (0, notification_settings_1.setNotificationSettings)({ ...settings, providers: settings.providers.filter((p) => p.id !== args.id) });
                return { content: [{ type: "text", text: JSON.stringify({ deleted: provider, providers: after.providers }, null, 2) }] };
            }
            case "run_job": {
                const ids = Array.isArray(args.ids) ? args.ids : args.id ? [args.id] : [];
                if (ids.length === 0) {
                    return { content: [{ type: "text", text: JSON.stringify({ error: "no job id provided" }) }], isError: true };
                }
                const scheduler = (0, singleton_1.getJobScheduler)();
                if (!scheduler) {
                    return {
                        content: [{ type: "text", text: JSON.stringify({ results: ids.map((id) => ({ id, status: "scheduler not available" })) }) }],
                    };
                }
                const running = scheduler.getRunningJobs();
                const jobs = (0, job_storage_1.loadJobs)();
                const results = ids.map((id) => {
                    const job = jobs.find((j) => j.id === id);
                    if (!job)
                        return { id, status: "not_found" };
                    if (running.has(id))
                        return { id, name: job.name, status: "already_running" };
                    void scheduler.triggerJob(id).catch((err) => console.error("[cockpit-mcp] run_job", id, err));
                    return { id, name: job.name, status: "started" };
                });
                return { content: [{ type: "text", text: JSON.stringify({ results }, null, 2) }] };
            }
            case "stop_job": {
                const jobId = args.id;
                if (!jobId) {
                    return { content: [{ type: "text", text: JSON.stringify({ error: "no job id provided" }) }], isError: true };
                }
                const scheduler = (0, singleton_1.getJobScheduler)();
                if (!scheduler) {
                    return { content: [{ type: "text", text: JSON.stringify({ error: "scheduler not available" }) }], isError: true };
                }
                try {
                    const run = scheduler.stopJob(jobId);
                    const jobs = (0, job_storage_1.loadJobs)();
                    const nameMap = new Map(jobs.map((j) => [j.id, j.name]));
                    return {
                        content: [
                            {
                                type: "text",
                                text: JSON.stringify({
                                    jobId: run.jobId,
                                    name: nameMap.get(run.jobId) ?? "unknown",
                                    runId: run.id,
                                    status: run.status,
                                    startedAt: run.startedAt,
                                    elapsedMs: run.durationMs ?? Date.now() - run.startedAt,
                                    messageCount: run.messageCount,
                                    toolCount: run.toolsUsed.length,
                                }, null, 2),
                            },
                        ],
                    };
                }
                catch (err) {
                    return {
                        content: [{ type: "text", text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }) }],
                        isError: true,
                    };
                }
            }
            case "list_running_jobs": {
                const scheduler = (0, singleton_1.getJobScheduler)();
                if (!scheduler) {
                    return { content: [{ type: "text", text: JSON.stringify({ running: [], count: 0, note: "scheduler not available" }) }] };
                }
                const jobs = (0, job_storage_1.loadJobs)();
                const nameMap = new Map(jobs.map((j) => [j.id, j.name]));
                const running = Array.from(scheduler.getRunningJobs().values()).map((r) => ({
                    jobId: r.jobId,
                    name: nameMap.get(r.jobId) ?? "unknown",
                    runId: r.id,
                    sessionId: r.sessionId,
                    status: r.status,
                    startedAt: r.startedAt,
                    elapsedMs: Date.now() - r.startedAt,
                    messageCount: r.messageCount,
                    toolCount: r.toolsUsed.length,
                }));
                return { content: [{ type: "text", text: JSON.stringify({ running, count: running.length }, null, 2) }] };
            }
            default:
                return { content: [{ type: "text", text: JSON.stringify({ error: `Unknown tool: ${name}` }) }], isError: true };
        }
    }
    catch (err) {
        return {
            content: [{ type: "text", text: JSON.stringify({ error: err instanceof Error ? err.message : String(err) }) }],
            isError: true,
        };
    }
}
class CockpitMcpServer {
    httpServer = null;
    port = 0;
    async start(host = "127.0.0.1", port = 0) {
        this.httpServer = (0, node_http_1.createServer)((req, res) => {
            (async () => {
                if (req.url !== "/mcp" || req.method !== "POST") {
                    res.writeHead(404, { "Content-Type": "application/json" });
                    res.end(JSON.stringify({ error: "not found" }));
                    return;
                }
                const authHeader = req.headers.authorization ?? "";
                const token = authHeader.startsWith("Bearer ") ? authHeader.slice(7) : "";
                if (!(0, run_context_1.isValidToken)(token)) {
                    res.writeHead(401, { "Content-Type": "application/json" });
                    res.end(JSON.stringify({ error: "unauthorized" }));
                    return;
                }
                const transport = new streamableHttp_js_1.StreamableHTTPServerTransport({ sessionIdGenerator: undefined });
                const mcpServer = new index_js_1.Server({ name: "cockpit-config", version: "1.0.0" }, { capabilities: { tools: {} } });
                mcpServer.setRequestHandler(types_js_1.ListToolsRequestSchema, async () => ({ tools: TOOL_DEFINITIONS }));
                mcpServer.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
                    const toolName = request.params.name;
                    const toolArgs = request.params.arguments ?? {};
                    return handleToolCall(toolName, toolArgs, token);
                });
                await mcpServer.connect(transport);
                await transport.handleRequest(req, res);
            })().catch((err) => {
                console.error("[cockpit-mcp] request handler error:", err);
                if (!res.writableEnded) {
                    res.writeHead(500, { "Content-Type": "application/json" });
                    res.end(JSON.stringify({ error: "internal error" }));
                }
            });
        });
        await new Promise((resolve, reject) => {
            this.httpServer.once("error", reject);
            this.httpServer.listen(port, host, () => {
                const addr = this.httpServer.address();
                if (addr && typeof addr === "object")
                    this.port = addr.port;
                resolve();
            });
        });
    }
    getUrl(host = "127.0.0.1") {
        return `http://${host}:${this.port}`;
    }
    async stop() {
        if (!this.httpServer)
            return;
        await new Promise((resolve) => this.httpServer.close(() => resolve()));
        this.httpServer = null;
    }
}
exports.CockpitMcpServer = CockpitMcpServer;
