"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.McpServerService = void 0;
const zod_1 = require("zod");
const mcp_js_1 = require("@modelcontextprotocol/sdk/server/mcp.js");
const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
const McpWebsocketTransport_1 = require("./McpWebsocketTransport");
class McpServerService {
    toolsService;
    server = null;
    constructor(toolsService) {
        this.toolsService = toolsService;
    }
    registeredTools = new Set();
    serverConfig = null;
    createServer(name, version) {
        if (this.server) {
            return this;
        }
        this.server = new mcp_js_1.McpServer({
            name,
            version,
        });
        this.serverConfig = { name, version };
        return this;
    }
    toZodSchema(properties, required) {
        const schema = {};
        for (const [key, value] of Object.entries(properties)) {
            if (value.type === "string") {
                schema[key] = zod_1.z.string();
            }
            else if (value.type === "number") {
                schema[key] = zod_1.z.number();
            }
            else if (value.type === "boolean") {
                schema[key] = zod_1.z.boolean();
            }
            else if (value.type === "array" && value?.items?.properties) {
                schema[key] = zod_1.z.array(this.toZodSchema(value.items.properties, required));
            }
            else if (value.type === "object" && value.properties) {
                schema[key] = this.toZodSchema(value.properties, required);
            }
            else {
                schema[key] = zod_1.z.any();
            }
            if (required && !required.includes(key)) {
                schema[key] = schema[key].optional();
            }
        }
        return zod_1.z.object(schema);
    }
    withTools(tools) {
        for (const tool of tools) {
            const props = tool.function.parameters.properties;
            const required = tool.function.parameters.required;
            if (!props) {
                console.warn(`Tool ${tool.function.name} has no properties`);
                continue;
            }
            if (this.registeredTools.has(tool.function.name)) {
                console.log(`Tool ${tool.function.name} already registered`);
                continue;
            }
            console.log(`Registering tool ${tool.function.name}`);
            this.registeredTools.add(tool.function.name);
            const shape = this.toZodSchema(props, required).shape;
            this.server.tool(tool.function.name, tool.function.description, shape, async (args, extra) => {
                const fn = this.toolsService.getFunction(tool.function.name);
                let response = "";
                if (tool.function.parameters.positional) {
                    response = await fn(...Object.values(args));
                }
                else {
                    response = await fn(args);
                }
                if (response && typeof response === "object" && response.content) {
                    return response;
                }
                return {
                    content: [
                        {
                            type: "text",
                            text: typeof response === "string"
                                ? response
                                : JSON.stringify(response),
                        },
                    ],
                };
            });
        }
        return this;
    }
    createServerWithAllTools(name, version) {
        return this.createServer(name, version).withTools(this.toolsService.getTools());
    }
    async reset() {
        if (this.server) {
            try {
                await this.server.close();
            }
            catch (err) {
                console.warn("McpServerService: error closing server during reset:", err);
            }
            this.server = null;
        }
        this.registeredTools = new Set();
        if (this.serverConfig) {
            this.server = new mcp_js_1.McpServer({
                name: this.serverConfig.name,
                version: this.serverConfig.version,
            });
        }
    }
    async runStdioServer() {
        const transport = new stdio_js_1.StdioServerTransport();
        await this.server.connect(transport);
        console.error(`MCP Server running on stdio`);
    }
    async runWsServer(ws) {
        const transport = new McpWebsocketTransport_1.MCPWebSocketTransport(ws);
        await this.server.connect(transport);
        console.error(`MCP Server running on websocket`);
    }
}
exports.McpServerService = McpServerService;
//# sourceMappingURL=McpServer.js.map