"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.McpService = void 0;
const backend_common_1 = require("@n8n/backend-common");
const config_1 = require("@n8n/config");
const db_1 = require("@n8n/db");
const di_1 = require("@n8n/di");
const n8n_core_1 = require("n8n-core");
const n8n_workflow_1 = require("n8n-workflow");
const data_table_1 = require("./tools/data-table");
const execute_workflow_tool_1 = require("./tools/execute-workflow.tool");
const get_execution_tool_1 = require("./tools/get-execution.tool");
const get_workflow_details_tool_1 = require("./tools/get-workflow-details.tool");
const publish_workflow_tool_1 = require("./tools/publish-workflow.tool");
const search_folders_tool_1 = require("./tools/search-folders.tool");
const search_projects_tool_1 = require("./tools/search-projects.tool");
const search_workflows_tool_1 = require("./tools/search-workflows.tool");
const unpublish_workflow_tool_1 = require("./tools/unpublish-workflow.tool");
const create_workflow_from_code_tool_1 = require("./tools/workflow-builder/create-workflow-from-code.tool");
const delete_workflow_tool_1 = require("./tools/workflow-builder/delete-workflow.tool");
const update_workflow_tool_1 = require("./tools/workflow-builder/update-workflow.tool");
const get_suggested_workflow_nodes_tool_1 = require("./tools/workflow-builder/get-suggested-workflow-nodes.tool");
const get_workflow_node_types_tool_1 = require("./tools/workflow-builder/get-workflow-node-types.tool");
const get_workflow_sdk_reference_tool_1 = require("./tools/workflow-builder/get-workflow-sdk-reference.tool");
const mcp_instructions_1 = require("./tools/workflow-builder/mcp-instructions");
const search_workflow_nodes_tool_1 = require("./tools/workflow-builder/search-workflow-nodes.tool");
const sdk_reference_content_1 = require("./tools/workflow-builder/sdk-reference-content");
const validate_workflow_code_tool_1 = require("./tools/workflow-builder/validate-workflow-code.tool");
const workflow_builder_tools_service_1 = require("./tools/workflow-builder/workflow-builder-tools.service");
const active_executions_1 = require("../../active-executions");
const credentials_service_1 = require("../../credentials/credentials.service");
const data_table_proxy_service_1 = require("../../modules/data-table/data-table-proxy.service");
const node_types_1 = require("../../node-types");
const project_service_ee_1 = require("../../services/project.service.ee");
const role_service_1 = require("../../services/role.service");
const url_service_1 = require("../../services/url.service");
const telemetry_1 = require("../../telemetry");
const workflow_runner_1 = require("../../workflow-runner");
const workflow_creation_service_1 = require("../../workflows/workflow-creation.service");
const workflow_finder_service_1 = require("../../workflows/workflow-finder.service");
const workflow_service_1 = require("../../workflows/workflow.service");
const prepare_workflow_pin_data_tool_1 = require("./tools/prepare-workflow-pin-data.tool");
const test_workflow_tool_1 = require("./tools/test-workflow.tool");
const execution_service_1 = require("../../executions/execution.service");
let McpService = class McpService {
    constructor(logger, executionsConfig, _instanceSettings, workflowFinderService, workflowService, urlService, credentialsService, activeExecutions, globalConfig, telemetry, workflowRunner, roleService, projectService, workflowBuilderToolsService, workflowCreationService, nodeTypes, projectRepository, folderRepository, sharedWorkflowRepository, executionRepository, executionService, dataTableProxyService) {
        this.logger = logger;
        this.executionsConfig = executionsConfig;
        this.workflowFinderService = workflowFinderService;
        this.workflowService = workflowService;
        this.urlService = urlService;
        this.credentialsService = credentialsService;
        this.activeExecutions = activeExecutions;
        this.globalConfig = globalConfig;
        this.telemetry = telemetry;
        this.workflowRunner = workflowRunner;
        this.roleService = roleService;
        this.projectService = projectService;
        this.workflowBuilderToolsService = workflowBuilderToolsService;
        this.workflowCreationService = workflowCreationService;
        this.nodeTypes = nodeTypes;
        this.projectRepository = projectRepository;
        this.folderRepository = folderRepository;
        this.sharedWorkflowRepository = sharedWorkflowRepository;
        this.executionRepository = executionRepository;
        this.executionService = executionService;
        this.dataTableProxyService = dataTableProxyService;
        this.pendingResponses = new Map();
    }
    async getServer(user) {
        const { McpServer } = await Promise.resolve().then(() => __importStar(require('@modelcontextprotocol/sdk/server/mcp.js')));
        const builderEnabled = this.globalConfig.endpoints.mcpBuilderEnabled;
        const server = new McpServer({
            name: 'n8n MCP Server',
            version: builderEnabled ? '1.1.0' : '1.0.0',
        }, {
            instructions: (0, mcp_instructions_1.getMcpInstructions)(builderEnabled),
        });
        const workflowSearchTool = (0, search_workflows_tool_1.createSearchWorkflowsTool)(user, this.workflowService, this.telemetry);
        server.registerTool(workflowSearchTool.name, workflowSearchTool.config, workflowSearchTool.handler);
        const executeWorkflowTool = (0, execute_workflow_tool_1.createExecuteWorkflowTool)(user, this.workflowFinderService, this.workflowRunner, this.telemetry, this);
        server.registerTool(executeWorkflowTool.name, executeWorkflowTool.config, executeWorkflowTool.handler);
        const getExecutionTool = (0, get_execution_tool_1.createGetExecutionTool)(user, this.executionRepository, this.workflowFinderService, this.telemetry);
        server.registerTool(getExecutionTool.name, getExecutionTool.config, getExecutionTool.handler);
        const workflowDetailsTool = (0, get_workflow_details_tool_1.createWorkflowDetailsTool)(user, this.urlService.getWebhookBaseUrl(), this.workflowFinderService, this.credentialsService, {
            webhook: this.globalConfig.endpoints.webhook,
            webhookTest: this.globalConfig.endpoints.webhookTest,
        }, this.telemetry, this.roleService, this.projectService);
        server.registerTool(workflowDetailsTool.name, workflowDetailsTool.config, workflowDetailsTool.handler);
        const publishWorkflowTool = (0, publish_workflow_tool_1.createPublishWorkflowTool)(user, this.workflowFinderService, this.workflowService, this.telemetry);
        server.registerTool(publishWorkflowTool.name, publishWorkflowTool.config, publishWorkflowTool.handler);
        const unpublishWorkflowTool = (0, unpublish_workflow_tool_1.createUnpublishWorkflowTool)(user, this.workflowFinderService, this.workflowService, this.telemetry);
        server.registerTool(unpublishWorkflowTool.name, unpublishWorkflowTool.config, unpublishWorkflowTool.handler);
        const prepareTestPinDataTool = (0, prepare_workflow_pin_data_tool_1.createPrepareTestPinDataTool)(user, this.workflowFinderService, this.executionService, this.nodeTypes, this.telemetry, this.logger);
        server.registerTool(prepareTestPinDataTool.name, prepareTestPinDataTool.config, prepareTestPinDataTool.handler);
        const testWorkflowTool = (0, test_workflow_tool_1.createTestWorkflowTool)(user, this.workflowFinderService, this.activeExecutions, this.workflowRunner, this.nodeTypes, this.telemetry, this);
        server.registerTool(testWorkflowTool.name, testWorkflowTool.config, testWorkflowTool.handler);
        const dataTableOps = this.dataTableProxyService.makeDataTableOperationsForUser(user);
        const searchDataTablesTool = (0, data_table_1.createSearchDataTablesTool)(user, dataTableOps, this.telemetry);
        server.registerTool(searchDataTablesTool.name, searchDataTablesTool.config, searchDataTablesTool.handler);
        const createDataTableTool = (0, data_table_1.createCreateDataTableTool)(user, dataTableOps, this.telemetry);
        server.registerTool(createDataTableTool.name, createDataTableTool.config, createDataTableTool.handler);
        const renameDataTableTool = (0, data_table_1.createRenameDataTableTool)(user, dataTableOps, this.telemetry);
        server.registerTool(renameDataTableTool.name, renameDataTableTool.config, renameDataTableTool.handler);
        const addDataTableColumnTool = (0, data_table_1.createAddDataTableColumnTool)(user, dataTableOps, this.telemetry);
        server.registerTool(addDataTableColumnTool.name, addDataTableColumnTool.config, addDataTableColumnTool.handler);
        const deleteDataTableColumnTool = (0, data_table_1.createDeleteDataTableColumnTool)(user, dataTableOps, this.telemetry);
        server.registerTool(deleteDataTableColumnTool.name, deleteDataTableColumnTool.config, deleteDataTableColumnTool.handler);
        const renameDataTableColumnTool = (0, data_table_1.createRenameDataTableColumnTool)(user, dataTableOps, this.telemetry);
        server.registerTool(renameDataTableColumnTool.name, renameDataTableColumnTool.config, renameDataTableColumnTool.handler);
        const addDataTableRowsTool = (0, data_table_1.createAddDataTableRowsTool)(user, dataTableOps, this.telemetry);
        server.registerTool(addDataTableRowsTool.name, addDataTableRowsTool.config, addDataTableRowsTool.handler);
        if (builderEnabled) {
            await this.registerBuilderTools(server, user);
        }
        return server;
    }
    async registerBuilderTools(server, user) {
        await this.workflowBuilderToolsService.initialize();
        const searchNodesTool = (0, search_workflow_nodes_tool_1.createSearchWorkflowNodesTool)(user, this.workflowBuilderToolsService, this.telemetry);
        server.registerTool(searchNodesTool.name, searchNodesTool.config, searchNodesTool.handler);
        const getNodeTypesTool = (0, get_workflow_node_types_tool_1.createGetWorkflowNodeTypesTool)(user, this.workflowBuilderToolsService, this.telemetry);
        server.registerTool(getNodeTypesTool.name, getNodeTypesTool.config, getNodeTypesTool.handler);
        const suggestedNodesTool = (0, get_suggested_workflow_nodes_tool_1.createGetSuggestedWorkflowNodesTool)(user, this.workflowBuilderToolsService, this.telemetry);
        server.registerTool(suggestedNodesTool.name, suggestedNodesTool.config, suggestedNodesTool.handler);
        const validateTool = (0, validate_workflow_code_tool_1.createValidateWorkflowCodeTool)(user, this.telemetry);
        server.registerTool(validateTool.name, validateTool.config, validateTool.handler);
        const createTool = (0, create_workflow_from_code_tool_1.createCreateWorkflowFromCodeTool)(user, this.workflowCreationService, this.urlService, this.telemetry, this.nodeTypes, this.credentialsService, this.projectRepository);
        server.registerTool(createTool.name, createTool.config, createTool.handler);
        const searchProjectsTool = (0, search_projects_tool_1.createSearchProjectsTool)(user, this.projectRepository, this.telemetry);
        server.registerTool(searchProjectsTool.name, searchProjectsTool.config, searchProjectsTool.handler);
        const searchFoldersTool = (0, search_folders_tool_1.createSearchFoldersTool)(user, this.folderRepository, this.projectService, this.telemetry);
        server.registerTool(searchFoldersTool.name, searchFoldersTool.config, searchFoldersTool.handler);
        const archiveTool = (0, delete_workflow_tool_1.createArchiveWorkflowTool)(user, this.workflowService, this.telemetry);
        server.registerTool(archiveTool.name, archiveTool.config, archiveTool.handler);
        const updateTool = (0, update_workflow_tool_1.createUpdateWorkflowTool)(user, this.workflowFinderService, this.workflowService, this.urlService, this.telemetry, this.nodeTypes, this.credentialsService, this.sharedWorkflowRepository);
        server.registerTool(updateTool.name, updateTool.config, updateTool.handler);
        server.resource('workflow-sdk-reference', 'n8n://workflow-sdk/reference', {
            description: 'n8n Workflow SDK reference — patterns, expressions, and rules for building workflows. Get this FIRST before building workflows to learn the SDK.',
        }, async () => ({
            contents: [
                {
                    uri: 'n8n://workflow-sdk/reference',
                    mimeType: 'text/plain',
                    text: (0, sdk_reference_content_1.getSdkReferenceContent)(),
                },
            ],
        }));
        const sdkRefTool = (0, get_workflow_sdk_reference_tool_1.createGetWorkflowSdkReferenceTool)(user, this.telemetry);
        server.registerTool(sdkRefTool.name, sdkRefTool.config, sdkRefTool.handler);
    }
    get isQueueMode() {
        return this.executionsConfig.mode === 'queue';
    }
    createPendingResponse(executionId) {
        const deferred = (0, n8n_workflow_1.createDeferredPromise)();
        this.pendingResponses.set(executionId, {
            executionId,
            promise: deferred,
            createdAt: new Date(),
        });
        return deferred;
    }
    handleWorkerResponse(executionId, runData) {
        const pending = this.pendingResponses.get(executionId);
        if (!pending) {
            this.logger.warn('Received MCP response for unknown execution', { executionId });
            return;
        }
        pending.promise.resolve(runData);
        this.pendingResponses.delete(executionId);
    }
    removePendingResponse(executionId) {
        if (this.pendingResponses.has(executionId)) {
            this.pendingResponses.delete(executionId);
            this.logger.debug('Removed pending MCP response', { executionId });
        }
    }
    cancelPendingExecution(executionId, reason = 'MCP execution cancelled') {
        const pending = this.pendingResponses.get(executionId);
        if (!pending) {
            this.logger.debug('No pending MCP execution to cancel', { executionId });
            return;
        }
        this.logger.debug('Cancelling pending MCP execution', { executionId, reason });
        const cancellationError = new n8n_workflow_1.ManualExecutionCancelledError(executionId);
        pending.promise.reject(cancellationError);
        this.pendingResponses.delete(executionId);
        if (this.activeExecutions.has(executionId)) {
            this.activeExecutions.stopExecution(executionId, cancellationError);
        }
    }
    cancelAllPendingExecutions(reason = 'MCP service shutdown') {
        const executionIds = Array.from(this.pendingResponses.keys());
        this.logger.debug('Cancelling all pending MCP executions', {
            count: executionIds.length,
            reason,
        });
        for (const executionId of executionIds) {
            this.cancelPendingExecution(executionId, reason);
        }
    }
    get pendingExecutionCount() {
        return this.pendingResponses.size;
    }
};
exports.McpService = McpService;
exports.McpService = McpService = __decorate([
    (0, di_1.Service)(),
    __metadata("design:paramtypes", [backend_common_1.Logger,
        config_1.ExecutionsConfig,
        n8n_core_1.InstanceSettings,
        workflow_finder_service_1.WorkflowFinderService,
        workflow_service_1.WorkflowService,
        url_service_1.UrlService,
        credentials_service_1.CredentialsService,
        active_executions_1.ActiveExecutions,
        config_1.GlobalConfig,
        telemetry_1.Telemetry,
        workflow_runner_1.WorkflowRunner,
        role_service_1.RoleService,
        project_service_ee_1.ProjectService,
        workflow_builder_tools_service_1.WorkflowBuilderToolsService,
        workflow_creation_service_1.WorkflowCreationService,
        node_types_1.NodeTypes,
        db_1.ProjectRepository,
        db_1.FolderRepository,
        db_1.SharedWorkflowRepository,
        db_1.ExecutionRepository,
        execution_service_1.ExecutionService,
        data_table_proxy_service_1.DataTableProxyService])
], McpService);
//# sourceMappingURL=mcp.service.js.map