This is page 33 of 46. Use http://codebase.md/czlonkowski/n8n-mcp?lines=false&page={x} to view the full context. # Directory Structure ``` ├── _config.yml ├── .claude │ └── agents │ ├── code-reviewer.md │ ├── context-manager.md │ ├── debugger.md │ ├── deployment-engineer.md │ ├── mcp-backend-engineer.md │ ├── n8n-mcp-tester.md │ ├── technical-researcher.md │ └── test-automator.md ├── .dockerignore ├── .env.docker ├── .env.example ├── .env.n8n.example ├── .env.test ├── .env.test.example ├── .github │ ├── ABOUT.md │ ├── BENCHMARK_THRESHOLDS.md │ ├── FUNDING.yml │ ├── gh-pages.yml │ ├── secret_scanning.yml │ └── workflows │ ├── benchmark-pr.yml │ ├── benchmark.yml │ ├── docker-build-fast.yml │ ├── docker-build-n8n.yml │ ├── docker-build.yml │ ├── release.yml │ ├── test.yml │ └── update-n8n-deps.yml ├── .gitignore ├── .npmignore ├── ATTRIBUTION.md ├── CHANGELOG.md ├── CLAUDE.md ├── codecov.yml ├── coverage.json ├── data │ ├── .gitkeep │ ├── nodes.db │ ├── nodes.db-shm │ ├── nodes.db-wal │ └── templates.db ├── deploy │ └── quick-deploy-n8n.sh ├── docker │ ├── docker-entrypoint.sh │ ├── n8n-mcp │ ├── parse-config.js │ └── README.md ├── docker-compose.buildkit.yml ├── docker-compose.extract.yml ├── docker-compose.n8n.yml ├── docker-compose.override.yml.example ├── docker-compose.test-n8n.yml ├── docker-compose.yml ├── Dockerfile ├── Dockerfile.railway ├── Dockerfile.test ├── docs │ ├── AUTOMATED_RELEASES.md │ ├── BENCHMARKS.md │ ├── CHANGELOG.md │ ├── CLAUDE_CODE_SETUP.md │ ├── CLAUDE_INTERVIEW.md │ ├── CODECOV_SETUP.md │ ├── CODEX_SETUP.md │ ├── CURSOR_SETUP.md │ ├── DEPENDENCY_UPDATES.md │ ├── DOCKER_README.md │ ├── DOCKER_TROUBLESHOOTING.md │ ├── FINAL_AI_VALIDATION_SPEC.md │ ├── FLEXIBLE_INSTANCE_CONFIGURATION.md │ ├── HTTP_DEPLOYMENT.md │ ├── img │ │ ├── cc_command.png │ │ ├── cc_connected.png │ │ ├── codex_connected.png │ │ ├── cursor_tut.png │ │ ├── Railway_api.png │ │ ├── Railway_server_address.png │ │ ├── vsc_ghcp_chat_agent_mode.png │ │ ├── vsc_ghcp_chat_instruction_files.png │ │ ├── vsc_ghcp_chat_thinking_tool.png │ │ └── windsurf_tut.png │ ├── INSTALLATION.md │ ├── LIBRARY_USAGE.md │ ├── local │ │ ├── DEEP_DIVE_ANALYSIS_2025-10-02.md │ │ ├── DEEP_DIVE_ANALYSIS_README.md │ │ ├── Deep_dive_p1_p2.md │ │ ├── integration-testing-plan.md │ │ ├── integration-tests-phase1-summary.md │ │ ├── N8N_AI_WORKFLOW_BUILDER_ANALYSIS.md │ │ ├── P0_IMPLEMENTATION_PLAN.md │ │ └── TEMPLATE_MINING_ANALYSIS.md │ ├── MCP_ESSENTIALS_README.md │ ├── MCP_QUICK_START_GUIDE.md │ ├── N8N_DEPLOYMENT.md │ ├── RAILWAY_DEPLOYMENT.md │ ├── README_CLAUDE_SETUP.md │ ├── README.md │ ├── tools-documentation-usage.md │ ├── VS_CODE_PROJECT_SETUP.md │ ├── WINDSURF_SETUP.md │ └── workflow-diff-examples.md ├── examples │ └── enhanced-documentation-demo.js ├── fetch_log.txt ├── LICENSE ├── MEMORY_N8N_UPDATE.md ├── MEMORY_TEMPLATE_UPDATE.md ├── monitor_fetch.sh ├── N8N_HTTP_STREAMABLE_SETUP.md ├── n8n-nodes.db ├── P0-R3-TEST-PLAN.md ├── package-lock.json ├── package.json ├── package.runtime.json ├── PRIVACY.md ├── railway.json ├── README.md ├── renovate.json ├── scripts │ ├── analyze-optimization.sh │ ├── audit-schema-coverage.ts │ ├── build-optimized.sh │ ├── compare-benchmarks.js │ ├── demo-optimization.sh │ ├── deploy-http.sh │ ├── deploy-to-vm.sh │ ├── export-webhook-workflows.ts │ ├── extract-changelog.js │ ├── extract-from-docker.js │ ├── extract-nodes-docker.sh │ ├── extract-nodes-simple.sh │ ├── format-benchmark-results.js │ ├── generate-benchmark-stub.js │ ├── generate-detailed-reports.js │ ├── generate-test-summary.js │ ├── http-bridge.js │ ├── mcp-http-client.js │ ├── migrate-nodes-fts.ts │ ├── migrate-tool-docs.ts │ ├── n8n-docs-mcp.service │ ├── nginx-n8n-mcp.conf │ ├── prebuild-fts5.ts │ ├── prepare-release.js │ ├── publish-npm-quick.sh │ ├── publish-npm.sh │ ├── quick-test.ts │ ├── run-benchmarks-ci.js │ ├── sync-runtime-version.js │ ├── test-ai-validation-debug.ts │ ├── test-code-node-enhancements.ts │ ├── test-code-node-fixes.ts │ ├── test-docker-config.sh │ ├── test-docker-fingerprint.ts │ ├── test-docker-optimization.sh │ ├── test-docker.sh │ ├── test-empty-connection-validation.ts │ ├── test-error-message-tracking.ts │ ├── test-error-output-validation.ts │ ├── test-error-validation.js │ ├── test-essentials.ts │ ├── test-expression-code-validation.ts │ ├── test-expression-format-validation.js │ ├── test-fts5-search.ts │ ├── test-fuzzy-fix.ts │ ├── test-fuzzy-simple.ts │ ├── test-helpers-validation.ts │ ├── test-http-search.ts │ ├── test-http.sh │ ├── test-jmespath-validation.ts │ ├── test-multi-tenant-simple.ts │ ├── test-multi-tenant.ts │ ├── test-n8n-integration.sh │ ├── test-node-info.js │ ├── test-node-type-validation.ts │ ├── test-nodes-base-prefix.ts │ ├── test-operation-validation.ts │ ├── test-optimized-docker.sh │ ├── test-release-automation.js │ ├── test-search-improvements.ts │ ├── test-security.ts │ ├── test-single-session.sh │ ├── test-sqljs-triggers.ts │ ├── test-telemetry-debug.ts │ ├── test-telemetry-direct.ts │ ├── test-telemetry-env.ts │ ├── test-telemetry-integration.ts │ ├── test-telemetry-no-select.ts │ ├── test-telemetry-security.ts │ ├── test-telemetry-simple.ts │ ├── test-typeversion-validation.ts │ ├── test-url-configuration.ts │ ├── test-user-id-persistence.ts │ ├── test-webhook-validation.ts │ ├── test-workflow-insert.ts │ ├── test-workflow-sanitizer.ts │ ├── test-workflow-tracking-debug.ts │ ├── update-and-publish-prep.sh │ ├── update-n8n-deps.js │ ├── update-readme-version.js │ ├── vitest-benchmark-json-reporter.js │ └── vitest-benchmark-reporter.ts ├── SECURITY.md ├── src │ ├── config │ │ └── n8n-api.ts │ ├── data │ │ └── canonical-ai-tool-examples.json │ ├── database │ │ ├── database-adapter.ts │ │ ├── migrations │ │ │ └── add-template-node-configs.sql │ │ ├── node-repository.ts │ │ ├── nodes.db │ │ ├── schema-optimized.sql │ │ └── schema.sql │ ├── errors │ │ └── validation-service-error.ts │ ├── http-server-single-session.ts │ ├── http-server.ts │ ├── index.ts │ ├── loaders │ │ └── node-loader.ts │ ├── mappers │ │ └── docs-mapper.ts │ ├── mcp │ │ ├── handlers-n8n-manager.ts │ │ ├── handlers-workflow-diff.ts │ │ ├── index.ts │ │ ├── server.ts │ │ ├── stdio-wrapper.ts │ │ ├── tool-docs │ │ │ ├── configuration │ │ │ │ ├── get-node-as-tool-info.ts │ │ │ │ ├── get-node-documentation.ts │ │ │ │ ├── get-node-essentials.ts │ │ │ │ ├── get-node-info.ts │ │ │ │ ├── get-property-dependencies.ts │ │ │ │ ├── index.ts │ │ │ │ └── search-node-properties.ts │ │ │ ├── discovery │ │ │ │ ├── get-database-statistics.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list-ai-tools.ts │ │ │ │ ├── list-nodes.ts │ │ │ │ └── search-nodes.ts │ │ │ ├── guides │ │ │ │ ├── ai-agents-guide.ts │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ ├── system │ │ │ │ ├── index.ts │ │ │ │ ├── n8n-diagnostic.ts │ │ │ │ ├── n8n-health-check.ts │ │ │ │ ├── n8n-list-available-tools.ts │ │ │ │ └── tools-documentation.ts │ │ │ ├── templates │ │ │ │ ├── get-template.ts │ │ │ │ ├── get-templates-for-task.ts │ │ │ │ ├── index.ts │ │ │ │ ├── list-node-templates.ts │ │ │ │ ├── list-tasks.ts │ │ │ │ ├── search-templates-by-metadata.ts │ │ │ │ └── search-templates.ts │ │ │ ├── types.ts │ │ │ ├── validation │ │ │ │ ├── index.ts │ │ │ │ ├── validate-node-minimal.ts │ │ │ │ ├── validate-node-operation.ts │ │ │ │ ├── validate-workflow-connections.ts │ │ │ │ ├── validate-workflow-expressions.ts │ │ │ │ └── validate-workflow.ts │ │ │ └── workflow_management │ │ │ ├── index.ts │ │ │ ├── n8n-autofix-workflow.ts │ │ │ ├── n8n-create-workflow.ts │ │ │ ├── n8n-delete-execution.ts │ │ │ ├── n8n-delete-workflow.ts │ │ │ ├── n8n-get-execution.ts │ │ │ ├── n8n-get-workflow-details.ts │ │ │ ├── n8n-get-workflow-minimal.ts │ │ │ ├── n8n-get-workflow-structure.ts │ │ │ ├── n8n-get-workflow.ts │ │ │ ├── n8n-list-executions.ts │ │ │ ├── n8n-list-workflows.ts │ │ │ ├── n8n-trigger-webhook-workflow.ts │ │ │ ├── n8n-update-full-workflow.ts │ │ │ ├── n8n-update-partial-workflow.ts │ │ │ └── n8n-validate-workflow.ts │ │ ├── tools-documentation.ts │ │ ├── tools-n8n-friendly.ts │ │ ├── tools-n8n-manager.ts │ │ ├── tools.ts │ │ └── workflow-examples.ts │ ├── mcp-engine.ts │ ├── mcp-tools-engine.ts │ ├── n8n │ │ ├── MCPApi.credentials.ts │ │ └── MCPNode.node.ts │ ├── parsers │ │ ├── node-parser.ts │ │ ├── property-extractor.ts │ │ └── simple-parser.ts │ ├── scripts │ │ ├── debug-http-search.ts │ │ ├── extract-from-docker.ts │ │ ├── fetch-templates-robust.ts │ │ ├── fetch-templates.ts │ │ ├── rebuild-database.ts │ │ ├── rebuild-optimized.ts │ │ ├── rebuild.ts │ │ ├── sanitize-templates.ts │ │ ├── seed-canonical-ai-examples.ts │ │ ├── test-autofix-documentation.ts │ │ ├── test-autofix-workflow.ts │ │ ├── test-execution-filtering.ts │ │ ├── test-node-suggestions.ts │ │ ├── test-protocol-negotiation.ts │ │ ├── test-summary.ts │ │ ├── test-webhook-autofix.ts │ │ ├── validate.ts │ │ └── validation-summary.ts │ ├── services │ │ ├── ai-node-validator.ts │ │ ├── ai-tool-validators.ts │ │ ├── confidence-scorer.ts │ │ ├── config-validator.ts │ │ ├── enhanced-config-validator.ts │ │ ├── example-generator.ts │ │ ├── execution-processor.ts │ │ ├── expression-format-validator.ts │ │ ├── expression-validator.ts │ │ ├── n8n-api-client.ts │ │ ├── n8n-validation.ts │ │ ├── node-documentation-service.ts │ │ ├── node-sanitizer.ts │ │ ├── node-similarity-service.ts │ │ ├── node-specific-validators.ts │ │ ├── operation-similarity-service.ts │ │ ├── property-dependencies.ts │ │ ├── property-filter.ts │ │ ├── resource-similarity-service.ts │ │ ├── sqlite-storage-service.ts │ │ ├── task-templates.ts │ │ ├── universal-expression-validator.ts │ │ ├── workflow-auto-fixer.ts │ │ ├── workflow-diff-engine.ts │ │ └── workflow-validator.ts │ ├── telemetry │ │ ├── batch-processor.ts │ │ ├── config-manager.ts │ │ ├── early-error-logger.ts │ │ ├── error-sanitization-utils.ts │ │ ├── error-sanitizer.ts │ │ ├── event-tracker.ts │ │ ├── event-validator.ts │ │ ├── index.ts │ │ ├── performance-monitor.ts │ │ ├── rate-limiter.ts │ │ ├── startup-checkpoints.ts │ │ ├── telemetry-error.ts │ │ ├── telemetry-manager.ts │ │ ├── telemetry-types.ts │ │ └── workflow-sanitizer.ts │ ├── templates │ │ ├── batch-processor.ts │ │ ├── metadata-generator.ts │ │ ├── README.md │ │ ├── template-fetcher.ts │ │ ├── template-repository.ts │ │ └── template-service.ts │ ├── types │ │ ├── index.ts │ │ ├── instance-context.ts │ │ ├── n8n-api.ts │ │ ├── node-types.ts │ │ └── workflow-diff.ts │ └── utils │ ├── auth.ts │ ├── bridge.ts │ ├── cache-utils.ts │ ├── console-manager.ts │ ├── documentation-fetcher.ts │ ├── enhanced-documentation-fetcher.ts │ ├── error-handler.ts │ ├── example-generator.ts │ ├── fixed-collection-validator.ts │ ├── logger.ts │ ├── mcp-client.ts │ ├── n8n-errors.ts │ ├── node-source-extractor.ts │ ├── node-type-normalizer.ts │ ├── node-type-utils.ts │ ├── node-utils.ts │ ├── npm-version-checker.ts │ ├── protocol-version.ts │ ├── simple-cache.ts │ ├── ssrf-protection.ts │ ├── template-node-resolver.ts │ ├── template-sanitizer.ts │ ├── url-detector.ts │ ├── validation-schemas.ts │ └── version.ts ├── test-output.txt ├── test-reinit-fix.sh ├── tests │ ├── __snapshots__ │ │ └── .gitkeep │ ├── auth.test.ts │ ├── benchmarks │ │ ├── database-queries.bench.ts │ │ ├── index.ts │ │ ├── mcp-tools.bench.ts │ │ ├── mcp-tools.bench.ts.disabled │ │ ├── mcp-tools.bench.ts.skip │ │ ├── node-loading.bench.ts.disabled │ │ ├── README.md │ │ ├── search-operations.bench.ts.disabled │ │ └── validation-performance.bench.ts.disabled │ ├── bridge.test.ts │ ├── comprehensive-extraction-test.js │ ├── data │ │ └── .gitkeep │ ├── debug-slack-doc.js │ ├── demo-enhanced-documentation.js │ ├── docker-tests-README.md │ ├── error-handler.test.ts │ ├── examples │ │ └── using-database-utils.test.ts │ ├── extracted-nodes-db │ │ ├── database-import.json │ │ ├── extraction-report.json │ │ ├── insert-nodes.sql │ │ ├── n8n-nodes-base__Airtable.json │ │ ├── n8n-nodes-base__Discord.json │ │ ├── n8n-nodes-base__Function.json │ │ ├── n8n-nodes-base__HttpRequest.json │ │ ├── n8n-nodes-base__If.json │ │ ├── n8n-nodes-base__Slack.json │ │ ├── n8n-nodes-base__SplitInBatches.json │ │ └── n8n-nodes-base__Webhook.json │ ├── factories │ │ ├── node-factory.ts │ │ └── property-definition-factory.ts │ ├── fixtures │ │ ├── .gitkeep │ │ ├── database │ │ │ └── test-nodes.json │ │ ├── factories │ │ │ ├── node.factory.ts │ │ │ └── parser-node.factory.ts │ │ └── template-configs.ts │ ├── helpers │ │ └── env-helpers.ts │ ├── http-server-auth.test.ts │ ├── integration │ │ ├── ai-validation │ │ │ ├── ai-agent-validation.test.ts │ │ │ ├── ai-tool-validation.test.ts │ │ │ ├── chat-trigger-validation.test.ts │ │ │ ├── e2e-validation.test.ts │ │ │ ├── helpers.ts │ │ │ ├── llm-chain-validation.test.ts │ │ │ ├── README.md │ │ │ └── TEST_REPORT.md │ │ ├── ci │ │ │ └── database-population.test.ts │ │ ├── database │ │ │ ├── connection-management.test.ts │ │ │ ├── empty-database.test.ts │ │ │ ├── fts5-search.test.ts │ │ │ ├── node-fts5-search.test.ts │ │ │ ├── node-repository.test.ts │ │ │ ├── performance.test.ts │ │ │ ├── sqljs-memory-leak.test.ts │ │ │ ├── template-node-configs.test.ts │ │ │ ├── template-repository.test.ts │ │ │ ├── test-utils.ts │ │ │ └── transactions.test.ts │ │ ├── database-integration.test.ts │ │ ├── docker │ │ │ ├── docker-config.test.ts │ │ │ ├── docker-entrypoint.test.ts │ │ │ └── test-helpers.ts │ │ ├── flexible-instance-config.test.ts │ │ ├── mcp │ │ │ └── template-examples-e2e.test.ts │ │ ├── mcp-protocol │ │ │ ├── basic-connection.test.ts │ │ │ ├── error-handling.test.ts │ │ │ ├── performance.test.ts │ │ │ ├── protocol-compliance.test.ts │ │ │ ├── README.md │ │ │ ├── session-management.test.ts │ │ │ ├── test-helpers.ts │ │ │ ├── tool-invocation.test.ts │ │ │ └── workflow-error-validation.test.ts │ │ ├── msw-setup.test.ts │ │ ├── n8n-api │ │ │ ├── executions │ │ │ │ ├── delete-execution.test.ts │ │ │ │ ├── get-execution.test.ts │ │ │ │ ├── list-executions.test.ts │ │ │ │ └── trigger-webhook.test.ts │ │ │ ├── scripts │ │ │ │ └── cleanup-orphans.ts │ │ │ ├── system │ │ │ │ ├── diagnostic.test.ts │ │ │ │ ├── health-check.test.ts │ │ │ │ └── list-tools.test.ts │ │ │ ├── test-connection.ts │ │ │ ├── types │ │ │ │ └── mcp-responses.ts │ │ │ ├── utils │ │ │ │ ├── cleanup-helpers.ts │ │ │ │ ├── credentials.ts │ │ │ │ ├── factories.ts │ │ │ │ ├── fixtures.ts │ │ │ │ ├── mcp-context.ts │ │ │ │ ├── n8n-client.ts │ │ │ │ ├── node-repository.ts │ │ │ │ ├── response-types.ts │ │ │ │ ├── test-context.ts │ │ │ │ └── webhook-workflows.ts │ │ │ └── workflows │ │ │ ├── autofix-workflow.test.ts │ │ │ ├── create-workflow.test.ts │ │ │ ├── delete-workflow.test.ts │ │ │ ├── get-workflow-details.test.ts │ │ │ ├── get-workflow-minimal.test.ts │ │ │ ├── get-workflow-structure.test.ts │ │ │ ├── get-workflow.test.ts │ │ │ ├── list-workflows.test.ts │ │ │ ├── smart-parameters.test.ts │ │ │ ├── update-partial-workflow.test.ts │ │ │ ├── update-workflow.test.ts │ │ │ └── validate-workflow.test.ts │ │ ├── security │ │ │ ├── command-injection-prevention.test.ts │ │ │ └── rate-limiting.test.ts │ │ ├── setup │ │ │ ├── integration-setup.ts │ │ │ └── msw-test-server.ts │ │ ├── telemetry │ │ │ ├── docker-user-id-stability.test.ts │ │ │ └── mcp-telemetry.test.ts │ │ ├── templates │ │ │ └── metadata-operations.test.ts │ │ └── workflow-creation-node-type-format.test.ts │ ├── logger.test.ts │ ├── MOCKING_STRATEGY.md │ ├── mocks │ │ ├── n8n-api │ │ │ ├── data │ │ │ │ ├── credentials.ts │ │ │ │ ├── executions.ts │ │ │ │ └── workflows.ts │ │ │ ├── handlers.ts │ │ │ └── index.ts │ │ └── README.md │ ├── node-storage-export.json │ ├── setup │ │ ├── global-setup.ts │ │ ├── msw-setup.ts │ │ ├── TEST_ENV_DOCUMENTATION.md │ │ └── test-env.ts │ ├── test-database-extraction.js │ ├── test-direct-extraction.js │ ├── test-enhanced-documentation.js │ ├── test-enhanced-integration.js │ ├── test-mcp-extraction.js │ ├── test-mcp-server-extraction.js │ ├── test-mcp-tools-integration.js │ ├── test-node-documentation-service.js │ ├── test-node-list.js │ ├── test-package-info.js │ ├── test-parsing-operations.js │ ├── test-slack-node-complete.js │ ├── test-small-rebuild.js │ ├── test-sqlite-search.js │ ├── test-storage-system.js │ ├── unit │ │ ├── __mocks__ │ │ │ ├── n8n-nodes-base.test.ts │ │ │ ├── n8n-nodes-base.ts │ │ │ └── README.md │ │ ├── database │ │ │ ├── __mocks__ │ │ │ │ └── better-sqlite3.ts │ │ │ ├── database-adapter-unit.test.ts │ │ │ ├── node-repository-core.test.ts │ │ │ ├── node-repository-operations.test.ts │ │ │ ├── node-repository-outputs.test.ts │ │ │ ├── README.md │ │ │ └── template-repository-core.test.ts │ │ ├── docker │ │ │ ├── config-security.test.ts │ │ │ ├── edge-cases.test.ts │ │ │ ├── parse-config.test.ts │ │ │ └── serve-command.test.ts │ │ ├── errors │ │ │ └── validation-service-error.test.ts │ │ ├── examples │ │ │ └── using-n8n-nodes-base-mock.test.ts │ │ ├── flexible-instance-security-advanced.test.ts │ │ ├── flexible-instance-security.test.ts │ │ ├── http-server │ │ │ └── multi-tenant-support.test.ts │ │ ├── http-server-n8n-mode.test.ts │ │ ├── http-server-n8n-reinit.test.ts │ │ ├── http-server-session-management.test.ts │ │ ├── loaders │ │ │ └── node-loader.test.ts │ │ ├── mappers │ │ │ └── docs-mapper.test.ts │ │ ├── mcp │ │ │ ├── get-node-essentials-examples.test.ts │ │ │ ├── handlers-n8n-manager-simple.test.ts │ │ │ ├── handlers-n8n-manager.test.ts │ │ │ ├── handlers-workflow-diff.test.ts │ │ │ ├── lru-cache-behavior.test.ts │ │ │ ├── multi-tenant-tool-listing.test.ts.disabled │ │ │ ├── parameter-validation.test.ts │ │ │ ├── search-nodes-examples.test.ts │ │ │ ├── tools-documentation.test.ts │ │ │ └── tools.test.ts │ │ ├── monitoring │ │ │ └── cache-metrics.test.ts │ │ ├── MULTI_TENANT_TEST_COVERAGE.md │ │ ├── multi-tenant-integration.test.ts │ │ ├── parsers │ │ │ ├── node-parser-outputs.test.ts │ │ │ ├── node-parser.test.ts │ │ │ ├── property-extractor.test.ts │ │ │ └── simple-parser.test.ts │ │ ├── scripts │ │ │ └── fetch-templates-extraction.test.ts │ │ ├── services │ │ │ ├── ai-node-validator.test.ts │ │ │ ├── ai-tool-validators.test.ts │ │ │ ├── confidence-scorer.test.ts │ │ │ ├── config-validator-basic.test.ts │ │ │ ├── config-validator-edge-cases.test.ts │ │ │ ├── config-validator-node-specific.test.ts │ │ │ ├── config-validator-security.test.ts │ │ │ ├── debug-validator.test.ts │ │ │ ├── enhanced-config-validator-integration.test.ts │ │ │ ├── enhanced-config-validator-operations.test.ts │ │ │ ├── enhanced-config-validator.test.ts │ │ │ ├── example-generator.test.ts │ │ │ ├── execution-processor.test.ts │ │ │ ├── expression-format-validator.test.ts │ │ │ ├── expression-validator-edge-cases.test.ts │ │ │ ├── expression-validator.test.ts │ │ │ ├── fixed-collection-validation.test.ts │ │ │ ├── loop-output-edge-cases.test.ts │ │ │ ├── n8n-api-client.test.ts │ │ │ ├── n8n-validation.test.ts │ │ │ ├── node-sanitizer.test.ts │ │ │ ├── node-similarity-service.test.ts │ │ │ ├── node-specific-validators.test.ts │ │ │ ├── operation-similarity-service-comprehensive.test.ts │ │ │ ├── operation-similarity-service.test.ts │ │ │ ├── property-dependencies.test.ts │ │ │ ├── property-filter-edge-cases.test.ts │ │ │ ├── property-filter.test.ts │ │ │ ├── resource-similarity-service-comprehensive.test.ts │ │ │ ├── resource-similarity-service.test.ts │ │ │ ├── task-templates.test.ts │ │ │ ├── template-service.test.ts │ │ │ ├── universal-expression-validator.test.ts │ │ │ ├── validation-fixes.test.ts │ │ │ ├── workflow-auto-fixer.test.ts │ │ │ ├── workflow-diff-engine.test.ts │ │ │ ├── workflow-fixed-collection-validation.test.ts │ │ │ ├── workflow-validator-comprehensive.test.ts │ │ │ ├── workflow-validator-edge-cases.test.ts │ │ │ ├── workflow-validator-error-outputs.test.ts │ │ │ ├── workflow-validator-expression-format.test.ts │ │ │ ├── workflow-validator-loops-simple.test.ts │ │ │ ├── workflow-validator-loops.test.ts │ │ │ ├── workflow-validator-mocks.test.ts │ │ │ ├── workflow-validator-performance.test.ts │ │ │ ├── workflow-validator-with-mocks.test.ts │ │ │ └── workflow-validator.test.ts │ │ ├── telemetry │ │ │ ├── batch-processor.test.ts │ │ │ ├── config-manager.test.ts │ │ │ ├── event-tracker.test.ts │ │ │ ├── event-validator.test.ts │ │ │ ├── rate-limiter.test.ts │ │ │ ├── telemetry-error.test.ts │ │ │ ├── telemetry-manager.test.ts │ │ │ ├── v2.18.3-fixes-verification.test.ts │ │ │ └── workflow-sanitizer.test.ts │ │ ├── templates │ │ │ ├── batch-processor.test.ts │ │ │ ├── metadata-generator.test.ts │ │ │ ├── template-repository-metadata.test.ts │ │ │ └── template-repository-security.test.ts │ │ ├── test-env-example.test.ts │ │ ├── test-infrastructure.test.ts │ │ ├── types │ │ │ ├── instance-context-coverage.test.ts │ │ │ └── instance-context-multi-tenant.test.ts │ │ ├── utils │ │ │ ├── auth-timing-safe.test.ts │ │ │ ├── cache-utils.test.ts │ │ │ ├── console-manager.test.ts │ │ │ ├── database-utils.test.ts │ │ │ ├── fixed-collection-validator.test.ts │ │ │ ├── n8n-errors.test.ts │ │ │ ├── node-type-normalizer.test.ts │ │ │ ├── node-type-utils.test.ts │ │ │ ├── node-utils.test.ts │ │ │ ├── simple-cache-memory-leak-fix.test.ts │ │ │ ├── ssrf-protection.test.ts │ │ │ └── template-node-resolver.test.ts │ │ └── validation-fixes.test.ts │ └── utils │ ├── assertions.ts │ ├── builders │ │ └── workflow.builder.ts │ ├── data-generators.ts │ ├── database-utils.ts │ ├── README.md │ └── test-helpers.ts ├── thumbnail.png ├── tsconfig.build.json ├── tsconfig.json ├── types │ ├── mcp.d.ts │ └── test-env.d.ts ├── verify-telemetry-fix.js ├── versioned-nodes.md ├── vitest.config.benchmark.ts ├── vitest.config.integration.ts └── vitest.config.ts ``` # Files -------------------------------------------------------------------------------- /tests/extracted-nodes-db/n8n-nodes-base__SplitInBatches.json: -------------------------------------------------------------------------------- ```json { "node_type": "n8n-nodes-base.SplitInBatches", "name": "SplitInBatches", "package_name": "n8n-nodes-base", "code_hash": "c751422a11e30bf361a6c4803376289740a40434aeb77f90e18cd4dd7ba5c019", "code_length": 1135, "source_location": "node_modules/n8n-nodes-base/dist/nodes/SplitInBatches/SplitInBatches.node.js", "has_credentials": false, "source_code": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.SplitInBatches = void 0;\nconst n8n_workflow_1 = require(\"n8n-workflow\");\nconst SplitInBatchesV1_node_1 = require(\"./v1/SplitInBatchesV1.node\");\nconst SplitInBatchesV2_node_1 = require(\"./v2/SplitInBatchesV2.node\");\nconst SplitInBatchesV3_node_1 = require(\"./v3/SplitInBatchesV3.node\");\nclass SplitInBatches extends n8n_workflow_1.VersionedNodeType {\n constructor() {\n const baseDescription = {\n displayName: 'Split In Batches',\n name: 'splitInBatches',\n icon: 'fa:th-large',\n group: ['organization'],\n description: 'Split data into batches and iterate over each batch',\n defaultVersion: 3,\n };\n const nodeVersions = {\n 1: new SplitInBatchesV1_node_1.SplitInBatchesV1(),\n 2: new SplitInBatchesV2_node_1.SplitInBatchesV2(),\n 3: new SplitInBatchesV3_node_1.SplitInBatchesV3(),\n };\n super(nodeVersions, baseDescription);\n }\n}\nexports.SplitInBatches = SplitInBatches;\n//# sourceMappingURL=SplitInBatches.node.js.map", "package_info": { "name": "n8n-nodes-base", "version": "1.14.1", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", "author": { "name": "Jan Oberhauser", "email": "[email protected]" }, "main": "index.js", "repository": { "type": "git", "url": "git+https://github.com/n8n-io/n8n.git" }, "files": [ "dist" ], "n8n": { "credentials": [ "dist/credentials/ActionNetworkApi.credentials.js", "dist/credentials/ActiveCampaignApi.credentials.js", "dist/credentials/AcuitySchedulingApi.credentials.js", "dist/credentials/AcuitySchedulingOAuth2Api.credentials.js", "dist/credentials/AdaloApi.credentials.js", "dist/credentials/AffinityApi.credentials.js", "dist/credentials/AgileCrmApi.credentials.js", "dist/credentials/AirtableApi.credentials.js", "dist/credentials/AirtableOAuth2Api.credentials.js", "dist/credentials/AirtableTokenApi.credentials.js", "dist/credentials/AlienVaultApi.credentials.js", "dist/credentials/Amqp.credentials.js", "dist/credentials/ApiTemplateIoApi.credentials.js", "dist/credentials/AsanaApi.credentials.js", "dist/credentials/AsanaOAuth2Api.credentials.js", "dist/credentials/Auth0ManagementApi.credentials.js", "dist/credentials/AutomizyApi.credentials.js", "dist/credentials/AutopilotApi.credentials.js", "dist/credentials/Aws.credentials.js", "dist/credentials/BambooHrApi.credentials.js", "dist/credentials/BannerbearApi.credentials.js", "dist/credentials/BaserowApi.credentials.js", "dist/credentials/BeeminderApi.credentials.js", "dist/credentials/BitbucketApi.credentials.js", "dist/credentials/BitlyApi.credentials.js", "dist/credentials/BitlyOAuth2Api.credentials.js", "dist/credentials/BitwardenApi.credentials.js", "dist/credentials/BoxOAuth2Api.credentials.js", "dist/credentials/BrandfetchApi.credentials.js", "dist/credentials/BubbleApi.credentials.js", "dist/credentials/CalApi.credentials.js", "dist/credentials/CalendlyApi.credentials.js", "dist/credentials/CarbonBlackApi.credentials.js", "dist/credentials/ChargebeeApi.credentials.js", "dist/credentials/CircleCiApi.credentials.js", "dist/credentials/CiscoMerakiApi.credentials.js", "dist/credentials/CiscoSecureEndpointApi.credentials.js", "dist/credentials/CiscoWebexOAuth2Api.credentials.js", "dist/credentials/CiscoUmbrellaApi.credentials.js", "dist/credentials/CitrixAdcApi.credentials.js", "dist/credentials/CloudflareApi.credentials.js", "dist/credentials/ClearbitApi.credentials.js", "dist/credentials/ClickUpApi.credentials.js", "dist/credentials/ClickUpOAuth2Api.credentials.js", "dist/credentials/ClockifyApi.credentials.js", "dist/credentials/CockpitApi.credentials.js", "dist/credentials/CodaApi.credentials.js", "dist/credentials/ContentfulApi.credentials.js", "dist/credentials/ConvertKitApi.credentials.js", "dist/credentials/CopperApi.credentials.js", "dist/credentials/CortexApi.credentials.js", "dist/credentials/CrateDb.credentials.js", "dist/credentials/CrowdStrikeOAuth2Api.credentials.js", "dist/credentials/CrowdDevApi.credentials.js", "dist/credentials/CustomerIoApi.credentials.js", "dist/credentials/DeepLApi.credentials.js", "dist/credentials/DemioApi.credentials.js", "dist/credentials/DhlApi.credentials.js", "dist/credentials/DiscourseApi.credentials.js", "dist/credentials/DisqusApi.credentials.js", "dist/credentials/DriftApi.credentials.js", "dist/credentials/DriftOAuth2Api.credentials.js", "dist/credentials/DropboxApi.credentials.js", "dist/credentials/DropboxOAuth2Api.credentials.js", "dist/credentials/DropcontactApi.credentials.js", "dist/credentials/EgoiApi.credentials.js", "dist/credentials/ElasticsearchApi.credentials.js", "dist/credentials/ElasticSecurityApi.credentials.js", "dist/credentials/EmeliaApi.credentials.js", "dist/credentials/ERPNextApi.credentials.js", "dist/credentials/EventbriteApi.credentials.js", "dist/credentials/EventbriteOAuth2Api.credentials.js", "dist/credentials/F5BigIpApi.credentials.js", "dist/credentials/FacebookGraphApi.credentials.js", "dist/credentials/FacebookGraphAppApi.credentials.js", "dist/credentials/FacebookLeadAdsOAuth2Api.credentials.js", "dist/credentials/FigmaApi.credentials.js", "dist/credentials/FileMaker.credentials.js", "dist/credentials/FlowApi.credentials.js", "dist/credentials/FormIoApi.credentials.js", "dist/credentials/FormstackApi.credentials.js", "dist/credentials/FormstackOAuth2Api.credentials.js", "dist/credentials/FortiGateApi.credentials.js", "dist/credentials/FreshdeskApi.credentials.js", "dist/credentials/FreshserviceApi.credentials.js", "dist/credentials/FreshworksCrmApi.credentials.js", "dist/credentials/Ftp.credentials.js", "dist/credentials/GetResponseApi.credentials.js", "dist/credentials/GetResponseOAuth2Api.credentials.js", "dist/credentials/GhostAdminApi.credentials.js", "dist/credentials/GhostContentApi.credentials.js", "dist/credentials/GithubApi.credentials.js", "dist/credentials/GithubOAuth2Api.credentials.js", "dist/credentials/GitlabApi.credentials.js", "dist/credentials/GitlabOAuth2Api.credentials.js", "dist/credentials/GitPassword.credentials.js", "dist/credentials/GmailOAuth2Api.credentials.js", "dist/credentials/GoogleAdsOAuth2Api.credentials.js", "dist/credentials/GoogleAnalyticsOAuth2Api.credentials.js", "dist/credentials/GoogleApi.credentials.js", "dist/credentials/GoogleBigQueryOAuth2Api.credentials.js", "dist/credentials/GoogleBooksOAuth2Api.credentials.js", "dist/credentials/GoogleCalendarOAuth2Api.credentials.js", "dist/credentials/GoogleCloudNaturalLanguageOAuth2Api.credentials.js", "dist/credentials/GoogleCloudStorageOAuth2Api.credentials.js", "dist/credentials/GoogleContactsOAuth2Api.credentials.js", "dist/credentials/GoogleDocsOAuth2Api.credentials.js", "dist/credentials/GoogleDriveOAuth2Api.credentials.js", "dist/credentials/GoogleFirebaseCloudFirestoreOAuth2Api.credentials.js", "dist/credentials/GoogleFirebaseRealtimeDatabaseOAuth2Api.credentials.js", "dist/credentials/GoogleOAuth2Api.credentials.js", "dist/credentials/GooglePerspectiveOAuth2Api.credentials.js", "dist/credentials/GoogleSheetsOAuth2Api.credentials.js", "dist/credentials/GoogleSheetsTriggerOAuth2Api.credentials.js", "dist/credentials/GoogleSlidesOAuth2Api.credentials.js", "dist/credentials/GoogleTasksOAuth2Api.credentials.js", "dist/credentials/GoogleTranslateOAuth2Api.credentials.js", "dist/credentials/GotifyApi.credentials.js", "dist/credentials/GoToWebinarOAuth2Api.credentials.js", "dist/credentials/GristApi.credentials.js", "dist/credentials/GrafanaApi.credentials.js", "dist/credentials/GSuiteAdminOAuth2Api.credentials.js", "dist/credentials/GumroadApi.credentials.js", "dist/credentials/HaloPSAApi.credentials.js", "dist/credentials/HarvestApi.credentials.js", "dist/credentials/HarvestOAuth2Api.credentials.js", "dist/credentials/HelpScoutOAuth2Api.credentials.js", "dist/credentials/HighLevelApi.credentials.js", "dist/credentials/HomeAssistantApi.credentials.js", "dist/credentials/HttpBasicAuth.credentials.js", "dist/credentials/HttpDigestAuth.credentials.js", "dist/credentials/HttpHeaderAuth.credentials.js", "dist/credentials/HttpCustomAuth.credentials.js", "dist/credentials/HttpQueryAuth.credentials.js", "dist/credentials/HubspotApi.credentials.js", "dist/credentials/HubspotAppToken.credentials.js", "dist/credentials/HubspotDeveloperApi.credentials.js", "dist/credentials/HubspotOAuth2Api.credentials.js", "dist/credentials/HumanticAiApi.credentials.js", "dist/credentials/HunterApi.credentials.js", "dist/credentials/HybridAnalysisApi.credentials.js", "dist/credentials/Imap.credentials.js", "dist/credentials/ImpervaWafApi.credentials.js", "dist/credentials/IntercomApi.credentials.js", "dist/credentials/InvoiceNinjaApi.credentials.js", "dist/credentials/IterableApi.credentials.js", "dist/credentials/JenkinsApi.credentials.js", "dist/credentials/JiraSoftwareCloudApi.credentials.js", "dist/credentials/JiraSoftwareServerApi.credentials.js", "dist/credentials/JotFormApi.credentials.js", "dist/credentials/Kafka.credentials.js", "dist/credentials/KeapOAuth2Api.credentials.js", "dist/credentials/KibanaApi.credentials.js", "dist/credentials/KitemakerApi.credentials.js", "dist/credentials/KoBoToolboxApi.credentials.js", "dist/credentials/Ldap.credentials.js", "dist/credentials/LemlistApi.credentials.js", "dist/credentials/LinearApi.credentials.js", "dist/credentials/LinearOAuth2Api.credentials.js", "dist/credentials/LineNotifyOAuth2Api.credentials.js", "dist/credentials/LingvaNexApi.credentials.js", "dist/credentials/LinkedInOAuth2Api.credentials.js", "dist/credentials/LoneScaleApi.credentials.js", "dist/credentials/Magento2Api.credentials.js", "dist/credentials/MailcheckApi.credentials.js", "dist/credentials/MailchimpApi.credentials.js", "dist/credentials/MailchimpOAuth2Api.credentials.js", "dist/credentials/MailerLiteApi.credentials.js", "dist/credentials/MailgunApi.credentials.js", "dist/credentials/MailjetEmailApi.credentials.js", "dist/credentials/MailjetSmsApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", "dist/credentials/MarketstackApi.credentials.js", "dist/credentials/MatrixApi.credentials.js", "dist/credentials/MattermostApi.credentials.js", "dist/credentials/MauticApi.credentials.js", "dist/credentials/MauticOAuth2Api.credentials.js", "dist/credentials/MediumApi.credentials.js", "dist/credentials/MediumOAuth2Api.credentials.js", "dist/credentials/MetabaseApi.credentials.js", "dist/credentials/MessageBirdApi.credentials.js", "dist/credentials/MetabaseApi.credentials.js", "dist/credentials/MicrosoftDynamicsOAuth2Api.credentials.js", "dist/credentials/MicrosoftEntraOAuth2Api.credentials.js", "dist/credentials/MicrosoftExcelOAuth2Api.credentials.js", "dist/credentials/MicrosoftGraphSecurityOAuth2Api.credentials.js", "dist/credentials/MicrosoftOAuth2Api.credentials.js", "dist/credentials/MicrosoftOneDriveOAuth2Api.credentials.js", "dist/credentials/MicrosoftOutlookOAuth2Api.credentials.js", "dist/credentials/MicrosoftSql.credentials.js", "dist/credentials/MicrosoftTeamsOAuth2Api.credentials.js", "dist/credentials/MicrosoftToDoOAuth2Api.credentials.js", "dist/credentials/MindeeInvoiceApi.credentials.js", "dist/credentials/MindeeReceiptApi.credentials.js", "dist/credentials/MispApi.credentials.js", "dist/credentials/MistApi.credentials.js", "dist/credentials/MoceanApi.credentials.js", "dist/credentials/MondayComApi.credentials.js", "dist/credentials/MondayComOAuth2Api.credentials.js", "dist/credentials/MongoDb.credentials.js", "dist/credentials/MonicaCrmApi.credentials.js", "dist/credentials/Mqtt.credentials.js", "dist/credentials/Msg91Api.credentials.js", "dist/credentials/MySql.credentials.js", "dist/credentials/N8nApi.credentials.js", "dist/credentials/NasaApi.credentials.js", "dist/credentials/NetlifyApi.credentials.js", "dist/credentials/NextCloudApi.credentials.js", "dist/credentials/NextCloudOAuth2Api.credentials.js", "dist/credentials/NocoDb.credentials.js", "dist/credentials/NocoDbApiToken.credentials.js", "dist/credentials/NotionApi.credentials.js", "dist/credentials/NotionOAuth2Api.credentials.js", "dist/credentials/NpmApi.credentials.js", "dist/credentials/OAuth1Api.credentials.js", "dist/credentials/OAuth2Api.credentials.js", "dist/credentials/OdooApi.credentials.js", "dist/credentials/OktaApi.credentials.js", "dist/credentials/OneSimpleApi.credentials.js", "dist/credentials/OnfleetApi.credentials.js", "dist/credentials/OpenAiApi.credentials.js", "dist/credentials/OpenCTIApi.credentials.js", "dist/credentials/OpenWeatherMapApi.credentials.js", "dist/credentials/OrbitApi.credentials.js", "dist/credentials/OuraApi.credentials.js", "dist/credentials/PaddleApi.credentials.js", "dist/credentials/PagerDutyApi.credentials.js", "dist/credentials/PagerDutyOAuth2Api.credentials.js", "dist/credentials/PayPalApi.credentials.js", "dist/credentials/PeekalinkApi.credentials.js", "dist/credentials/PhantombusterApi.credentials.js", "dist/credentials/PhilipsHueOAuth2Api.credentials.js", "dist/credentials/PipedriveApi.credentials.js", "dist/credentials/PipedriveOAuth2Api.credentials.js", "dist/credentials/PlivoApi.credentials.js", "dist/credentials/Postgres.credentials.js", "dist/credentials/PostHogApi.credentials.js", "dist/credentials/PostmarkApi.credentials.js", "dist/credentials/ProfitWellApi.credentials.js", "dist/credentials/PushbulletOAuth2Api.credentials.js", "dist/credentials/PushcutApi.credentials.js", "dist/credentials/PushoverApi.credentials.js", "dist/credentials/QRadarApi.credentials.js", "dist/credentials/QualysApi.credentials.js", "dist/credentials/QuestDb.credentials.js", "dist/credentials/QuickBaseApi.credentials.js", "dist/credentials/QuickBooksOAuth2Api.credentials.js", "dist/credentials/RabbitMQ.credentials.js", "dist/credentials/RaindropOAuth2Api.credentials.js", "dist/credentials/RecordedFutureApi.credentials.js", "dist/credentials/RedditOAuth2Api.credentials.js", "dist/credentials/Redis.credentials.js", "dist/credentials/RocketchatApi.credentials.js", "dist/credentials/RundeckApi.credentials.js", "dist/credentials/S3.credentials.js", "dist/credentials/SalesforceJwtApi.credentials.js", "dist/credentials/SalesforceOAuth2Api.credentials.js", "dist/credentials/SalesmateApi.credentials.js", "dist/credentials/SeaTableApi.credentials.js", "dist/credentials/SecurityScorecardApi.credentials.js", "dist/credentials/SegmentApi.credentials.js", "dist/credentials/SekoiaApi.credentials.js", "dist/credentials/SendGridApi.credentials.js", "dist/credentials/BrevoApi.credentials.js", "dist/credentials/SendyApi.credentials.js", "dist/credentials/SentryIoApi.credentials.js", "dist/credentials/SentryIoOAuth2Api.credentials.js", "dist/credentials/SentryIoServerApi.credentials.js", "dist/credentials/ServiceNowOAuth2Api.credentials.js", "dist/credentials/ServiceNowBasicApi.credentials.js", "dist/credentials/Sftp.credentials.js", "dist/credentials/ShopifyApi.credentials.js", "dist/credentials/ShopifyAccessTokenApi.credentials.js", "dist/credentials/ShopifyOAuth2Api.credentials.js", "dist/credentials/Signl4Api.credentials.js", "dist/credentials/SlackApi.credentials.js", "dist/credentials/SlackOAuth2Api.credentials.js", "dist/credentials/Sms77Api.credentials.js", "dist/credentials/Smtp.credentials.js", "dist/credentials/Snowflake.credentials.js", "dist/credentials/SplunkApi.credentials.js", "dist/credentials/SpontitApi.credentials.js", "dist/credentials/SpotifyOAuth2Api.credentials.js", "dist/credentials/ShufflerApi.credentials.js", "dist/credentials/SshPassword.credentials.js", "dist/credentials/SshPrivateKey.credentials.js", "dist/credentials/StackbyApi.credentials.js", "dist/credentials/StoryblokContentApi.credentials.js", "dist/credentials/StoryblokManagementApi.credentials.js", "dist/credentials/StrapiApi.credentials.js", "dist/credentials/StrapiTokenApi.credentials.js", "dist/credentials/StravaOAuth2Api.credentials.js", "dist/credentials/StripeApi.credentials.js", "dist/credentials/SupabaseApi.credentials.js", "dist/credentials/SurveyMonkeyApi.credentials.js", "dist/credentials/SurveyMonkeyOAuth2Api.credentials.js", "dist/credentials/SyncroMspApi.credentials.js", "dist/credentials/TaigaApi.credentials.js", "dist/credentials/TapfiliateApi.credentials.js", "dist/credentials/TelegramApi.credentials.js", "dist/credentials/TheHiveProjectApi.credentials.js", "dist/credentials/TheHiveApi.credentials.js", "dist/credentials/TimescaleDb.credentials.js", "dist/credentials/TodoistApi.credentials.js", "dist/credentials/TodoistOAuth2Api.credentials.js", "dist/credentials/TogglApi.credentials.js", "dist/credentials/TotpApi.credentials.js", "dist/credentials/TravisCiApi.credentials.js", "dist/credentials/TrellixEpoApi.credentials.js", "dist/credentials/TrelloApi.credentials.js", "dist/credentials/TwakeCloudApi.credentials.js", "dist/credentials/TwakeServerApi.credentials.js", "dist/credentials/TwilioApi.credentials.js", "dist/credentials/TwistOAuth2Api.credentials.js", "dist/credentials/TwitterOAuth1Api.credentials.js", "dist/credentials/TwitterOAuth2Api.credentials.js", "dist/credentials/TypeformApi.credentials.js", "dist/credentials/TypeformOAuth2Api.credentials.js", "dist/credentials/UnleashedSoftwareApi.credentials.js", "dist/credentials/UpleadApi.credentials.js", "dist/credentials/UProcApi.credentials.js", "dist/credentials/UptimeRobotApi.credentials.js", "dist/credentials/UrlScanIoApi.credentials.js", "dist/credentials/VeroApi.credentials.js", "dist/credentials/VirusTotalApi.credentials.js", "dist/credentials/VonageApi.credentials.js", "dist/credentials/VenafiTlsProtectCloudApi.credentials.js", "dist/credentials/VenafiTlsProtectDatacenterApi.credentials.js", "dist/credentials/WebflowApi.credentials.js", "dist/credentials/WebflowOAuth2Api.credentials.js", "dist/credentials/WekanApi.credentials.js", "dist/credentials/WhatsAppApi.credentials.js", "dist/credentials/WiseApi.credentials.js", "dist/credentials/WooCommerceApi.credentials.js", "dist/credentials/WordpressApi.credentials.js", "dist/credentials/WorkableApi.credentials.js", "dist/credentials/WufooApi.credentials.js", "dist/credentials/XeroOAuth2Api.credentials.js", "dist/credentials/YourlsApi.credentials.js", "dist/credentials/YouTubeOAuth2Api.credentials.js", "dist/credentials/ZammadBasicAuthApi.credentials.js", "dist/credentials/ZammadTokenAuthApi.credentials.js", "dist/credentials/ZendeskApi.credentials.js", "dist/credentials/ZendeskOAuth2Api.credentials.js", "dist/credentials/ZohoOAuth2Api.credentials.js", "dist/credentials/ZoomApi.credentials.js", "dist/credentials/ZoomOAuth2Api.credentials.js", "dist/credentials/ZscalerZiaApi.credentials.js", "dist/credentials/ZulipApi.credentials.js" ], "nodes": [ "dist/nodes/ActionNetwork/ActionNetwork.node.js", "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", "dist/nodes/ActiveCampaign/ActiveCampaignTrigger.node.js", "dist/nodes/AcuityScheduling/AcuitySchedulingTrigger.node.js", "dist/nodes/Adalo/Adalo.node.js", "dist/nodes/Affinity/Affinity.node.js", "dist/nodes/Affinity/AffinityTrigger.node.js", "dist/nodes/AgileCrm/AgileCrm.node.js", "dist/nodes/Airtable/Airtable.node.js", "dist/nodes/Airtable/AirtableTrigger.node.js", "dist/nodes/Amqp/Amqp.node.js", "dist/nodes/Amqp/AmqpTrigger.node.js", "dist/nodes/ApiTemplateIo/ApiTemplateIo.node.js", "dist/nodes/Asana/Asana.node.js", "dist/nodes/Asana/AsanaTrigger.node.js", "dist/nodes/Automizy/Automizy.node.js", "dist/nodes/Autopilot/Autopilot.node.js", "dist/nodes/Autopilot/AutopilotTrigger.node.js", "dist/nodes/Aws/AwsLambda.node.js", "dist/nodes/Aws/AwsSns.node.js", "dist/nodes/Aws/AwsSnsTrigger.node.js", "dist/nodes/Aws/CertificateManager/AwsCertificateManager.node.js", "dist/nodes/Aws/Comprehend/AwsComprehend.node.js", "dist/nodes/Aws/DynamoDB/AwsDynamoDB.node.js", "dist/nodes/Aws/ELB/AwsElb.node.js", "dist/nodes/Aws/Rekognition/AwsRekognition.node.js", "dist/nodes/Aws/S3/AwsS3.node.js", "dist/nodes/Aws/SES/AwsSes.node.js", "dist/nodes/Aws/SQS/AwsSqs.node.js", "dist/nodes/Aws/Textract/AwsTextract.node.js", "dist/nodes/Aws/Transcribe/AwsTranscribe.node.js", "dist/nodes/BambooHr/BambooHr.node.js", "dist/nodes/Bannerbear/Bannerbear.node.js", "dist/nodes/Baserow/Baserow.node.js", "dist/nodes/Beeminder/Beeminder.node.js", "dist/nodes/Bitbucket/BitbucketTrigger.node.js", "dist/nodes/Bitly/Bitly.node.js", "dist/nodes/Bitwarden/Bitwarden.node.js", "dist/nodes/Box/Box.node.js", "dist/nodes/Box/BoxTrigger.node.js", "dist/nodes/Brandfetch/Brandfetch.node.js", "dist/nodes/Bubble/Bubble.node.js", "dist/nodes/Cal/CalTrigger.node.js", "dist/nodes/Calendly/CalendlyTrigger.node.js", "dist/nodes/Chargebee/Chargebee.node.js", "dist/nodes/Chargebee/ChargebeeTrigger.node.js", "dist/nodes/CircleCi/CircleCi.node.js", "dist/nodes/Cisco/Webex/CiscoWebex.node.js", "dist/nodes/Citrix/ADC/CitrixAdc.node.js", "dist/nodes/Cisco/Webex/CiscoWebexTrigger.node.js", "dist/nodes/Cloudflare/Cloudflare.node.js", "dist/nodes/Clearbit/Clearbit.node.js", "dist/nodes/ClickUp/ClickUp.node.js", "dist/nodes/ClickUp/ClickUpTrigger.node.js", "dist/nodes/Clockify/Clockify.node.js", "dist/nodes/Clockify/ClockifyTrigger.node.js", "dist/nodes/Cockpit/Cockpit.node.js", "dist/nodes/Coda/Coda.node.js", "dist/nodes/Code/Code.node.js", "dist/nodes/CoinGecko/CoinGecko.node.js", "dist/nodes/CompareDatasets/CompareDatasets.node.js", "dist/nodes/Compression/Compression.node.js", "dist/nodes/Contentful/Contentful.node.js", "dist/nodes/ConvertKit/ConvertKit.node.js", "dist/nodes/ConvertKit/ConvertKitTrigger.node.js", "dist/nodes/Copper/Copper.node.js", "dist/nodes/Copper/CopperTrigger.node.js", "dist/nodes/Cortex/Cortex.node.js", "dist/nodes/CrateDb/CrateDb.node.js", "dist/nodes/Cron/Cron.node.js", "dist/nodes/CrowdDev/CrowdDev.node.js", "dist/nodes/CrowdDev/CrowdDevTrigger.node.js", "dist/nodes/Crypto/Crypto.node.js", "dist/nodes/CustomerIo/CustomerIo.node.js", "dist/nodes/CustomerIo/CustomerIoTrigger.node.js", "dist/nodes/DateTime/DateTime.node.js", "dist/nodes/DebugHelper/DebugHelper.node.js", "dist/nodes/DeepL/DeepL.node.js", "dist/nodes/Demio/Demio.node.js", "dist/nodes/Dhl/Dhl.node.js", "dist/nodes/Discord/Discord.node.js", "dist/nodes/Discourse/Discourse.node.js", "dist/nodes/Disqus/Disqus.node.js", "dist/nodes/Drift/Drift.node.js", "dist/nodes/Dropbox/Dropbox.node.js", "dist/nodes/Dropcontact/Dropcontact.node.js", "dist/nodes/EditImage/EditImage.node.js", "dist/nodes/E2eTest/E2eTest.node.js", "dist/nodes/Egoi/Egoi.node.js", "dist/nodes/Elastic/Elasticsearch/Elasticsearch.node.js", "dist/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.js", "dist/nodes/EmailReadImap/EmailReadImap.node.js", "dist/nodes/EmailSend/EmailSend.node.js", "dist/nodes/Emelia/Emelia.node.js", "dist/nodes/Emelia/EmeliaTrigger.node.js", "dist/nodes/ERPNext/ERPNext.node.js", "dist/nodes/ErrorTrigger/ErrorTrigger.node.js", "dist/nodes/Eventbrite/EventbriteTrigger.node.js", "dist/nodes/ExecuteCommand/ExecuteCommand.node.js", "dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js", "dist/nodes/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node.js", "dist/nodes/ExecutionData/ExecutionData.node.js", "dist/nodes/Facebook/FacebookGraphApi.node.js", "dist/nodes/Facebook/FacebookTrigger.node.js", "dist/nodes/FacebookLeadAds/FacebookLeadAdsTrigger.node.js", "dist/nodes/Figma/FigmaTrigger.node.js", "dist/nodes/FileMaker/FileMaker.node.js", "dist/nodes/Filter/Filter.node.js", "dist/nodes/Flow/Flow.node.js", "dist/nodes/Flow/FlowTrigger.node.js", "dist/nodes/Form/FormTrigger.node.js", "dist/nodes/FormIo/FormIoTrigger.node.js", "dist/nodes/Formstack/FormstackTrigger.node.js", "dist/nodes/Freshdesk/Freshdesk.node.js", "dist/nodes/Freshservice/Freshservice.node.js", "dist/nodes/FreshworksCrm/FreshworksCrm.node.js", "dist/nodes/Ftp/Ftp.node.js", "dist/nodes/Function/Function.node.js", "dist/nodes/FunctionItem/FunctionItem.node.js", "dist/nodes/GetResponse/GetResponse.node.js", "dist/nodes/GetResponse/GetResponseTrigger.node.js", "dist/nodes/Ghost/Ghost.node.js", "dist/nodes/Git/Git.node.js", "dist/nodes/Github/Github.node.js", "dist/nodes/Github/GithubTrigger.node.js", "dist/nodes/Gitlab/Gitlab.node.js", "dist/nodes/Gitlab/GitlabTrigger.node.js", "dist/nodes/Google/Ads/GoogleAds.node.js", "dist/nodes/Google/Analytics/GoogleAnalytics.node.js", "dist/nodes/Google/BigQuery/GoogleBigQuery.node.js", "dist/nodes/Google/Books/GoogleBooks.node.js", "dist/nodes/Google/Calendar/GoogleCalendar.node.js", "dist/nodes/Google/Calendar/GoogleCalendarTrigger.node.js", "dist/nodes/Google/Chat/GoogleChat.node.js", "dist/nodes/Google/CloudNaturalLanguage/GoogleCloudNaturalLanguage.node.js", "dist/nodes/Google/CloudStorage/GoogleCloudStorage.node.js", "dist/nodes/Google/Contacts/GoogleContacts.node.js", "dist/nodes/Google/Docs/GoogleDocs.node.js", "dist/nodes/Google/Drive/GoogleDrive.node.js", "dist/nodes/Google/Drive/GoogleDriveTrigger.node.js", "dist/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.js", "dist/nodes/Google/Firebase/RealtimeDatabase/GoogleFirebaseRealtimeDatabase.node.js", "dist/nodes/Google/Gmail/Gmail.node.js", "dist/nodes/Google/Gmail/GmailTrigger.node.js", "dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js", "dist/nodes/Google/Perspective/GooglePerspective.node.js", "dist/nodes/Google/Sheet/GoogleSheets.node.js", "dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js", "dist/nodes/Google/Slides/GoogleSlides.node.js", "dist/nodes/Google/Task/GoogleTasks.node.js", "dist/nodes/Google/Translate/GoogleTranslate.node.js", "dist/nodes/Google/YouTube/YouTube.node.js", "dist/nodes/Gotify/Gotify.node.js", "dist/nodes/GoToWebinar/GoToWebinar.node.js", "dist/nodes/Grafana/Grafana.node.js", "dist/nodes/GraphQL/GraphQL.node.js", "dist/nodes/Grist/Grist.node.js", "dist/nodes/Gumroad/GumroadTrigger.node.js", "dist/nodes/HackerNews/HackerNews.node.js", "dist/nodes/HaloPSA/HaloPSA.node.js", "dist/nodes/Harvest/Harvest.node.js", "dist/nodes/HelpScout/HelpScout.node.js", "dist/nodes/HelpScout/HelpScoutTrigger.node.js", "dist/nodes/HighLevel/HighLevel.node.js", "dist/nodes/HomeAssistant/HomeAssistant.node.js", "dist/nodes/HtmlExtract/HtmlExtract.node.js", "dist/nodes/Html/Html.node.js", "dist/nodes/HttpRequest/HttpRequest.node.js", "dist/nodes/Hubspot/Hubspot.node.js", "dist/nodes/Hubspot/HubspotTrigger.node.js", "dist/nodes/HumanticAI/HumanticAi.node.js", "dist/nodes/Hunter/Hunter.node.js", "dist/nodes/ICalendar/ICalendar.node.js", "dist/nodes/If/If.node.js", "dist/nodes/Intercom/Intercom.node.js", "dist/nodes/Interval/Interval.node.js", "dist/nodes/InvoiceNinja/InvoiceNinja.node.js", "dist/nodes/InvoiceNinja/InvoiceNinjaTrigger.node.js", "dist/nodes/ItemLists/ItemLists.node.js", "dist/nodes/Iterable/Iterable.node.js", "dist/nodes/Jenkins/Jenkins.node.js", "dist/nodes/Jira/Jira.node.js", "dist/nodes/Jira/JiraTrigger.node.js", "dist/nodes/JotForm/JotFormTrigger.node.js", "dist/nodes/Kafka/Kafka.node.js", "dist/nodes/Kafka/KafkaTrigger.node.js", "dist/nodes/Keap/Keap.node.js", "dist/nodes/Keap/KeapTrigger.node.js", "dist/nodes/Kitemaker/Kitemaker.node.js", "dist/nodes/KoBoToolbox/KoBoToolbox.node.js", "dist/nodes/KoBoToolbox/KoBoToolboxTrigger.node.js", "dist/nodes/Ldap/Ldap.node.js", "dist/nodes/Lemlist/Lemlist.node.js", "dist/nodes/Lemlist/LemlistTrigger.node.js", "dist/nodes/Line/Line.node.js", "dist/nodes/Linear/Linear.node.js", "dist/nodes/Linear/LinearTrigger.node.js", "dist/nodes/LingvaNex/LingvaNex.node.js", "dist/nodes/LinkedIn/LinkedIn.node.js", "dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js", "dist/nodes/LoneScale/LoneScaleTrigger.node.js", "dist/nodes/LoneScale/LoneScale.node.js", "dist/nodes/Magento/Magento2.node.js", "dist/nodes/Mailcheck/Mailcheck.node.js", "dist/nodes/Mailchimp/Mailchimp.node.js", "dist/nodes/Mailchimp/MailchimpTrigger.node.js", "dist/nodes/MailerLite/MailerLite.node.js", "dist/nodes/MailerLite/MailerLiteTrigger.node.js", "dist/nodes/Mailgun/Mailgun.node.js", "dist/nodes/Mailjet/Mailjet.node.js", "dist/nodes/Mailjet/MailjetTrigger.node.js", "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/ManualTrigger/ManualTrigger.node.js", "dist/nodes/Markdown/Markdown.node.js", "dist/nodes/Marketstack/Marketstack.node.js", "dist/nodes/Matrix/Matrix.node.js", "dist/nodes/Mattermost/Mattermost.node.js", "dist/nodes/Mautic/Mautic.node.js", "dist/nodes/Mautic/MauticTrigger.node.js", "dist/nodes/Medium/Medium.node.js", "dist/nodes/Merge/Merge.node.js", "dist/nodes/MessageBird/MessageBird.node.js", "dist/nodes/Metabase/Metabase.node.js", "dist/nodes/Microsoft/Dynamics/MicrosoftDynamicsCrm.node.js", "dist/nodes/Microsoft/Excel/MicrosoftExcel.node.js", "dist/nodes/Microsoft/GraphSecurity/MicrosoftGraphSecurity.node.js", "dist/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.js", "dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js", "dist/nodes/Microsoft/Sql/MicrosoftSql.node.js", "dist/nodes/Microsoft/Teams/MicrosoftTeams.node.js", "dist/nodes/Microsoft/ToDo/MicrosoftToDo.node.js", "dist/nodes/Mindee/Mindee.node.js", "dist/nodes/Misp/Misp.node.js", "dist/nodes/Mocean/Mocean.node.js", "dist/nodes/MondayCom/MondayCom.node.js", "dist/nodes/MongoDb/MongoDb.node.js", "dist/nodes/MonicaCrm/MonicaCrm.node.js", "dist/nodes/MoveBinaryData/MoveBinaryData.node.js", "dist/nodes/MQTT/Mqtt.node.js", "dist/nodes/MQTT/MqttTrigger.node.js", "dist/nodes/Msg91/Msg91.node.js", "dist/nodes/MySql/MySql.node.js", "dist/nodes/N8n/N8n.node.js", "dist/nodes/N8nTrainingCustomerDatastore/N8nTrainingCustomerDatastore.node.js", "dist/nodes/N8nTrainingCustomerMessenger/N8nTrainingCustomerMessenger.node.js", "dist/nodes/N8nTrigger/N8nTrigger.node.js", "dist/nodes/Nasa/Nasa.node.js", "dist/nodes/Netlify/Netlify.node.js", "dist/nodes/Netlify/NetlifyTrigger.node.js", "dist/nodes/NextCloud/NextCloud.node.js", "dist/nodes/NocoDB/NocoDB.node.js", "dist/nodes/Brevo/Brevo.node.js", "dist/nodes/Brevo/BrevoTrigger.node.js", "dist/nodes/StickyNote/StickyNote.node.js", "dist/nodes/NoOp/NoOp.node.js", "dist/nodes/Onfleet/Onfleet.node.js", "dist/nodes/Onfleet/OnfleetTrigger.node.js", "dist/nodes/Notion/Notion.node.js", "dist/nodes/Notion/NotionTrigger.node.js", "dist/nodes/Npm/Npm.node.js", "dist/nodes/Odoo/Odoo.node.js", "dist/nodes/OneSimpleApi/OneSimpleApi.node.js", "dist/nodes/OpenAi/OpenAi.node.js", "dist/nodes/OpenThesaurus/OpenThesaurus.node.js", "dist/nodes/OpenWeatherMap/OpenWeatherMap.node.js", "dist/nodes/Orbit/Orbit.node.js", "dist/nodes/Oura/Oura.node.js", "dist/nodes/Paddle/Paddle.node.js", "dist/nodes/PagerDuty/PagerDuty.node.js", "dist/nodes/PayPal/PayPal.node.js", "dist/nodes/PayPal/PayPalTrigger.node.js", "dist/nodes/Peekalink/Peekalink.node.js", "dist/nodes/Phantombuster/Phantombuster.node.js", "dist/nodes/PhilipsHue/PhilipsHue.node.js", "dist/nodes/Pipedrive/Pipedrive.node.js", "dist/nodes/Pipedrive/PipedriveTrigger.node.js", "dist/nodes/Plivo/Plivo.node.js", "dist/nodes/PostBin/PostBin.node.js", "dist/nodes/Postgres/Postgres.node.js", "dist/nodes/Postgres/PostgresTrigger.node.js", "dist/nodes/PostHog/PostHog.node.js", "dist/nodes/Postmark/PostmarkTrigger.node.js", "dist/nodes/ProfitWell/ProfitWell.node.js", "dist/nodes/Pushbullet/Pushbullet.node.js", "dist/nodes/Pushcut/Pushcut.node.js", "dist/nodes/Pushcut/PushcutTrigger.node.js", "dist/nodes/Pushover/Pushover.node.js", "dist/nodes/QuestDb/QuestDb.node.js", "dist/nodes/QuickBase/QuickBase.node.js", "dist/nodes/QuickBooks/QuickBooks.node.js", "dist/nodes/QuickChart/QuickChart.node.js", "dist/nodes/RabbitMQ/RabbitMQ.node.js", "dist/nodes/RabbitMQ/RabbitMQTrigger.node.js", "dist/nodes/Raindrop/Raindrop.node.js", "dist/nodes/ReadBinaryFile/ReadBinaryFile.node.js", "dist/nodes/ReadBinaryFiles/ReadBinaryFiles.node.js", "dist/nodes/ReadPdf/ReadPDF.node.js", "dist/nodes/Reddit/Reddit.node.js", "dist/nodes/Redis/Redis.node.js", "dist/nodes/Redis/RedisTrigger.node.js", "dist/nodes/RenameKeys/RenameKeys.node.js", "dist/nodes/RespondToWebhook/RespondToWebhook.node.js", "dist/nodes/Rocketchat/Rocketchat.node.js", "dist/nodes/RssFeedRead/RssFeedRead.node.js", "dist/nodes/RssFeedRead/RssFeedReadTrigger.node.js", "dist/nodes/Rundeck/Rundeck.node.js", "dist/nodes/S3/S3.node.js", "dist/nodes/Salesforce/Salesforce.node.js", "dist/nodes/Salesmate/Salesmate.node.js", "dist/nodes/Schedule/ScheduleTrigger.node.js", "dist/nodes/SeaTable/SeaTable.node.js", "dist/nodes/SeaTable/SeaTableTrigger.node.js", "dist/nodes/SecurityScorecard/SecurityScorecard.node.js", "dist/nodes/Segment/Segment.node.js", "dist/nodes/SendGrid/SendGrid.node.js", "dist/nodes/Sendy/Sendy.node.js", "dist/nodes/SentryIo/SentryIo.node.js", "dist/nodes/ServiceNow/ServiceNow.node.js", "dist/nodes/Set/Set.node.js", "dist/nodes/Shopify/Shopify.node.js", "dist/nodes/Shopify/ShopifyTrigger.node.js", "dist/nodes/Signl4/Signl4.node.js", "dist/nodes/Slack/Slack.node.js", "dist/nodes/Sms77/Sms77.node.js", "dist/nodes/Snowflake/Snowflake.node.js", "dist/nodes/SplitInBatches/SplitInBatches.node.js", "dist/nodes/Splunk/Splunk.node.js", "dist/nodes/Spontit/Spontit.node.js", "dist/nodes/Spotify/Spotify.node.js", "dist/nodes/SpreadsheetFile/SpreadsheetFile.node.js", "dist/nodes/SseTrigger/SseTrigger.node.js", "dist/nodes/Ssh/Ssh.node.js", "dist/nodes/Stackby/Stackby.node.js", "dist/nodes/Start/Start.node.js", "dist/nodes/StopAndError/StopAndError.node.js", "dist/nodes/Storyblok/Storyblok.node.js", "dist/nodes/Strapi/Strapi.node.js", "dist/nodes/Strava/Strava.node.js", "dist/nodes/Strava/StravaTrigger.node.js", "dist/nodes/Stripe/Stripe.node.js", "dist/nodes/Stripe/StripeTrigger.node.js", "dist/nodes/Supabase/Supabase.node.js", "dist/nodes/SurveyMonkey/SurveyMonkeyTrigger.node.js", "dist/nodes/Switch/Switch.node.js", "dist/nodes/SyncroMSP/SyncroMsp.node.js", "dist/nodes/Taiga/Taiga.node.js", "dist/nodes/Taiga/TaigaTrigger.node.js", "dist/nodes/Tapfiliate/Tapfiliate.node.js", "dist/nodes/Telegram/Telegram.node.js", "dist/nodes/Telegram/TelegramTrigger.node.js", "dist/nodes/TheHiveProject/TheHiveProject.node.js", "dist/nodes/TheHiveProject/TheHiveProjectTrigger.node.js", "dist/nodes/TheHive/TheHive.node.js", "dist/nodes/TheHive/TheHiveTrigger.node.js", "dist/nodes/TimescaleDb/TimescaleDb.node.js", "dist/nodes/Todoist/Todoist.node.js", "dist/nodes/Toggl/TogglTrigger.node.js", "dist/nodes/Totp/Totp.node.js", "dist/nodes/TravisCi/TravisCi.node.js", "dist/nodes/Trello/Trello.node.js", "dist/nodes/Trello/TrelloTrigger.node.js", "dist/nodes/Twake/Twake.node.js", "dist/nodes/Twilio/Twilio.node.js", "dist/nodes/Twist/Twist.node.js", "dist/nodes/Twitter/Twitter.node.js", "dist/nodes/Typeform/TypeformTrigger.node.js", "dist/nodes/UnleashedSoftware/UnleashedSoftware.node.js", "dist/nodes/Uplead/Uplead.node.js", "dist/nodes/UProc/UProc.node.js", "dist/nodes/UptimeRobot/UptimeRobot.node.js", "dist/nodes/UrlScanIo/UrlScanIo.node.js", "dist/nodes/Vero/Vero.node.js", "dist/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.js", "dist/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloudTrigger.node.js", "dist/nodes/Venafi/Datacenter/VenafiTlsProtectDatacenter.node.js", "dist/nodes/Vonage/Vonage.node.js", "dist/nodes/Wait/Wait.node.js", "dist/nodes/Webflow/Webflow.node.js", "dist/nodes/Webflow/WebflowTrigger.node.js", "dist/nodes/Webhook/Webhook.node.js", "dist/nodes/Wekan/Wekan.node.js", "dist/nodes/WhatsApp/WhatsApp.node.js", "dist/nodes/Wise/Wise.node.js", "dist/nodes/Wise/WiseTrigger.node.js", "dist/nodes/WooCommerce/WooCommerce.node.js", "dist/nodes/WooCommerce/WooCommerceTrigger.node.js", "dist/nodes/Wordpress/Wordpress.node.js", "dist/nodes/Workable/WorkableTrigger.node.js", "dist/nodes/WorkflowTrigger/WorkflowTrigger.node.js", "dist/nodes/WriteBinaryFile/WriteBinaryFile.node.js", "dist/nodes/Wufoo/WufooTrigger.node.js", "dist/nodes/Xero/Xero.node.js", "dist/nodes/Xml/Xml.node.js", "dist/nodes/Yourls/Yourls.node.js", "dist/nodes/Zammad/Zammad.node.js", "dist/nodes/Zendesk/Zendesk.node.js", "dist/nodes/Zendesk/ZendeskTrigger.node.js", "dist/nodes/Zoho/ZohoCrm.node.js", "dist/nodes/Zoom/Zoom.node.js", "dist/nodes/Zulip/Zulip.node.js" ] }, "devDependencies": { "@types/amqplib": "^0.10.1", "@types/aws4": "^1.5.1", "@types/basic-auth": "^1.1.3", "@types/cheerio": "^0.22.15", "@types/cron": "~1.7.1", "@types/eventsource": "^1.1.2", "@types/express": "^4.17.6", "@types/gm": "^1.25.0", "@types/imap-simple": "^4.2.0", "@types/js-nacl": "^1.3.0", "@types/jsonwebtoken": "^9.0.1", "@types/lodash": "^4.14.195", "@types/lossless-json": "^1.0.0", "@types/mailparser": "^2.7.3", "@types/mime-types": "^2.1.0", "@types/mssql": "^6.0.2", "@types/node-ssh": "^7.0.1", "@types/nodemailer": "^6.4.0", "@types/promise-ftp": "^1.3.4", "@types/redis": "^2.8.11", "@types/request-promise-native": "~1.0.15", "@types/rfc2047": "^2.0.1", "@types/showdown": "^1.9.4", "@types/snowflake-sdk": "^1.6.12", "@types/ssh2-sftp-client": "^5.1.0", "@types/tmp": "^0.2.0", "@types/uuid": "^8.3.2", "@types/xml2js": "^0.4.11", "eslint-plugin-n8n-nodes-base": "^1.16.0", "gulp": "^4.0.0", "n8n-core": "1.14.1" }, "dependencies": { "@kafkajs/confluent-schema-registry": "1.0.6", "@n8n/vm2": "^3.9.20", "amqplib": "^0.10.3", "aws4": "^1.8.0", "basic-auth": "^2.0.1", "change-case": "^4.1.1", "cheerio": "1.0.0-rc.6", "chokidar": "3.5.2", "cron": "~1.7.2", "csv-parse": "^5.5.0", "currency-codes": "^2.1.0", "eventsource": "^2.0.2", "fast-glob": "^3.2.5", "fflate": "^0.7.0", "get-system-fonts": "^2.0.2", "gm": "^1.25.0", "iconv-lite": "^0.6.2", "ics": "^2.27.0", "imap-simple": "^4.3.0", "isbot": "^3.6.13", "iso-639-1": "^2.1.3", "js-nacl": "^1.4.0", "jsonwebtoken": "^9.0.0", "kafkajs": "^1.14.0", "ldapts": "^4.2.6", "lodash": "^4.17.21", "lossless-json": "^1.0.4", "luxon": "^3.3.0", "mailparser": "^3.2.0", "minifaker": "^1.34.1", "moment": "~2.29.2", "moment-timezone": "^0.5.28", "mongodb": "^4.17.1", "mqtt": "^5.0.2", "mssql": "^8.1.2", "mysql2": "~2.3.0", "nanoid": "^3.3.6", "node-html-markdown": "^1.1.3", "node-ssh": "^12.0.0", "nodemailer": "^6.7.1", "otpauth": "^9.1.1", "pdfjs-dist": "^2.16.105", "pg": "^8.3.0", "pg-promise": "^10.5.8", "pretty-bytes": "^5.6.0", "promise-ftp": "^1.3.5", "pyodide": "^0.23.4", "redis": "^3.1.1", "rfc2047": "^4.0.1", "rhea": "^1.0.11", "rss-parser": "^3.7.0", "semver": "^7.5.4", "showdown": "^2.0.3", "simple-git": "^3.17.0", "snowflake-sdk": "^1.8.0", "ssh2-sftp-client": "^7.0.0", "tmp-promise": "^3.0.2", "typedi": "^0.10.0", "uuid": "^8.3.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz", "xml2js": "^0.5.0", "n8n-workflow": "1.14.1" }, "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", "typecheck": "tsc", "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && gulp build:icons && gulp build:translations && pnpm build:metadata", "build:translations": "gulp build:translations", "build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types", "format": "prettier --write . --ignore-path ../../.prettierignore", "lint": "eslint . --quiet && node ./scripts/validate-load-options-methods.js", "lintfix": "eslint . --fix", "watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"", "test": "jest" } }, "extraction_time_ms": 5, "extracted_at": "2025-06-07T17:49:22.730Z" } ``` -------------------------------------------------------------------------------- /tests/extracted-nodes-db/n8n-nodes-base__HttpRequest.json: -------------------------------------------------------------------------------- ```json { "node_type": "n8n-nodes-base.HttpRequest", "name": "HttpRequest", "package_name": "n8n-nodes-base", "code_hash": "5b5e2328474b7e85361c940dfe942e167b3f0057f38062f56d6b693f0a7ffe7e", "code_length": 1343, "source_location": "node_modules/n8n-nodes-base/dist/nodes/HttpRequest/HttpRequest.node.js", "has_credentials": false, "source_code": "\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.HttpRequest = void 0;\nconst n8n_workflow_1 = require(\"n8n-workflow\");\nconst HttpRequestV1_node_1 = require(\"./V1/HttpRequestV1.node\");\nconst HttpRequestV2_node_1 = require(\"./V2/HttpRequestV2.node\");\nconst HttpRequestV3_node_1 = require(\"./V3/HttpRequestV3.node\");\nclass HttpRequest extends n8n_workflow_1.VersionedNodeType {\n constructor() {\n const baseDescription = {\n displayName: 'HTTP Request',\n name: 'httpRequest',\n icon: 'fa:at',\n group: ['output'],\n subtitle: '={{$parameter[\"requestMethod\"] + \": \" + $parameter[\"url\"]}}',\n description: 'Makes an HTTP request and returns the response data',\n defaultVersion: 4.1,\n };\n const nodeVersions = {\n 1: new HttpRequestV1_node_1.HttpRequestV1(baseDescription),\n 2: new HttpRequestV2_node_1.HttpRequestV2(baseDescription),\n 3: new HttpRequestV3_node_1.HttpRequestV3(baseDescription),\n 4: new HttpRequestV3_node_1.HttpRequestV3(baseDescription),\n 4.1: new HttpRequestV3_node_1.HttpRequestV3(baseDescription),\n };\n super(nodeVersions, baseDescription);\n }\n}\nexports.HttpRequest = HttpRequest;\n//# sourceMappingURL=HttpRequest.node.js.map", "package_info": { "name": "n8n-nodes-base", "version": "1.14.1", "description": "Base nodes of n8n", "license": "SEE LICENSE IN LICENSE.md", "homepage": "https://n8n.io", "author": { "name": "Jan Oberhauser", "email": "[email protected]" }, "main": "index.js", "repository": { "type": "git", "url": "git+https://github.com/n8n-io/n8n.git" }, "files": [ "dist" ], "n8n": { "credentials": [ "dist/credentials/ActionNetworkApi.credentials.js", "dist/credentials/ActiveCampaignApi.credentials.js", "dist/credentials/AcuitySchedulingApi.credentials.js", "dist/credentials/AcuitySchedulingOAuth2Api.credentials.js", "dist/credentials/AdaloApi.credentials.js", "dist/credentials/AffinityApi.credentials.js", "dist/credentials/AgileCrmApi.credentials.js", "dist/credentials/AirtableApi.credentials.js", "dist/credentials/AirtableOAuth2Api.credentials.js", "dist/credentials/AirtableTokenApi.credentials.js", "dist/credentials/AlienVaultApi.credentials.js", "dist/credentials/Amqp.credentials.js", "dist/credentials/ApiTemplateIoApi.credentials.js", "dist/credentials/AsanaApi.credentials.js", "dist/credentials/AsanaOAuth2Api.credentials.js", "dist/credentials/Auth0ManagementApi.credentials.js", "dist/credentials/AutomizyApi.credentials.js", "dist/credentials/AutopilotApi.credentials.js", "dist/credentials/Aws.credentials.js", "dist/credentials/BambooHrApi.credentials.js", "dist/credentials/BannerbearApi.credentials.js", "dist/credentials/BaserowApi.credentials.js", "dist/credentials/BeeminderApi.credentials.js", "dist/credentials/BitbucketApi.credentials.js", "dist/credentials/BitlyApi.credentials.js", "dist/credentials/BitlyOAuth2Api.credentials.js", "dist/credentials/BitwardenApi.credentials.js", "dist/credentials/BoxOAuth2Api.credentials.js", "dist/credentials/BrandfetchApi.credentials.js", "dist/credentials/BubbleApi.credentials.js", "dist/credentials/CalApi.credentials.js", "dist/credentials/CalendlyApi.credentials.js", "dist/credentials/CarbonBlackApi.credentials.js", "dist/credentials/ChargebeeApi.credentials.js", "dist/credentials/CircleCiApi.credentials.js", "dist/credentials/CiscoMerakiApi.credentials.js", "dist/credentials/CiscoSecureEndpointApi.credentials.js", "dist/credentials/CiscoWebexOAuth2Api.credentials.js", "dist/credentials/CiscoUmbrellaApi.credentials.js", "dist/credentials/CitrixAdcApi.credentials.js", "dist/credentials/CloudflareApi.credentials.js", "dist/credentials/ClearbitApi.credentials.js", "dist/credentials/ClickUpApi.credentials.js", "dist/credentials/ClickUpOAuth2Api.credentials.js", "dist/credentials/ClockifyApi.credentials.js", "dist/credentials/CockpitApi.credentials.js", "dist/credentials/CodaApi.credentials.js", "dist/credentials/ContentfulApi.credentials.js", "dist/credentials/ConvertKitApi.credentials.js", "dist/credentials/CopperApi.credentials.js", "dist/credentials/CortexApi.credentials.js", "dist/credentials/CrateDb.credentials.js", "dist/credentials/CrowdStrikeOAuth2Api.credentials.js", "dist/credentials/CrowdDevApi.credentials.js", "dist/credentials/CustomerIoApi.credentials.js", "dist/credentials/DeepLApi.credentials.js", "dist/credentials/DemioApi.credentials.js", "dist/credentials/DhlApi.credentials.js", "dist/credentials/DiscourseApi.credentials.js", "dist/credentials/DisqusApi.credentials.js", "dist/credentials/DriftApi.credentials.js", "dist/credentials/DriftOAuth2Api.credentials.js", "dist/credentials/DropboxApi.credentials.js", "dist/credentials/DropboxOAuth2Api.credentials.js", "dist/credentials/DropcontactApi.credentials.js", "dist/credentials/EgoiApi.credentials.js", "dist/credentials/ElasticsearchApi.credentials.js", "dist/credentials/ElasticSecurityApi.credentials.js", "dist/credentials/EmeliaApi.credentials.js", "dist/credentials/ERPNextApi.credentials.js", "dist/credentials/EventbriteApi.credentials.js", "dist/credentials/EventbriteOAuth2Api.credentials.js", "dist/credentials/F5BigIpApi.credentials.js", "dist/credentials/FacebookGraphApi.credentials.js", "dist/credentials/FacebookGraphAppApi.credentials.js", "dist/credentials/FacebookLeadAdsOAuth2Api.credentials.js", "dist/credentials/FigmaApi.credentials.js", "dist/credentials/FileMaker.credentials.js", "dist/credentials/FlowApi.credentials.js", "dist/credentials/FormIoApi.credentials.js", "dist/credentials/FormstackApi.credentials.js", "dist/credentials/FormstackOAuth2Api.credentials.js", "dist/credentials/FortiGateApi.credentials.js", "dist/credentials/FreshdeskApi.credentials.js", "dist/credentials/FreshserviceApi.credentials.js", "dist/credentials/FreshworksCrmApi.credentials.js", "dist/credentials/Ftp.credentials.js", "dist/credentials/GetResponseApi.credentials.js", "dist/credentials/GetResponseOAuth2Api.credentials.js", "dist/credentials/GhostAdminApi.credentials.js", "dist/credentials/GhostContentApi.credentials.js", "dist/credentials/GithubApi.credentials.js", "dist/credentials/GithubOAuth2Api.credentials.js", "dist/credentials/GitlabApi.credentials.js", "dist/credentials/GitlabOAuth2Api.credentials.js", "dist/credentials/GitPassword.credentials.js", "dist/credentials/GmailOAuth2Api.credentials.js", "dist/credentials/GoogleAdsOAuth2Api.credentials.js", "dist/credentials/GoogleAnalyticsOAuth2Api.credentials.js", "dist/credentials/GoogleApi.credentials.js", "dist/credentials/GoogleBigQueryOAuth2Api.credentials.js", "dist/credentials/GoogleBooksOAuth2Api.credentials.js", "dist/credentials/GoogleCalendarOAuth2Api.credentials.js", "dist/credentials/GoogleCloudNaturalLanguageOAuth2Api.credentials.js", "dist/credentials/GoogleCloudStorageOAuth2Api.credentials.js", "dist/credentials/GoogleContactsOAuth2Api.credentials.js", "dist/credentials/GoogleDocsOAuth2Api.credentials.js", "dist/credentials/GoogleDriveOAuth2Api.credentials.js", "dist/credentials/GoogleFirebaseCloudFirestoreOAuth2Api.credentials.js", "dist/credentials/GoogleFirebaseRealtimeDatabaseOAuth2Api.credentials.js", "dist/credentials/GoogleOAuth2Api.credentials.js", "dist/credentials/GooglePerspectiveOAuth2Api.credentials.js", "dist/credentials/GoogleSheetsOAuth2Api.credentials.js", "dist/credentials/GoogleSheetsTriggerOAuth2Api.credentials.js", "dist/credentials/GoogleSlidesOAuth2Api.credentials.js", "dist/credentials/GoogleTasksOAuth2Api.credentials.js", "dist/credentials/GoogleTranslateOAuth2Api.credentials.js", "dist/credentials/GotifyApi.credentials.js", "dist/credentials/GoToWebinarOAuth2Api.credentials.js", "dist/credentials/GristApi.credentials.js", "dist/credentials/GrafanaApi.credentials.js", "dist/credentials/GSuiteAdminOAuth2Api.credentials.js", "dist/credentials/GumroadApi.credentials.js", "dist/credentials/HaloPSAApi.credentials.js", "dist/credentials/HarvestApi.credentials.js", "dist/credentials/HarvestOAuth2Api.credentials.js", "dist/credentials/HelpScoutOAuth2Api.credentials.js", "dist/credentials/HighLevelApi.credentials.js", "dist/credentials/HomeAssistantApi.credentials.js", "dist/credentials/HttpBasicAuth.credentials.js", "dist/credentials/HttpDigestAuth.credentials.js", "dist/credentials/HttpHeaderAuth.credentials.js", "dist/credentials/HttpCustomAuth.credentials.js", "dist/credentials/HttpQueryAuth.credentials.js", "dist/credentials/HubspotApi.credentials.js", "dist/credentials/HubspotAppToken.credentials.js", "dist/credentials/HubspotDeveloperApi.credentials.js", "dist/credentials/HubspotOAuth2Api.credentials.js", "dist/credentials/HumanticAiApi.credentials.js", "dist/credentials/HunterApi.credentials.js", "dist/credentials/HybridAnalysisApi.credentials.js", "dist/credentials/Imap.credentials.js", "dist/credentials/ImpervaWafApi.credentials.js", "dist/credentials/IntercomApi.credentials.js", "dist/credentials/InvoiceNinjaApi.credentials.js", "dist/credentials/IterableApi.credentials.js", "dist/credentials/JenkinsApi.credentials.js", "dist/credentials/JiraSoftwareCloudApi.credentials.js", "dist/credentials/JiraSoftwareServerApi.credentials.js", "dist/credentials/JotFormApi.credentials.js", "dist/credentials/Kafka.credentials.js", "dist/credentials/KeapOAuth2Api.credentials.js", "dist/credentials/KibanaApi.credentials.js", "dist/credentials/KitemakerApi.credentials.js", "dist/credentials/KoBoToolboxApi.credentials.js", "dist/credentials/Ldap.credentials.js", "dist/credentials/LemlistApi.credentials.js", "dist/credentials/LinearApi.credentials.js", "dist/credentials/LinearOAuth2Api.credentials.js", "dist/credentials/LineNotifyOAuth2Api.credentials.js", "dist/credentials/LingvaNexApi.credentials.js", "dist/credentials/LinkedInOAuth2Api.credentials.js", "dist/credentials/LoneScaleApi.credentials.js", "dist/credentials/Magento2Api.credentials.js", "dist/credentials/MailcheckApi.credentials.js", "dist/credentials/MailchimpApi.credentials.js", "dist/credentials/MailchimpOAuth2Api.credentials.js", "dist/credentials/MailerLiteApi.credentials.js", "dist/credentials/MailgunApi.credentials.js", "dist/credentials/MailjetEmailApi.credentials.js", "dist/credentials/MailjetSmsApi.credentials.js", "dist/credentials/MandrillApi.credentials.js", "dist/credentials/MarketstackApi.credentials.js", "dist/credentials/MatrixApi.credentials.js", "dist/credentials/MattermostApi.credentials.js", "dist/credentials/MauticApi.credentials.js", "dist/credentials/MauticOAuth2Api.credentials.js", "dist/credentials/MediumApi.credentials.js", "dist/credentials/MediumOAuth2Api.credentials.js", "dist/credentials/MetabaseApi.credentials.js", "dist/credentials/MessageBirdApi.credentials.js", "dist/credentials/MetabaseApi.credentials.js", "dist/credentials/MicrosoftDynamicsOAuth2Api.credentials.js", "dist/credentials/MicrosoftEntraOAuth2Api.credentials.js", "dist/credentials/MicrosoftExcelOAuth2Api.credentials.js", "dist/credentials/MicrosoftGraphSecurityOAuth2Api.credentials.js", "dist/credentials/MicrosoftOAuth2Api.credentials.js", "dist/credentials/MicrosoftOneDriveOAuth2Api.credentials.js", "dist/credentials/MicrosoftOutlookOAuth2Api.credentials.js", "dist/credentials/MicrosoftSql.credentials.js", "dist/credentials/MicrosoftTeamsOAuth2Api.credentials.js", "dist/credentials/MicrosoftToDoOAuth2Api.credentials.js", "dist/credentials/MindeeInvoiceApi.credentials.js", "dist/credentials/MindeeReceiptApi.credentials.js", "dist/credentials/MispApi.credentials.js", "dist/credentials/MistApi.credentials.js", "dist/credentials/MoceanApi.credentials.js", "dist/credentials/MondayComApi.credentials.js", "dist/credentials/MondayComOAuth2Api.credentials.js", "dist/credentials/MongoDb.credentials.js", "dist/credentials/MonicaCrmApi.credentials.js", "dist/credentials/Mqtt.credentials.js", "dist/credentials/Msg91Api.credentials.js", "dist/credentials/MySql.credentials.js", "dist/credentials/N8nApi.credentials.js", "dist/credentials/NasaApi.credentials.js", "dist/credentials/NetlifyApi.credentials.js", "dist/credentials/NextCloudApi.credentials.js", "dist/credentials/NextCloudOAuth2Api.credentials.js", "dist/credentials/NocoDb.credentials.js", "dist/credentials/NocoDbApiToken.credentials.js", "dist/credentials/NotionApi.credentials.js", "dist/credentials/NotionOAuth2Api.credentials.js", "dist/credentials/NpmApi.credentials.js", "dist/credentials/OAuth1Api.credentials.js", "dist/credentials/OAuth2Api.credentials.js", "dist/credentials/OdooApi.credentials.js", "dist/credentials/OktaApi.credentials.js", "dist/credentials/OneSimpleApi.credentials.js", "dist/credentials/OnfleetApi.credentials.js", "dist/credentials/OpenAiApi.credentials.js", "dist/credentials/OpenCTIApi.credentials.js", "dist/credentials/OpenWeatherMapApi.credentials.js", "dist/credentials/OrbitApi.credentials.js", "dist/credentials/OuraApi.credentials.js", "dist/credentials/PaddleApi.credentials.js", "dist/credentials/PagerDutyApi.credentials.js", "dist/credentials/PagerDutyOAuth2Api.credentials.js", "dist/credentials/PayPalApi.credentials.js", "dist/credentials/PeekalinkApi.credentials.js", "dist/credentials/PhantombusterApi.credentials.js", "dist/credentials/PhilipsHueOAuth2Api.credentials.js", "dist/credentials/PipedriveApi.credentials.js", "dist/credentials/PipedriveOAuth2Api.credentials.js", "dist/credentials/PlivoApi.credentials.js", "dist/credentials/Postgres.credentials.js", "dist/credentials/PostHogApi.credentials.js", "dist/credentials/PostmarkApi.credentials.js", "dist/credentials/ProfitWellApi.credentials.js", "dist/credentials/PushbulletOAuth2Api.credentials.js", "dist/credentials/PushcutApi.credentials.js", "dist/credentials/PushoverApi.credentials.js", "dist/credentials/QRadarApi.credentials.js", "dist/credentials/QualysApi.credentials.js", "dist/credentials/QuestDb.credentials.js", "dist/credentials/QuickBaseApi.credentials.js", "dist/credentials/QuickBooksOAuth2Api.credentials.js", "dist/credentials/RabbitMQ.credentials.js", "dist/credentials/RaindropOAuth2Api.credentials.js", "dist/credentials/RecordedFutureApi.credentials.js", "dist/credentials/RedditOAuth2Api.credentials.js", "dist/credentials/Redis.credentials.js", "dist/credentials/RocketchatApi.credentials.js", "dist/credentials/RundeckApi.credentials.js", "dist/credentials/S3.credentials.js", "dist/credentials/SalesforceJwtApi.credentials.js", "dist/credentials/SalesforceOAuth2Api.credentials.js", "dist/credentials/SalesmateApi.credentials.js", "dist/credentials/SeaTableApi.credentials.js", "dist/credentials/SecurityScorecardApi.credentials.js", "dist/credentials/SegmentApi.credentials.js", "dist/credentials/SekoiaApi.credentials.js", "dist/credentials/SendGridApi.credentials.js", "dist/credentials/BrevoApi.credentials.js", "dist/credentials/SendyApi.credentials.js", "dist/credentials/SentryIoApi.credentials.js", "dist/credentials/SentryIoOAuth2Api.credentials.js", "dist/credentials/SentryIoServerApi.credentials.js", "dist/credentials/ServiceNowOAuth2Api.credentials.js", "dist/credentials/ServiceNowBasicApi.credentials.js", "dist/credentials/Sftp.credentials.js", "dist/credentials/ShopifyApi.credentials.js", "dist/credentials/ShopifyAccessTokenApi.credentials.js", "dist/credentials/ShopifyOAuth2Api.credentials.js", "dist/credentials/Signl4Api.credentials.js", "dist/credentials/SlackApi.credentials.js", "dist/credentials/SlackOAuth2Api.credentials.js", "dist/credentials/Sms77Api.credentials.js", "dist/credentials/Smtp.credentials.js", "dist/credentials/Snowflake.credentials.js", "dist/credentials/SplunkApi.credentials.js", "dist/credentials/SpontitApi.credentials.js", "dist/credentials/SpotifyOAuth2Api.credentials.js", "dist/credentials/ShufflerApi.credentials.js", "dist/credentials/SshPassword.credentials.js", "dist/credentials/SshPrivateKey.credentials.js", "dist/credentials/StackbyApi.credentials.js", "dist/credentials/StoryblokContentApi.credentials.js", "dist/credentials/StoryblokManagementApi.credentials.js", "dist/credentials/StrapiApi.credentials.js", "dist/credentials/StrapiTokenApi.credentials.js", "dist/credentials/StravaOAuth2Api.credentials.js", "dist/credentials/StripeApi.credentials.js", "dist/credentials/SupabaseApi.credentials.js", "dist/credentials/SurveyMonkeyApi.credentials.js", "dist/credentials/SurveyMonkeyOAuth2Api.credentials.js", "dist/credentials/SyncroMspApi.credentials.js", "dist/credentials/TaigaApi.credentials.js", "dist/credentials/TapfiliateApi.credentials.js", "dist/credentials/TelegramApi.credentials.js", "dist/credentials/TheHiveProjectApi.credentials.js", "dist/credentials/TheHiveApi.credentials.js", "dist/credentials/TimescaleDb.credentials.js", "dist/credentials/TodoistApi.credentials.js", "dist/credentials/TodoistOAuth2Api.credentials.js", "dist/credentials/TogglApi.credentials.js", "dist/credentials/TotpApi.credentials.js", "dist/credentials/TravisCiApi.credentials.js", "dist/credentials/TrellixEpoApi.credentials.js", "dist/credentials/TrelloApi.credentials.js", "dist/credentials/TwakeCloudApi.credentials.js", "dist/credentials/TwakeServerApi.credentials.js", "dist/credentials/TwilioApi.credentials.js", "dist/credentials/TwistOAuth2Api.credentials.js", "dist/credentials/TwitterOAuth1Api.credentials.js", "dist/credentials/TwitterOAuth2Api.credentials.js", "dist/credentials/TypeformApi.credentials.js", "dist/credentials/TypeformOAuth2Api.credentials.js", "dist/credentials/UnleashedSoftwareApi.credentials.js", "dist/credentials/UpleadApi.credentials.js", "dist/credentials/UProcApi.credentials.js", "dist/credentials/UptimeRobotApi.credentials.js", "dist/credentials/UrlScanIoApi.credentials.js", "dist/credentials/VeroApi.credentials.js", "dist/credentials/VirusTotalApi.credentials.js", "dist/credentials/VonageApi.credentials.js", "dist/credentials/VenafiTlsProtectCloudApi.credentials.js", "dist/credentials/VenafiTlsProtectDatacenterApi.credentials.js", "dist/credentials/WebflowApi.credentials.js", "dist/credentials/WebflowOAuth2Api.credentials.js", "dist/credentials/WekanApi.credentials.js", "dist/credentials/WhatsAppApi.credentials.js", "dist/credentials/WiseApi.credentials.js", "dist/credentials/WooCommerceApi.credentials.js", "dist/credentials/WordpressApi.credentials.js", "dist/credentials/WorkableApi.credentials.js", "dist/credentials/WufooApi.credentials.js", "dist/credentials/XeroOAuth2Api.credentials.js", "dist/credentials/YourlsApi.credentials.js", "dist/credentials/YouTubeOAuth2Api.credentials.js", "dist/credentials/ZammadBasicAuthApi.credentials.js", "dist/credentials/ZammadTokenAuthApi.credentials.js", "dist/credentials/ZendeskApi.credentials.js", "dist/credentials/ZendeskOAuth2Api.credentials.js", "dist/credentials/ZohoOAuth2Api.credentials.js", "dist/credentials/ZoomApi.credentials.js", "dist/credentials/ZoomOAuth2Api.credentials.js", "dist/credentials/ZscalerZiaApi.credentials.js", "dist/credentials/ZulipApi.credentials.js" ], "nodes": [ "dist/nodes/ActionNetwork/ActionNetwork.node.js", "dist/nodes/ActiveCampaign/ActiveCampaign.node.js", "dist/nodes/ActiveCampaign/ActiveCampaignTrigger.node.js", "dist/nodes/AcuityScheduling/AcuitySchedulingTrigger.node.js", "dist/nodes/Adalo/Adalo.node.js", "dist/nodes/Affinity/Affinity.node.js", "dist/nodes/Affinity/AffinityTrigger.node.js", "dist/nodes/AgileCrm/AgileCrm.node.js", "dist/nodes/Airtable/Airtable.node.js", "dist/nodes/Airtable/AirtableTrigger.node.js", "dist/nodes/Amqp/Amqp.node.js", "dist/nodes/Amqp/AmqpTrigger.node.js", "dist/nodes/ApiTemplateIo/ApiTemplateIo.node.js", "dist/nodes/Asana/Asana.node.js", "dist/nodes/Asana/AsanaTrigger.node.js", "dist/nodes/Automizy/Automizy.node.js", "dist/nodes/Autopilot/Autopilot.node.js", "dist/nodes/Autopilot/AutopilotTrigger.node.js", "dist/nodes/Aws/AwsLambda.node.js", "dist/nodes/Aws/AwsSns.node.js", "dist/nodes/Aws/AwsSnsTrigger.node.js", "dist/nodes/Aws/CertificateManager/AwsCertificateManager.node.js", "dist/nodes/Aws/Comprehend/AwsComprehend.node.js", "dist/nodes/Aws/DynamoDB/AwsDynamoDB.node.js", "dist/nodes/Aws/ELB/AwsElb.node.js", "dist/nodes/Aws/Rekognition/AwsRekognition.node.js", "dist/nodes/Aws/S3/AwsS3.node.js", "dist/nodes/Aws/SES/AwsSes.node.js", "dist/nodes/Aws/SQS/AwsSqs.node.js", "dist/nodes/Aws/Textract/AwsTextract.node.js", "dist/nodes/Aws/Transcribe/AwsTranscribe.node.js", "dist/nodes/BambooHr/BambooHr.node.js", "dist/nodes/Bannerbear/Bannerbear.node.js", "dist/nodes/Baserow/Baserow.node.js", "dist/nodes/Beeminder/Beeminder.node.js", "dist/nodes/Bitbucket/BitbucketTrigger.node.js", "dist/nodes/Bitly/Bitly.node.js", "dist/nodes/Bitwarden/Bitwarden.node.js", "dist/nodes/Box/Box.node.js", "dist/nodes/Box/BoxTrigger.node.js", "dist/nodes/Brandfetch/Brandfetch.node.js", "dist/nodes/Bubble/Bubble.node.js", "dist/nodes/Cal/CalTrigger.node.js", "dist/nodes/Calendly/CalendlyTrigger.node.js", "dist/nodes/Chargebee/Chargebee.node.js", "dist/nodes/Chargebee/ChargebeeTrigger.node.js", "dist/nodes/CircleCi/CircleCi.node.js", "dist/nodes/Cisco/Webex/CiscoWebex.node.js", "dist/nodes/Citrix/ADC/CitrixAdc.node.js", "dist/nodes/Cisco/Webex/CiscoWebexTrigger.node.js", "dist/nodes/Cloudflare/Cloudflare.node.js", "dist/nodes/Clearbit/Clearbit.node.js", "dist/nodes/ClickUp/ClickUp.node.js", "dist/nodes/ClickUp/ClickUpTrigger.node.js", "dist/nodes/Clockify/Clockify.node.js", "dist/nodes/Clockify/ClockifyTrigger.node.js", "dist/nodes/Cockpit/Cockpit.node.js", "dist/nodes/Coda/Coda.node.js", "dist/nodes/Code/Code.node.js", "dist/nodes/CoinGecko/CoinGecko.node.js", "dist/nodes/CompareDatasets/CompareDatasets.node.js", "dist/nodes/Compression/Compression.node.js", "dist/nodes/Contentful/Contentful.node.js", "dist/nodes/ConvertKit/ConvertKit.node.js", "dist/nodes/ConvertKit/ConvertKitTrigger.node.js", "dist/nodes/Copper/Copper.node.js", "dist/nodes/Copper/CopperTrigger.node.js", "dist/nodes/Cortex/Cortex.node.js", "dist/nodes/CrateDb/CrateDb.node.js", "dist/nodes/Cron/Cron.node.js", "dist/nodes/CrowdDev/CrowdDev.node.js", "dist/nodes/CrowdDev/CrowdDevTrigger.node.js", "dist/nodes/Crypto/Crypto.node.js", "dist/nodes/CustomerIo/CustomerIo.node.js", "dist/nodes/CustomerIo/CustomerIoTrigger.node.js", "dist/nodes/DateTime/DateTime.node.js", "dist/nodes/DebugHelper/DebugHelper.node.js", "dist/nodes/DeepL/DeepL.node.js", "dist/nodes/Demio/Demio.node.js", "dist/nodes/Dhl/Dhl.node.js", "dist/nodes/Discord/Discord.node.js", "dist/nodes/Discourse/Discourse.node.js", "dist/nodes/Disqus/Disqus.node.js", "dist/nodes/Drift/Drift.node.js", "dist/nodes/Dropbox/Dropbox.node.js", "dist/nodes/Dropcontact/Dropcontact.node.js", "dist/nodes/EditImage/EditImage.node.js", "dist/nodes/E2eTest/E2eTest.node.js", "dist/nodes/Egoi/Egoi.node.js", "dist/nodes/Elastic/Elasticsearch/Elasticsearch.node.js", "dist/nodes/Elastic/ElasticSecurity/ElasticSecurity.node.js", "dist/nodes/EmailReadImap/EmailReadImap.node.js", "dist/nodes/EmailSend/EmailSend.node.js", "dist/nodes/Emelia/Emelia.node.js", "dist/nodes/Emelia/EmeliaTrigger.node.js", "dist/nodes/ERPNext/ERPNext.node.js", "dist/nodes/ErrorTrigger/ErrorTrigger.node.js", "dist/nodes/Eventbrite/EventbriteTrigger.node.js", "dist/nodes/ExecuteCommand/ExecuteCommand.node.js", "dist/nodes/ExecuteWorkflow/ExecuteWorkflow.node.js", "dist/nodes/ExecuteWorkflowTrigger/ExecuteWorkflowTrigger.node.js", "dist/nodes/ExecutionData/ExecutionData.node.js", "dist/nodes/Facebook/FacebookGraphApi.node.js", "dist/nodes/Facebook/FacebookTrigger.node.js", "dist/nodes/FacebookLeadAds/FacebookLeadAdsTrigger.node.js", "dist/nodes/Figma/FigmaTrigger.node.js", "dist/nodes/FileMaker/FileMaker.node.js", "dist/nodes/Filter/Filter.node.js", "dist/nodes/Flow/Flow.node.js", "dist/nodes/Flow/FlowTrigger.node.js", "dist/nodes/Form/FormTrigger.node.js", "dist/nodes/FormIo/FormIoTrigger.node.js", "dist/nodes/Formstack/FormstackTrigger.node.js", "dist/nodes/Freshdesk/Freshdesk.node.js", "dist/nodes/Freshservice/Freshservice.node.js", "dist/nodes/FreshworksCrm/FreshworksCrm.node.js", "dist/nodes/Ftp/Ftp.node.js", "dist/nodes/Function/Function.node.js", "dist/nodes/FunctionItem/FunctionItem.node.js", "dist/nodes/GetResponse/GetResponse.node.js", "dist/nodes/GetResponse/GetResponseTrigger.node.js", "dist/nodes/Ghost/Ghost.node.js", "dist/nodes/Git/Git.node.js", "dist/nodes/Github/Github.node.js", "dist/nodes/Github/GithubTrigger.node.js", "dist/nodes/Gitlab/Gitlab.node.js", "dist/nodes/Gitlab/GitlabTrigger.node.js", "dist/nodes/Google/Ads/GoogleAds.node.js", "dist/nodes/Google/Analytics/GoogleAnalytics.node.js", "dist/nodes/Google/BigQuery/GoogleBigQuery.node.js", "dist/nodes/Google/Books/GoogleBooks.node.js", "dist/nodes/Google/Calendar/GoogleCalendar.node.js", "dist/nodes/Google/Calendar/GoogleCalendarTrigger.node.js", "dist/nodes/Google/Chat/GoogleChat.node.js", "dist/nodes/Google/CloudNaturalLanguage/GoogleCloudNaturalLanguage.node.js", "dist/nodes/Google/CloudStorage/GoogleCloudStorage.node.js", "dist/nodes/Google/Contacts/GoogleContacts.node.js", "dist/nodes/Google/Docs/GoogleDocs.node.js", "dist/nodes/Google/Drive/GoogleDrive.node.js", "dist/nodes/Google/Drive/GoogleDriveTrigger.node.js", "dist/nodes/Google/Firebase/CloudFirestore/GoogleFirebaseCloudFirestore.node.js", "dist/nodes/Google/Firebase/RealtimeDatabase/GoogleFirebaseRealtimeDatabase.node.js", "dist/nodes/Google/Gmail/Gmail.node.js", "dist/nodes/Google/Gmail/GmailTrigger.node.js", "dist/nodes/Google/GSuiteAdmin/GSuiteAdmin.node.js", "dist/nodes/Google/Perspective/GooglePerspective.node.js", "dist/nodes/Google/Sheet/GoogleSheets.node.js", "dist/nodes/Google/Sheet/GoogleSheetsTrigger.node.js", "dist/nodes/Google/Slides/GoogleSlides.node.js", "dist/nodes/Google/Task/GoogleTasks.node.js", "dist/nodes/Google/Translate/GoogleTranslate.node.js", "dist/nodes/Google/YouTube/YouTube.node.js", "dist/nodes/Gotify/Gotify.node.js", "dist/nodes/GoToWebinar/GoToWebinar.node.js", "dist/nodes/Grafana/Grafana.node.js", "dist/nodes/GraphQL/GraphQL.node.js", "dist/nodes/Grist/Grist.node.js", "dist/nodes/Gumroad/GumroadTrigger.node.js", "dist/nodes/HackerNews/HackerNews.node.js", "dist/nodes/HaloPSA/HaloPSA.node.js", "dist/nodes/Harvest/Harvest.node.js", "dist/nodes/HelpScout/HelpScout.node.js", "dist/nodes/HelpScout/HelpScoutTrigger.node.js", "dist/nodes/HighLevel/HighLevel.node.js", "dist/nodes/HomeAssistant/HomeAssistant.node.js", "dist/nodes/HtmlExtract/HtmlExtract.node.js", "dist/nodes/Html/Html.node.js", "dist/nodes/HttpRequest/HttpRequest.node.js", "dist/nodes/Hubspot/Hubspot.node.js", "dist/nodes/Hubspot/HubspotTrigger.node.js", "dist/nodes/HumanticAI/HumanticAi.node.js", "dist/nodes/Hunter/Hunter.node.js", "dist/nodes/ICalendar/ICalendar.node.js", "dist/nodes/If/If.node.js", "dist/nodes/Intercom/Intercom.node.js", "dist/nodes/Interval/Interval.node.js", "dist/nodes/InvoiceNinja/InvoiceNinja.node.js", "dist/nodes/InvoiceNinja/InvoiceNinjaTrigger.node.js", "dist/nodes/ItemLists/ItemLists.node.js", "dist/nodes/Iterable/Iterable.node.js", "dist/nodes/Jenkins/Jenkins.node.js", "dist/nodes/Jira/Jira.node.js", "dist/nodes/Jira/JiraTrigger.node.js", "dist/nodes/JotForm/JotFormTrigger.node.js", "dist/nodes/Kafka/Kafka.node.js", "dist/nodes/Kafka/KafkaTrigger.node.js", "dist/nodes/Keap/Keap.node.js", "dist/nodes/Keap/KeapTrigger.node.js", "dist/nodes/Kitemaker/Kitemaker.node.js", "dist/nodes/KoBoToolbox/KoBoToolbox.node.js", "dist/nodes/KoBoToolbox/KoBoToolboxTrigger.node.js", "dist/nodes/Ldap/Ldap.node.js", "dist/nodes/Lemlist/Lemlist.node.js", "dist/nodes/Lemlist/LemlistTrigger.node.js", "dist/nodes/Line/Line.node.js", "dist/nodes/Linear/Linear.node.js", "dist/nodes/Linear/LinearTrigger.node.js", "dist/nodes/LingvaNex/LingvaNex.node.js", "dist/nodes/LinkedIn/LinkedIn.node.js", "dist/nodes/LocalFileTrigger/LocalFileTrigger.node.js", "dist/nodes/LoneScale/LoneScaleTrigger.node.js", "dist/nodes/LoneScale/LoneScale.node.js", "dist/nodes/Magento/Magento2.node.js", "dist/nodes/Mailcheck/Mailcheck.node.js", "dist/nodes/Mailchimp/Mailchimp.node.js", "dist/nodes/Mailchimp/MailchimpTrigger.node.js", "dist/nodes/MailerLite/MailerLite.node.js", "dist/nodes/MailerLite/MailerLiteTrigger.node.js", "dist/nodes/Mailgun/Mailgun.node.js", "dist/nodes/Mailjet/Mailjet.node.js", "dist/nodes/Mailjet/MailjetTrigger.node.js", "dist/nodes/Mandrill/Mandrill.node.js", "dist/nodes/ManualTrigger/ManualTrigger.node.js", "dist/nodes/Markdown/Markdown.node.js", "dist/nodes/Marketstack/Marketstack.node.js", "dist/nodes/Matrix/Matrix.node.js", "dist/nodes/Mattermost/Mattermost.node.js", "dist/nodes/Mautic/Mautic.node.js", "dist/nodes/Mautic/MauticTrigger.node.js", "dist/nodes/Medium/Medium.node.js", "dist/nodes/Merge/Merge.node.js", "dist/nodes/MessageBird/MessageBird.node.js", "dist/nodes/Metabase/Metabase.node.js", "dist/nodes/Microsoft/Dynamics/MicrosoftDynamicsCrm.node.js", "dist/nodes/Microsoft/Excel/MicrosoftExcel.node.js", "dist/nodes/Microsoft/GraphSecurity/MicrosoftGraphSecurity.node.js", "dist/nodes/Microsoft/OneDrive/MicrosoftOneDrive.node.js", "dist/nodes/Microsoft/Outlook/MicrosoftOutlook.node.js", "dist/nodes/Microsoft/Sql/MicrosoftSql.node.js", "dist/nodes/Microsoft/Teams/MicrosoftTeams.node.js", "dist/nodes/Microsoft/ToDo/MicrosoftToDo.node.js", "dist/nodes/Mindee/Mindee.node.js", "dist/nodes/Misp/Misp.node.js", "dist/nodes/Mocean/Mocean.node.js", "dist/nodes/MondayCom/MondayCom.node.js", "dist/nodes/MongoDb/MongoDb.node.js", "dist/nodes/MonicaCrm/MonicaCrm.node.js", "dist/nodes/MoveBinaryData/MoveBinaryData.node.js", "dist/nodes/MQTT/Mqtt.node.js", "dist/nodes/MQTT/MqttTrigger.node.js", "dist/nodes/Msg91/Msg91.node.js", "dist/nodes/MySql/MySql.node.js", "dist/nodes/N8n/N8n.node.js", "dist/nodes/N8nTrainingCustomerDatastore/N8nTrainingCustomerDatastore.node.js", "dist/nodes/N8nTrainingCustomerMessenger/N8nTrainingCustomerMessenger.node.js", "dist/nodes/N8nTrigger/N8nTrigger.node.js", "dist/nodes/Nasa/Nasa.node.js", "dist/nodes/Netlify/Netlify.node.js", "dist/nodes/Netlify/NetlifyTrigger.node.js", "dist/nodes/NextCloud/NextCloud.node.js", "dist/nodes/NocoDB/NocoDB.node.js", "dist/nodes/Brevo/Brevo.node.js", "dist/nodes/Brevo/BrevoTrigger.node.js", "dist/nodes/StickyNote/StickyNote.node.js", "dist/nodes/NoOp/NoOp.node.js", "dist/nodes/Onfleet/Onfleet.node.js", "dist/nodes/Onfleet/OnfleetTrigger.node.js", "dist/nodes/Notion/Notion.node.js", "dist/nodes/Notion/NotionTrigger.node.js", "dist/nodes/Npm/Npm.node.js", "dist/nodes/Odoo/Odoo.node.js", "dist/nodes/OneSimpleApi/OneSimpleApi.node.js", "dist/nodes/OpenAi/OpenAi.node.js", "dist/nodes/OpenThesaurus/OpenThesaurus.node.js", "dist/nodes/OpenWeatherMap/OpenWeatherMap.node.js", "dist/nodes/Orbit/Orbit.node.js", "dist/nodes/Oura/Oura.node.js", "dist/nodes/Paddle/Paddle.node.js", "dist/nodes/PagerDuty/PagerDuty.node.js", "dist/nodes/PayPal/PayPal.node.js", "dist/nodes/PayPal/PayPalTrigger.node.js", "dist/nodes/Peekalink/Peekalink.node.js", "dist/nodes/Phantombuster/Phantombuster.node.js", "dist/nodes/PhilipsHue/PhilipsHue.node.js", "dist/nodes/Pipedrive/Pipedrive.node.js", "dist/nodes/Pipedrive/PipedriveTrigger.node.js", "dist/nodes/Plivo/Plivo.node.js", "dist/nodes/PostBin/PostBin.node.js", "dist/nodes/Postgres/Postgres.node.js", "dist/nodes/Postgres/PostgresTrigger.node.js", "dist/nodes/PostHog/PostHog.node.js", "dist/nodes/Postmark/PostmarkTrigger.node.js", "dist/nodes/ProfitWell/ProfitWell.node.js", "dist/nodes/Pushbullet/Pushbullet.node.js", "dist/nodes/Pushcut/Pushcut.node.js", "dist/nodes/Pushcut/PushcutTrigger.node.js", "dist/nodes/Pushover/Pushover.node.js", "dist/nodes/QuestDb/QuestDb.node.js", "dist/nodes/QuickBase/QuickBase.node.js", "dist/nodes/QuickBooks/QuickBooks.node.js", "dist/nodes/QuickChart/QuickChart.node.js", "dist/nodes/RabbitMQ/RabbitMQ.node.js", "dist/nodes/RabbitMQ/RabbitMQTrigger.node.js", "dist/nodes/Raindrop/Raindrop.node.js", "dist/nodes/ReadBinaryFile/ReadBinaryFile.node.js", "dist/nodes/ReadBinaryFiles/ReadBinaryFiles.node.js", "dist/nodes/ReadPdf/ReadPDF.node.js", "dist/nodes/Reddit/Reddit.node.js", "dist/nodes/Redis/Redis.node.js", "dist/nodes/Redis/RedisTrigger.node.js", "dist/nodes/RenameKeys/RenameKeys.node.js", "dist/nodes/RespondToWebhook/RespondToWebhook.node.js", "dist/nodes/Rocketchat/Rocketchat.node.js", "dist/nodes/RssFeedRead/RssFeedRead.node.js", "dist/nodes/RssFeedRead/RssFeedReadTrigger.node.js", "dist/nodes/Rundeck/Rundeck.node.js", "dist/nodes/S3/S3.node.js", "dist/nodes/Salesforce/Salesforce.node.js", "dist/nodes/Salesmate/Salesmate.node.js", "dist/nodes/Schedule/ScheduleTrigger.node.js", "dist/nodes/SeaTable/SeaTable.node.js", "dist/nodes/SeaTable/SeaTableTrigger.node.js", "dist/nodes/SecurityScorecard/SecurityScorecard.node.js", "dist/nodes/Segment/Segment.node.js", "dist/nodes/SendGrid/SendGrid.node.js", "dist/nodes/Sendy/Sendy.node.js", "dist/nodes/SentryIo/SentryIo.node.js", "dist/nodes/ServiceNow/ServiceNow.node.js", "dist/nodes/Set/Set.node.js", "dist/nodes/Shopify/Shopify.node.js", "dist/nodes/Shopify/ShopifyTrigger.node.js", "dist/nodes/Signl4/Signl4.node.js", "dist/nodes/Slack/Slack.node.js", "dist/nodes/Sms77/Sms77.node.js", "dist/nodes/Snowflake/Snowflake.node.js", "dist/nodes/SplitInBatches/SplitInBatches.node.js", "dist/nodes/Splunk/Splunk.node.js", "dist/nodes/Spontit/Spontit.node.js", "dist/nodes/Spotify/Spotify.node.js", "dist/nodes/SpreadsheetFile/SpreadsheetFile.node.js", "dist/nodes/SseTrigger/SseTrigger.node.js", "dist/nodes/Ssh/Ssh.node.js", "dist/nodes/Stackby/Stackby.node.js", "dist/nodes/Start/Start.node.js", "dist/nodes/StopAndError/StopAndError.node.js", "dist/nodes/Storyblok/Storyblok.node.js", "dist/nodes/Strapi/Strapi.node.js", "dist/nodes/Strava/Strava.node.js", "dist/nodes/Strava/StravaTrigger.node.js", "dist/nodes/Stripe/Stripe.node.js", "dist/nodes/Stripe/StripeTrigger.node.js", "dist/nodes/Supabase/Supabase.node.js", "dist/nodes/SurveyMonkey/SurveyMonkeyTrigger.node.js", "dist/nodes/Switch/Switch.node.js", "dist/nodes/SyncroMSP/SyncroMsp.node.js", "dist/nodes/Taiga/Taiga.node.js", "dist/nodes/Taiga/TaigaTrigger.node.js", "dist/nodes/Tapfiliate/Tapfiliate.node.js", "dist/nodes/Telegram/Telegram.node.js", "dist/nodes/Telegram/TelegramTrigger.node.js", "dist/nodes/TheHiveProject/TheHiveProject.node.js", "dist/nodes/TheHiveProject/TheHiveProjectTrigger.node.js", "dist/nodes/TheHive/TheHive.node.js", "dist/nodes/TheHive/TheHiveTrigger.node.js", "dist/nodes/TimescaleDb/TimescaleDb.node.js", "dist/nodes/Todoist/Todoist.node.js", "dist/nodes/Toggl/TogglTrigger.node.js", "dist/nodes/Totp/Totp.node.js", "dist/nodes/TravisCi/TravisCi.node.js", "dist/nodes/Trello/Trello.node.js", "dist/nodes/Trello/TrelloTrigger.node.js", "dist/nodes/Twake/Twake.node.js", "dist/nodes/Twilio/Twilio.node.js", "dist/nodes/Twist/Twist.node.js", "dist/nodes/Twitter/Twitter.node.js", "dist/nodes/Typeform/TypeformTrigger.node.js", "dist/nodes/UnleashedSoftware/UnleashedSoftware.node.js", "dist/nodes/Uplead/Uplead.node.js", "dist/nodes/UProc/UProc.node.js", "dist/nodes/UptimeRobot/UptimeRobot.node.js", "dist/nodes/UrlScanIo/UrlScanIo.node.js", "dist/nodes/Vero/Vero.node.js", "dist/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloud.node.js", "dist/nodes/Venafi/ProtectCloud/VenafiTlsProtectCloudTrigger.node.js", "dist/nodes/Venafi/Datacenter/VenafiTlsProtectDatacenter.node.js", "dist/nodes/Vonage/Vonage.node.js", "dist/nodes/Wait/Wait.node.js", "dist/nodes/Webflow/Webflow.node.js", "dist/nodes/Webflow/WebflowTrigger.node.js", "dist/nodes/Webhook/Webhook.node.js", "dist/nodes/Wekan/Wekan.node.js", "dist/nodes/WhatsApp/WhatsApp.node.js", "dist/nodes/Wise/Wise.node.js", "dist/nodes/Wise/WiseTrigger.node.js", "dist/nodes/WooCommerce/WooCommerce.node.js", "dist/nodes/WooCommerce/WooCommerceTrigger.node.js", "dist/nodes/Wordpress/Wordpress.node.js", "dist/nodes/Workable/WorkableTrigger.node.js", "dist/nodes/WorkflowTrigger/WorkflowTrigger.node.js", "dist/nodes/WriteBinaryFile/WriteBinaryFile.node.js", "dist/nodes/Wufoo/WufooTrigger.node.js", "dist/nodes/Xero/Xero.node.js", "dist/nodes/Xml/Xml.node.js", "dist/nodes/Yourls/Yourls.node.js", "dist/nodes/Zammad/Zammad.node.js", "dist/nodes/Zendesk/Zendesk.node.js", "dist/nodes/Zendesk/ZendeskTrigger.node.js", "dist/nodes/Zoho/ZohoCrm.node.js", "dist/nodes/Zoom/Zoom.node.js", "dist/nodes/Zulip/Zulip.node.js" ] }, "devDependencies": { "@types/amqplib": "^0.10.1", "@types/aws4": "^1.5.1", "@types/basic-auth": "^1.1.3", "@types/cheerio": "^0.22.15", "@types/cron": "~1.7.1", "@types/eventsource": "^1.1.2", "@types/express": "^4.17.6", "@types/gm": "^1.25.0", "@types/imap-simple": "^4.2.0", "@types/js-nacl": "^1.3.0", "@types/jsonwebtoken": "^9.0.1", "@types/lodash": "^4.14.195", "@types/lossless-json": "^1.0.0", "@types/mailparser": "^2.7.3", "@types/mime-types": "^2.1.0", "@types/mssql": "^6.0.2", "@types/node-ssh": "^7.0.1", "@types/nodemailer": "^6.4.0", "@types/promise-ftp": "^1.3.4", "@types/redis": "^2.8.11", "@types/request-promise-native": "~1.0.15", "@types/rfc2047": "^2.0.1", "@types/showdown": "^1.9.4", "@types/snowflake-sdk": "^1.6.12", "@types/ssh2-sftp-client": "^5.1.0", "@types/tmp": "^0.2.0", "@types/uuid": "^8.3.2", "@types/xml2js": "^0.4.11", "eslint-plugin-n8n-nodes-base": "^1.16.0", "gulp": "^4.0.0", "n8n-core": "1.14.1" }, "dependencies": { "@kafkajs/confluent-schema-registry": "1.0.6", "@n8n/vm2": "^3.9.20", "amqplib": "^0.10.3", "aws4": "^1.8.0", "basic-auth": "^2.0.1", "change-case": "^4.1.1", "cheerio": "1.0.0-rc.6", "chokidar": "3.5.2", "cron": "~1.7.2", "csv-parse": "^5.5.0", "currency-codes": "^2.1.0", "eventsource": "^2.0.2", "fast-glob": "^3.2.5", "fflate": "^0.7.0", "get-system-fonts": "^2.0.2", "gm": "^1.25.0", "iconv-lite": "^0.6.2", "ics": "^2.27.0", "imap-simple": "^4.3.0", "isbot": "^3.6.13", "iso-639-1": "^2.1.3", "js-nacl": "^1.4.0", "jsonwebtoken": "^9.0.0", "kafkajs": "^1.14.0", "ldapts": "^4.2.6", "lodash": "^4.17.21", "lossless-json": "^1.0.4", "luxon": "^3.3.0", "mailparser": "^3.2.0", "minifaker": "^1.34.1", "moment": "~2.29.2", "moment-timezone": "^0.5.28", "mongodb": "^4.17.1", "mqtt": "^5.0.2", "mssql": "^8.1.2", "mysql2": "~2.3.0", "nanoid": "^3.3.6", "node-html-markdown": "^1.1.3", "node-ssh": "^12.0.0", "nodemailer": "^6.7.1", "otpauth": "^9.1.1", "pdfjs-dist": "^2.16.105", "pg": "^8.3.0", "pg-promise": "^10.5.8", "pretty-bytes": "^5.6.0", "promise-ftp": "^1.3.5", "pyodide": "^0.23.4", "redis": "^3.1.1", "rfc2047": "^4.0.1", "rhea": "^1.0.11", "rss-parser": "^3.7.0", "semver": "^7.5.4", "showdown": "^2.0.3", "simple-git": "^3.17.0", "snowflake-sdk": "^1.8.0", "ssh2-sftp-client": "^7.0.0", "tmp-promise": "^3.0.2", "typedi": "^0.10.0", "uuid": "^8.3.2", "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz", "xml2js": "^0.5.0", "n8n-workflow": "1.14.1" }, "scripts": { "clean": "rimraf dist .turbo", "dev": "pnpm watch", "typecheck": "tsc", "build": "tsc -p tsconfig.build.json && tsc-alias -p tsconfig.build.json && gulp build:icons && gulp build:translations && pnpm build:metadata", "build:translations": "gulp build:translations", "build:metadata": "pnpm n8n-generate-known && pnpm n8n-generate-ui-types", "format": "prettier --write . --ignore-path ../../.prettierignore", "lint": "eslint . --quiet && node ./scripts/validate-load-options-methods.js", "lintfix": "eslint . --fix", "watch": "tsc-watch -p tsconfig.build.json --onCompilationComplete \"tsc-alias -p tsconfig.build.json\" --onSuccess \"pnpm n8n-generate-ui-types\"", "test": "jest" } }, "extraction_time_ms": 7, "extracted_at": "2025-06-07T17:49:22.717Z" } ``` -------------------------------------------------------------------------------- /src/http-server-single-session.ts: -------------------------------------------------------------------------------- ```typescript #!/usr/bin/env node /** * Single-Session HTTP server for n8n-MCP * Implements Hybrid Single-Session Architecture for protocol compliance * while maintaining simplicity for single-player use case */ import express from 'express'; import rateLimit from 'express-rate-limit'; import { StreamableHTTPServerTransport } from '@modelcontextprotocol/sdk/server/streamableHttp.js'; import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js'; import { N8NDocumentationMCPServer } from './mcp/server'; import { ConsoleManager } from './utils/console-manager'; import { logger } from './utils/logger'; import { AuthManager } from './utils/auth'; import { readFileSync } from 'fs'; import dotenv from 'dotenv'; import { getStartupBaseUrl, formatEndpointUrls, detectBaseUrl } from './utils/url-detector'; import { PROJECT_VERSION } from './utils/version'; import { v4 as uuidv4 } from 'uuid'; import { createHash } from 'crypto'; import { isInitializeRequest } from '@modelcontextprotocol/sdk/types.js'; import { negotiateProtocolVersion, logProtocolNegotiation, STANDARD_PROTOCOL_VERSION } from './utils/protocol-version'; import { InstanceContext, validateInstanceContext } from './types/instance-context'; dotenv.config(); // Protocol version constant - will be negotiated per client const DEFAULT_PROTOCOL_VERSION = STANDARD_PROTOCOL_VERSION; // Type-safe headers interface for multi-tenant support interface MultiTenantHeaders { 'x-n8n-url'?: string; 'x-n8n-key'?: string; 'x-instance-id'?: string; 'x-session-id'?: string; } // Session management constants const MAX_SESSIONS = 100; const SESSION_CLEANUP_INTERVAL = 5 * 60 * 1000; // 5 minutes interface Session { server: N8NDocumentationMCPServer; transport: StreamableHTTPServerTransport | SSEServerTransport; lastAccess: Date; sessionId: string; initialized: boolean; isSSE: boolean; } interface SessionMetrics { totalSessions: number; activeSessions: number; expiredSessions: number; lastCleanup: Date; } /** * Extract multi-tenant headers in a type-safe manner */ function extractMultiTenantHeaders(req: express.Request): MultiTenantHeaders { return { 'x-n8n-url': req.headers['x-n8n-url'] as string | undefined, 'x-n8n-key': req.headers['x-n8n-key'] as string | undefined, 'x-instance-id': req.headers['x-instance-id'] as string | undefined, 'x-session-id': req.headers['x-session-id'] as string | undefined, }; } export class SingleSessionHTTPServer { // Map to store transports by session ID (following SDK pattern) private transports: { [sessionId: string]: StreamableHTTPServerTransport } = {}; private servers: { [sessionId: string]: N8NDocumentationMCPServer } = {}; private sessionMetadata: { [sessionId: string]: { lastAccess: Date; createdAt: Date } } = {}; private sessionContexts: { [sessionId: string]: InstanceContext | undefined } = {}; private contextSwitchLocks: Map<string, Promise<void>> = new Map(); private session: Session | null = null; // Keep for SSE compatibility private consoleManager = new ConsoleManager(); private expressServer: any; private sessionTimeout = 30 * 60 * 1000; // 30 minutes private authToken: string | null = null; private cleanupTimer: NodeJS.Timeout | null = null; constructor() { // Validate environment on construction this.validateEnvironment(); // No longer pre-create session - will be created per initialize request following SDK pattern // Start periodic session cleanup this.startSessionCleanup(); } /** * Start periodic session cleanup */ private startSessionCleanup(): void { this.cleanupTimer = setInterval(async () => { try { await this.cleanupExpiredSessions(); } catch (error) { logger.error('Error during session cleanup', error); } }, SESSION_CLEANUP_INTERVAL); logger.info('Session cleanup started', { interval: SESSION_CLEANUP_INTERVAL / 1000 / 60, maxSessions: MAX_SESSIONS, sessionTimeout: this.sessionTimeout / 1000 / 60 }); } /** * Clean up expired sessions based on last access time */ private cleanupExpiredSessions(): void { const now = Date.now(); const expiredSessions: string[] = []; // Check for expired sessions for (const sessionId in this.sessionMetadata) { const metadata = this.sessionMetadata[sessionId]; if (now - metadata.lastAccess.getTime() > this.sessionTimeout) { expiredSessions.push(sessionId); } } // Also check for orphaned contexts (sessions that were removed but context remained) for (const sessionId in this.sessionContexts) { if (!this.sessionMetadata[sessionId]) { // Context exists but session doesn't - clean it up delete this.sessionContexts[sessionId]; logger.debug('Cleaned orphaned session context', { sessionId }); } } // Remove expired sessions for (const sessionId of expiredSessions) { this.removeSession(sessionId, 'expired'); } if (expiredSessions.length > 0) { logger.info('Cleaned up expired sessions', { removed: expiredSessions.length, remaining: this.getActiveSessionCount() }); } } /** * Remove a session and clean up resources */ private async removeSession(sessionId: string, reason: string): Promise<void> { try { // Close transport if exists if (this.transports[sessionId]) { await this.transports[sessionId].close(); delete this.transports[sessionId]; } // Remove server, metadata, and context delete this.servers[sessionId]; delete this.sessionMetadata[sessionId]; delete this.sessionContexts[sessionId]; logger.info('Session removed', { sessionId, reason }); } catch (error) { logger.warn('Error removing session', { sessionId, reason, error }); } } /** * Get current active session count */ private getActiveSessionCount(): number { return Object.keys(this.transports).length; } /** * Check if we can create a new session */ private canCreateSession(): boolean { return this.getActiveSessionCount() < MAX_SESSIONS; } /** * Validate session ID format * * Accepts any non-empty string to support various MCP clients: * - UUIDv4 (internal n8n-mcp format) * - instance-{userId}-{hash}-{uuid} (multi-tenant format) * - Custom formats from mcp-remote and other proxies * * Security: Session validation happens via lookup in this.transports, * not format validation. This ensures compatibility with all MCP clients. * * @param sessionId - Session identifier from MCP client * @returns true if valid, false otherwise */ private isValidSessionId(sessionId: string): boolean { // Accept any non-empty string as session ID // This ensures compatibility with all MCP clients and proxies return Boolean(sessionId && sessionId.length > 0); } /** * Sanitize error information for client responses */ private sanitizeErrorForClient(error: unknown): { message: string; code: string } { const isProduction = process.env.NODE_ENV === 'production'; if (error instanceof Error) { // In production, only return generic messages if (isProduction) { // Map known error types to safe messages if (error.message.includes('Unauthorized') || error.message.includes('authentication')) { return { message: 'Authentication failed', code: 'AUTH_ERROR' }; } if (error.message.includes('Session') || error.message.includes('session')) { return { message: 'Session error', code: 'SESSION_ERROR' }; } if (error.message.includes('Invalid') || error.message.includes('validation')) { return { message: 'Validation error', code: 'VALIDATION_ERROR' }; } // Default generic error return { message: 'Internal server error', code: 'INTERNAL_ERROR' }; } // In development, return more details but no stack traces return { message: error.message.substring(0, 200), // Limit message length code: error.name || 'ERROR' }; } // For non-Error objects return { message: 'An error occurred', code: 'UNKNOWN_ERROR' }; } /** * Update session last access time */ private updateSessionAccess(sessionId: string): void { if (this.sessionMetadata[sessionId]) { this.sessionMetadata[sessionId].lastAccess = new Date(); } } /** * Switch session context with locking to prevent race conditions */ private async switchSessionContext(sessionId: string, newContext: InstanceContext): Promise<void> { // Check if there's already a switch in progress for this session const existingLock = this.contextSwitchLocks.get(sessionId); if (existingLock) { // Wait for the existing switch to complete await existingLock; return; } // Create a promise for this switch operation const switchPromise = this.performContextSwitch(sessionId, newContext); this.contextSwitchLocks.set(sessionId, switchPromise); try { await switchPromise; } finally { // Clean up the lock after completion this.contextSwitchLocks.delete(sessionId); } } /** * Perform the actual context switch */ private async performContextSwitch(sessionId: string, newContext: InstanceContext): Promise<void> { const existingContext = this.sessionContexts[sessionId]; // Only switch if the context has actually changed if (JSON.stringify(existingContext) !== JSON.stringify(newContext)) { logger.info('Multi-tenant shared mode: Updating instance context for session', { sessionId, oldInstanceId: existingContext?.instanceId, newInstanceId: newContext.instanceId }); // Update the session context this.sessionContexts[sessionId] = newContext; // Update the MCP server's instance context if it exists if (this.servers[sessionId]) { (this.servers[sessionId] as any).instanceContext = newContext; } } } /** * Get session metrics for monitoring */ private getSessionMetrics(): SessionMetrics { const now = Date.now(); let expiredCount = 0; for (const sessionId in this.sessionMetadata) { const metadata = this.sessionMetadata[sessionId]; if (now - metadata.lastAccess.getTime() > this.sessionTimeout) { expiredCount++; } } return { totalSessions: Object.keys(this.sessionMetadata).length, activeSessions: this.getActiveSessionCount(), expiredSessions: expiredCount, lastCleanup: new Date() }; } /** * Load auth token from environment variable or file */ private loadAuthToken(): string | null { // First, try AUTH_TOKEN environment variable if (process.env.AUTH_TOKEN) { logger.info('Using AUTH_TOKEN from environment variable'); return process.env.AUTH_TOKEN; } // Then, try AUTH_TOKEN_FILE if (process.env.AUTH_TOKEN_FILE) { try { const token = readFileSync(process.env.AUTH_TOKEN_FILE, 'utf-8').trim(); logger.info(`Loaded AUTH_TOKEN from file: ${process.env.AUTH_TOKEN_FILE}`); return token; } catch (error) { logger.error(`Failed to read AUTH_TOKEN_FILE: ${process.env.AUTH_TOKEN_FILE}`, error); console.error(`ERROR: Failed to read AUTH_TOKEN_FILE: ${process.env.AUTH_TOKEN_FILE}`); console.error(error instanceof Error ? error.message : 'Unknown error'); return null; } } return null; } /** * Validate required environment variables */ private validateEnvironment(): void { // Load auth token from env var or file this.authToken = this.loadAuthToken(); if (!this.authToken || this.authToken.trim() === '') { const message = 'No authentication token found or token is empty. Set AUTH_TOKEN environment variable or AUTH_TOKEN_FILE pointing to a file containing the token.'; logger.error(message); throw new Error(message); } // Update authToken to trimmed version this.authToken = this.authToken.trim(); if (this.authToken.length < 32) { logger.warn('AUTH_TOKEN should be at least 32 characters for security'); } // Check for default token and show prominent warnings const isDefaultToken = this.authToken === 'REPLACE_THIS_AUTH_TOKEN_32_CHARS_MIN_abcdefgh'; const isProduction = process.env.NODE_ENV === 'production'; if (isDefaultToken) { if (isProduction) { const message = 'CRITICAL SECURITY ERROR: Cannot start in production with default AUTH_TOKEN. Generate secure token: openssl rand -base64 32'; logger.error(message); console.error('\n🚨 CRITICAL SECURITY ERROR 🚨'); console.error(message); console.error('Set NODE_ENV to development for testing, or update AUTH_TOKEN for production\n'); throw new Error(message); } logger.warn('⚠️ SECURITY WARNING: Using default AUTH_TOKEN - CHANGE IMMEDIATELY!'); logger.warn('Generate secure token with: openssl rand -base64 32'); // Only show console warnings in HTTP mode if (process.env.MCP_MODE === 'http') { console.warn('\n⚠️ SECURITY WARNING ⚠️'); console.warn('Using default AUTH_TOKEN - CHANGE IMMEDIATELY!'); console.warn('Generate secure token: openssl rand -base64 32'); console.warn('Update via Railway dashboard environment variables\n'); } } } /** * Handle incoming MCP request using proper SDK pattern * * @param req - Express request object * @param res - Express response object * @param instanceContext - Optional instance-specific configuration */ async handleRequest( req: express.Request, res: express.Response, instanceContext?: InstanceContext ): Promise<void> { const startTime = Date.now(); // Wrap all operations to prevent console interference return this.consoleManager.wrapOperation(async () => { try { const sessionId = req.headers['mcp-session-id'] as string | undefined; const isInitialize = req.body ? isInitializeRequest(req.body) : false; // Log comprehensive incoming request details for debugging logger.info('handleRequest: Processing MCP request - SDK PATTERN', { requestId: req.get('x-request-id') || 'unknown', sessionId: sessionId, method: req.method, url: req.url, bodyType: typeof req.body, bodyContent: req.body ? JSON.stringify(req.body, null, 2) : 'undefined', existingTransports: Object.keys(this.transports), isInitializeRequest: isInitialize }); let transport: StreamableHTTPServerTransport; if (isInitialize) { // Check session limits before creating new session if (!this.canCreateSession()) { logger.warn('handleRequest: Session limit reached', { currentSessions: this.getActiveSessionCount(), maxSessions: MAX_SESSIONS }); res.status(429).json({ jsonrpc: '2.0', error: { code: -32000, message: `Session limit reached (${MAX_SESSIONS}). Please wait for existing sessions to expire.` }, id: req.body?.id || null }); return; } // For initialize requests: always create new transport and server logger.info('handleRequest: Creating new transport for initialize request'); // Generate session ID based on multi-tenant configuration let sessionIdToUse: string; const isMultiTenantEnabled = process.env.ENABLE_MULTI_TENANT === 'true'; const sessionStrategy = process.env.MULTI_TENANT_SESSION_STRATEGY || 'instance'; if (isMultiTenantEnabled && sessionStrategy === 'instance' && instanceContext?.instanceId) { // In multi-tenant mode with instance strategy, create session per instance // This ensures each tenant gets isolated sessions // Include configuration hash to prevent collisions with different configs const configHash = createHash('sha256') .update(JSON.stringify({ url: instanceContext.n8nApiUrl, instanceId: instanceContext.instanceId })) .digest('hex') .substring(0, 8); sessionIdToUse = `instance-${instanceContext.instanceId}-${configHash}-${uuidv4()}`; logger.info('Multi-tenant mode: Creating instance-specific session', { instanceId: instanceContext.instanceId, configHash, sessionId: sessionIdToUse }); } else { // Use client-provided session ID or generate a standard one sessionIdToUse = sessionId || uuidv4(); } const server = new N8NDocumentationMCPServer(instanceContext); transport = new StreamableHTTPServerTransport({ sessionIdGenerator: () => sessionIdToUse, onsessioninitialized: (initializedSessionId: string) => { // Store both transport and server by session ID when session is initialized logger.info('handleRequest: Session initialized, storing transport and server', { sessionId: initializedSessionId }); this.transports[initializedSessionId] = transport; this.servers[initializedSessionId] = server; // Store session metadata and context this.sessionMetadata[initializedSessionId] = { lastAccess: new Date(), createdAt: new Date() }; this.sessionContexts[initializedSessionId] = instanceContext; } }); // Set up cleanup handlers transport.onclose = () => { const sid = transport.sessionId; if (sid) { logger.info('handleRequest: Transport closed, cleaning up', { sessionId: sid }); this.removeSession(sid, 'transport_closed'); } }; // Handle transport errors to prevent connection drops transport.onerror = (error: Error) => { const sid = transport.sessionId; logger.error('Transport error', { sessionId: sid, error: error.message }); if (sid) { this.removeSession(sid, 'transport_error').catch(err => { logger.error('Error during transport error cleanup', { error: err }); }); } }; // Connect the server to the transport BEFORE handling the request logger.info('handleRequest: Connecting server to new transport'); await server.connect(transport); } else if (sessionId && this.transports[sessionId]) { // Validate session ID format if (!this.isValidSessionId(sessionId)) { logger.warn('handleRequest: Invalid session ID format', { sessionId }); res.status(400).json({ jsonrpc: '2.0', error: { code: -32602, message: 'Invalid session ID format' }, id: req.body?.id || null }); return; } // For non-initialize requests: reuse existing transport for this session logger.info('handleRequest: Reusing existing transport for session', { sessionId }); transport = this.transports[sessionId]; // In multi-tenant shared mode, update instance context if provided const isMultiTenantEnabled = process.env.ENABLE_MULTI_TENANT === 'true'; const sessionStrategy = process.env.MULTI_TENANT_SESSION_STRATEGY || 'instance'; if (isMultiTenantEnabled && sessionStrategy === 'shared' && instanceContext) { // Update the context for this session with locking to prevent race conditions await this.switchSessionContext(sessionId, instanceContext); } // Update session access time this.updateSessionAccess(sessionId); } else { // Invalid request - no session ID and not an initialize request const errorDetails = { hasSessionId: !!sessionId, isInitialize: isInitialize, sessionIdValid: sessionId ? this.isValidSessionId(sessionId) : false, sessionExists: sessionId ? !!this.transports[sessionId] : false }; logger.warn('handleRequest: Invalid request - no session ID and not initialize', errorDetails); let errorMessage = 'Bad Request: No valid session ID provided and not an initialize request'; if (sessionId && !this.isValidSessionId(sessionId)) { errorMessage = 'Bad Request: Invalid session ID format'; } else if (sessionId && !this.transports[sessionId]) { errorMessage = 'Bad Request: Session not found or expired'; } res.status(400).json({ jsonrpc: '2.0', error: { code: -32000, message: errorMessage }, id: req.body?.id || null }); return; } // Handle request with the transport logger.info('handleRequest: Handling request with transport', { sessionId: isInitialize ? 'new' : sessionId, isInitialize }); await transport.handleRequest(req, res, req.body); const duration = Date.now() - startTime; logger.info('MCP request completed', { duration, sessionId: transport.sessionId }); } catch (error) { logger.error('handleRequest: MCP request error:', { error: error instanceof Error ? error.message : error, errorName: error instanceof Error ? error.name : 'Unknown', stack: error instanceof Error ? error.stack : undefined, activeTransports: Object.keys(this.transports), requestDetails: { method: req.method, url: req.url, hasBody: !!req.body, sessionId: req.headers['mcp-session-id'] }, duration: Date.now() - startTime }); if (!res.headersSent) { // Send sanitized error to client const sanitizedError = this.sanitizeErrorForClient(error); res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: sanitizedError.message, data: { code: sanitizedError.code } }, id: req.body?.id || null }); } } }); } /** * Reset the session for SSE - clean up old and create new SSE transport */ private async resetSessionSSE(res: express.Response): Promise<void> { // Clean up old session if exists if (this.session) { try { logger.info('Closing previous session for SSE', { sessionId: this.session.sessionId }); await this.session.transport.close(); } catch (error) { logger.warn('Error closing previous session:', error); } } try { // Create new session logger.info('Creating new N8NDocumentationMCPServer for SSE...'); const server = new N8NDocumentationMCPServer(); // Generate cryptographically secure session ID const sessionId = uuidv4(); logger.info('Creating SSEServerTransport...'); const transport = new SSEServerTransport('/mcp', res); logger.info('Connecting server to SSE transport...'); await server.connect(transport); // Note: server.connect() automatically calls transport.start(), so we don't need to call it again this.session = { server, transport, lastAccess: new Date(), sessionId, initialized: false, isSSE: true }; logger.info('Created new SSE session successfully', { sessionId: this.session.sessionId }); } catch (error) { logger.error('Failed to create SSE session:', error); throw error; } } /** * Check if current session is expired */ private isExpired(): boolean { if (!this.session) return true; return Date.now() - this.session.lastAccess.getTime() > this.sessionTimeout; } /** * Start the HTTP server */ async start(): Promise<void> { const app = express(); // Create JSON parser middleware for endpoints that need it const jsonParser = express.json({ limit: '10mb' }); // Configure trust proxy for correct IP logging behind reverse proxies const trustProxy = process.env.TRUST_PROXY ? Number(process.env.TRUST_PROXY) : 0; if (trustProxy > 0) { app.set('trust proxy', trustProxy); logger.info(`Trust proxy enabled with ${trustProxy} hop(s)`); } // DON'T use any body parser globally - StreamableHTTPServerTransport needs raw stream // Only use JSON parser for specific endpoints that need it // Security headers app.use((req, res, next) => { res.setHeader('X-Content-Type-Options', 'nosniff'); res.setHeader('X-Frame-Options', 'DENY'); res.setHeader('X-XSS-Protection', '1; mode=block'); res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains'); next(); }); // CORS configuration app.use((req, res, next) => { const allowedOrigin = process.env.CORS_ORIGIN || '*'; res.setHeader('Access-Control-Allow-Origin', allowedOrigin); res.setHeader('Access-Control-Allow-Methods', 'POST, GET, DELETE, OPTIONS'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Accept, Mcp-Session-Id'); res.setHeader('Access-Control-Expose-Headers', 'Mcp-Session-Id'); res.setHeader('Access-Control-Max-Age', '86400'); if (req.method === 'OPTIONS') { res.sendStatus(204); return; } next(); }); // Request logging middleware app.use((req, res, next) => { logger.info(`${req.method} ${req.path}`, { ip: req.ip, userAgent: req.get('user-agent'), contentLength: req.get('content-length') }); next(); }); // Root endpoint with API information app.get('/', (req, res) => { const port = parseInt(process.env.PORT || '3000'); const host = process.env.HOST || '0.0.0.0'; const baseUrl = detectBaseUrl(req, host, port); const endpoints = formatEndpointUrls(baseUrl); res.json({ name: 'n8n Documentation MCP Server', version: PROJECT_VERSION, description: 'Model Context Protocol server providing comprehensive n8n node documentation and workflow management', endpoints: { health: { url: endpoints.health, method: 'GET', description: 'Health check and status information' }, mcp: { url: endpoints.mcp, method: 'GET/POST', description: 'MCP endpoint - GET for info, POST for JSON-RPC' } }, authentication: { type: 'Bearer Token', header: 'Authorization: Bearer <token>', required_for: ['POST /mcp'] }, documentation: 'https://github.com/czlonkowski/n8n-mcp' }); }); // Health check endpoint (no body parsing needed for GET) app.get('/health', (req, res) => { const activeTransports = Object.keys(this.transports); const activeServers = Object.keys(this.servers); const sessionMetrics = this.getSessionMetrics(); const isProduction = process.env.NODE_ENV === 'production'; const isDefaultToken = this.authToken === 'REPLACE_THIS_AUTH_TOKEN_32_CHARS_MIN_abcdefgh'; res.json({ status: 'ok', mode: 'sdk-pattern-transports', version: PROJECT_VERSION, environment: process.env.NODE_ENV || 'development', uptime: Math.floor(process.uptime()), sessions: { active: sessionMetrics.activeSessions, total: sessionMetrics.totalSessions, expired: sessionMetrics.expiredSessions, max: MAX_SESSIONS, usage: `${sessionMetrics.activeSessions}/${MAX_SESSIONS}`, sessionIds: activeTransports }, security: { production: isProduction, defaultToken: isDefaultToken, tokenLength: this.authToken?.length || 0 }, activeTransports: activeTransports.length, // Legacy field activeServers: activeServers.length, // Legacy field legacySessionActive: !!this.session, // For SSE compatibility memory: { used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024), total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024), unit: 'MB' }, timestamp: new Date().toISOString() }); }); // Test endpoint for manual testing without auth app.post('/mcp/test', jsonParser, async (req: express.Request, res: express.Response): Promise<void> => { logger.info('TEST ENDPOINT: Manual test request received', { method: req.method, headers: req.headers, body: req.body, bodyType: typeof req.body, bodyContent: req.body ? JSON.stringify(req.body, null, 2) : 'undefined' }); // Negotiate protocol version for test endpoint const negotiationResult = negotiateProtocolVersion( undefined, // no client version in test undefined, // no client info req.get('user-agent'), req.headers ); logProtocolNegotiation(negotiationResult, logger, 'TEST_ENDPOINT'); // Test what a basic MCP initialize request should look like const testResponse = { jsonrpc: '2.0', id: req.body?.id || 1, result: { protocolVersion: negotiationResult.version, capabilities: { tools: {} }, serverInfo: { name: 'n8n-mcp', version: PROJECT_VERSION } } }; logger.info('TEST ENDPOINT: Sending test response', { response: testResponse }); res.json(testResponse); }); // MCP information endpoint (no auth required for discovery) and SSE support app.get('/mcp', async (req, res) => { // Handle StreamableHTTP transport requests with new pattern const sessionId = req.headers['mcp-session-id'] as string | undefined; if (sessionId && this.transports[sessionId]) { // Let the StreamableHTTPServerTransport handle the GET request try { await this.transports[sessionId].handleRequest(req, res, undefined); return; } catch (error) { logger.error('StreamableHTTP GET request failed:', error); // Fall through to standard response } } // Check Accept header for text/event-stream (SSE support) const accept = req.headers.accept; if (accept && accept.includes('text/event-stream')) { logger.info('SSE stream request received - establishing SSE connection'); try { // Create or reset session for SSE await this.resetSessionSSE(res); logger.info('SSE connection established successfully'); } catch (error) { logger.error('Failed to establish SSE connection:', error); res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Failed to establish SSE connection' }, id: null }); } return; } // In n8n mode, return protocol version and server info if (process.env.N8N_MODE === 'true') { // Negotiate protocol version for n8n mode const negotiationResult = negotiateProtocolVersion( undefined, // no client version in GET request undefined, // no client info req.get('user-agent'), req.headers ); logProtocolNegotiation(negotiationResult, logger, 'N8N_MODE_GET'); res.json({ protocolVersion: negotiationResult.version, serverInfo: { name: 'n8n-mcp', version: PROJECT_VERSION, capabilities: { tools: {} } } }); return; } // Standard response for non-n8n mode res.json({ description: 'n8n Documentation MCP Server', version: PROJECT_VERSION, endpoints: { mcp: { method: 'POST', path: '/mcp', description: 'Main MCP JSON-RPC endpoint', authentication: 'Bearer token required' }, health: { method: 'GET', path: '/health', description: 'Health check endpoint', authentication: 'None' }, root: { method: 'GET', path: '/', description: 'API information', authentication: 'None' } }, documentation: 'https://github.com/czlonkowski/n8n-mcp' }); }); // Session termination endpoint app.delete('/mcp', async (req: express.Request, res: express.Response): Promise<void> => { const mcpSessionId = req.headers['mcp-session-id'] as string; if (!mcpSessionId) { res.status(400).json({ jsonrpc: '2.0', error: { code: -32602, message: 'Mcp-Session-Id header is required' }, id: null }); return; } // Validate session ID format if (!this.isValidSessionId(mcpSessionId)) { res.status(400).json({ jsonrpc: '2.0', error: { code: -32602, message: 'Invalid session ID format' }, id: null }); return; } // Check if session exists in new transport map if (this.transports[mcpSessionId]) { logger.info('Terminating session via DELETE request', { sessionId: mcpSessionId }); try { await this.removeSession(mcpSessionId, 'manual_termination'); res.status(204).send(); // No content } catch (error) { logger.error('Error terminating session:', error); res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Error terminating session' }, id: null }); } } else { res.status(404).json({ jsonrpc: '2.0', error: { code: -32001, message: 'Session not found' }, id: null }); } }); // SECURITY: Rate limiting for authentication endpoint // Prevents brute force attacks and DoS // See: https://github.com/czlonkowski/n8n-mcp/issues/265 (HIGH-02) const authLimiter = rateLimit({ windowMs: parseInt(process.env.AUTH_RATE_LIMIT_WINDOW || '900000'), // 15 minutes max: parseInt(process.env.AUTH_RATE_LIMIT_MAX || '20'), // 20 authentication attempts per IP message: { jsonrpc: '2.0', error: { code: -32000, message: 'Too many authentication attempts. Please try again later.' }, id: null }, standardHeaders: true, // Return rate limit info in `RateLimit-*` headers legacyHeaders: false, // Disable `X-RateLimit-*` headers handler: (req, res) => { logger.warn('Rate limit exceeded', { ip: req.ip, userAgent: req.get('user-agent'), event: 'rate_limit' }); res.status(429).json({ jsonrpc: '2.0', error: { code: -32000, message: 'Too many authentication attempts' }, id: null }); } }); // Main MCP endpoint with authentication and rate limiting app.post('/mcp', authLimiter, jsonParser, async (req: express.Request, res: express.Response): Promise<void> => { // Log comprehensive debug info about the request logger.info('POST /mcp request received - DETAILED DEBUG', { headers: req.headers, readable: req.readable, readableEnded: req.readableEnded, complete: req.complete, bodyType: typeof req.body, bodyContent: req.body ? JSON.stringify(req.body, null, 2) : 'undefined', contentLength: req.get('content-length'), contentType: req.get('content-type'), userAgent: req.get('user-agent'), ip: req.ip, method: req.method, url: req.url, originalUrl: req.originalUrl }); // Handle connection close to immediately clean up sessions const sessionId = req.headers['mcp-session-id'] as string | undefined; // Only add event listener if the request object supports it (not in test mocks) if (typeof req.on === 'function') { const closeHandler = () => { if (!res.headersSent && sessionId) { logger.info('Connection closed before response sent', { sessionId }); // Schedule immediate cleanup if connection closes unexpectedly setImmediate(() => { if (this.sessionMetadata[sessionId]) { const metadata = this.sessionMetadata[sessionId]; const timeSinceAccess = Date.now() - metadata.lastAccess.getTime(); // Only remove if it's been inactive for a bit to avoid race conditions if (timeSinceAccess > 60000) { // 1 minute this.removeSession(sessionId, 'connection_closed').catch(err => { logger.error('Error during connection close cleanup', { error: err }); }); } } }); } }; req.on('close', closeHandler); // Clean up event listener when response ends to prevent memory leaks res.on('finish', () => { req.removeListener('close', closeHandler); }); } // Enhanced authentication check with specific logging const authHeader = req.headers.authorization; // Check if Authorization header is missing if (!authHeader) { logger.warn('Authentication failed: Missing Authorization header', { ip: req.ip, userAgent: req.get('user-agent'), reason: 'no_auth_header' }); res.status(401).json({ jsonrpc: '2.0', error: { code: -32001, message: 'Unauthorized' }, id: null }); return; } // Check if Authorization header has Bearer prefix if (!authHeader.startsWith('Bearer ')) { logger.warn('Authentication failed: Invalid Authorization header format (expected Bearer token)', { ip: req.ip, userAgent: req.get('user-agent'), reason: 'invalid_auth_format', headerPrefix: authHeader.substring(0, Math.min(authHeader.length, 10)) + '...' // Log first 10 chars for debugging }); res.status(401).json({ jsonrpc: '2.0', error: { code: -32001, message: 'Unauthorized' }, id: null }); return; } // Extract token and trim whitespace const token = authHeader.slice(7).trim(); // SECURITY: Use timing-safe comparison to prevent timing attacks // See: https://github.com/czlonkowski/n8n-mcp/issues/265 (CRITICAL-02) const isValidToken = this.authToken && AuthManager.timingSafeCompare(token, this.authToken); if (!isValidToken) { logger.warn('Authentication failed: Invalid token', { ip: req.ip, userAgent: req.get('user-agent'), reason: 'invalid_token' }); res.status(401).json({ jsonrpc: '2.0', error: { code: -32001, message: 'Unauthorized' }, id: null }); return; } // Handle request with single session logger.info('Authentication successful - proceeding to handleRequest', { hasSession: !!this.session, sessionType: this.session?.isSSE ? 'SSE' : 'StreamableHTTP', sessionInitialized: this.session?.initialized }); // Extract instance context from headers if present (for multi-tenant support) const instanceContext: InstanceContext | undefined = (() => { // Use type-safe header extraction const headers = extractMultiTenantHeaders(req); const hasUrl = headers['x-n8n-url']; const hasKey = headers['x-n8n-key']; if (!hasUrl && !hasKey) return undefined; // Create context with proper type handling const context: InstanceContext = { n8nApiUrl: hasUrl || undefined, n8nApiKey: hasKey || undefined, instanceId: headers['x-instance-id'] || undefined, sessionId: headers['x-session-id'] || undefined }; // Add metadata if available if (req.headers['user-agent'] || req.ip) { context.metadata = { userAgent: req.headers['user-agent'] as string | undefined, ip: req.ip }; } // Validate the context const validation = validateInstanceContext(context); if (!validation.valid) { logger.warn('Invalid instance context from headers', { errors: validation.errors, hasUrl: !!hasUrl, hasKey: !!hasKey }); return undefined; } return context; })(); // Log context extraction for debugging (only if context exists) if (instanceContext) { // Use sanitized logging for security logger.debug('Instance context extracted from headers', { hasUrl: !!instanceContext.n8nApiUrl, hasKey: !!instanceContext.n8nApiKey, instanceId: instanceContext.instanceId ? instanceContext.instanceId.substring(0, 8) + '...' : undefined, sessionId: instanceContext.sessionId ? instanceContext.sessionId.substring(0, 8) + '...' : undefined, urlDomain: instanceContext.n8nApiUrl ? new URL(instanceContext.n8nApiUrl).hostname : undefined }); } await this.handleRequest(req, res, instanceContext); logger.info('POST /mcp request completed - checking response status', { responseHeadersSent: res.headersSent, responseStatusCode: res.statusCode, responseFinished: res.finished }); }); // 404 handler app.use((req, res) => { res.status(404).json({ error: 'Not found', message: `Cannot ${req.method} ${req.path}` }); }); // Error handler app.use((err: any, req: express.Request, res: express.Response, next: express.NextFunction) => { logger.error('Express error handler:', err); if (!res.headersSent) { res.status(500).json({ jsonrpc: '2.0', error: { code: -32603, message: 'Internal server error', data: process.env.NODE_ENV === 'development' ? err.message : undefined }, id: null }); } }); const port = parseInt(process.env.PORT || '3000'); const host = process.env.HOST || '0.0.0.0'; this.expressServer = app.listen(port, host, () => { const isProduction = process.env.NODE_ENV === 'production'; const isDefaultToken = this.authToken === 'REPLACE_THIS_AUTH_TOKEN_32_CHARS_MIN_abcdefgh'; logger.info(`n8n MCP Single-Session HTTP Server started`, { port, host, environment: process.env.NODE_ENV || 'development', maxSessions: MAX_SESSIONS, sessionTimeout: this.sessionTimeout / 1000 / 60, production: isProduction, defaultToken: isDefaultToken }); // Detect the base URL using our utility const baseUrl = getStartupBaseUrl(host, port); const endpoints = formatEndpointUrls(baseUrl); console.log(`n8n MCP Single-Session HTTP Server running on ${host}:${port}`); console.log(`Environment: ${process.env.NODE_ENV || 'development'}`); console.log(`Session Limits: ${MAX_SESSIONS} max sessions, ${this.sessionTimeout / 1000 / 60}min timeout`); console.log(`Health check: ${endpoints.health}`); console.log(`MCP endpoint: ${endpoints.mcp}`); if (isProduction) { console.log('🔒 Running in PRODUCTION mode - enhanced security enabled'); } else { console.log('🛠️ Running in DEVELOPMENT mode'); } console.log('\nPress Ctrl+C to stop the server'); // Start periodic warning timer if using default token if (isDefaultToken && !isProduction) { setInterval(() => { logger.warn('⚠️ Still using default AUTH_TOKEN - security risk!'); if (process.env.MCP_MODE === 'http') { console.warn('⚠️ REMINDER: Still using default AUTH_TOKEN - please change it!'); } }, 300000); // Every 5 minutes } if (process.env.BASE_URL || process.env.PUBLIC_URL) { console.log(`\nPublic URL configured: ${baseUrl}`); } else if (process.env.TRUST_PROXY && Number(process.env.TRUST_PROXY) > 0) { console.log(`\nNote: TRUST_PROXY is enabled. URLs will be auto-detected from proxy headers.`); } }); // Handle server errors this.expressServer.on('error', (error: any) => { if (error.code === 'EADDRINUSE') { logger.error(`Port ${port} is already in use`); console.error(`ERROR: Port ${port} is already in use`); process.exit(1); } else { logger.error('Server error:', error); console.error('Server error:', error); process.exit(1); } }); } /** * Graceful shutdown */ async shutdown(): Promise<void> { logger.info('Shutting down Single-Session HTTP server...'); // Stop session cleanup timer if (this.cleanupTimer) { clearInterval(this.cleanupTimer); this.cleanupTimer = null; logger.info('Session cleanup timer stopped'); } // Close all active transports (SDK pattern) const sessionIds = Object.keys(this.transports); logger.info(`Closing ${sessionIds.length} active sessions`); for (const sessionId of sessionIds) { try { logger.info(`Closing transport for session ${sessionId}`); await this.removeSession(sessionId, 'server_shutdown'); } catch (error) { logger.warn(`Error closing transport for session ${sessionId}:`, error); } } // Clean up legacy session (for SSE compatibility) if (this.session) { try { await this.session.transport.close(); logger.info('Legacy session closed'); } catch (error) { logger.warn('Error closing legacy session:', error); } this.session = null; } // Close Express server if (this.expressServer) { await new Promise<void>((resolve) => { this.expressServer.close(() => { logger.info('HTTP server closed'); resolve(); }); }); } logger.info('Single-Session HTTP server shutdown completed'); } /** * Get current session info (for testing/debugging) */ getSessionInfo(): { active: boolean; sessionId?: string; age?: number; sessions?: { total: number; active: number; expired: number; max: number; sessionIds: string[]; }; } { const metrics = this.getSessionMetrics(); // Legacy SSE session info if (!this.session) { return { active: false, sessions: { total: metrics.totalSessions, active: metrics.activeSessions, expired: metrics.expiredSessions, max: MAX_SESSIONS, sessionIds: Object.keys(this.transports) } }; } return { active: true, sessionId: this.session.sessionId, age: Date.now() - this.session.lastAccess.getTime(), sessions: { total: metrics.totalSessions, active: metrics.activeSessions, expired: metrics.expiredSessions, max: MAX_SESSIONS, sessionIds: Object.keys(this.transports) } }; } } // Start if called directly if (require.main === module) { const server = new SingleSessionHTTPServer(); // Graceful shutdown handlers const shutdown = async () => { await server.shutdown(); process.exit(0); }; process.on('SIGTERM', shutdown); process.on('SIGINT', shutdown); // Handle uncaught errors process.on('uncaughtException', (error) => { logger.error('Uncaught exception:', error); console.error('Uncaught exception:', error); shutdown(); }); process.on('unhandledRejection', (reason, promise) => { logger.error('Unhandled rejection:', reason); console.error('Unhandled rejection at:', promise, 'reason:', reason); shutdown(); }); // Start server server.start().catch(error => { logger.error('Failed to start Single-Session HTTP server:', error); console.error('Failed to start Single-Session HTTP server:', error); process.exit(1); }); } ```