import { randomUUID } from 'crypto';
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
import { CallToolRequestSchema, ErrorCode, ListToolsRequestSchema, McpError, } from '@modelcontextprotocol/sdk/types.js';
import { daemonRequest, ensureDaemonReady, } from './client.js';
async function withDaemonRetry(workspace, daemonRef, options, operation) {
    try {
        return await operation(daemonRef.current);
    }
    catch {
        daemonRef.current = await ensureDaemonReady(workspace, {
            entrypoint: options.entrypoint,
            timeoutMs: options.timeoutMs,
        });
        return operation(daemonRef.current);
    }
}
export async function startDaemonBackedMcpProxy(workspace, options = {}) {
    const daemonRef = {
        current: await ensureDaemonReady(workspace, {
            entrypoint: options.entrypoint,
            timeoutMs: options.timeoutMs,
        }),
    };
    const sessionId = randomUUID();
    const server = new Server({ name: 'nexus-prime-mcp-proxy', version: '0.1.0' }, { capabilities: { tools: {} } });
    server.setRequestHandler(ListToolsRequestSchema, async () => {
        const payload = await withDaemonRetry(workspace, daemonRef, options, (record) => daemonRequest(record, '/rpc/list-tools', { sessionId }));
        return {
            tools: payload.tools,
        };
    });
    server.setRequestHandler(CallToolRequestSchema, async (request) => {
        const payload = await withDaemonRetry(workspace, daemonRef, options, (record) => daemonRequest(record, '/rpc/call-tool', {
            sessionId,
            name: request.params?.name,
            arguments: request.params?.arguments ?? {},
        }));
        if (payload.queued) {
            return {
                content: [{
                        type: 'text',
                        text: JSON.stringify({
                            queued: true,
                            runId: payload.runId,
                        }, null, 2),
                    }],
            };
        }
        if (!payload.result) {
            throw new McpError(ErrorCode.InternalError, 'Daemon returned an empty MCP payload.');
        }
        return payload.result;
    });
    const transport = new StdioServerTransport();
    await server.connect(transport);
    const shutdown = async () => {
        await server.close();
    };
    process.on('SIGINT', () => {
        void shutdown();
    });
    process.on('SIGTERM', () => {
        void shutdown();
    });
}
