n8n-atom-mcp 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (794) hide show
  1. package/.env.example +220 -0
  2. package/LICENSE +21 -0
  3. package/README.md +78 -0
  4. package/data/nodes.db +0 -0
  5. package/dist/community/community-node-fetcher.d.ts +118 -0
  6. package/dist/community/community-node-fetcher.d.ts.map +1 -0
  7. package/dist/community/community-node-fetcher.js +239 -0
  8. package/dist/community/community-node-fetcher.js.map +1 -0
  9. package/dist/community/community-node-service.d.ts +42 -0
  10. package/dist/community/community-node-service.d.ts.map +1 -0
  11. package/dist/community/community-node-service.js +210 -0
  12. package/dist/community/community-node-service.js.map +1 -0
  13. package/dist/community/documentation-batch-processor.d.ts +33 -0
  14. package/dist/community/documentation-batch-processor.d.ts.map +1 -0
  15. package/dist/community/documentation-batch-processor.js +156 -0
  16. package/dist/community/documentation-batch-processor.js.map +1 -0
  17. package/dist/community/documentation-generator.d.ts +65 -0
  18. package/dist/community/documentation-generator.d.ts.map +1 -0
  19. package/dist/community/documentation-generator.js +220 -0
  20. package/dist/community/documentation-generator.js.map +1 -0
  21. package/dist/community/index.d.ts +5 -0
  22. package/dist/community/index.d.ts.map +1 -0
  23. package/dist/community/index.js +14 -0
  24. package/dist/community/index.js.map +1 -0
  25. package/dist/config/n8n-api.d.ts +15 -0
  26. package/dist/config/n8n-api.d.ts.map +1 -0
  27. package/dist/config/n8n-api.js +53 -0
  28. package/dist/config/n8n-api.js.map +1 -0
  29. package/dist/constants/type-structures.d.ts +123 -0
  30. package/dist/constants/type-structures.d.ts.map +1 -0
  31. package/dist/constants/type-structures.js +654 -0
  32. package/dist/constants/type-structures.js.map +1 -0
  33. package/dist/database/database-adapter.d.ts +33 -0
  34. package/dist/database/database-adapter.d.ts.map +1 -0
  35. package/dist/database/database-adapter.js +420 -0
  36. package/dist/database/database-adapter.js.map +1 -0
  37. package/dist/database/node-repository.d.ts +152 -0
  38. package/dist/database/node-repository.d.ts.map +1 -0
  39. package/dist/database/node-repository.js +791 -0
  40. package/dist/database/node-repository.js.map +1 -0
  41. package/dist/errors/validation-service-error.d.ts +10 -0
  42. package/dist/errors/validation-service-error.d.ts.map +1 -0
  43. package/dist/errors/validation-service-error.js +26 -0
  44. package/dist/errors/validation-service-error.js.map +1 -0
  45. package/dist/http-server-single-session.d.ts +52 -0
  46. package/dist/http-server-single-session.d.ts.map +1 -0
  47. package/dist/http-server-single-session.js +1180 -0
  48. package/dist/http-server-single-session.js.map +1 -0
  49. package/dist/http-server.d.ts +9 -0
  50. package/dist/http-server.d.ts.map +1 -0
  51. package/dist/http-server.js +481 -0
  52. package/dist/http-server.js.map +1 -0
  53. package/dist/index.d.ts +11 -0
  54. package/dist/index.d.ts.map +1 -0
  55. package/dist/index.js +20 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/loaders/node-loader.d.ts +11 -0
  58. package/dist/loaders/node-loader.d.ts.map +1 -0
  59. package/dist/loaders/node-loader.js +79 -0
  60. package/dist/loaders/node-loader.js.map +1 -0
  61. package/dist/mappers/docs-mapper.d.ts +7 -0
  62. package/dist/mappers/docs-mapper.d.ts.map +1 -0
  63. package/dist/mappers/docs-mapper.js +106 -0
  64. package/dist/mappers/docs-mapper.js.map +1 -0
  65. package/dist/mcp/handlers-n8n-manager.d.ts +58 -0
  66. package/dist/mcp/handlers-n8n-manager.d.ts.map +1 -0
  67. package/dist/mcp/handlers-n8n-manager.js +3299 -0
  68. package/dist/mcp/handlers-n8n-manager.js.map +1 -0
  69. package/dist/mcp/handlers-workflow-diff.d.ts +5 -0
  70. package/dist/mcp/handlers-workflow-diff.d.ts.map +1 -0
  71. package/dist/mcp/handlers-workflow-diff.js +461 -0
  72. package/dist/mcp/handlers-workflow-diff.js.map +1 -0
  73. package/dist/mcp/index.d.ts +3 -0
  74. package/dist/mcp/index.d.ts.map +1 -0
  75. package/dist/mcp/index.js +228 -0
  76. package/dist/mcp/index.js.map +1 -0
  77. package/dist/mcp/server.d.ts +82 -0
  78. package/dist/mcp/server.d.ts.map +1 -0
  79. package/dist/mcp/server.js +3006 -0
  80. package/dist/mcp/server.js.map +1 -0
  81. package/dist/mcp/stdio-wrapper.d.ts +3 -0
  82. package/dist/mcp/stdio-wrapper.d.ts.map +1 -0
  83. package/dist/mcp/stdio-wrapper.js +81 -0
  84. package/dist/mcp/stdio-wrapper.js.map +1 -0
  85. package/dist/mcp/tool-docs/configuration/get-node.d.ts +3 -0
  86. package/dist/mcp/tool-docs/configuration/get-node.d.ts.map +1 -0
  87. package/dist/mcp/tool-docs/configuration/get-node.js +90 -0
  88. package/dist/mcp/tool-docs/configuration/get-node.js.map +1 -0
  89. package/dist/mcp/tool-docs/configuration/index.d.ts +2 -0
  90. package/dist/mcp/tool-docs/configuration/index.d.ts.map +1 -0
  91. package/dist/mcp/tool-docs/configuration/index.js +6 -0
  92. package/dist/mcp/tool-docs/configuration/index.js.map +1 -0
  93. package/dist/mcp/tool-docs/discovery/index.d.ts +2 -0
  94. package/dist/mcp/tool-docs/discovery/index.d.ts.map +1 -0
  95. package/dist/mcp/tool-docs/discovery/index.js +6 -0
  96. package/dist/mcp/tool-docs/discovery/index.js.map +1 -0
  97. package/dist/mcp/tool-docs/discovery/search-nodes.d.ts +3 -0
  98. package/dist/mcp/tool-docs/discovery/search-nodes.d.ts.map +1 -0
  99. package/dist/mcp/tool-docs/discovery/search-nodes.js +70 -0
  100. package/dist/mcp/tool-docs/discovery/search-nodes.js.map +1 -0
  101. package/dist/mcp/tool-docs/guides/ai-agents-guide.d.ts +3 -0
  102. package/dist/mcp/tool-docs/guides/ai-agents-guide.d.ts.map +1 -0
  103. package/dist/mcp/tool-docs/guides/ai-agents-guide.js +739 -0
  104. package/dist/mcp/tool-docs/guides/ai-agents-guide.js.map +1 -0
  105. package/dist/mcp/tool-docs/guides/index.d.ts +2 -0
  106. package/dist/mcp/tool-docs/guides/index.d.ts.map +1 -0
  107. package/dist/mcp/tool-docs/guides/index.js +6 -0
  108. package/dist/mcp/tool-docs/guides/index.js.map +1 -0
  109. package/dist/mcp/tool-docs/index.d.ts +4 -0
  110. package/dist/mcp/tool-docs/index.d.ts.map +1 -0
  111. package/dist/mcp/tool-docs/index.js +34 -0
  112. package/dist/mcp/tool-docs/index.js.map +1 -0
  113. package/dist/mcp/tool-docs/system/index.d.ts +3 -0
  114. package/dist/mcp/tool-docs/system/index.d.ts.map +1 -0
  115. package/dist/mcp/tool-docs/system/index.js +8 -0
  116. package/dist/mcp/tool-docs/system/index.js.map +1 -0
  117. package/dist/mcp/tool-docs/system/n8n-diagnostic.d.ts +3 -0
  118. package/dist/mcp/tool-docs/system/n8n-diagnostic.d.ts.map +1 -0
  119. package/dist/mcp/tool-docs/system/n8n-diagnostic.js +99 -0
  120. package/dist/mcp/tool-docs/system/n8n-diagnostic.js.map +1 -0
  121. package/dist/mcp/tool-docs/system/n8n-health-check.d.ts +3 -0
  122. package/dist/mcp/tool-docs/system/n8n-health-check.d.ts.map +1 -0
  123. package/dist/mcp/tool-docs/system/n8n-health-check.js +102 -0
  124. package/dist/mcp/tool-docs/system/n8n-health-check.js.map +1 -0
  125. package/dist/mcp/tool-docs/system/n8n-list-available-tools.d.ts +3 -0
  126. package/dist/mcp/tool-docs/system/n8n-list-available-tools.d.ts.map +1 -0
  127. package/dist/mcp/tool-docs/system/n8n-list-available-tools.js +75 -0
  128. package/dist/mcp/tool-docs/system/n8n-list-available-tools.js.map +1 -0
  129. package/dist/mcp/tool-docs/system/tools-documentation.d.ts +3 -0
  130. package/dist/mcp/tool-docs/system/tools-documentation.d.ts.map +1 -0
  131. package/dist/mcp/tool-docs/system/tools-documentation.js +65 -0
  132. package/dist/mcp/tool-docs/system/tools-documentation.js.map +1 -0
  133. package/dist/mcp/tool-docs/templates/get-template.d.ts +3 -0
  134. package/dist/mcp/tool-docs/templates/get-template.d.ts.map +1 -0
  135. package/dist/mcp/tool-docs/templates/get-template.js +84 -0
  136. package/dist/mcp/tool-docs/templates/get-template.js.map +1 -0
  137. package/dist/mcp/tool-docs/templates/index.d.ts +3 -0
  138. package/dist/mcp/tool-docs/templates/index.d.ts.map +1 -0
  139. package/dist/mcp/tool-docs/templates/index.js +8 -0
  140. package/dist/mcp/tool-docs/templates/index.js.map +1 -0
  141. package/dist/mcp/tool-docs/templates/search-templates.d.ts +3 -0
  142. package/dist/mcp/tool-docs/templates/search-templates.d.ts.map +1 -0
  143. package/dist/mcp/tool-docs/templates/search-templates.js +143 -0
  144. package/dist/mcp/tool-docs/templates/search-templates.js.map +1 -0
  145. package/dist/mcp/tool-docs/types.d.ts +32 -0
  146. package/dist/mcp/tool-docs/types.d.ts.map +1 -0
  147. package/dist/mcp/tool-docs/types.js +3 -0
  148. package/dist/mcp/tool-docs/types.js.map +1 -0
  149. package/dist/mcp/tool-docs/validation/index.d.ts +3 -0
  150. package/dist/mcp/tool-docs/validation/index.d.ts.map +1 -0
  151. package/dist/mcp/tool-docs/validation/index.js +8 -0
  152. package/dist/mcp/tool-docs/validation/index.js.map +1 -0
  153. package/dist/mcp/tool-docs/validation/validate-node.d.ts +3 -0
  154. package/dist/mcp/tool-docs/validation/validate-node.d.ts.map +1 -0
  155. package/dist/mcp/tool-docs/validation/validate-node.js +82 -0
  156. package/dist/mcp/tool-docs/validation/validate-node.js.map +1 -0
  157. package/dist/mcp/tool-docs/validation/validate-workflow.d.ts +3 -0
  158. package/dist/mcp/tool-docs/validation/validate-workflow.d.ts.map +1 -0
  159. package/dist/mcp/tool-docs/validation/validate-workflow.js +86 -0
  160. package/dist/mcp/tool-docs/validation/validate-workflow.js.map +1 -0
  161. package/dist/mcp/tool-docs/workflow_management/index.d.ts +13 -0
  162. package/dist/mcp/tool-docs/workflow_management/index.d.ts.map +1 -0
  163. package/dist/mcp/tool-docs/workflow_management/index.js +28 -0
  164. package/dist/mcp/tool-docs/workflow_management/index.js.map +1 -0
  165. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.d.ts +3 -0
  166. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.d.ts.map +1 -0
  167. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.js +162 -0
  168. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.js.map +1 -0
  169. package/dist/mcp/tool-docs/workflow_management/n8n-create-workflow.d.ts +3 -0
  170. package/dist/mcp/tool-docs/workflow_management/n8n-create-workflow.d.ts.map +1 -0
  171. package/dist/mcp/tool-docs/workflow_management/n8n-create-workflow.js +102 -0
  172. package/dist/mcp/tool-docs/workflow_management/n8n-create-workflow.js.map +1 -0
  173. package/dist/mcp/tool-docs/workflow_management/n8n-delete-workflow.d.ts +3 -0
  174. package/dist/mcp/tool-docs/workflow_management/n8n-delete-workflow.d.ts.map +1 -0
  175. package/dist/mcp/tool-docs/workflow_management/n8n-delete-workflow.js +52 -0
  176. package/dist/mcp/tool-docs/workflow_management/n8n-delete-workflow.js.map +1 -0
  177. package/dist/mcp/tool-docs/workflow_management/n8n-deploy-template.d.ts +3 -0
  178. package/dist/mcp/tool-docs/workflow_management/n8n-deploy-template.d.ts.map +1 -0
  179. package/dist/mcp/tool-docs/workflow_management/n8n-deploy-template.js +73 -0
  180. package/dist/mcp/tool-docs/workflow_management/n8n-deploy-template.js.map +1 -0
  181. package/dist/mcp/tool-docs/workflow_management/n8n-executions.d.ts +3 -0
  182. package/dist/mcp/tool-docs/workflow_management/n8n-executions.d.ts.map +1 -0
  183. package/dist/mcp/tool-docs/workflow_management/n8n-executions.js +109 -0
  184. package/dist/mcp/tool-docs/workflow_management/n8n-executions.js.map +1 -0
  185. package/dist/mcp/tool-docs/workflow_management/n8n-get-workflow.d.ts +3 -0
  186. package/dist/mcp/tool-docs/workflow_management/n8n-get-workflow.d.ts.map +1 -0
  187. package/dist/mcp/tool-docs/workflow_management/n8n-get-workflow.js +68 -0
  188. package/dist/mcp/tool-docs/workflow_management/n8n-get-workflow.js.map +1 -0
  189. package/dist/mcp/tool-docs/workflow_management/n8n-list-workflows.d.ts +3 -0
  190. package/dist/mcp/tool-docs/workflow_management/n8n-list-workflows.d.ts.map +1 -0
  191. package/dist/mcp/tool-docs/workflow_management/n8n-list-workflows.js +57 -0
  192. package/dist/mcp/tool-docs/workflow_management/n8n-list-workflows.js.map +1 -0
  193. package/dist/mcp/tool-docs/workflow_management/n8n-test-workflow.d.ts +3 -0
  194. package/dist/mcp/tool-docs/workflow_management/n8n-test-workflow.d.ts.map +1 -0
  195. package/dist/mcp/tool-docs/workflow_management/n8n-test-workflow.js +140 -0
  196. package/dist/mcp/tool-docs/workflow_management/n8n-test-workflow.js.map +1 -0
  197. package/dist/mcp/tool-docs/workflow_management/n8n-update-full-workflow.d.ts +3 -0
  198. package/dist/mcp/tool-docs/workflow_management/n8n-update-full-workflow.d.ts.map +1 -0
  199. package/dist/mcp/tool-docs/workflow_management/n8n-update-full-workflow.js +61 -0
  200. package/dist/mcp/tool-docs/workflow_management/n8n-update-full-workflow.js.map +1 -0
  201. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.d.ts +3 -0
  202. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.d.ts.map +1 -0
  203. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js +420 -0
  204. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js.map +1 -0
  205. package/dist/mcp/tool-docs/workflow_management/n8n-validate-workflow.d.ts +3 -0
  206. package/dist/mcp/tool-docs/workflow_management/n8n-validate-workflow.d.ts.map +1 -0
  207. package/dist/mcp/tool-docs/workflow_management/n8n-validate-workflow.js +73 -0
  208. package/dist/mcp/tool-docs/workflow_management/n8n-validate-workflow.js.map +1 -0
  209. package/dist/mcp/tool-docs/workflow_management/n8n-workflow-versions.d.ts +3 -0
  210. package/dist/mcp/tool-docs/workflow_management/n8n-workflow-versions.d.ts.map +1 -0
  211. package/dist/mcp/tool-docs/workflow_management/n8n-workflow-versions.js +170 -0
  212. package/dist/mcp/tool-docs/workflow_management/n8n-workflow-versions.js.map +1 -0
  213. package/dist/mcp/tools-documentation.d.ts +6 -0
  214. package/dist/mcp/tools-documentation.d.ts.map +1 -0
  215. package/dist/mcp/tools-documentation.js +682 -0
  216. package/dist/mcp/tools-documentation.js.map +1 -0
  217. package/dist/mcp/tools-file-operations.d.ts +154 -0
  218. package/dist/mcp/tools-file-operations.d.ts.map +1 -0
  219. package/dist/mcp/tools-file-operations.js +213 -0
  220. package/dist/mcp/tools-file-operations.js.map +1 -0
  221. package/dist/mcp/tools-n8n-friendly.d.ts +6 -0
  222. package/dist/mcp/tools-n8n-friendly.d.ts.map +1 -0
  223. package/dist/mcp/tools-n8n-friendly.js +89 -0
  224. package/dist/mcp/tools-n8n-friendly.js.map +1 -0
  225. package/dist/mcp/tools-n8n-manager.d.ts +3 -0
  226. package/dist/mcp/tools-n8n-manager.d.ts.map +1 -0
  227. package/dist/mcp/tools-n8n-manager.js +1320 -0
  228. package/dist/mcp/tools-n8n-manager.js.map +1 -0
  229. package/dist/mcp/tools.d.ts +3 -0
  230. package/dist/mcp/tools.d.ts.map +1 -0
  231. package/dist/mcp/tools.js +424 -0
  232. package/dist/mcp/tools.js.map +1 -0
  233. package/dist/mcp/workflow-examples.d.ts +76 -0
  234. package/dist/mcp/workflow-examples.d.ts.map +1 -0
  235. package/dist/mcp/workflow-examples.js +111 -0
  236. package/dist/mcp/workflow-examples.js.map +1 -0
  237. package/dist/mcp-engine.d.ts +36 -0
  238. package/dist/mcp-engine.d.ts.map +1 -0
  239. package/dist/mcp-engine.js +77 -0
  240. package/dist/mcp-engine.js.map +1 -0
  241. package/dist/mcp-tools-engine.d.ts +47 -0
  242. package/dist/mcp-tools-engine.d.ts.map +1 -0
  243. package/dist/mcp-tools-engine.js +89 -0
  244. package/dist/mcp-tools-engine.js.map +1 -0
  245. package/dist/n8n/MCPApi.credentials.d.ts +8 -0
  246. package/dist/n8n/MCPApi.credentials.d.ts.map +1 -0
  247. package/dist/n8n/MCPApi.credentials.js +53 -0
  248. package/dist/n8n/MCPApi.credentials.js.map +1 -0
  249. package/dist/n8n/MCPNode.node.d.ts +13 -0
  250. package/dist/n8n/MCPNode.node.d.ts.map +1 -0
  251. package/dist/n8n/MCPNode.node.js +260 -0
  252. package/dist/n8n/MCPNode.node.js.map +1 -0
  253. package/dist/parsers/node-parser.d.ts +38 -0
  254. package/dist/parsers/node-parser.d.ts.map +1 -0
  255. package/dist/parsers/node-parser.js +250 -0
  256. package/dist/parsers/node-parser.js.map +1 -0
  257. package/dist/parsers/property-extractor.d.ts +11 -0
  258. package/dist/parsers/property-extractor.d.ts.map +1 -0
  259. package/dist/parsers/property-extractor.js +172 -0
  260. package/dist/parsers/property-extractor.js.map +1 -0
  261. package/dist/parsers/simple-parser.d.ts +25 -0
  262. package/dist/parsers/simple-parser.d.ts.map +1 -0
  263. package/dist/parsers/simple-parser.js +212 -0
  264. package/dist/parsers/simple-parser.js.map +1 -0
  265. package/dist/scripts/debug-http-search.d.ts +3 -0
  266. package/dist/scripts/debug-http-search.d.ts.map +1 -0
  267. package/dist/scripts/debug-http-search.js +57 -0
  268. package/dist/scripts/debug-http-search.js.map +1 -0
  269. package/dist/scripts/extract-from-docker.d.ts +3 -0
  270. package/dist/scripts/extract-from-docker.d.ts.map +1 -0
  271. package/dist/scripts/extract-from-docker.js +210 -0
  272. package/dist/scripts/extract-from-docker.js.map +1 -0
  273. package/dist/scripts/fetch-community-nodes.d.ts +3 -0
  274. package/dist/scripts/fetch-community-nodes.d.ts.map +1 -0
  275. package/dist/scripts/fetch-community-nodes.js +114 -0
  276. package/dist/scripts/fetch-community-nodes.js.map +1 -0
  277. package/dist/scripts/fetch-templates-robust.d.ts +4 -0
  278. package/dist/scripts/fetch-templates-robust.d.ts.map +1 -0
  279. package/dist/scripts/fetch-templates-robust.js +132 -0
  280. package/dist/scripts/fetch-templates-robust.js.map +1 -0
  281. package/dist/scripts/fetch-templates.d.ts +4 -0
  282. package/dist/scripts/fetch-templates.d.ts.map +1 -0
  283. package/dist/scripts/fetch-templates.js +411 -0
  284. package/dist/scripts/fetch-templates.js.map +1 -0
  285. package/dist/scripts/generate-community-docs.d.ts +3 -0
  286. package/dist/scripts/generate-community-docs.d.ts.map +1 -0
  287. package/dist/scripts/generate-community-docs.js +183 -0
  288. package/dist/scripts/generate-community-docs.js.map +1 -0
  289. package/dist/scripts/migrate-readme-columns.d.ts +2 -0
  290. package/dist/scripts/migrate-readme-columns.d.ts.map +1 -0
  291. package/dist/scripts/migrate-readme-columns.js +62 -0
  292. package/dist/scripts/migrate-readme-columns.js.map +1 -0
  293. package/dist/scripts/rebuild-database.d.ts +4 -0
  294. package/dist/scripts/rebuild-database.d.ts.map +1 -0
  295. package/dist/scripts/rebuild-database.js +95 -0
  296. package/dist/scripts/rebuild-database.js.map +1 -0
  297. package/dist/scripts/rebuild-optimized.d.ts +3 -0
  298. package/dist/scripts/rebuild-optimized.d.ts.map +1 -0
  299. package/dist/scripts/rebuild-optimized.js +198 -0
  300. package/dist/scripts/rebuild-optimized.js.map +1 -0
  301. package/dist/scripts/rebuild.d.ts +3 -0
  302. package/dist/scripts/rebuild.d.ts.map +1 -0
  303. package/dist/scripts/rebuild.js +258 -0
  304. package/dist/scripts/rebuild.js.map +1 -0
  305. package/dist/scripts/sanitize-templates.d.ts +3 -0
  306. package/dist/scripts/sanitize-templates.d.ts.map +1 -0
  307. package/dist/scripts/sanitize-templates.js +88 -0
  308. package/dist/scripts/sanitize-templates.js.map +1 -0
  309. package/dist/scripts/seed-canonical-ai-examples.d.ts +4 -0
  310. package/dist/scripts/seed-canonical-ai-examples.d.ts.map +1 -0
  311. package/dist/scripts/seed-canonical-ai-examples.js +121 -0
  312. package/dist/scripts/seed-canonical-ai-examples.js.map +1 -0
  313. package/dist/scripts/test-autofix-documentation.d.ts +3 -0
  314. package/dist/scripts/test-autofix-documentation.d.ts.map +1 -0
  315. package/dist/scripts/test-autofix-documentation.js +103 -0
  316. package/dist/scripts/test-autofix-documentation.js.map +1 -0
  317. package/dist/scripts/test-autofix-workflow.d.ts +2 -0
  318. package/dist/scripts/test-autofix-workflow.d.ts.map +1 -0
  319. package/dist/scripts/test-autofix-workflow.js +223 -0
  320. package/dist/scripts/test-autofix-workflow.js.map +1 -0
  321. package/dist/scripts/test-execution-filtering.d.ts +3 -0
  322. package/dist/scripts/test-execution-filtering.d.ts.map +1 -0
  323. package/dist/scripts/test-execution-filtering.js +206 -0
  324. package/dist/scripts/test-execution-filtering.js.map +1 -0
  325. package/dist/scripts/test-node-suggestions.d.ts +3 -0
  326. package/dist/scripts/test-node-suggestions.d.ts.map +1 -0
  327. package/dist/scripts/test-node-suggestions.js +165 -0
  328. package/dist/scripts/test-node-suggestions.js.map +1 -0
  329. package/dist/scripts/test-protocol-negotiation.d.ts +3 -0
  330. package/dist/scripts/test-protocol-negotiation.d.ts.map +1 -0
  331. package/dist/scripts/test-protocol-negotiation.js +154 -0
  332. package/dist/scripts/test-protocol-negotiation.js.map +1 -0
  333. package/dist/scripts/test-summary.d.ts +3 -0
  334. package/dist/scripts/test-summary.d.ts.map +1 -0
  335. package/dist/scripts/test-summary.js +77 -0
  336. package/dist/scripts/test-summary.js.map +1 -0
  337. package/dist/scripts/test-telemetry-mutations-verbose.d.ts +2 -0
  338. package/dist/scripts/test-telemetry-mutations-verbose.d.ts.map +1 -0
  339. package/dist/scripts/test-telemetry-mutations-verbose.js +133 -0
  340. package/dist/scripts/test-telemetry-mutations-verbose.js.map +1 -0
  341. package/dist/scripts/test-telemetry-mutations.d.ts +2 -0
  342. package/dist/scripts/test-telemetry-mutations.d.ts.map +1 -0
  343. package/dist/scripts/test-telemetry-mutations.js +129 -0
  344. package/dist/scripts/test-telemetry-mutations.js.map +1 -0
  345. package/dist/scripts/test-webhook-autofix.d.ts +3 -0
  346. package/dist/scripts/test-webhook-autofix.d.ts.map +1 -0
  347. package/dist/scripts/test-webhook-autofix.js +117 -0
  348. package/dist/scripts/test-webhook-autofix.js.map +1 -0
  349. package/dist/scripts/validate.d.ts +3 -0
  350. package/dist/scripts/validate.d.ts.map +1 -0
  351. package/dist/scripts/validate.js +121 -0
  352. package/dist/scripts/validate.js.map +1 -0
  353. package/dist/scripts/validation-summary.d.ts +3 -0
  354. package/dist/scripts/validation-summary.d.ts.map +1 -0
  355. package/dist/scripts/validation-summary.js +135 -0
  356. package/dist/scripts/validation-summary.js.map +1 -0
  357. package/dist/services/ai-node-validator.d.ts +12 -0
  358. package/dist/services/ai-node-validator.d.ts.map +1 -0
  359. package/dist/services/ai-node-validator.js +429 -0
  360. package/dist/services/ai-node-validator.js.map +1 -0
  361. package/dist/services/ai-tool-validators.d.ts +58 -0
  362. package/dist/services/ai-tool-validators.d.ts.map +1 -0
  363. package/dist/services/ai-tool-validators.js +438 -0
  364. package/dist/services/ai-tool-validators.js.map +1 -0
  365. package/dist/services/breaking-change-detector.d.ts +38 -0
  366. package/dist/services/breaking-change-detector.d.ts.map +1 -0
  367. package/dist/services/breaking-change-detector.js +184 -0
  368. package/dist/services/breaking-change-detector.js.map +1 -0
  369. package/dist/services/breaking-changes-registry.d.ts +28 -0
  370. package/dist/services/breaking-changes-registry.d.ts.map +1 -0
  371. package/dist/services/breaking-changes-registry.js +200 -0
  372. package/dist/services/breaking-changes-registry.js.map +1 -0
  373. package/dist/services/community-package-service.d.ts +69 -0
  374. package/dist/services/community-package-service.d.ts.map +1 -0
  375. package/dist/services/community-package-service.js +202 -0
  376. package/dist/services/community-package-service.js.map +1 -0
  377. package/dist/services/confidence-scorer.d.ts +24 -0
  378. package/dist/services/confidence-scorer.d.ts.map +1 -0
  379. package/dist/services/confidence-scorer.js +139 -0
  380. package/dist/services/confidence-scorer.js.map +1 -0
  381. package/dist/services/config-validator.d.ts +49 -0
  382. package/dist/services/config-validator.d.ts.map +1 -0
  383. package/dist/services/config-validator.js +724 -0
  384. package/dist/services/config-validator.js.map +1 -0
  385. package/dist/services/enhanced-config-validator.d.ts +54 -0
  386. package/dist/services/enhanced-config-validator.d.ts.map +1 -0
  387. package/dist/services/enhanced-config-validator.js +789 -0
  388. package/dist/services/enhanced-config-validator.js.map +1 -0
  389. package/dist/services/error-execution-processor.d.ts +9 -0
  390. package/dist/services/error-execution-processor.d.ts.map +1 -0
  391. package/dist/services/error-execution-processor.js +380 -0
  392. package/dist/services/error-execution-processor.js.map +1 -0
  393. package/dist/services/example-generator.d.ts +14 -0
  394. package/dist/services/example-generator.d.ts.map +1 -0
  395. package/dist/services/example-generator.js +970 -0
  396. package/dist/services/example-generator.js.map +1 -0
  397. package/dist/services/execution-processor.d.ts +8 -0
  398. package/dist/services/execution-processor.d.ts.map +1 -0
  399. package/dist/services/execution-processor.js +381 -0
  400. package/dist/services/execution-processor.js.map +1 -0
  401. package/dist/services/expression-format-validator.d.ts +33 -0
  402. package/dist/services/expression-format-validator.d.ts.map +1 -0
  403. package/dist/services/expression-format-validator.js +209 -0
  404. package/dist/services/expression-format-validator.js.map +1 -0
  405. package/dist/services/expression-validator.d.ts +27 -0
  406. package/dist/services/expression-validator.d.ts.map +1 -0
  407. package/dist/services/expression-validator.js +187 -0
  408. package/dist/services/expression-validator.js.map +1 -0
  409. package/dist/services/installed-node-sync-service.d.ts +32 -0
  410. package/dist/services/installed-node-sync-service.d.ts.map +1 -0
  411. package/dist/services/installed-node-sync-service.js +190 -0
  412. package/dist/services/installed-node-sync-service.js.map +1 -0
  413. package/dist/services/n8n-api-client.d.ts +48 -0
  414. package/dist/services/n8n-api-client.d.ts.map +1 -0
  415. package/dist/services/n8n-api-client.js +458 -0
  416. package/dist/services/n8n-api-client.js.map +1 -0
  417. package/dist/services/n8n-file-format.d.ts +58 -0
  418. package/dist/services/n8n-file-format.d.ts.map +1 -0
  419. package/dist/services/n8n-file-format.js +203 -0
  420. package/dist/services/n8n-file-format.js.map +1 -0
  421. package/dist/services/n8n-validation.d.ts +273 -0
  422. package/dist/services/n8n-validation.d.ts.map +1 -0
  423. package/dist/services/n8n-validation.js +491 -0
  424. package/dist/services/n8n-validation.js.map +1 -0
  425. package/dist/services/n8n-version.d.ts +23 -0
  426. package/dist/services/n8n-version.d.ts.map +1 -0
  427. package/dist/services/n8n-version.js +151 -0
  428. package/dist/services/n8n-version.js.map +1 -0
  429. package/dist/services/node-documentation-service.d.ts +70 -0
  430. package/dist/services/node-documentation-service.d.ts.map +1 -0
  431. package/dist/services/node-documentation-service.js +518 -0
  432. package/dist/services/node-documentation-service.js.map +1 -0
  433. package/dist/services/node-migration-service.d.ts +44 -0
  434. package/dist/services/node-migration-service.d.ts.map +1 -0
  435. package/dist/services/node-migration-service.js +231 -0
  436. package/dist/services/node-migration-service.js.map +1 -0
  437. package/dist/services/node-sanitizer.d.ts +5 -0
  438. package/dist/services/node-sanitizer.d.ts.map +1 -0
  439. package/dist/services/node-sanitizer.js +225 -0
  440. package/dist/services/node-sanitizer.js.map +1 -0
  441. package/dist/services/node-similarity-service.d.ts +51 -0
  442. package/dist/services/node-similarity-service.d.ts.map +1 -0
  443. package/dist/services/node-similarity-service.js +352 -0
  444. package/dist/services/node-similarity-service.js.map +1 -0
  445. package/dist/services/node-specific-validators.d.ts +37 -0
  446. package/dist/services/node-specific-validators.d.ts.map +1 -0
  447. package/dist/services/node-specific-validators.js +1331 -0
  448. package/dist/services/node-specific-validators.js.map +1 -0
  449. package/dist/services/node-version-service.d.ts +63 -0
  450. package/dist/services/node-version-service.d.ts.map +1 -0
  451. package/dist/services/node-version-service.js +215 -0
  452. package/dist/services/node-version-service.js.map +1 -0
  453. package/dist/services/operation-similarity-service.d.ts +32 -0
  454. package/dist/services/operation-similarity-service.d.ts.map +1 -0
  455. package/dist/services/operation-similarity-service.js +341 -0
  456. package/dist/services/operation-similarity-service.js.map +1 -0
  457. package/dist/services/post-update-validator.d.ts +59 -0
  458. package/dist/services/post-update-validator.d.ts.map +1 -0
  459. package/dist/services/post-update-validator.js +231 -0
  460. package/dist/services/post-update-validator.js.map +1 -0
  461. package/dist/services/property-dependencies.d.ts +36 -0
  462. package/dist/services/property-dependencies.d.ts.map +1 -0
  463. package/dist/services/property-dependencies.js +168 -0
  464. package/dist/services/property-dependencies.js.map +1 -0
  465. package/dist/services/property-filter.d.ts +44 -0
  466. package/dist/services/property-filter.d.ts.map +1 -0
  467. package/dist/services/property-filter.js +395 -0
  468. package/dist/services/property-filter.js.map +1 -0
  469. package/dist/services/resource-similarity-service.d.ts +33 -0
  470. package/dist/services/resource-similarity-service.d.ts.map +1 -0
  471. package/dist/services/resource-similarity-service.js +358 -0
  472. package/dist/services/resource-similarity-service.js.map +1 -0
  473. package/dist/services/sqlite-storage-service.d.ts +11 -0
  474. package/dist/services/sqlite-storage-service.d.ts.map +1 -0
  475. package/dist/services/sqlite-storage-service.js +74 -0
  476. package/dist/services/sqlite-storage-service.js.map +1 -0
  477. package/dist/services/task-templates.d.ts +27 -0
  478. package/dist/services/task-templates.d.ts.map +1 -0
  479. package/dist/services/task-templates.js +1397 -0
  480. package/dist/services/task-templates.js.map +1 -0
  481. package/dist/services/tool-variant-generator.d.ts +10 -0
  482. package/dist/services/tool-variant-generator.d.ts.map +1 -0
  483. package/dist/services/tool-variant-generator.js +93 -0
  484. package/dist/services/tool-variant-generator.js.map +1 -0
  485. package/dist/services/type-structure-service.d.ts +23 -0
  486. package/dist/services/type-structure-service.d.ts.map +1 -0
  487. package/dist/services/type-structure-service.js +109 -0
  488. package/dist/services/type-structure-service.js.map +1 -0
  489. package/dist/services/universal-expression-validator.d.ts +20 -0
  490. package/dist/services/universal-expression-validator.d.ts.map +1 -0
  491. package/dist/services/universal-expression-validator.js +192 -0
  492. package/dist/services/universal-expression-validator.js.map +1 -0
  493. package/dist/services/workflow-analytics-service.d.ts +34 -0
  494. package/dist/services/workflow-analytics-service.d.ts.map +1 -0
  495. package/dist/services/workflow-analytics-service.js +144 -0
  496. package/dist/services/workflow-analytics-service.js.map +1 -0
  497. package/dist/services/workflow-auto-fixer.d.ts +74 -0
  498. package/dist/services/workflow-auto-fixer.d.ts.map +1 -0
  499. package/dist/services/workflow-auto-fixer.js +557 -0
  500. package/dist/services/workflow-auto-fixer.js.map +1 -0
  501. package/dist/services/workflow-comparison.d.ts +13 -0
  502. package/dist/services/workflow-comparison.d.ts.map +1 -0
  503. package/dist/services/workflow-comparison.js +306 -0
  504. package/dist/services/workflow-comparison.js.map +1 -0
  505. package/dist/services/workflow-debugging-service.d.ts +62 -0
  506. package/dist/services/workflow-debugging-service.d.ts.map +1 -0
  507. package/dist/services/workflow-debugging-service.js +153 -0
  508. package/dist/services/workflow-debugging-service.js.map +1 -0
  509. package/dist/services/workflow-diff-engine.d.ts +45 -0
  510. package/dist/services/workflow-diff-engine.d.ts.map +1 -0
  511. package/dist/services/workflow-diff-engine.js +830 -0
  512. package/dist/services/workflow-diff-engine.js.map +1 -0
  513. package/dist/services/workflow-validator.d.ts +112 -0
  514. package/dist/services/workflow-validator.d.ts.map +1 -0
  515. package/dist/services/workflow-validator.js +1328 -0
  516. package/dist/services/workflow-validator.js.map +1 -0
  517. package/dist/services/workflow-versioning-service.d.ts +102 -0
  518. package/dist/services/workflow-versioning-service.d.ts.map +1 -0
  519. package/dist/services/workflow-versioning-service.js +264 -0
  520. package/dist/services/workflow-versioning-service.js.map +1 -0
  521. package/dist/telemetry/batch-processor.d.ts +34 -0
  522. package/dist/telemetry/batch-processor.d.ts.map +1 -0
  523. package/dist/telemetry/batch-processor.js +337 -0
  524. package/dist/telemetry/batch-processor.js.map +1 -0
  525. package/dist/telemetry/config-manager.d.ts +32 -0
  526. package/dist/telemetry/config-manager.d.ts.map +1 -0
  527. package/dist/telemetry/config-manager.js +289 -0
  528. package/dist/telemetry/config-manager.js.map +1 -0
  529. package/dist/telemetry/early-error-logger.d.ts +26 -0
  530. package/dist/telemetry/early-error-logger.d.ts.map +1 -0
  531. package/dist/telemetry/early-error-logger.js +187 -0
  532. package/dist/telemetry/early-error-logger.js.map +1 -0
  533. package/dist/telemetry/error-sanitization-utils.d.ts +2 -0
  534. package/dist/telemetry/error-sanitization-utils.d.ts.map +1 -0
  535. package/dist/telemetry/error-sanitization-utils.js +37 -0
  536. package/dist/telemetry/error-sanitization-utils.js.map +1 -0
  537. package/dist/telemetry/error-sanitizer.d.ts +4 -0
  538. package/dist/telemetry/error-sanitizer.d.ts.map +1 -0
  539. package/dist/telemetry/error-sanitizer.js +45 -0
  540. package/dist/telemetry/error-sanitizer.js.map +1 -0
  541. package/dist/telemetry/event-tracker.d.ts +71 -0
  542. package/dist/telemetry/event-tracker.d.ts.map +1 -0
  543. package/dist/telemetry/event-tracker.js +356 -0
  544. package/dist/telemetry/event-tracker.js.map +1 -0
  545. package/dist/telemetry/event-validator.d.ts +78 -0
  546. package/dist/telemetry/event-validator.d.ts.map +1 -0
  547. package/dist/telemetry/event-validator.js +227 -0
  548. package/dist/telemetry/event-validator.js.map +1 -0
  549. package/dist/telemetry/index.d.ts +5 -0
  550. package/dist/telemetry/index.d.ts.map +1 -0
  551. package/dist/telemetry/index.js +11 -0
  552. package/dist/telemetry/index.js.map +1 -0
  553. package/dist/telemetry/intent-classifier.d.ts +11 -0
  554. package/dist/telemetry/intent-classifier.d.ts.map +1 -0
  555. package/dist/telemetry/intent-classifier.js +141 -0
  556. package/dist/telemetry/intent-classifier.js.map +1 -0
  557. package/dist/telemetry/intent-sanitizer.d.ts +9 -0
  558. package/dist/telemetry/intent-sanitizer.d.ts.map +1 -0
  559. package/dist/telemetry/intent-sanitizer.js +103 -0
  560. package/dist/telemetry/intent-sanitizer.js.map +1 -0
  561. package/dist/telemetry/mutation-tracker.d.ts +15 -0
  562. package/dist/telemetry/mutation-tracker.d.ts.map +1 -0
  563. package/dist/telemetry/mutation-tracker.js +177 -0
  564. package/dist/telemetry/mutation-tracker.js.map +1 -0
  565. package/dist/telemetry/mutation-types.d.ts +106 -0
  566. package/dist/telemetry/mutation-types.d.ts.map +1 -0
  567. package/dist/telemetry/mutation-types.js +18 -0
  568. package/dist/telemetry/mutation-types.js.map +1 -0
  569. package/dist/telemetry/mutation-validator.d.ts +20 -0
  570. package/dist/telemetry/mutation-validator.d.ts.map +1 -0
  571. package/dist/telemetry/mutation-validator.js +144 -0
  572. package/dist/telemetry/mutation-validator.js.map +1 -0
  573. package/dist/telemetry/performance-monitor.d.ts +113 -0
  574. package/dist/telemetry/performance-monitor.d.ts.map +1 -0
  575. package/dist/telemetry/performance-monitor.js +208 -0
  576. package/dist/telemetry/performance-monitor.js.map +1 -0
  577. package/dist/telemetry/rate-limiter.d.ts +30 -0
  578. package/dist/telemetry/rate-limiter.d.ts.map +1 -0
  579. package/dist/telemetry/rate-limiter.js +103 -0
  580. package/dist/telemetry/rate-limiter.js.map +1 -0
  581. package/dist/telemetry/startup-checkpoints.d.ts +26 -0
  582. package/dist/telemetry/startup-checkpoints.d.ts.map +1 -0
  583. package/dist/telemetry/startup-checkpoints.js +65 -0
  584. package/dist/telemetry/startup-checkpoints.js.map +1 -0
  585. package/dist/telemetry/telemetry-error.d.ts +44 -0
  586. package/dist/telemetry/telemetry-error.d.ts.map +1 -0
  587. package/dist/telemetry/telemetry-error.js +153 -0
  588. package/dist/telemetry/telemetry-error.js.map +1 -0
  589. package/dist/telemetry/telemetry-manager.d.ts +130 -0
  590. package/dist/telemetry/telemetry-manager.d.ts.map +1 -0
  591. package/dist/telemetry/telemetry-manager.js +257 -0
  592. package/dist/telemetry/telemetry-manager.js.map +1 -0
  593. package/dist/telemetry/telemetry-types.d.ts +103 -0
  594. package/dist/telemetry/telemetry-types.d.ts.map +1 -0
  595. package/dist/telemetry/telemetry-types.js +29 -0
  596. package/dist/telemetry/telemetry-types.js.map +1 -0
  597. package/dist/telemetry/workflow-sanitizer.d.ts +34 -0
  598. package/dist/telemetry/workflow-sanitizer.d.ts.map +1 -0
  599. package/dist/telemetry/workflow-sanitizer.js +242 -0
  600. package/dist/telemetry/workflow-sanitizer.js.map +1 -0
  601. package/dist/templates/batch-processor.d.ts +35 -0
  602. package/dist/templates/batch-processor.d.ts.map +1 -0
  603. package/dist/templates/batch-processor.js +320 -0
  604. package/dist/templates/batch-processor.js.map +1 -0
  605. package/dist/templates/metadata-generator.d.ts +52 -0
  606. package/dist/templates/metadata-generator.d.ts.map +1 -0
  607. package/dist/templates/metadata-generator.js +252 -0
  608. package/dist/templates/metadata-generator.js.map +1 -0
  609. package/dist/templates/template-fetcher.d.ts +45 -0
  610. package/dist/templates/template-fetcher.d.ts.map +1 -0
  611. package/dist/templates/template-fetcher.js +122 -0
  612. package/dist/templates/template-fetcher.js.map +1 -0
  613. package/dist/templates/template-repository.d.ts +93 -0
  614. package/dist/templates/template-repository.d.ts.map +1 -0
  615. package/dist/templates/template-repository.js +644 -0
  616. package/dist/templates/template-repository.js.map +1 -0
  617. package/dist/templates/template-service.d.ts +79 -0
  618. package/dist/templates/template-service.d.ts.map +1 -0
  619. package/dist/templates/template-service.js +300 -0
  620. package/dist/templates/template-service.js.map +1 -0
  621. package/dist/triggers/handlers/base-handler.d.ts +21 -0
  622. package/dist/triggers/handlers/base-handler.d.ts.map +1 -0
  623. package/dist/triggers/handlers/base-handler.js +60 -0
  624. package/dist/triggers/handlers/base-handler.js.map +1 -0
  625. package/dist/triggers/handlers/chat-handler.d.ts +38 -0
  626. package/dist/triggers/handlers/chat-handler.d.ts.map +1 -0
  627. package/dist/triggers/handlers/chat-handler.js +129 -0
  628. package/dist/triggers/handlers/chat-handler.js.map +1 -0
  629. package/dist/triggers/handlers/form-handler.d.ts +35 -0
  630. package/dist/triggers/handlers/form-handler.d.ts.map +1 -0
  631. package/dist/triggers/handlers/form-handler.js +362 -0
  632. package/dist/triggers/handlers/form-handler.js.map +1 -0
  633. package/dist/triggers/handlers/webhook-handler.d.ts +38 -0
  634. package/dist/triggers/handlers/webhook-handler.d.ts.map +1 -0
  635. package/dist/triggers/handlers/webhook-handler.js +115 -0
  636. package/dist/triggers/handlers/webhook-handler.js.map +1 -0
  637. package/dist/triggers/index.d.ts +5 -0
  638. package/dist/triggers/index.d.ts.map +1 -0
  639. package/dist/triggers/index.js +14 -0
  640. package/dist/triggers/index.js.map +1 -0
  641. package/dist/triggers/trigger-detector.d.ts +6 -0
  642. package/dist/triggers/trigger-detector.d.ts.map +1 -0
  643. package/dist/triggers/trigger-detector.js +201 -0
  644. package/dist/triggers/trigger-detector.js.map +1 -0
  645. package/dist/triggers/trigger-registry.d.ts +18 -0
  646. package/dist/triggers/trigger-registry.d.ts.map +1 -0
  647. package/dist/triggers/trigger-registry.js +87 -0
  648. package/dist/triggers/trigger-registry.js.map +1 -0
  649. package/dist/triggers/types.d.ts +76 -0
  650. package/dist/triggers/types.d.ts.map +1 -0
  651. package/dist/triggers/types.js +3 -0
  652. package/dist/triggers/types.js.map +1 -0
  653. package/dist/types/index.d.ts +49 -0
  654. package/dist/types/index.d.ts.map +1 -0
  655. package/dist/types/index.js +21 -0
  656. package/dist/types/index.js.map +1 -0
  657. package/dist/types/instance-context.d.ts +20 -0
  658. package/dist/types/instance-context.d.ts.map +1 -0
  659. package/dist/types/instance-context.js +153 -0
  660. package/dist/types/instance-context.js.map +1 -0
  661. package/dist/types/n8n-api.d.ts +376 -0
  662. package/dist/types/n8n-api.d.ts.map +1 -0
  663. package/dist/types/n8n-api.js +10 -0
  664. package/dist/types/n8n-api.js.map +1 -0
  665. package/dist/types/node-types.d.ts +19 -0
  666. package/dist/types/node-types.d.ts.map +1 -0
  667. package/dist/types/node-types.js +62 -0
  668. package/dist/types/node-types.js.map +1 -0
  669. package/dist/types/session-state.d.ts +15 -0
  670. package/dist/types/session-state.d.ts.map +1 -0
  671. package/dist/types/session-state.js +3 -0
  672. package/dist/types/session-state.js.map +1 -0
  673. package/dist/types/type-structures.d.ts +42 -0
  674. package/dist/types/type-structures.d.ts.map +1 -0
  675. package/dist/types/type-structures.js +32 -0
  676. package/dist/types/type-structures.js.map +1 -0
  677. package/dist/types/workflow-comparison.d.ts +51 -0
  678. package/dist/types/workflow-comparison.d.ts.map +1 -0
  679. package/dist/types/workflow-comparison.js +3 -0
  680. package/dist/types/workflow-comparison.js.map +1 -0
  681. package/dist/types/workflow-diff.d.ts +148 -0
  682. package/dist/types/workflow-diff.d.ts.map +1 -0
  683. package/dist/types/workflow-diff.js +15 -0
  684. package/dist/types/workflow-diff.js.map +1 -0
  685. package/dist/utils/auth.d.ts +13 -0
  686. package/dist/utils/auth.d.ts.map +1 -0
  687. package/dist/utils/auth.js +82 -0
  688. package/dist/utils/auth.js.map +1 -0
  689. package/dist/utils/bridge.d.ts +12 -0
  690. package/dist/utils/bridge.d.ts.map +1 -0
  691. package/dist/utils/bridge.js +127 -0
  692. package/dist/utils/bridge.js.map +1 -0
  693. package/dist/utils/cache-utils.d.ts +58 -0
  694. package/dist/utils/cache-utils.d.ts.map +1 -0
  695. package/dist/utils/cache-utils.js +243 -0
  696. package/dist/utils/cache-utils.js.map +1 -0
  697. package/dist/utils/console-manager.d.ts +10 -0
  698. package/dist/utils/console-manager.d.ts.map +1 -0
  699. package/dist/utils/console-manager.js +63 -0
  700. package/dist/utils/console-manager.js.map +1 -0
  701. package/dist/utils/documentation-fetcher.d.ts +2 -0
  702. package/dist/utils/documentation-fetcher.d.ts.map +1 -0
  703. package/dist/utils/documentation-fetcher.js +18 -0
  704. package/dist/utils/documentation-fetcher.js.map +1 -0
  705. package/dist/utils/enhanced-documentation-fetcher.d.ts +74 -0
  706. package/dist/utils/enhanced-documentation-fetcher.d.ts.map +1 -0
  707. package/dist/utils/enhanced-documentation-fetcher.js +521 -0
  708. package/dist/utils/enhanced-documentation-fetcher.js.map +1 -0
  709. package/dist/utils/error-handler.d.ts +24 -0
  710. package/dist/utils/error-handler.d.ts.map +1 -0
  711. package/dist/utils/error-handler.js +84 -0
  712. package/dist/utils/error-handler.js.map +1 -0
  713. package/dist/utils/example-generator.d.ts +8 -0
  714. package/dist/utils/example-generator.d.ts.map +1 -0
  715. package/dist/utils/example-generator.js +106 -0
  716. package/dist/utils/example-generator.js.map +1 -0
  717. package/dist/utils/expression-utils.d.ts +6 -0
  718. package/dist/utils/expression-utils.d.ts.map +1 -0
  719. package/dist/utils/expression-utils.js +47 -0
  720. package/dist/utils/expression-utils.js.map +1 -0
  721. package/dist/utils/fixed-collection-validator.d.ts +35 -0
  722. package/dist/utils/fixed-collection-validator.d.ts.map +1 -0
  723. package/dist/utils/fixed-collection-validator.js +358 -0
  724. package/dist/utils/fixed-collection-validator.js.map +1 -0
  725. package/dist/utils/logger.d.ts +33 -0
  726. package/dist/utils/logger.d.ts.map +1 -0
  727. package/dist/utils/logger.js +101 -0
  728. package/dist/utils/logger.js.map +1 -0
  729. package/dist/utils/mcp-client.d.ts +21 -0
  730. package/dist/utils/mcp-client.d.ts.map +1 -0
  731. package/dist/utils/mcp-client.js +96 -0
  732. package/dist/utils/mcp-client.js.map +1 -0
  733. package/dist/utils/n8n-errors.d.ts +27 -0
  734. package/dist/utils/n8n-errors.d.ts.map +1 -0
  735. package/dist/utils/n8n-errors.js +138 -0
  736. package/dist/utils/n8n-errors.js.map +1 -0
  737. package/dist/utils/node-classification.d.ts +5 -0
  738. package/dist/utils/node-classification.d.ts.map +1 -0
  739. package/dist/utils/node-classification.js +31 -0
  740. package/dist/utils/node-classification.js.map +1 -0
  741. package/dist/utils/node-source-extractor.d.ts +21 -0
  742. package/dist/utils/node-source-extractor.d.ts.map +1 -0
  743. package/dist/utils/node-source-extractor.js +377 -0
  744. package/dist/utils/node-source-extractor.js.map +1 -0
  745. package/dist/utils/node-type-normalizer.d.ts +17 -0
  746. package/dist/utils/node-type-normalizer.d.ts.map +1 -0
  747. package/dist/utils/node-type-normalizer.js +87 -0
  748. package/dist/utils/node-type-normalizer.js.map +1 -0
  749. package/dist/utils/node-type-utils.d.ts +12 -0
  750. package/dist/utils/node-type-utils.d.ts.map +1 -0
  751. package/dist/utils/node-type-utils.js +126 -0
  752. package/dist/utils/node-type-utils.js.map +1 -0
  753. package/dist/utils/node-utils.d.ts +4 -0
  754. package/dist/utils/node-utils.d.ts.map +1 -0
  755. package/dist/utils/node-utils.js +81 -0
  756. package/dist/utils/node-utils.js.map +1 -0
  757. package/dist/utils/npm-version-checker.d.ts +14 -0
  758. package/dist/utils/npm-version-checker.d.ts.map +1 -0
  759. package/dist/utils/npm-version-checker.js +125 -0
  760. package/dist/utils/npm-version-checker.js.map +1 -0
  761. package/dist/utils/protocol-version.d.ts +19 -0
  762. package/dist/utils/protocol-version.d.ts.map +1 -0
  763. package/dist/utils/protocol-version.js +95 -0
  764. package/dist/utils/protocol-version.js.map +1 -0
  765. package/dist/utils/simple-cache.d.ts +10 -0
  766. package/dist/utils/simple-cache.d.ts.map +1 -0
  767. package/dist/utils/simple-cache.js +42 -0
  768. package/dist/utils/simple-cache.js.map +1 -0
  769. package/dist/utils/ssrf-protection.d.ts +7 -0
  770. package/dist/utils/ssrf-protection.d.ts.map +1 -0
  771. package/dist/utils/ssrf-protection.js +118 -0
  772. package/dist/utils/ssrf-protection.js.map +1 -0
  773. package/dist/utils/template-node-resolver.d.ts +2 -0
  774. package/dist/utils/template-node-resolver.d.ts.map +1 -0
  775. package/dist/utils/template-node-resolver.js +161 -0
  776. package/dist/utils/template-node-resolver.js.map +1 -0
  777. package/dist/utils/template-sanitizer.d.ts +21 -0
  778. package/dist/utils/template-sanitizer.d.ts.map +1 -0
  779. package/dist/utils/template-sanitizer.js +126 -0
  780. package/dist/utils/template-sanitizer.js.map +1 -0
  781. package/dist/utils/url-detector.d.ts +9 -0
  782. package/dist/utils/url-detector.d.ts.map +1 -0
  783. package/dist/utils/url-detector.js +79 -0
  784. package/dist/utils/url-detector.js.map +1 -0
  785. package/dist/utils/validation-schemas.d.ts +32 -0
  786. package/dist/utils/validation-schemas.d.ts.map +1 -0
  787. package/dist/utils/validation-schemas.js +219 -0
  788. package/dist/utils/validation-schemas.js.map +1 -0
  789. package/dist/utils/version.d.ts +2 -0
  790. package/dist/utils/version.d.ts.map +1 -0
  791. package/dist/utils/version.js +18 -0
  792. package/dist/utils/version.js.map +1 -0
  793. package/package.json +178 -0
  794. package/package.runtime.json +24 -0
@@ -0,0 +1,3006 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.N8NDocumentationMCPServer = void 0;
40
+ const index_js_1 = require("@modelcontextprotocol/sdk/server/index.js");
41
+ const stdio_js_1 = require("@modelcontextprotocol/sdk/server/stdio.js");
42
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
43
+ const fs_1 = require("fs");
44
+ const path_1 = __importDefault(require("path"));
45
+ const tools_1 = require("./tools");
46
+ const tools_n8n_manager_1 = require("./tools-n8n-manager");
47
+ const tools_n8n_friendly_1 = require("./tools-n8n-friendly");
48
+ const workflow_examples_1 = require("./workflow-examples");
49
+ const logger_1 = require("../utils/logger");
50
+ const node_repository_1 = require("../database/node-repository");
51
+ const database_adapter_1 = require("../database/database-adapter");
52
+ const property_filter_1 = require("../services/property-filter");
53
+ const task_templates_1 = require("../services/task-templates");
54
+ const config_validator_1 = require("../services/config-validator");
55
+ const enhanced_config_validator_1 = require("../services/enhanced-config-validator");
56
+ const property_dependencies_1 = require("../services/property-dependencies");
57
+ const type_structure_service_1 = require("../services/type-structure-service");
58
+ const simple_cache_1 = require("../utils/simple-cache");
59
+ const template_service_1 = require("../templates/template-service");
60
+ const workflow_validator_1 = require("../services/workflow-validator");
61
+ const n8n_api_1 = require("../config/n8n-api");
62
+ const n8nHandlers = __importStar(require("./handlers-n8n-manager"));
63
+ const handlers_workflow_diff_1 = require("./handlers-workflow-diff");
64
+ const tools_documentation_1 = require("./tools-documentation");
65
+ const version_1 = require("../utils/version");
66
+ const node_utils_1 = require("../utils/node-utils");
67
+ const node_type_normalizer_1 = require("../utils/node-type-normalizer");
68
+ const validation_schemas_1 = require("../utils/validation-schemas");
69
+ const protocol_version_1 = require("../utils/protocol-version");
70
+ const telemetry_1 = require("../telemetry");
71
+ const startup_checkpoints_1 = require("../telemetry/startup-checkpoints");
72
+ class N8NDocumentationMCPServer {
73
+ constructor(instanceContext, earlyLogger) {
74
+ this.db = null;
75
+ this.repository = null;
76
+ this.templateService = null;
77
+ this.cache = new simple_cache_1.SimpleCache();
78
+ this.clientInfo = null;
79
+ this.previousTool = null;
80
+ this.previousToolTimestamp = Date.now();
81
+ this.earlyLogger = null;
82
+ this.disabledToolsCache = null;
83
+ this.dbHealthChecked = false;
84
+ this.instanceContext = instanceContext;
85
+ this.earlyLogger = earlyLogger || null;
86
+ const envDbPath = process.env.NODE_DB_PATH;
87
+ let dbPath = null;
88
+ let possiblePaths = [];
89
+ if (envDbPath && (envDbPath === ':memory:' || (0, fs_1.existsSync)(envDbPath))) {
90
+ dbPath = envDbPath;
91
+ }
92
+ else {
93
+ possiblePaths = [
94
+ path_1.default.join(process.cwd(), 'data', 'nodes.db'),
95
+ path_1.default.join(__dirname, '../../data', 'nodes.db'),
96
+ './data/nodes.db'
97
+ ];
98
+ for (const p of possiblePaths) {
99
+ if ((0, fs_1.existsSync)(p)) {
100
+ dbPath = p;
101
+ break;
102
+ }
103
+ }
104
+ }
105
+ if (!dbPath) {
106
+ logger_1.logger.error('Database not found in any of the expected locations:', possiblePaths);
107
+ throw new Error('Database nodes.db not found. Please run npm run rebuild first.');
108
+ }
109
+ this.initialized = this.initializeDatabase(dbPath).then(() => {
110
+ if (this.earlyLogger) {
111
+ this.earlyLogger.logCheckpoint(startup_checkpoints_1.STARTUP_CHECKPOINTS.N8N_API_CHECKING);
112
+ }
113
+ const apiConfigured = (0, n8n_api_1.isN8nApiConfigured)();
114
+ const totalTools = apiConfigured ?
115
+ tools_1.n8nDocumentationToolsFinal.length + tools_n8n_manager_1.n8nManagementTools.length :
116
+ tools_1.n8nDocumentationToolsFinal.length;
117
+ logger_1.logger.info(`MCP server initialized with ${totalTools} tools (n8n API: ${apiConfigured ? 'configured' : 'not configured'})`);
118
+ if (this.earlyLogger) {
119
+ this.earlyLogger.logCheckpoint(startup_checkpoints_1.STARTUP_CHECKPOINTS.N8N_API_READY);
120
+ }
121
+ });
122
+ logger_1.logger.info('Initializing n8n Documentation MCP server');
123
+ this.server = new index_js_1.Server({
124
+ name: 'n8n-documentation-mcp',
125
+ version: version_1.PROJECT_VERSION,
126
+ icons: [
127
+ {
128
+ src: "https://www.n8n-atom-mcp.com/logo.png",
129
+ mimeType: "image/png",
130
+ sizes: ["192x192"]
131
+ },
132
+ {
133
+ src: "https://www.n8n-atom-mcp.com/logo-128.png",
134
+ mimeType: "image/png",
135
+ sizes: ["128x128"]
136
+ },
137
+ {
138
+ src: "https://www.n8n-atom-mcp.com/logo-48.png",
139
+ mimeType: "image/png",
140
+ sizes: ["48x48"]
141
+ }
142
+ ],
143
+ websiteUrl: "https://n8n-atom-mcp.com"
144
+ }, {
145
+ capabilities: {
146
+ tools: {},
147
+ },
148
+ });
149
+ this.setupHandlers();
150
+ }
151
+ async close() {
152
+ try {
153
+ await this.server.close();
154
+ this.cache.destroy();
155
+ if (this.db) {
156
+ try {
157
+ this.db.close();
158
+ }
159
+ catch (dbError) {
160
+ logger_1.logger.warn('Error closing database', {
161
+ error: dbError instanceof Error ? dbError.message : String(dbError)
162
+ });
163
+ }
164
+ }
165
+ this.db = null;
166
+ this.repository = null;
167
+ this.templateService = null;
168
+ this.earlyLogger = null;
169
+ }
170
+ catch (error) {
171
+ logger_1.logger.warn('Error closing MCP server', { error: error instanceof Error ? error.message : String(error) });
172
+ }
173
+ }
174
+ async initializeDatabase(dbPath) {
175
+ try {
176
+ if (this.earlyLogger) {
177
+ this.earlyLogger.logCheckpoint(startup_checkpoints_1.STARTUP_CHECKPOINTS.DATABASE_CONNECTING);
178
+ }
179
+ logger_1.logger.debug('Database initialization starting...', { dbPath });
180
+ this.db = await (0, database_adapter_1.createDatabaseAdapter)(dbPath);
181
+ logger_1.logger.debug('Database adapter created');
182
+ if (dbPath === ':memory:') {
183
+ await this.initializeInMemorySchema();
184
+ logger_1.logger.debug('In-memory schema initialized');
185
+ }
186
+ this.repository = new node_repository_1.NodeRepository(this.db);
187
+ logger_1.logger.debug('Node repository initialized');
188
+ this.templateService = new template_service_1.TemplateService(this.db);
189
+ logger_1.logger.debug('Template service initialized');
190
+ enhanced_config_validator_1.EnhancedConfigValidator.initializeSimilarityServices(this.repository);
191
+ logger_1.logger.debug('Similarity services initialized');
192
+ if (this.earlyLogger) {
193
+ this.earlyLogger.logCheckpoint(startup_checkpoints_1.STARTUP_CHECKPOINTS.DATABASE_CONNECTED);
194
+ }
195
+ logger_1.logger.info(`Database initialized successfully from: ${dbPath}`);
196
+ }
197
+ catch (error) {
198
+ logger_1.logger.error('Failed to initialize database:', error);
199
+ throw new Error(`Failed to open database: ${error instanceof Error ? error.message : 'Unknown error'}`);
200
+ }
201
+ }
202
+ async initializeInMemorySchema() {
203
+ if (!this.db)
204
+ return;
205
+ const schemaPath = path_1.default.join(__dirname, '../../src/database/schema.sql');
206
+ const schema = await fs_1.promises.readFile(schemaPath, 'utf-8');
207
+ const statements = this.parseSQLStatements(schema);
208
+ for (const statement of statements) {
209
+ if (statement.trim()) {
210
+ try {
211
+ this.db.exec(statement);
212
+ }
213
+ catch (error) {
214
+ logger_1.logger.error(`Failed to execute SQL statement: ${statement.substring(0, 100)}...`, error);
215
+ throw error;
216
+ }
217
+ }
218
+ }
219
+ }
220
+ parseSQLStatements(sql) {
221
+ const statements = [];
222
+ let current = '';
223
+ let inBlock = false;
224
+ const lines = sql.split('\n');
225
+ for (const line of lines) {
226
+ const trimmed = line.trim().toUpperCase();
227
+ if (trimmed.startsWith('--') || trimmed === '') {
228
+ continue;
229
+ }
230
+ if (trimmed.includes('BEGIN')) {
231
+ inBlock = true;
232
+ }
233
+ current += line + '\n';
234
+ if (inBlock && trimmed === 'END;') {
235
+ statements.push(current.trim());
236
+ current = '';
237
+ inBlock = false;
238
+ continue;
239
+ }
240
+ if (!inBlock && trimmed.endsWith(';')) {
241
+ statements.push(current.trim());
242
+ current = '';
243
+ }
244
+ }
245
+ if (current.trim()) {
246
+ statements.push(current.trim());
247
+ }
248
+ return statements.filter(s => s.length > 0);
249
+ }
250
+ async ensureInitialized() {
251
+ await this.initialized;
252
+ if (!this.db || !this.repository) {
253
+ throw new Error('Database not initialized');
254
+ }
255
+ if (!this.dbHealthChecked) {
256
+ await this.validateDatabaseHealth();
257
+ this.dbHealthChecked = true;
258
+ }
259
+ }
260
+ async validateDatabaseHealth() {
261
+ if (!this.db)
262
+ return;
263
+ try {
264
+ const nodeCount = this.db.prepare('SELECT COUNT(*) as count FROM nodes').get();
265
+ if (nodeCount.count === 0) {
266
+ logger_1.logger.error('CRITICAL: Database is empty - no nodes found! Please run: npm run rebuild');
267
+ throw new Error('Database is empty. Run "npm run rebuild" to populate node data.');
268
+ }
269
+ try {
270
+ const ftsExists = this.db.prepare(`
271
+ SELECT name FROM sqlite_master
272
+ WHERE type='table' AND name='nodes_fts'
273
+ `).get();
274
+ if (!ftsExists) {
275
+ logger_1.logger.warn('FTS5 table missing - search performance will be degraded. Please run: npm run rebuild');
276
+ }
277
+ else {
278
+ const ftsCount = this.db.prepare('SELECT COUNT(*) as count FROM nodes_fts').get();
279
+ if (ftsCount.count === 0) {
280
+ logger_1.logger.warn('FTS5 index is empty - search will not work properly. Please run: npm run rebuild');
281
+ }
282
+ }
283
+ }
284
+ catch (ftsError) {
285
+ logger_1.logger.warn('FTS5 not available - using fallback search. For better performance, ensure better-sqlite3 is properly installed.');
286
+ }
287
+ logger_1.logger.info(`Database health check passed: ${nodeCount.count} nodes loaded`);
288
+ }
289
+ catch (error) {
290
+ logger_1.logger.error('Database health check failed:', error);
291
+ throw error;
292
+ }
293
+ }
294
+ getDisabledTools() {
295
+ if (this.disabledToolsCache !== null) {
296
+ return this.disabledToolsCache;
297
+ }
298
+ let disabledToolsEnv = process.env.DISABLED_TOOLS || '';
299
+ if (!disabledToolsEnv) {
300
+ this.disabledToolsCache = new Set();
301
+ return this.disabledToolsCache;
302
+ }
303
+ if (disabledToolsEnv.length > 10000) {
304
+ logger_1.logger.warn(`DISABLED_TOOLS environment variable too long (${disabledToolsEnv.length} chars), truncating to 10000`);
305
+ disabledToolsEnv = disabledToolsEnv.substring(0, 10000);
306
+ }
307
+ let tools = disabledToolsEnv
308
+ .split(',')
309
+ .map(t => t.trim())
310
+ .filter(Boolean);
311
+ if (tools.length > 200) {
312
+ logger_1.logger.warn(`DISABLED_TOOLS contains ${tools.length} tools, limiting to first 200`);
313
+ tools = tools.slice(0, 200);
314
+ }
315
+ if (tools.length > 0) {
316
+ logger_1.logger.info(`Disabled tools configured: ${tools.join(', ')}`);
317
+ }
318
+ this.disabledToolsCache = new Set(tools);
319
+ return this.disabledToolsCache;
320
+ }
321
+ setupHandlers() {
322
+ this.server.setRequestHandler(types_js_1.InitializeRequestSchema, async (request) => {
323
+ const clientVersion = request.params.protocolVersion;
324
+ const clientCapabilities = request.params.capabilities;
325
+ const clientInfo = request.params.clientInfo;
326
+ logger_1.logger.info('MCP Initialize request received', {
327
+ clientVersion,
328
+ clientCapabilities,
329
+ clientInfo
330
+ });
331
+ telemetry_1.telemetry.trackSessionStart();
332
+ this.clientInfo = clientInfo;
333
+ const negotiationResult = (0, protocol_version_1.negotiateProtocolVersion)(clientVersion, clientInfo, undefined, undefined);
334
+ (0, protocol_version_1.logProtocolNegotiation)(negotiationResult, logger_1.logger, 'MCP_INITIALIZE');
335
+ if (clientVersion && clientVersion !== negotiationResult.version) {
336
+ logger_1.logger.warn(`Protocol version negotiated: client requested ${clientVersion}, server will use ${negotiationResult.version}`, {
337
+ reasoning: negotiationResult.reasoning
338
+ });
339
+ }
340
+ const response = {
341
+ protocolVersion: negotiationResult.version,
342
+ capabilities: {
343
+ tools: {},
344
+ },
345
+ serverInfo: {
346
+ name: 'n8n-documentation-mcp',
347
+ version: version_1.PROJECT_VERSION,
348
+ },
349
+ };
350
+ logger_1.logger.info('MCP Initialize response', { response });
351
+ return response;
352
+ });
353
+ this.server.setRequestHandler(types_js_1.ListToolsRequestSchema, async (request) => {
354
+ const disabledTools = this.getDisabledTools();
355
+ const enabledDocTools = tools_1.n8nDocumentationToolsFinal.filter(tool => !disabledTools.has(tool.name));
356
+ let tools = [...enabledDocTools];
357
+ const hasEnvConfig = (0, n8n_api_1.isN8nApiConfigured)();
358
+ const hasInstanceConfig = !!(this.instanceContext?.n8nApiUrl && this.instanceContext?.n8nApiKey);
359
+ const isMultiTenantEnabled = process.env.ENABLE_MULTI_TENANT === 'true';
360
+ const shouldIncludeManagementTools = hasEnvConfig || hasInstanceConfig || isMultiTenantEnabled;
361
+ if (shouldIncludeManagementTools) {
362
+ const enabledMgmtTools = tools_n8n_manager_1.n8nManagementTools.filter(tool => !disabledTools.has(tool.name));
363
+ tools.push(...enabledMgmtTools);
364
+ logger_1.logger.debug(`Tool listing: ${tools.length} tools available (${enabledDocTools.length} documentation + ${enabledMgmtTools.length} management)`, {
365
+ hasEnvConfig,
366
+ hasInstanceConfig,
367
+ isMultiTenantEnabled,
368
+ disabledToolsCount: disabledTools.size
369
+ });
370
+ }
371
+ else {
372
+ logger_1.logger.debug(`Tool listing: ${tools.length} tools available (documentation only)`, {
373
+ hasEnvConfig,
374
+ hasInstanceConfig,
375
+ isMultiTenantEnabled,
376
+ disabledToolsCount: disabledTools.size
377
+ });
378
+ }
379
+ if (disabledTools.size > 0) {
380
+ const totalAvailableTools = tools_1.n8nDocumentationToolsFinal.length + (shouldIncludeManagementTools ? tools_n8n_manager_1.n8nManagementTools.length : 0);
381
+ logger_1.logger.debug(`Filtered ${disabledTools.size} disabled tools, ${tools.length}/${totalAvailableTools} tools available`);
382
+ }
383
+ const clientInfo = this.clientInfo;
384
+ const isN8nClient = clientInfo?.name?.includes('n8n') ||
385
+ clientInfo?.name?.includes('langchain');
386
+ if (isN8nClient) {
387
+ logger_1.logger.info('Detected n8n client, using n8n-friendly tool descriptions');
388
+ tools = (0, tools_n8n_friendly_1.makeToolsN8nFriendly)(tools);
389
+ }
390
+ const validationTools = tools.filter(t => t.name.startsWith('validate_'));
391
+ validationTools.forEach(tool => {
392
+ logger_1.logger.info('Validation tool schema', {
393
+ toolName: tool.name,
394
+ inputSchema: JSON.stringify(tool.inputSchema, null, 2),
395
+ hasOutputSchema: !!tool.outputSchema,
396
+ description: tool.description
397
+ });
398
+ });
399
+ return { tools };
400
+ });
401
+ this.server.setRequestHandler(types_js_1.CallToolRequestSchema, async (request) => {
402
+ const { name, arguments: args } = request.params;
403
+ logger_1.logger.info('Tool call received - DETAILED DEBUG', {
404
+ toolName: name,
405
+ arguments: JSON.stringify(args, null, 2),
406
+ argumentsType: typeof args,
407
+ argumentsKeys: args ? Object.keys(args) : [],
408
+ hasNodeType: args && 'nodeType' in args,
409
+ hasConfig: args && 'config' in args,
410
+ configType: args && args.config ? typeof args.config : 'N/A',
411
+ rawRequest: JSON.stringify(request.params)
412
+ });
413
+ const disabledTools = this.getDisabledTools();
414
+ if (disabledTools.has(name)) {
415
+ logger_1.logger.warn(`Attempted to call disabled tool: ${name}`);
416
+ return {
417
+ content: [{
418
+ type: 'text',
419
+ text: JSON.stringify({
420
+ error: 'TOOL_DISABLED',
421
+ message: `Tool '${name}' is not available in this deployment. It has been disabled via DISABLED_TOOLS environment variable.`,
422
+ tool: name
423
+ }, null, 2)
424
+ }]
425
+ };
426
+ }
427
+ let processedArgs = args;
428
+ if (args && typeof args === 'object' && 'output' in args) {
429
+ try {
430
+ const possibleNestedData = args.output;
431
+ if (typeof possibleNestedData === 'string' && possibleNestedData.trim().startsWith('{')) {
432
+ const parsed = JSON.parse(possibleNestedData);
433
+ if (parsed && typeof parsed === 'object') {
434
+ logger_1.logger.warn('Detected n8n nested output bug, attempting to extract actual arguments', {
435
+ originalArgs: args,
436
+ extractedArgs: parsed
437
+ });
438
+ if (this.validateExtractedArgs(name, parsed)) {
439
+ processedArgs = parsed;
440
+ }
441
+ else {
442
+ logger_1.logger.warn('Extracted arguments failed validation, using original args', {
443
+ toolName: name,
444
+ extractedArgs: parsed
445
+ });
446
+ }
447
+ }
448
+ }
449
+ }
450
+ catch (parseError) {
451
+ logger_1.logger.debug('Failed to parse nested output, continuing with original args', {
452
+ error: parseError instanceof Error ? parseError.message : String(parseError)
453
+ });
454
+ }
455
+ }
456
+ try {
457
+ logger_1.logger.debug(`Executing tool: ${name}`, { args: processedArgs });
458
+ const startTime = Date.now();
459
+ const result = await this.executeTool(name, processedArgs);
460
+ const duration = Date.now() - startTime;
461
+ logger_1.logger.debug(`Tool ${name} executed successfully`);
462
+ telemetry_1.telemetry.trackToolUsage(name, true, duration);
463
+ if (this.previousTool) {
464
+ const timeDelta = Date.now() - this.previousToolTimestamp;
465
+ telemetry_1.telemetry.trackToolSequence(this.previousTool, name, timeDelta);
466
+ }
467
+ this.previousTool = name;
468
+ this.previousToolTimestamp = Date.now();
469
+ let responseText;
470
+ let structuredContent = null;
471
+ try {
472
+ if (name.startsWith('validate_') && typeof result === 'object' && result !== null) {
473
+ const cleanResult = this.sanitizeValidationResult(result, name);
474
+ structuredContent = cleanResult;
475
+ responseText = JSON.stringify(cleanResult, null, 2);
476
+ }
477
+ else {
478
+ responseText = typeof result === 'string' ? result : JSON.stringify(result, null, 2);
479
+ }
480
+ }
481
+ catch (jsonError) {
482
+ logger_1.logger.warn(`Failed to stringify tool result for ${name}:`, jsonError);
483
+ responseText = String(result);
484
+ }
485
+ if (responseText.length > 1000000) {
486
+ logger_1.logger.warn(`Tool ${name} response is very large (${responseText.length} chars), truncating`);
487
+ responseText = responseText.substring(0, 999000) + '\n\n[Response truncated due to size limits]';
488
+ structuredContent = null;
489
+ }
490
+ const mcpResponse = {
491
+ content: [
492
+ {
493
+ type: 'text',
494
+ text: responseText,
495
+ },
496
+ ],
497
+ };
498
+ if (name.startsWith('validate_') && structuredContent !== null) {
499
+ mcpResponse.structuredContent = structuredContent;
500
+ }
501
+ return mcpResponse;
502
+ }
503
+ catch (error) {
504
+ logger_1.logger.error(`Error executing tool ${name}`, error);
505
+ const errorMessage = error instanceof Error ? error.message : 'Unknown error';
506
+ telemetry_1.telemetry.trackToolUsage(name, false);
507
+ telemetry_1.telemetry.trackError(error instanceof Error ? error.constructor.name : 'UnknownError', `tool_execution`, name, errorMessage);
508
+ if (this.previousTool) {
509
+ const timeDelta = Date.now() - this.previousToolTimestamp;
510
+ telemetry_1.telemetry.trackToolSequence(this.previousTool, name, timeDelta);
511
+ }
512
+ this.previousTool = name;
513
+ this.previousToolTimestamp = Date.now();
514
+ let helpfulMessage = `Error executing tool ${name}: ${errorMessage}`;
515
+ if (errorMessage.includes('required') || errorMessage.includes('missing')) {
516
+ helpfulMessage += '\n\nNote: This error often occurs when the AI agent sends incomplete or incorrectly formatted parameters. Please ensure all required fields are provided with the correct types.';
517
+ }
518
+ else if (errorMessage.includes('type') || errorMessage.includes('expected')) {
519
+ helpfulMessage += '\n\nNote: This error indicates a type mismatch. The AI agent may be sending data in the wrong format (e.g., string instead of object).';
520
+ }
521
+ else if (errorMessage.includes('Unknown category') || errorMessage.includes('not found')) {
522
+ helpfulMessage += '\n\nNote: The requested resource or category was not found. Please check the available options.';
523
+ }
524
+ if (name.startsWith('validate_') && (errorMessage.includes('config') || errorMessage.includes('nodeType'))) {
525
+ helpfulMessage += '\n\nFor validation tools:\n- nodeType should be a string (e.g., "nodes-base.webhook")\n- config should be an object (e.g., {})';
526
+ }
527
+ return {
528
+ content: [
529
+ {
530
+ type: 'text',
531
+ text: helpfulMessage,
532
+ },
533
+ ],
534
+ isError: true,
535
+ };
536
+ }
537
+ });
538
+ }
539
+ sanitizeValidationResult(result, toolName) {
540
+ if (!result || typeof result !== 'object') {
541
+ return result;
542
+ }
543
+ const sanitized = { ...result };
544
+ if (toolName === 'validate_node_minimal') {
545
+ const filtered = {
546
+ nodeType: String(sanitized.nodeType || ''),
547
+ displayName: String(sanitized.displayName || ''),
548
+ valid: Boolean(sanitized.valid),
549
+ missingRequiredFields: Array.isArray(sanitized.missingRequiredFields)
550
+ ? sanitized.missingRequiredFields.map(String)
551
+ : []
552
+ };
553
+ return filtered;
554
+ }
555
+ else if (toolName === 'validate_node_operation') {
556
+ let summary = sanitized.summary;
557
+ if (!summary || typeof summary !== 'object') {
558
+ summary = {
559
+ hasErrors: Array.isArray(sanitized.errors) ? sanitized.errors.length > 0 : false,
560
+ errorCount: Array.isArray(sanitized.errors) ? sanitized.errors.length : 0,
561
+ warningCount: Array.isArray(sanitized.warnings) ? sanitized.warnings.length : 0,
562
+ suggestionCount: Array.isArray(sanitized.suggestions) ? sanitized.suggestions.length : 0
563
+ };
564
+ }
565
+ const filtered = {
566
+ nodeType: String(sanitized.nodeType || ''),
567
+ workflowNodeType: String(sanitized.workflowNodeType || sanitized.nodeType || ''),
568
+ displayName: String(sanitized.displayName || ''),
569
+ valid: Boolean(sanitized.valid),
570
+ errors: Array.isArray(sanitized.errors) ? sanitized.errors : [],
571
+ warnings: Array.isArray(sanitized.warnings) ? sanitized.warnings : [],
572
+ suggestions: Array.isArray(sanitized.suggestions) ? sanitized.suggestions : [],
573
+ summary: summary
574
+ };
575
+ return filtered;
576
+ }
577
+ else if (toolName.startsWith('validate_workflow')) {
578
+ sanitized.valid = Boolean(sanitized.valid);
579
+ sanitized.errors = Array.isArray(sanitized.errors) ? sanitized.errors : [];
580
+ sanitized.warnings = Array.isArray(sanitized.warnings) ? sanitized.warnings : [];
581
+ if (toolName === 'validate_workflow') {
582
+ if (!sanitized.summary || typeof sanitized.summary !== 'object') {
583
+ sanitized.summary = {
584
+ totalNodes: 0,
585
+ enabledNodes: 0,
586
+ triggerNodes: 0,
587
+ validConnections: 0,
588
+ invalidConnections: 0,
589
+ expressionsValidated: 0,
590
+ errorCount: sanitized.errors.length,
591
+ warningCount: sanitized.warnings.length
592
+ };
593
+ }
594
+ }
595
+ else {
596
+ if (!sanitized.statistics || typeof sanitized.statistics !== 'object') {
597
+ sanitized.statistics = {
598
+ totalNodes: 0,
599
+ triggerNodes: 0,
600
+ validConnections: 0,
601
+ invalidConnections: 0,
602
+ expressionsValidated: 0
603
+ };
604
+ }
605
+ }
606
+ }
607
+ return JSON.parse(JSON.stringify(sanitized));
608
+ }
609
+ validateToolParams(toolName, args, legacyRequiredParams) {
610
+ try {
611
+ let validationResult;
612
+ switch (toolName) {
613
+ case 'validate_node':
614
+ validationResult = validation_schemas_1.ToolValidation.validateNodeOperation(args);
615
+ break;
616
+ case 'validate_workflow':
617
+ validationResult = validation_schemas_1.ToolValidation.validateWorkflow(args);
618
+ break;
619
+ case 'search_nodes':
620
+ validationResult = validation_schemas_1.ToolValidation.validateSearchNodes(args);
621
+ break;
622
+ case 'n8n_create_workflow':
623
+ validationResult = validation_schemas_1.ToolValidation.validateCreateWorkflow(args);
624
+ break;
625
+ case 'n8n_get_workflow':
626
+ case 'n8n_update_full_workflow':
627
+ case 'n8n_delete_workflow':
628
+ case 'n8n_validate_workflow':
629
+ case 'n8n_autofix_workflow':
630
+ validationResult = validation_schemas_1.ToolValidation.validateWorkflowId(args);
631
+ break;
632
+ case 'n8n_executions':
633
+ validationResult = args.action
634
+ ? { valid: true, errors: [] }
635
+ : { valid: false, errors: [{ field: 'action', message: 'action is required' }] };
636
+ break;
637
+ case 'n8n_deploy_template':
638
+ validationResult = args.templateId !== undefined
639
+ ? { valid: true, errors: [] }
640
+ : { valid: false, errors: [{ field: 'templateId', message: 'templateId is required' }] };
641
+ break;
642
+ default:
643
+ return this.validateToolParamsBasic(toolName, args, legacyRequiredParams || []);
644
+ }
645
+ if (!validationResult.valid) {
646
+ const errorMessage = validation_schemas_1.Validator.formatErrors(validationResult, toolName);
647
+ logger_1.logger.error(`Parameter validation failed for ${toolName}:`, errorMessage);
648
+ throw new validation_schemas_1.ValidationError(errorMessage);
649
+ }
650
+ }
651
+ catch (error) {
652
+ if (error instanceof validation_schemas_1.ValidationError) {
653
+ throw error;
654
+ }
655
+ logger_1.logger.error(`Validation system error for ${toolName}:`, error);
656
+ const errorMessage = error instanceof Error
657
+ ? `Internal validation error: ${error.message}`
658
+ : `Internal validation error while processing ${toolName}`;
659
+ throw new Error(errorMessage);
660
+ }
661
+ }
662
+ validateToolParamsBasic(toolName, args, requiredParams) {
663
+ const missing = [];
664
+ const invalid = [];
665
+ for (const param of requiredParams) {
666
+ if (!(param in args) || args[param] === undefined || args[param] === null) {
667
+ missing.push(param);
668
+ }
669
+ else if (typeof args[param] === 'string' && args[param].trim() === '') {
670
+ invalid.push(`${param} (empty string)`);
671
+ }
672
+ }
673
+ if (missing.length > 0) {
674
+ throw new Error(`Missing required parameters for ${toolName}: ${missing.join(', ')}. Please provide the required parameters to use this tool.`);
675
+ }
676
+ if (invalid.length > 0) {
677
+ throw new Error(`Invalid parameters for ${toolName}: ${invalid.join(', ')}. String parameters cannot be empty.`);
678
+ }
679
+ }
680
+ validateExtractedArgs(toolName, args) {
681
+ if (!args || typeof args !== 'object') {
682
+ return false;
683
+ }
684
+ const allTools = [...tools_1.n8nDocumentationToolsFinal, ...tools_n8n_manager_1.n8nManagementTools];
685
+ const tool = allTools.find(t => t.name === toolName);
686
+ if (!tool || !tool.inputSchema) {
687
+ return true;
688
+ }
689
+ const schema = tool.inputSchema;
690
+ const required = schema.required || [];
691
+ const properties = schema.properties || {};
692
+ for (const requiredField of required) {
693
+ if (!(requiredField in args)) {
694
+ logger_1.logger.debug(`Extracted args missing required field: ${requiredField}`, {
695
+ toolName,
696
+ extractedArgs: args,
697
+ required
698
+ });
699
+ return false;
700
+ }
701
+ }
702
+ for (const [fieldName, fieldValue] of Object.entries(args)) {
703
+ if (properties[fieldName]) {
704
+ const expectedType = properties[fieldName].type;
705
+ const actualType = Array.isArray(fieldValue) ? 'array' : typeof fieldValue;
706
+ if (expectedType && expectedType !== actualType) {
707
+ if (expectedType === 'number' && actualType === 'string' && !isNaN(Number(fieldValue))) {
708
+ continue;
709
+ }
710
+ logger_1.logger.debug(`Extracted args field type mismatch: ${fieldName}`, {
711
+ toolName,
712
+ expectedType,
713
+ actualType,
714
+ fieldValue
715
+ });
716
+ return false;
717
+ }
718
+ }
719
+ }
720
+ if (schema.additionalProperties === false) {
721
+ const allowedFields = Object.keys(properties);
722
+ const extraFields = Object.keys(args).filter(field => !allowedFields.includes(field));
723
+ if (extraFields.length > 0) {
724
+ logger_1.logger.debug(`Extracted args have extra fields`, {
725
+ toolName,
726
+ extraFields,
727
+ allowedFields
728
+ });
729
+ }
730
+ }
731
+ return true;
732
+ }
733
+ async executeTool(name, args) {
734
+ args = args || {};
735
+ const disabledTools = this.getDisabledTools();
736
+ if (disabledTools.has(name)) {
737
+ throw new Error(`Tool '${name}' is disabled via DISABLED_TOOLS environment variable`);
738
+ }
739
+ logger_1.logger.info(`Tool execution: ${name}`, {
740
+ args: typeof args === 'object' ? JSON.stringify(args) : args,
741
+ argsType: typeof args,
742
+ argsKeys: typeof args === 'object' ? Object.keys(args) : 'not-object'
743
+ });
744
+ if (typeof args !== 'object' || args === null) {
745
+ throw new Error(`Invalid arguments for tool ${name}: expected object, got ${typeof args}`);
746
+ }
747
+ switch (name) {
748
+ case 'tools_documentation':
749
+ return this.getToolsDocumentation(args.topic, args.depth);
750
+ case 'search_nodes':
751
+ this.validateToolParams(name, args, ['query']);
752
+ const limit = args.limit !== undefined ? Number(args.limit) || 20 : 20;
753
+ return this.searchNodes(args.query, limit, {
754
+ mode: args.mode,
755
+ includeExamples: args.includeExamples,
756
+ source: args.source
757
+ });
758
+ case 'get_node':
759
+ this.validateToolParams(name, args, ['nodeType']);
760
+ if (args.mode === 'docs') {
761
+ return this.getNodeDocumentation(args.nodeType);
762
+ }
763
+ if (args.mode === 'search_properties') {
764
+ if (!args.propertyQuery) {
765
+ throw new Error('propertyQuery is required for mode=search_properties');
766
+ }
767
+ const maxResults = args.maxPropertyResults !== undefined ? Number(args.maxPropertyResults) || 20 : 20;
768
+ return this.searchNodeProperties(args.nodeType, args.propertyQuery, maxResults);
769
+ }
770
+ return this.getNode(args.nodeType, args.detail, args.mode, args.includeTypeInfo, args.includeExamples, args.fromVersion, args.toVersion);
771
+ case 'validate_node':
772
+ this.validateToolParams(name, args, ['nodeType', 'config']);
773
+ if (typeof args.config !== 'object' || args.config === null) {
774
+ logger_1.logger.warn(`validate_node called with invalid config type: ${typeof args.config}`);
775
+ const validationMode = args.mode || 'full';
776
+ if (validationMode === 'minimal') {
777
+ return {
778
+ nodeType: args.nodeType || 'unknown',
779
+ displayName: 'Unknown Node',
780
+ valid: false,
781
+ missingRequiredFields: [
782
+ 'Invalid config format - expected object',
783
+ '🔧 RECOVERY: Use format { "resource": "...", "operation": "..." } or {} for empty config'
784
+ ]
785
+ };
786
+ }
787
+ return {
788
+ nodeType: args.nodeType || 'unknown',
789
+ workflowNodeType: args.nodeType || 'unknown',
790
+ displayName: 'Unknown Node',
791
+ valid: false,
792
+ errors: [{
793
+ type: 'config',
794
+ property: 'config',
795
+ message: 'Invalid config format - expected object',
796
+ fix: 'Provide config as an object with node properties'
797
+ }],
798
+ warnings: [],
799
+ suggestions: [
800
+ '🔧 RECOVERY: Invalid config detected. Fix with:',
801
+ ' • Ensure config is an object: { "resource": "...", "operation": "..." }',
802
+ ' • Use get_node to see required fields for this node type',
803
+ ' • Check if the node type is correct before configuring it'
804
+ ],
805
+ summary: {
806
+ hasErrors: true,
807
+ errorCount: 1,
808
+ warningCount: 0,
809
+ suggestionCount: 3
810
+ }
811
+ };
812
+ }
813
+ const validationMode = args.mode || 'full';
814
+ if (validationMode === 'minimal') {
815
+ return this.validateNodeMinimal(args.nodeType, args.config);
816
+ }
817
+ return this.validateNodeConfig(args.nodeType, args.config, 'operation', args.profile);
818
+ case 'get_template':
819
+ this.validateToolParams(name, args, ['templateId']);
820
+ const templateId = Number(args.templateId);
821
+ const templateMode = args.mode || 'full';
822
+ return this.getTemplate(templateId, templateMode);
823
+ case 'search_templates': {
824
+ const searchMode = args.searchMode || 'keyword';
825
+ const searchLimit = Math.min(Math.max(Number(args.limit) || 20, 1), 100);
826
+ const searchOffset = Math.max(Number(args.offset) || 0, 0);
827
+ switch (searchMode) {
828
+ case 'by_nodes':
829
+ if (!args.nodeTypes || !Array.isArray(args.nodeTypes) || args.nodeTypes.length === 0) {
830
+ throw new Error('nodeTypes array is required for searchMode=by_nodes');
831
+ }
832
+ return this.listNodeTemplates(args.nodeTypes, searchLimit, searchOffset);
833
+ case 'by_task':
834
+ if (!args.task) {
835
+ throw new Error('task is required for searchMode=by_task');
836
+ }
837
+ return this.getTemplatesForTask(args.task, searchLimit, searchOffset);
838
+ case 'by_metadata':
839
+ return this.searchTemplatesByMetadata({
840
+ category: args.category,
841
+ complexity: args.complexity,
842
+ maxSetupMinutes: args.maxSetupMinutes ? Number(args.maxSetupMinutes) : undefined,
843
+ minSetupMinutes: args.minSetupMinutes ? Number(args.minSetupMinutes) : undefined,
844
+ requiredService: args.requiredService,
845
+ targetAudience: args.targetAudience
846
+ }, searchLimit, searchOffset);
847
+ case 'keyword':
848
+ default:
849
+ if (!args.query) {
850
+ throw new Error('query is required for searchMode=keyword');
851
+ }
852
+ const searchFields = args.fields;
853
+ return this.searchTemplates(args.query, searchLimit, searchOffset, searchFields);
854
+ }
855
+ }
856
+ case 'validate_workflow':
857
+ this.validateToolParams(name, args, ['workflow']);
858
+ return this.validateWorkflow(args.workflow, args.options);
859
+ case 'n8n_create_workflow':
860
+ this.validateToolParams(name, args, ['name', 'nodes', 'connections']);
861
+ return n8nHandlers.handleCreateWorkflow(args, this.instanceContext);
862
+ case 'n8n_get_workflow': {
863
+ this.validateToolParams(name, args, ['id']);
864
+ const workflowMode = args.mode || 'full';
865
+ switch (workflowMode) {
866
+ case 'details':
867
+ return n8nHandlers.handleGetWorkflowDetails(args, this.instanceContext);
868
+ case 'structure':
869
+ return n8nHandlers.handleGetWorkflowStructure(args, this.instanceContext);
870
+ case 'minimal':
871
+ return n8nHandlers.handleGetWorkflowMinimal(args, this.instanceContext);
872
+ case 'full':
873
+ default:
874
+ return n8nHandlers.handleGetWorkflow(args, this.instanceContext);
875
+ }
876
+ }
877
+ case 'n8n_update_full_workflow':
878
+ this.validateToolParams(name, args, ['id']);
879
+ return n8nHandlers.handleUpdateWorkflow(args, this.repository, this.instanceContext);
880
+ case 'n8n_update_partial_workflow':
881
+ this.validateToolParams(name, args, ['id', 'operations']);
882
+ return (0, handlers_workflow_diff_1.handleUpdatePartialWorkflow)(args, this.repository, this.instanceContext);
883
+ case 'n8n_delete_workflow':
884
+ this.validateToolParams(name, args, ['id']);
885
+ return n8nHandlers.handleDeleteWorkflow(args, this.instanceContext);
886
+ case 'n8n_list_workflows':
887
+ return n8nHandlers.handleListWorkflows(args, this.instanceContext);
888
+ case 'n8n_validate_workflow':
889
+ this.validateToolParams(name, args, ['id']);
890
+ await this.ensureInitialized();
891
+ if (!this.repository)
892
+ throw new Error('Repository not initialized');
893
+ return n8nHandlers.handleValidateWorkflow(args, this.repository, this.instanceContext);
894
+ case 'n8n_autofix_workflow':
895
+ this.validateToolParams(name, args, ['id']);
896
+ await this.ensureInitialized();
897
+ if (!this.repository)
898
+ throw new Error('Repository not initialized');
899
+ return n8nHandlers.handleAutofixWorkflow(args, this.repository, this.instanceContext);
900
+ case 'n8n_test_workflow':
901
+ this.validateToolParams(name, args, ['workflowId']);
902
+ return n8nHandlers.handleTestWorkflow(args, this.instanceContext);
903
+ case 'n8n_executions': {
904
+ this.validateToolParams(name, args, ['action']);
905
+ const execAction = args.action;
906
+ switch (execAction) {
907
+ case 'get':
908
+ if (!args.id) {
909
+ throw new Error('id is required for action=get');
910
+ }
911
+ return n8nHandlers.handleGetExecution(args, this.instanceContext);
912
+ case 'list':
913
+ return n8nHandlers.handleListExecutions(args, this.instanceContext);
914
+ case 'delete':
915
+ if (!args.id) {
916
+ throw new Error('id is required for action=delete');
917
+ }
918
+ return n8nHandlers.handleDeleteExecution(args, this.instanceContext);
919
+ default:
920
+ throw new Error(`Unknown action: ${execAction}. Valid actions: get, list, delete`);
921
+ }
922
+ }
923
+ case 'n8n_health_check':
924
+ if (args.mode === 'diagnostic') {
925
+ return n8nHandlers.handleDiagnostic({ params: { arguments: args } }, this.instanceContext);
926
+ }
927
+ return n8nHandlers.handleHealthCheck(this.instanceContext);
928
+ case 'n8n_workflow_versions':
929
+ this.validateToolParams(name, args, ['mode']);
930
+ return n8nHandlers.handleWorkflowVersions(args, this.repository, this.instanceContext);
931
+ case 'n8n_import_workflow_file':
932
+ this.validateToolParams(name, args, ['fileContent']);
933
+ return n8nHandlers.handleImportWorkflowFile(args, n8nHandlers.getN8nApiClient(this.instanceContext));
934
+ case 'n8n_export_workflow_file':
935
+ this.validateToolParams(name, args, ['workflowId']);
936
+ return n8nHandlers.handleExportWorkflowFile(args, n8nHandlers.getN8nApiClient(this.instanceContext));
937
+ case 'n8n_sync_workflow':
938
+ this.validateToolParams(name, args, ['workflowId', 'fileContent', 'direction']);
939
+ return n8nHandlers.handleSyncWorkflow(args, n8nHandlers.getN8nApiClient(this.instanceContext));
940
+ case 'n8n_validate_workflow_file':
941
+ this.validateToolParams(name, args, ['fileContent']);
942
+ return n8nHandlers.handleValidateWorkflowFile(args);
943
+ case 'n8n_deploy_template':
944
+ this.validateToolParams(name, args, ['templateId']);
945
+ await this.ensureInitialized();
946
+ if (!this.templateService)
947
+ throw new Error('Template service not initialized');
948
+ if (!this.repository)
949
+ throw new Error('Repository not initialized');
950
+ return n8nHandlers.handleDeployTemplate(args, this.templateService, this.repository, this.instanceContext);
951
+ case 'n8n_search_community_nodes':
952
+ this.validateToolParams(name, args, ['query']);
953
+ await this.ensureInitialized();
954
+ return n8nHandlers.handleSearchCommunityNodes(args, this.repository, this.instanceContext);
955
+ case 'n8n_list_community_packages':
956
+ return n8nHandlers.handleListCommunityPackages(args, this.instanceContext);
957
+ case 'n8n_install_community_package':
958
+ this.validateToolParams(name, args, ['packageName']);
959
+ return n8nHandlers.handleInstallCommunityPackage(args, this.instanceContext);
960
+ case 'n8n_uninstall_community_package':
961
+ this.validateToolParams(name, args, ['packageName']);
962
+ return n8nHandlers.handleUninstallCommunityPackage(args, this.instanceContext);
963
+ case 'n8n_update_community_package':
964
+ this.validateToolParams(name, args, ['packageName']);
965
+ return n8nHandlers.handleUpdateCommunityPackage(args, this.instanceContext);
966
+ case 'n8n_sync_installed_nodes':
967
+ await this.ensureInitialized();
968
+ if (!this.repository)
969
+ throw new Error('Repository not initialized');
970
+ return n8nHandlers.handleSyncInstalledNodes(args, this.repository, this.instanceContext);
971
+ case 'n8n_list_credentials':
972
+ return n8nHandlers.handleListCredentials(args, this.instanceContext);
973
+ case 'n8n_get_credential':
974
+ this.validateToolParams(name, args, ['id']);
975
+ return n8nHandlers.handleGetCredential(args, this.instanceContext);
976
+ case 'n8n_create_credential':
977
+ this.validateToolParams(name, args, ['name', 'type', 'data']);
978
+ return n8nHandlers.handleCreateCredential(args, this.instanceContext);
979
+ case 'n8n_delete_credential':
980
+ this.validateToolParams(name, args, ['id']);
981
+ return n8nHandlers.handleDeleteCredential(args, this.instanceContext);
982
+ case 'n8n_get_credential_types':
983
+ await this.ensureInitialized();
984
+ if (!this.repository)
985
+ throw new Error('Repository not initialized');
986
+ return n8nHandlers.handleGetCredentialTypes(args, this.repository, this.instanceContext);
987
+ case 'n8n_list_tags':
988
+ return n8nHandlers.handleListTags(args, this.instanceContext);
989
+ case 'n8n_create_tag':
990
+ this.validateToolParams(name, args, ['name']);
991
+ return n8nHandlers.handleCreateTag(args, this.instanceContext);
992
+ case 'n8n_update_tag':
993
+ this.validateToolParams(name, args, ['id', 'name']);
994
+ return n8nHandlers.handleUpdateTag(args, this.instanceContext);
995
+ case 'n8n_delete_tag':
996
+ this.validateToolParams(name, args, ['id']);
997
+ return n8nHandlers.handleDeleteTag(args, this.instanceContext);
998
+ case 'n8n_assign_tags_to_workflow':
999
+ this.validateToolParams(name, args, ['workflowId', 'tags']);
1000
+ return n8nHandlers.handleAssignTagsToWorkflow(args, this.instanceContext);
1001
+ case 'n8n_clone_workflow':
1002
+ this.validateToolParams(name, args, ['workflowId', 'newName']);
1003
+ return n8nHandlers.handleCloneWorkflow(args, this.instanceContext);
1004
+ case 'n8n_backup_workflows':
1005
+ return n8nHandlers.handleBackupWorkflows(args, this.instanceContext);
1006
+ case 'n8n_restore_workflow':
1007
+ this.validateToolParams(name, args, ['workflowData']);
1008
+ return n8nHandlers.handleRestoreWorkflow(args, this.instanceContext);
1009
+ case 'n8n_activate_workflow':
1010
+ this.validateToolParams(name, args, ['workflowId']);
1011
+ return n8nHandlers.handleActivateWorkflow(args, this.instanceContext);
1012
+ case 'n8n_deactivate_workflow':
1013
+ this.validateToolParams(name, args, ['workflowId']);
1014
+ return n8nHandlers.handleDeactivateWorkflow(args, this.instanceContext);
1015
+ case 'n8n_list_active_workflows':
1016
+ return n8nHandlers.handleListActiveWorkflows(args, this.instanceContext);
1017
+ case 'n8n_get_workflow_stats':
1018
+ this.validateToolParams(name, args, ['workflowId']);
1019
+ return n8nHandlers.handleGetWorkflowStats(args, this.instanceContext);
1020
+ case 'n8n_get_execution_trends':
1021
+ this.validateToolParams(name, args, ['workflowId']);
1022
+ return n8nHandlers.handleGetExecutionTrends(args, this.instanceContext);
1023
+ case 'n8n_get_slow_workflows':
1024
+ return n8nHandlers.handleGetSlowWorkflows(args, this.instanceContext);
1025
+ case 'n8n_trace_execution':
1026
+ this.validateToolParams(name, args, ['executionId']);
1027
+ return n8nHandlers.handleTraceExecution(args, this.instanceContext);
1028
+ case 'n8n_compare_executions':
1029
+ this.validateToolParams(name, args, ['executionId1', 'executionId2']);
1030
+ return n8nHandlers.handleCompareExecutions(args, this.instanceContext);
1031
+ default:
1032
+ throw new Error(`Unknown tool: ${name}`);
1033
+ }
1034
+ }
1035
+ async listNodes(filters = {}) {
1036
+ await this.ensureInitialized();
1037
+ let query = 'SELECT * FROM nodes WHERE 1=1';
1038
+ const params = [];
1039
+ if (filters.package) {
1040
+ const packageVariants = [
1041
+ filters.package,
1042
+ `@n8n/${filters.package}`,
1043
+ filters.package.replace('@n8n/', '')
1044
+ ];
1045
+ query += ' AND package_name IN (' + packageVariants.map(() => '?').join(',') + ')';
1046
+ params.push(...packageVariants);
1047
+ }
1048
+ if (filters.category) {
1049
+ query += ' AND category = ?';
1050
+ params.push(filters.category);
1051
+ }
1052
+ if (filters.developmentStyle) {
1053
+ query += ' AND development_style = ?';
1054
+ params.push(filters.developmentStyle);
1055
+ }
1056
+ if (filters.isAITool !== undefined) {
1057
+ query += ' AND is_ai_tool = ?';
1058
+ params.push(filters.isAITool ? 1 : 0);
1059
+ }
1060
+ query += ' ORDER BY display_name';
1061
+ if (filters.limit) {
1062
+ query += ' LIMIT ?';
1063
+ params.push(filters.limit);
1064
+ }
1065
+ const nodes = this.db.prepare(query).all(...params);
1066
+ return {
1067
+ nodes: nodes.map(node => ({
1068
+ nodeType: node.node_type,
1069
+ displayName: node.display_name,
1070
+ description: node.description,
1071
+ category: node.category,
1072
+ package: node.package_name,
1073
+ developmentStyle: node.development_style,
1074
+ isAITool: Number(node.is_ai_tool) === 1,
1075
+ isTrigger: Number(node.is_trigger) === 1,
1076
+ isVersioned: Number(node.is_versioned) === 1,
1077
+ })),
1078
+ totalCount: nodes.length,
1079
+ };
1080
+ }
1081
+ async getNodeInfo(nodeType) {
1082
+ await this.ensureInitialized();
1083
+ if (!this.repository)
1084
+ throw new Error('Repository not initialized');
1085
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
1086
+ let node = this.repository.getNode(normalizedType);
1087
+ if (!node && normalizedType !== nodeType) {
1088
+ node = this.repository.getNode(nodeType);
1089
+ }
1090
+ if (!node) {
1091
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
1092
+ for (const alt of alternatives) {
1093
+ const found = this.repository.getNode(alt);
1094
+ if (found) {
1095
+ node = found;
1096
+ break;
1097
+ }
1098
+ }
1099
+ }
1100
+ if (!node) {
1101
+ throw new Error(`Node ${nodeType} not found`);
1102
+ }
1103
+ const aiToolCapabilities = {
1104
+ canBeUsedAsTool: true,
1105
+ hasUsableAsToolProperty: node.isAITool ?? false,
1106
+ requiresEnvironmentVariable: !(node.isAITool ?? false) && node.package !== 'n8n-nodes-base',
1107
+ toolConnectionType: 'ai_tool',
1108
+ commonToolUseCases: this.getCommonAIToolUseCases(node.nodeType),
1109
+ environmentRequirement: node.package && node.package !== 'n8n-nodes-base' ?
1110
+ 'N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true' :
1111
+ null
1112
+ };
1113
+ let outputs = undefined;
1114
+ if (node.outputNames && Array.isArray(node.outputNames) && node.outputNames.length > 0) {
1115
+ outputs = node.outputNames.map((name, index) => {
1116
+ const descriptions = this.getOutputDescriptions(node.nodeType, name, index);
1117
+ return {
1118
+ index,
1119
+ name,
1120
+ description: descriptions?.description ?? '',
1121
+ connectionGuidance: descriptions?.connectionGuidance ?? ''
1122
+ };
1123
+ });
1124
+ }
1125
+ const result = {
1126
+ ...node,
1127
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package ?? 'n8n-nodes-base', node.nodeType),
1128
+ aiToolCapabilities,
1129
+ outputs
1130
+ };
1131
+ const toolVariantInfo = this.buildToolVariantGuidance(node);
1132
+ if (toolVariantInfo) {
1133
+ result.toolVariantInfo = toolVariantInfo;
1134
+ }
1135
+ return result;
1136
+ }
1137
+ async searchNodes(query, limit = 20, options) {
1138
+ await this.ensureInitialized();
1139
+ if (!this.db)
1140
+ throw new Error('Database not initialized');
1141
+ let normalizedQuery = query;
1142
+ if (query.includes('n8n-nodes-base.') || query.includes('@n8n/n8n-nodes-langchain.')) {
1143
+ normalizedQuery = query
1144
+ .replace(/n8n-nodes-base\./g, 'nodes-base.')
1145
+ .replace(/@n8n\/n8n-nodes-langchain\./g, 'nodes-langchain.');
1146
+ }
1147
+ const searchMode = options?.mode || 'OR';
1148
+ const ftsExists = this.db.prepare(`
1149
+ SELECT name FROM sqlite_master
1150
+ WHERE type='table' AND name='nodes_fts'
1151
+ `).get();
1152
+ if (ftsExists) {
1153
+ logger_1.logger.debug(`Using FTS5 search with includeExamples=${options?.includeExamples}`);
1154
+ return this.searchNodesFTS(normalizedQuery, limit, searchMode, options);
1155
+ }
1156
+ else {
1157
+ logger_1.logger.debug('Using LIKE search (no FTS5)');
1158
+ return this.searchNodesLIKE(normalizedQuery, limit, options);
1159
+ }
1160
+ }
1161
+ async searchNodesFTS(query, limit, mode, options) {
1162
+ if (!this.db)
1163
+ throw new Error('Database not initialized');
1164
+ const cleanedQuery = query.trim();
1165
+ if (!cleanedQuery) {
1166
+ return { query, results: [], totalCount: 0 };
1167
+ }
1168
+ if (mode === 'FUZZY') {
1169
+ return this.searchNodesFuzzy(cleanedQuery, limit);
1170
+ }
1171
+ let ftsQuery;
1172
+ if (cleanedQuery.startsWith('"') && cleanedQuery.endsWith('"')) {
1173
+ ftsQuery = cleanedQuery;
1174
+ }
1175
+ else {
1176
+ const words = cleanedQuery.split(/\s+/).filter(w => w.length > 0);
1177
+ switch (mode) {
1178
+ case 'AND':
1179
+ ftsQuery = words.join(' AND ');
1180
+ break;
1181
+ case 'OR':
1182
+ default:
1183
+ ftsQuery = words.join(' OR ');
1184
+ break;
1185
+ }
1186
+ }
1187
+ try {
1188
+ let sourceFilter = '';
1189
+ const sourceValue = options?.source || 'all';
1190
+ switch (sourceValue) {
1191
+ case 'core':
1192
+ sourceFilter = 'AND n.is_community = 0';
1193
+ break;
1194
+ case 'community':
1195
+ sourceFilter = 'AND n.is_community = 1';
1196
+ break;
1197
+ case 'verified':
1198
+ sourceFilter = 'AND n.is_community = 1 AND n.is_verified = 1';
1199
+ break;
1200
+ }
1201
+ const nodes = this.db.prepare(`
1202
+ SELECT
1203
+ n.*,
1204
+ rank
1205
+ FROM nodes n
1206
+ JOIN nodes_fts ON n.rowid = nodes_fts.rowid
1207
+ WHERE nodes_fts MATCH ?
1208
+ ${sourceFilter}
1209
+ ORDER BY
1210
+ CASE
1211
+ WHEN LOWER(n.display_name) = LOWER(?) THEN 0
1212
+ WHEN LOWER(n.display_name) LIKE LOWER(?) THEN 1
1213
+ WHEN LOWER(n.node_type) LIKE LOWER(?) THEN 2
1214
+ ELSE 3
1215
+ END,
1216
+ rank,
1217
+ n.display_name
1218
+ LIMIT ?
1219
+ `).all(ftsQuery, cleanedQuery, `%${cleanedQuery}%`, `%${cleanedQuery}%`, limit);
1220
+ const scoredNodes = nodes.map(node => {
1221
+ const relevanceScore = this.calculateRelevanceScore(node, cleanedQuery);
1222
+ return { ...node, relevanceScore };
1223
+ });
1224
+ scoredNodes.sort((a, b) => {
1225
+ if (a.display_name.toLowerCase() === cleanedQuery.toLowerCase())
1226
+ return -1;
1227
+ if (b.display_name.toLowerCase() === cleanedQuery.toLowerCase())
1228
+ return 1;
1229
+ if (a.relevanceScore !== b.relevanceScore) {
1230
+ return b.relevanceScore - a.relevanceScore;
1231
+ }
1232
+ return a.rank - b.rank;
1233
+ });
1234
+ const hasHttpRequest = scoredNodes.some(n => n.node_type === 'nodes-base.httpRequest');
1235
+ if (cleanedQuery.toLowerCase().includes('http') && !hasHttpRequest) {
1236
+ logger_1.logger.debug('FTS missed HTTP Request node, augmenting with LIKE search');
1237
+ return this.searchNodesLIKE(query, limit);
1238
+ }
1239
+ const result = {
1240
+ query,
1241
+ results: scoredNodes.map(node => {
1242
+ const nodeResult = {
1243
+ nodeType: node.node_type,
1244
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package_name, node.node_type),
1245
+ displayName: node.display_name,
1246
+ description: node.description,
1247
+ category: node.category,
1248
+ package: node.package_name,
1249
+ relevance: this.calculateRelevance(node, cleanedQuery)
1250
+ };
1251
+ if (node.is_community === 1) {
1252
+ nodeResult.isCommunity = true;
1253
+ nodeResult.isVerified = node.is_verified === 1;
1254
+ if (node.author_name) {
1255
+ nodeResult.authorName = node.author_name;
1256
+ }
1257
+ if (node.npm_downloads) {
1258
+ nodeResult.npmDownloads = node.npm_downloads;
1259
+ }
1260
+ }
1261
+ return nodeResult;
1262
+ }),
1263
+ totalCount: scoredNodes.length
1264
+ };
1265
+ if (mode !== 'OR') {
1266
+ result.mode = mode;
1267
+ }
1268
+ if (options && options.includeExamples) {
1269
+ try {
1270
+ for (const nodeResult of result.results) {
1271
+ const examples = this.db.prepare(`
1272
+ SELECT
1273
+ parameters_json,
1274
+ template_name,
1275
+ template_views
1276
+ FROM template_node_configs
1277
+ WHERE node_type = ?
1278
+ ORDER BY rank
1279
+ LIMIT 2
1280
+ `).all(nodeResult.workflowNodeType);
1281
+ if (examples.length > 0) {
1282
+ nodeResult.examples = examples.map((ex) => ({
1283
+ configuration: JSON.parse(ex.parameters_json),
1284
+ template: ex.template_name,
1285
+ views: ex.template_views
1286
+ }));
1287
+ }
1288
+ }
1289
+ }
1290
+ catch (error) {
1291
+ logger_1.logger.error(`Failed to add examples:`, error);
1292
+ }
1293
+ }
1294
+ telemetry_1.telemetry.trackSearchQuery(query, scoredNodes.length, mode ?? 'OR');
1295
+ return result;
1296
+ }
1297
+ catch (error) {
1298
+ logger_1.logger.warn('FTS5 search failed, falling back to LIKE search:', error.message);
1299
+ if (error.message.includes('syntax error') || error.message.includes('fts5')) {
1300
+ logger_1.logger.warn(`FTS5 syntax error for query "${query}" in mode ${mode}`);
1301
+ const likeResult = await this.searchNodesLIKE(query, limit);
1302
+ telemetry_1.telemetry.trackSearchQuery(query, likeResult.results?.length ?? 0, `${mode}_LIKE_FALLBACK`);
1303
+ return {
1304
+ ...likeResult,
1305
+ mode
1306
+ };
1307
+ }
1308
+ return this.searchNodesLIKE(query, limit);
1309
+ }
1310
+ }
1311
+ async searchNodesFuzzy(query, limit) {
1312
+ if (!this.db)
1313
+ throw new Error('Database not initialized');
1314
+ const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 0);
1315
+ if (words.length === 0) {
1316
+ return { query, results: [], totalCount: 0, mode: 'FUZZY' };
1317
+ }
1318
+ const candidateNodes = this.db.prepare(`
1319
+ SELECT * FROM nodes
1320
+ `).all();
1321
+ const scoredNodes = candidateNodes.map(node => {
1322
+ const score = this.calculateFuzzyScore(node, query);
1323
+ return { node, score };
1324
+ });
1325
+ const matchingNodes = scoredNodes
1326
+ .filter(item => item.score >= 200)
1327
+ .sort((a, b) => b.score - a.score)
1328
+ .slice(0, limit)
1329
+ .map(item => item.node);
1330
+ if (matchingNodes.length === 0) {
1331
+ const topScores = scoredNodes
1332
+ .sort((a, b) => b.score - a.score)
1333
+ .slice(0, 5);
1334
+ logger_1.logger.debug(`FUZZY search for "${query}" - no matches above 400. Top scores:`, topScores.map(s => ({ name: s.node.display_name, score: s.score })));
1335
+ }
1336
+ return {
1337
+ query,
1338
+ mode: 'FUZZY',
1339
+ results: matchingNodes.map(node => ({
1340
+ nodeType: node.node_type,
1341
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package_name, node.node_type),
1342
+ displayName: node.display_name,
1343
+ description: node.description,
1344
+ category: node.category,
1345
+ package: node.package_name
1346
+ })),
1347
+ totalCount: matchingNodes.length
1348
+ };
1349
+ }
1350
+ calculateFuzzyScore(node, query) {
1351
+ const queryLower = query.toLowerCase();
1352
+ const displayNameLower = node.display_name.toLowerCase();
1353
+ const nodeTypeLower = node.node_type.toLowerCase();
1354
+ const nodeTypeClean = nodeTypeLower.replace(/^nodes-base\./, '').replace(/^nodes-langchain\./, '');
1355
+ if (displayNameLower === queryLower || nodeTypeClean === queryLower) {
1356
+ return 1000;
1357
+ }
1358
+ const nameDistance = this.getEditDistance(queryLower, displayNameLower);
1359
+ const typeDistance = this.getEditDistance(queryLower, nodeTypeClean);
1360
+ const nameWords = displayNameLower.split(/\s+/);
1361
+ let minWordDistance = Infinity;
1362
+ for (const word of nameWords) {
1363
+ const distance = this.getEditDistance(queryLower, word);
1364
+ if (distance < minWordDistance) {
1365
+ minWordDistance = distance;
1366
+ }
1367
+ }
1368
+ const bestDistance = Math.min(nameDistance, typeDistance, minWordDistance);
1369
+ let matchedLen = queryLower.length;
1370
+ if (minWordDistance === bestDistance) {
1371
+ for (const word of nameWords) {
1372
+ if (this.getEditDistance(queryLower, word) === minWordDistance) {
1373
+ matchedLen = Math.max(queryLower.length, word.length);
1374
+ break;
1375
+ }
1376
+ }
1377
+ }
1378
+ else if (typeDistance === bestDistance) {
1379
+ matchedLen = Math.max(queryLower.length, nodeTypeClean.length);
1380
+ }
1381
+ else {
1382
+ matchedLen = Math.max(queryLower.length, displayNameLower.length);
1383
+ }
1384
+ const similarity = 1 - (bestDistance / matchedLen);
1385
+ if (displayNameLower.includes(queryLower) || nodeTypeClean.includes(queryLower)) {
1386
+ return 800 + (similarity * 100);
1387
+ }
1388
+ if (displayNameLower.startsWith(queryLower) ||
1389
+ nodeTypeClean.startsWith(queryLower) ||
1390
+ nameWords.some(w => w.startsWith(queryLower))) {
1391
+ return 700 + (similarity * 100);
1392
+ }
1393
+ if (bestDistance <= 2) {
1394
+ return 500 + ((2 - bestDistance) * 100) + (similarity * 50);
1395
+ }
1396
+ if (bestDistance <= 3 && queryLower.length >= 4) {
1397
+ return 400 + ((3 - bestDistance) * 50) + (similarity * 50);
1398
+ }
1399
+ return similarity * 300;
1400
+ }
1401
+ getEditDistance(s1, s2) {
1402
+ const m = s1.length;
1403
+ const n = s2.length;
1404
+ const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
1405
+ for (let i = 0; i <= m; i++)
1406
+ dp[i][0] = i;
1407
+ for (let j = 0; j <= n; j++)
1408
+ dp[0][j] = j;
1409
+ for (let i = 1; i <= m; i++) {
1410
+ for (let j = 1; j <= n; j++) {
1411
+ if (s1[i - 1] === s2[j - 1]) {
1412
+ dp[i][j] = dp[i - 1][j - 1];
1413
+ }
1414
+ else {
1415
+ dp[i][j] = 1 + Math.min(dp[i - 1][j], dp[i][j - 1], dp[i - 1][j - 1]);
1416
+ }
1417
+ }
1418
+ }
1419
+ return dp[m][n];
1420
+ }
1421
+ async searchNodesLIKE(query, limit, options) {
1422
+ if (!this.db)
1423
+ throw new Error('Database not initialized');
1424
+ let sourceFilter = '';
1425
+ const sourceValue = options?.source || 'all';
1426
+ switch (sourceValue) {
1427
+ case 'core':
1428
+ sourceFilter = 'AND is_community = 0';
1429
+ break;
1430
+ case 'community':
1431
+ sourceFilter = 'AND is_community = 1';
1432
+ break;
1433
+ case 'verified':
1434
+ sourceFilter = 'AND is_community = 1 AND is_verified = 1';
1435
+ break;
1436
+ }
1437
+ if (query.startsWith('"') && query.endsWith('"')) {
1438
+ const exactPhrase = query.slice(1, -1);
1439
+ const nodes = this.db.prepare(`
1440
+ SELECT * FROM nodes
1441
+ WHERE (node_type LIKE ? OR display_name LIKE ? OR description LIKE ?)
1442
+ ${sourceFilter}
1443
+ LIMIT ?
1444
+ `).all(`%${exactPhrase}%`, `%${exactPhrase}%`, `%${exactPhrase}%`, limit * 3);
1445
+ const rankedNodes = this.rankSearchResults(nodes, exactPhrase, limit);
1446
+ const result = {
1447
+ query,
1448
+ results: rankedNodes.map(node => {
1449
+ const nodeResult = {
1450
+ nodeType: node.node_type,
1451
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package_name, node.node_type),
1452
+ displayName: node.display_name,
1453
+ description: node.description,
1454
+ category: node.category,
1455
+ package: node.package_name
1456
+ };
1457
+ if (node.is_community === 1) {
1458
+ nodeResult.isCommunity = true;
1459
+ nodeResult.isVerified = node.is_verified === 1;
1460
+ if (node.author_name) {
1461
+ nodeResult.authorName = node.author_name;
1462
+ }
1463
+ if (node.npm_downloads) {
1464
+ nodeResult.npmDownloads = node.npm_downloads;
1465
+ }
1466
+ }
1467
+ return nodeResult;
1468
+ }),
1469
+ totalCount: rankedNodes.length
1470
+ };
1471
+ if (options?.includeExamples) {
1472
+ for (const nodeResult of result.results) {
1473
+ try {
1474
+ const examples = this.db.prepare(`
1475
+ SELECT
1476
+ parameters_json,
1477
+ template_name,
1478
+ template_views
1479
+ FROM template_node_configs
1480
+ WHERE node_type = ?
1481
+ ORDER BY rank
1482
+ LIMIT 2
1483
+ `).all(nodeResult.workflowNodeType);
1484
+ if (examples.length > 0) {
1485
+ nodeResult.examples = examples.map((ex) => ({
1486
+ configuration: JSON.parse(ex.parameters_json),
1487
+ template: ex.template_name,
1488
+ views: ex.template_views
1489
+ }));
1490
+ }
1491
+ }
1492
+ catch (error) {
1493
+ logger_1.logger.warn(`Failed to fetch examples for ${nodeResult.nodeType}:`, error.message);
1494
+ }
1495
+ }
1496
+ }
1497
+ return result;
1498
+ }
1499
+ const words = query.toLowerCase().split(/\s+/).filter(w => w.length > 0);
1500
+ if (words.length === 0) {
1501
+ return { query, results: [], totalCount: 0 };
1502
+ }
1503
+ const conditions = words.map(() => '(node_type LIKE ? OR display_name LIKE ? OR description LIKE ?)').join(' OR ');
1504
+ const params = words.flatMap(w => [`%${w}%`, `%${w}%`, `%${w}%`]);
1505
+ params.push(limit * 3);
1506
+ const nodes = this.db.prepare(`
1507
+ SELECT DISTINCT * FROM nodes
1508
+ WHERE (${conditions})
1509
+ ${sourceFilter}
1510
+ LIMIT ?
1511
+ `).all(...params);
1512
+ const rankedNodes = this.rankSearchResults(nodes, query, limit);
1513
+ const result = {
1514
+ query,
1515
+ results: rankedNodes.map(node => {
1516
+ const nodeResult = {
1517
+ nodeType: node.node_type,
1518
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package_name, node.node_type),
1519
+ displayName: node.display_name,
1520
+ description: node.description,
1521
+ category: node.category,
1522
+ package: node.package_name
1523
+ };
1524
+ if (node.is_community === 1) {
1525
+ nodeResult.isCommunity = true;
1526
+ nodeResult.isVerified = node.is_verified === 1;
1527
+ if (node.author_name) {
1528
+ nodeResult.authorName = node.author_name;
1529
+ }
1530
+ if (node.npm_downloads) {
1531
+ nodeResult.npmDownloads = node.npm_downloads;
1532
+ }
1533
+ }
1534
+ return nodeResult;
1535
+ }),
1536
+ totalCount: rankedNodes.length
1537
+ };
1538
+ if (options?.includeExamples) {
1539
+ for (const nodeResult of result.results) {
1540
+ try {
1541
+ const examples = this.db.prepare(`
1542
+ SELECT
1543
+ parameters_json,
1544
+ template_name,
1545
+ template_views
1546
+ FROM template_node_configs
1547
+ WHERE node_type = ?
1548
+ ORDER BY rank
1549
+ LIMIT 2
1550
+ `).all(nodeResult.workflowNodeType);
1551
+ if (examples.length > 0) {
1552
+ nodeResult.examples = examples.map((ex) => ({
1553
+ configuration: JSON.parse(ex.parameters_json),
1554
+ template: ex.template_name,
1555
+ views: ex.template_views
1556
+ }));
1557
+ }
1558
+ }
1559
+ catch (error) {
1560
+ logger_1.logger.warn(`Failed to fetch examples for ${nodeResult.nodeType}:`, error.message);
1561
+ }
1562
+ }
1563
+ }
1564
+ return result;
1565
+ }
1566
+ calculateRelevance(node, query) {
1567
+ const lowerQuery = query.toLowerCase();
1568
+ if (node.node_type.toLowerCase().includes(lowerQuery))
1569
+ return 'high';
1570
+ if (node.display_name.toLowerCase().includes(lowerQuery))
1571
+ return 'high';
1572
+ if (node.description?.toLowerCase().includes(lowerQuery))
1573
+ return 'medium';
1574
+ return 'low';
1575
+ }
1576
+ calculateRelevanceScore(node, query) {
1577
+ const query_lower = query.toLowerCase();
1578
+ const name_lower = node.display_name.toLowerCase();
1579
+ const type_lower = node.node_type.toLowerCase();
1580
+ const type_without_prefix = type_lower.replace(/^nodes-base\./, '').replace(/^nodes-langchain\./, '');
1581
+ let score = 0;
1582
+ if (name_lower === query_lower) {
1583
+ score = 1000;
1584
+ }
1585
+ else if (type_without_prefix === query_lower) {
1586
+ score = 950;
1587
+ }
1588
+ else if (query_lower === 'webhook' && node.node_type === 'nodes-base.webhook') {
1589
+ score = 900;
1590
+ }
1591
+ else if ((query_lower === 'http' || query_lower === 'http request' || query_lower === 'http call') && node.node_type === 'nodes-base.httpRequest') {
1592
+ score = 900;
1593
+ }
1594
+ else if (query_lower.includes('http') && query_lower.includes('call') && node.node_type === 'nodes-base.httpRequest') {
1595
+ score = 890;
1596
+ }
1597
+ else if (query_lower.includes('http') && node.node_type === 'nodes-base.httpRequest') {
1598
+ score = 850;
1599
+ }
1600
+ else if (query_lower.includes('webhook') && node.node_type === 'nodes-base.webhook') {
1601
+ score = 850;
1602
+ }
1603
+ else if (name_lower.startsWith(query_lower)) {
1604
+ score = 800;
1605
+ }
1606
+ else if (new RegExp(`\\b${query_lower}\\b`, 'i').test(node.display_name)) {
1607
+ score = 700;
1608
+ }
1609
+ else if (name_lower.includes(query_lower)) {
1610
+ score = 600;
1611
+ }
1612
+ else if (type_without_prefix.includes(query_lower)) {
1613
+ score = 500;
1614
+ }
1615
+ else if (node.description?.toLowerCase().includes(query_lower)) {
1616
+ score = 400;
1617
+ }
1618
+ return score;
1619
+ }
1620
+ rankSearchResults(nodes, query, limit) {
1621
+ const query_lower = query.toLowerCase();
1622
+ const scoredNodes = nodes.map(node => {
1623
+ const name_lower = node.display_name.toLowerCase();
1624
+ const type_lower = node.node_type.toLowerCase();
1625
+ const type_without_prefix = type_lower.replace(/^nodes-base\./, '').replace(/^nodes-langchain\./, '');
1626
+ let score = 0;
1627
+ if (name_lower === query_lower) {
1628
+ score = 1000;
1629
+ }
1630
+ else if (type_without_prefix === query_lower) {
1631
+ score = 950;
1632
+ }
1633
+ else if (query_lower === 'webhook' && node.node_type === 'nodes-base.webhook') {
1634
+ score = 900;
1635
+ }
1636
+ else if ((query_lower === 'http' || query_lower === 'http request' || query_lower === 'http call') && node.node_type === 'nodes-base.httpRequest') {
1637
+ score = 900;
1638
+ }
1639
+ else if (query_lower.includes('webhook') && node.node_type === 'nodes-base.webhook') {
1640
+ score = 850;
1641
+ }
1642
+ else if (query_lower.includes('http') && node.node_type === 'nodes-base.httpRequest') {
1643
+ score = 850;
1644
+ }
1645
+ else if (name_lower.startsWith(query_lower)) {
1646
+ score = 800;
1647
+ }
1648
+ else if (new RegExp(`\\b${query_lower}\\b`, 'i').test(node.display_name)) {
1649
+ score = 700;
1650
+ }
1651
+ else if (name_lower.includes(query_lower)) {
1652
+ score = 600;
1653
+ }
1654
+ else if (type_without_prefix.includes(query_lower)) {
1655
+ score = 500;
1656
+ }
1657
+ else if (node.description?.toLowerCase().includes(query_lower)) {
1658
+ score = 400;
1659
+ }
1660
+ const words = query_lower.split(/\s+/).filter(w => w.length > 0);
1661
+ if (words.length > 1) {
1662
+ const allWordsInName = words.every(word => name_lower.includes(word));
1663
+ const allWordsInDesc = words.every(word => node.description?.toLowerCase().includes(word));
1664
+ if (allWordsInName)
1665
+ score += 200;
1666
+ else if (allWordsInDesc)
1667
+ score += 100;
1668
+ if (query_lower === 'http call' && name_lower === 'http request') {
1669
+ score = 920;
1670
+ }
1671
+ }
1672
+ return { node, score };
1673
+ });
1674
+ scoredNodes.sort((a, b) => {
1675
+ if (a.score !== b.score) {
1676
+ return b.score - a.score;
1677
+ }
1678
+ return a.node.display_name.localeCompare(b.node.display_name);
1679
+ });
1680
+ return scoredNodes.slice(0, limit).map(item => item.node);
1681
+ }
1682
+ async listAITools() {
1683
+ await this.ensureInitialized();
1684
+ if (!this.repository)
1685
+ throw new Error('Repository not initialized');
1686
+ const tools = this.repository.getAITools();
1687
+ const aiCount = this.db.prepare('SELECT COUNT(*) as ai_count FROM nodes WHERE is_ai_tool = 1').get();
1688
+ return {
1689
+ tools,
1690
+ totalCount: tools.length,
1691
+ requirements: {
1692
+ environmentVariable: 'N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true',
1693
+ nodeProperty: 'usableAsTool: true',
1694
+ },
1695
+ usage: {
1696
+ description: 'These nodes have the usableAsTool property set to true, making them optimized for AI agent usage.',
1697
+ note: 'ANY node in n8n can be used as an AI tool by connecting it to the ai_tool port of an AI Agent node.',
1698
+ examples: [
1699
+ 'Regular nodes like Slack, Google Sheets, or HTTP Request can be used as tools',
1700
+ 'Connect any node to an AI Agent\'s tool port to make it available for AI-driven automation',
1701
+ 'Community nodes require the environment variable to be set'
1702
+ ]
1703
+ }
1704
+ };
1705
+ }
1706
+ async getNodeDocumentation(nodeType) {
1707
+ await this.ensureInitialized();
1708
+ if (!this.db)
1709
+ throw new Error('Database not initialized');
1710
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
1711
+ let node = this.db.prepare(`
1712
+ SELECT node_type, display_name, documentation, description,
1713
+ ai_documentation_summary, ai_summary_generated_at
1714
+ FROM nodes
1715
+ WHERE node_type = ?
1716
+ `).get(normalizedType);
1717
+ if (!node && normalizedType !== nodeType) {
1718
+ node = this.db.prepare(`
1719
+ SELECT node_type, display_name, documentation, description,
1720
+ ai_documentation_summary, ai_summary_generated_at
1721
+ FROM nodes
1722
+ WHERE node_type = ?
1723
+ `).get(nodeType);
1724
+ }
1725
+ if (!node) {
1726
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
1727
+ for (const alt of alternatives) {
1728
+ node = this.db.prepare(`
1729
+ SELECT node_type, display_name, documentation, description,
1730
+ ai_documentation_summary, ai_summary_generated_at
1731
+ FROM nodes
1732
+ WHERE node_type = ?
1733
+ `).get(alt);
1734
+ if (node)
1735
+ break;
1736
+ }
1737
+ }
1738
+ if (!node) {
1739
+ throw new Error(`Node ${nodeType} not found`);
1740
+ }
1741
+ const aiDocSummary = node.ai_documentation_summary
1742
+ ? this.safeJsonParse(node.ai_documentation_summary, null)
1743
+ : null;
1744
+ if (!node.documentation) {
1745
+ const essentials = await this.getNodeEssentials(nodeType);
1746
+ return {
1747
+ nodeType: node.node_type,
1748
+ displayName: node.display_name || 'Unknown Node',
1749
+ documentation: `
1750
+ # ${node.display_name || 'Unknown Node'}
1751
+
1752
+ ${node.description || 'No description available.'}
1753
+
1754
+ ## Common Properties
1755
+
1756
+ ${essentials?.commonProperties?.length > 0 ?
1757
+ essentials.commonProperties.map((p) => `### ${p.displayName || 'Property'}\n${p.description || `Type: ${p.type || 'unknown'}`}`).join('\n\n') :
1758
+ 'No common properties available.'}
1759
+
1760
+ ## Note
1761
+ Full documentation is being prepared. For now, use get_node_essentials for configuration help.
1762
+ `,
1763
+ hasDocumentation: false,
1764
+ aiDocumentationSummary: aiDocSummary,
1765
+ aiSummaryGeneratedAt: node.ai_summary_generated_at || null,
1766
+ };
1767
+ }
1768
+ return {
1769
+ nodeType: node.node_type,
1770
+ displayName: node.display_name || 'Unknown Node',
1771
+ documentation: node.documentation,
1772
+ hasDocumentation: true,
1773
+ aiDocumentationSummary: aiDocSummary,
1774
+ aiSummaryGeneratedAt: node.ai_summary_generated_at || null,
1775
+ };
1776
+ }
1777
+ safeJsonParse(json, defaultValue = null) {
1778
+ try {
1779
+ return JSON.parse(json);
1780
+ }
1781
+ catch {
1782
+ return defaultValue;
1783
+ }
1784
+ }
1785
+ async getDatabaseStatistics() {
1786
+ await this.ensureInitialized();
1787
+ if (!this.db)
1788
+ throw new Error('Database not initialized');
1789
+ const stats = this.db.prepare(`
1790
+ SELECT
1791
+ COUNT(*) as total,
1792
+ SUM(is_ai_tool) as ai_tools,
1793
+ SUM(is_trigger) as triggers,
1794
+ SUM(is_versioned) as versioned,
1795
+ SUM(CASE WHEN documentation IS NOT NULL THEN 1 ELSE 0 END) as with_docs,
1796
+ COUNT(DISTINCT package_name) as packages,
1797
+ COUNT(DISTINCT category) as categories
1798
+ FROM nodes
1799
+ `).get();
1800
+ const packages = this.db.prepare(`
1801
+ SELECT package_name, COUNT(*) as count
1802
+ FROM nodes
1803
+ GROUP BY package_name
1804
+ `).all();
1805
+ const templateStats = this.db.prepare(`
1806
+ SELECT
1807
+ COUNT(*) as total_templates,
1808
+ AVG(views) as avg_views,
1809
+ MIN(views) as min_views,
1810
+ MAX(views) as max_views
1811
+ FROM templates
1812
+ `).get();
1813
+ return {
1814
+ totalNodes: stats.total,
1815
+ totalTemplates: templateStats.total_templates || 0,
1816
+ statistics: {
1817
+ aiTools: stats.ai_tools,
1818
+ triggers: stats.triggers,
1819
+ versionedNodes: stats.versioned,
1820
+ nodesWithDocumentation: stats.with_docs,
1821
+ documentationCoverage: Math.round((stats.with_docs / stats.total) * 100) + '%',
1822
+ uniquePackages: stats.packages,
1823
+ uniqueCategories: stats.categories,
1824
+ templates: {
1825
+ total: templateStats.total_templates || 0,
1826
+ avgViews: Math.round(templateStats.avg_views || 0),
1827
+ minViews: templateStats.min_views || 0,
1828
+ maxViews: templateStats.max_views || 0
1829
+ }
1830
+ },
1831
+ packageBreakdown: packages.map(pkg => ({
1832
+ package: pkg.package_name,
1833
+ nodeCount: pkg.count,
1834
+ })),
1835
+ };
1836
+ }
1837
+ async getNodeEssentials(nodeType, includeExamples) {
1838
+ await this.ensureInitialized();
1839
+ if (!this.repository)
1840
+ throw new Error('Repository not initialized');
1841
+ const cacheKey = `essentials:${nodeType}:${includeExamples ? 'withExamples' : 'basic'}`;
1842
+ const cached = this.cache.get(cacheKey);
1843
+ if (cached)
1844
+ return cached;
1845
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
1846
+ let node = this.repository.getNode(normalizedType);
1847
+ if (!node && normalizedType !== nodeType) {
1848
+ node = this.repository.getNode(nodeType);
1849
+ }
1850
+ if (!node) {
1851
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
1852
+ for (const alt of alternatives) {
1853
+ const found = this.repository.getNode(alt);
1854
+ if (found) {
1855
+ node = found;
1856
+ break;
1857
+ }
1858
+ }
1859
+ }
1860
+ if (!node) {
1861
+ throw new Error(`Node ${nodeType} not found`);
1862
+ }
1863
+ const allProperties = node.properties || [];
1864
+ const essentials = property_filter_1.PropertyFilter.getEssentials(allProperties, node.nodeType);
1865
+ const operations = node.operations || [];
1866
+ const latestVersion = node.version ?? '1';
1867
+ const result = {
1868
+ nodeType: node.nodeType,
1869
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package ?? 'n8n-nodes-base', node.nodeType),
1870
+ displayName: node.displayName,
1871
+ description: node.description,
1872
+ category: node.category,
1873
+ version: latestVersion,
1874
+ isVersioned: node.isVersioned ?? false,
1875
+ versionNotice: `⚠️ Use typeVersion: ${latestVersion} when creating this node`,
1876
+ requiredProperties: essentials.required,
1877
+ commonProperties: essentials.common,
1878
+ operations: operations.map((op) => ({
1879
+ name: op.name || op.operation,
1880
+ description: op.description,
1881
+ action: op.action,
1882
+ resource: op.resource
1883
+ })),
1884
+ metadata: {
1885
+ totalProperties: allProperties.length,
1886
+ isAITool: node.isAITool ?? false,
1887
+ isTrigger: node.isTrigger ?? false,
1888
+ isWebhook: node.isWebhook ?? false,
1889
+ hasCredentials: node.credentials ? true : false,
1890
+ package: node.package ?? 'n8n-nodes-base',
1891
+ developmentStyle: node.developmentStyle ?? 'programmatic'
1892
+ }
1893
+ };
1894
+ const toolVariantInfo = this.buildToolVariantGuidance(node);
1895
+ if (toolVariantInfo) {
1896
+ result.toolVariantInfo = toolVariantInfo;
1897
+ }
1898
+ if (includeExamples) {
1899
+ try {
1900
+ const examples = this.db.prepare(`
1901
+ SELECT
1902
+ parameters_json,
1903
+ template_name,
1904
+ template_views,
1905
+ complexity,
1906
+ use_cases,
1907
+ has_credentials,
1908
+ has_expressions
1909
+ FROM template_node_configs
1910
+ WHERE node_type = ?
1911
+ ORDER BY rank
1912
+ LIMIT 3
1913
+ `).all(result.workflowNodeType);
1914
+ if (examples.length > 0) {
1915
+ result.examples = examples.map((ex) => ({
1916
+ configuration: JSON.parse(ex.parameters_json),
1917
+ source: {
1918
+ template: ex.template_name,
1919
+ views: ex.template_views,
1920
+ complexity: ex.complexity
1921
+ },
1922
+ useCases: ex.use_cases ? JSON.parse(ex.use_cases).slice(0, 2) : [],
1923
+ metadata: {
1924
+ hasCredentials: ex.has_credentials === 1,
1925
+ hasExpressions: ex.has_expressions === 1
1926
+ }
1927
+ }));
1928
+ result.examplesCount = examples.length;
1929
+ }
1930
+ else {
1931
+ result.examples = [];
1932
+ result.examplesCount = 0;
1933
+ }
1934
+ }
1935
+ catch (error) {
1936
+ logger_1.logger.warn(`Failed to fetch examples for ${nodeType}:`, error.message);
1937
+ result.examples = [];
1938
+ result.examplesCount = 0;
1939
+ }
1940
+ }
1941
+ this.cache.set(cacheKey, result, 3600);
1942
+ return result;
1943
+ }
1944
+ async getNode(nodeType, detail = 'standard', mode = 'info', includeTypeInfo, includeExamples, fromVersion, toVersion) {
1945
+ await this.ensureInitialized();
1946
+ if (!this.repository)
1947
+ throw new Error('Repository not initialized');
1948
+ const validDetailLevels = ['minimal', 'standard', 'full'];
1949
+ const validModes = ['info', 'versions', 'compare', 'breaking', 'migrations'];
1950
+ if (!validDetailLevels.includes(detail)) {
1951
+ throw new Error(`get_node: Invalid detail level "${detail}". Valid options: ${validDetailLevels.join(', ')}`);
1952
+ }
1953
+ if (!validModes.includes(mode)) {
1954
+ throw new Error(`get_node: Invalid mode "${mode}". Valid options: ${validModes.join(', ')}`);
1955
+ }
1956
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
1957
+ if (mode !== 'info') {
1958
+ return this.handleVersionMode(normalizedType, mode, fromVersion, toVersion);
1959
+ }
1960
+ return this.handleInfoMode(normalizedType, detail, includeTypeInfo, includeExamples);
1961
+ }
1962
+ async handleInfoMode(nodeType, detail, includeTypeInfo, includeExamples) {
1963
+ switch (detail) {
1964
+ case 'minimal': {
1965
+ let node = this.repository.getNode(nodeType);
1966
+ if (!node) {
1967
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(nodeType);
1968
+ for (const alt of alternatives) {
1969
+ const found = this.repository.getNode(alt);
1970
+ if (found) {
1971
+ node = found;
1972
+ break;
1973
+ }
1974
+ }
1975
+ }
1976
+ if (!node) {
1977
+ throw new Error(`Node ${nodeType} not found`);
1978
+ }
1979
+ const result = {
1980
+ nodeType: node.nodeType,
1981
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package ?? 'n8n-nodes-base', node.nodeType),
1982
+ displayName: node.displayName,
1983
+ description: node.description,
1984
+ category: node.category,
1985
+ package: node.package,
1986
+ isAITool: node.isAITool,
1987
+ isTrigger: node.isTrigger,
1988
+ isWebhook: node.isWebhook
1989
+ };
1990
+ const toolVariantInfo = this.buildToolVariantGuidance(node);
1991
+ if (toolVariantInfo) {
1992
+ result.toolVariantInfo = toolVariantInfo;
1993
+ }
1994
+ return result;
1995
+ }
1996
+ case 'standard': {
1997
+ const essentials = await this.getNodeEssentials(nodeType, includeExamples);
1998
+ const versionSummary = this.getVersionSummary(nodeType);
1999
+ if (includeTypeInfo) {
2000
+ essentials.requiredProperties = this.enrichPropertiesWithTypeInfo(essentials.requiredProperties);
2001
+ essentials.commonProperties = this.enrichPropertiesWithTypeInfo(essentials.commonProperties);
2002
+ }
2003
+ return {
2004
+ ...essentials,
2005
+ versionInfo: versionSummary
2006
+ };
2007
+ }
2008
+ case 'full': {
2009
+ const fullInfo = await this.getNodeInfo(nodeType);
2010
+ const versionSummary = this.getVersionSummary(nodeType);
2011
+ if (includeTypeInfo && fullInfo.properties) {
2012
+ fullInfo.properties = this.enrichPropertiesWithTypeInfo(fullInfo.properties);
2013
+ }
2014
+ return {
2015
+ ...fullInfo,
2016
+ versionInfo: versionSummary
2017
+ };
2018
+ }
2019
+ default:
2020
+ throw new Error(`Unknown detail level: ${detail}`);
2021
+ }
2022
+ }
2023
+ async handleVersionMode(nodeType, mode, fromVersion, toVersion) {
2024
+ switch (mode) {
2025
+ case 'versions':
2026
+ return this.getVersionHistory(nodeType);
2027
+ case 'compare':
2028
+ if (!fromVersion) {
2029
+ throw new Error(`get_node: fromVersion is required for compare mode (nodeType: ${nodeType})`);
2030
+ }
2031
+ return this.compareVersions(nodeType, fromVersion, toVersion);
2032
+ case 'breaking':
2033
+ if (!fromVersion) {
2034
+ throw new Error(`get_node: fromVersion is required for breaking mode (nodeType: ${nodeType})`);
2035
+ }
2036
+ return this.getBreakingChanges(nodeType, fromVersion, toVersion);
2037
+ case 'migrations':
2038
+ if (!fromVersion || !toVersion) {
2039
+ throw new Error(`get_node: Both fromVersion and toVersion are required for migrations mode (nodeType: ${nodeType})`);
2040
+ }
2041
+ return this.getMigrations(nodeType, fromVersion, toVersion);
2042
+ default:
2043
+ throw new Error(`get_node: Unknown mode: ${mode} (nodeType: ${nodeType})`);
2044
+ }
2045
+ }
2046
+ getVersionSummary(nodeType) {
2047
+ const cacheKey = `version-summary:${nodeType}`;
2048
+ const cached = this.cache.get(cacheKey);
2049
+ if (cached) {
2050
+ return cached;
2051
+ }
2052
+ const versions = this.repository.getNodeVersions(nodeType);
2053
+ const latest = this.repository.getLatestNodeVersion(nodeType);
2054
+ const summary = {
2055
+ currentVersion: latest?.version || 'unknown',
2056
+ totalVersions: versions.length,
2057
+ hasVersionHistory: versions.length > 0
2058
+ };
2059
+ this.cache.set(cacheKey, summary, 86400000);
2060
+ return summary;
2061
+ }
2062
+ getVersionHistory(nodeType) {
2063
+ const versions = this.repository.getNodeVersions(nodeType);
2064
+ return {
2065
+ nodeType,
2066
+ totalVersions: versions.length,
2067
+ versions: versions.map(v => ({
2068
+ version: v.version,
2069
+ isCurrent: v.isCurrentMax,
2070
+ minimumN8nVersion: v.minimumN8nVersion,
2071
+ releasedAt: v.releasedAt,
2072
+ hasBreakingChanges: (v.breakingChanges || []).length > 0,
2073
+ breakingChangesCount: (v.breakingChanges || []).length,
2074
+ deprecatedProperties: v.deprecatedProperties || [],
2075
+ addedProperties: v.addedProperties || []
2076
+ })),
2077
+ available: versions.length > 0,
2078
+ message: versions.length === 0 ?
2079
+ 'No version history available. Version tracking may not be enabled for this node.' :
2080
+ undefined
2081
+ };
2082
+ }
2083
+ compareVersions(nodeType, fromVersion, toVersion) {
2084
+ const latest = this.repository.getLatestNodeVersion(nodeType);
2085
+ const targetVersion = toVersion || latest?.version;
2086
+ if (!targetVersion) {
2087
+ throw new Error('No target version available');
2088
+ }
2089
+ const changes = this.repository.getPropertyChanges(nodeType, fromVersion, targetVersion);
2090
+ return {
2091
+ nodeType,
2092
+ fromVersion,
2093
+ toVersion: targetVersion,
2094
+ totalChanges: changes.length,
2095
+ breakingChanges: changes.filter(c => c.isBreaking).length,
2096
+ changes: changes.map(c => ({
2097
+ property: c.propertyName,
2098
+ changeType: c.changeType,
2099
+ isBreaking: c.isBreaking,
2100
+ severity: c.severity,
2101
+ oldValue: c.oldValue,
2102
+ newValue: c.newValue,
2103
+ migrationHint: c.migrationHint,
2104
+ autoMigratable: c.autoMigratable
2105
+ }))
2106
+ };
2107
+ }
2108
+ getBreakingChanges(nodeType, fromVersion, toVersion) {
2109
+ const breakingChanges = this.repository.getBreakingChanges(nodeType, fromVersion, toVersion);
2110
+ return {
2111
+ nodeType,
2112
+ fromVersion,
2113
+ toVersion: toVersion || 'latest',
2114
+ totalBreakingChanges: breakingChanges.length,
2115
+ changes: breakingChanges.map(c => ({
2116
+ fromVersion: c.fromVersion,
2117
+ toVersion: c.toVersion,
2118
+ property: c.propertyName,
2119
+ changeType: c.changeType,
2120
+ severity: c.severity,
2121
+ migrationHint: c.migrationHint,
2122
+ oldValue: c.oldValue,
2123
+ newValue: c.newValue
2124
+ })),
2125
+ upgradeSafe: breakingChanges.length === 0
2126
+ };
2127
+ }
2128
+ getMigrations(nodeType, fromVersion, toVersion) {
2129
+ const migrations = this.repository.getAutoMigratableChanges(nodeType, fromVersion, toVersion);
2130
+ const allChanges = this.repository.getPropertyChanges(nodeType, fromVersion, toVersion);
2131
+ return {
2132
+ nodeType,
2133
+ fromVersion,
2134
+ toVersion,
2135
+ autoMigratableChanges: migrations.length,
2136
+ totalChanges: allChanges.length,
2137
+ migrations: migrations.map(m => ({
2138
+ property: m.propertyName,
2139
+ changeType: m.changeType,
2140
+ migrationStrategy: m.migrationStrategy,
2141
+ severity: m.severity
2142
+ })),
2143
+ requiresManualMigration: migrations.length < allChanges.length
2144
+ };
2145
+ }
2146
+ enrichPropertyWithTypeInfo(property) {
2147
+ if (!property || !property.type)
2148
+ return property;
2149
+ const structure = type_structure_service_1.TypeStructureService.getStructure(property.type);
2150
+ if (!structure)
2151
+ return property;
2152
+ return {
2153
+ ...property,
2154
+ typeInfo: {
2155
+ category: structure.type,
2156
+ jsType: structure.jsType,
2157
+ description: structure.description,
2158
+ isComplex: type_structure_service_1.TypeStructureService.isComplexType(property.type),
2159
+ isPrimitive: type_structure_service_1.TypeStructureService.isPrimitiveType(property.type),
2160
+ allowsExpressions: structure.validation?.allowExpressions ?? true,
2161
+ allowsEmpty: structure.validation?.allowEmpty ?? false,
2162
+ ...(structure.structure && {
2163
+ structureHints: {
2164
+ hasProperties: !!structure.structure.properties,
2165
+ hasItems: !!structure.structure.items,
2166
+ isFlexible: structure.structure.flexible ?? false,
2167
+ requiredFields: structure.structure.required ?? []
2168
+ }
2169
+ }),
2170
+ ...(structure.notes && { notes: structure.notes })
2171
+ }
2172
+ };
2173
+ }
2174
+ enrichPropertiesWithTypeInfo(properties) {
2175
+ if (!properties || !Array.isArray(properties))
2176
+ return properties;
2177
+ return properties.map((prop) => this.enrichPropertyWithTypeInfo(prop));
2178
+ }
2179
+ async searchNodeProperties(nodeType, query, maxResults = 20) {
2180
+ await this.ensureInitialized();
2181
+ if (!this.repository)
2182
+ throw new Error('Repository not initialized');
2183
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
2184
+ let node = this.repository.getNode(normalizedType);
2185
+ if (!node && normalizedType !== nodeType) {
2186
+ node = this.repository.getNode(nodeType);
2187
+ }
2188
+ if (!node) {
2189
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
2190
+ for (const alt of alternatives) {
2191
+ const found = this.repository.getNode(alt);
2192
+ if (found) {
2193
+ node = found;
2194
+ break;
2195
+ }
2196
+ }
2197
+ }
2198
+ if (!node) {
2199
+ throw new Error(`Node ${nodeType} not found`);
2200
+ }
2201
+ const allProperties = node.properties || [];
2202
+ const matches = property_filter_1.PropertyFilter.searchProperties(allProperties, query, maxResults);
2203
+ return {
2204
+ nodeType: node.nodeType,
2205
+ query,
2206
+ matches: matches.map((match) => ({
2207
+ name: match.name,
2208
+ displayName: match.displayName,
2209
+ type: match.type,
2210
+ description: match.description,
2211
+ path: match.path || match.name,
2212
+ required: match.required,
2213
+ default: match.default,
2214
+ options: match.options,
2215
+ showWhen: match.showWhen
2216
+ })),
2217
+ totalMatches: matches.length,
2218
+ searchedIn: allProperties.length + ' properties'
2219
+ };
2220
+ }
2221
+ getPropertyValue(config, path) {
2222
+ const parts = path.split('.');
2223
+ let value = config;
2224
+ for (const part of parts) {
2225
+ const arrayMatch = part.match(/^(\w+)\[(\d+)\]$/);
2226
+ if (arrayMatch) {
2227
+ value = value?.[arrayMatch[1]]?.[parseInt(arrayMatch[2])];
2228
+ }
2229
+ else {
2230
+ value = value?.[part];
2231
+ }
2232
+ }
2233
+ return value;
2234
+ }
2235
+ async listTasks(category) {
2236
+ if (category) {
2237
+ const categories = task_templates_1.TaskTemplates.getTaskCategories();
2238
+ const tasks = categories[category];
2239
+ if (!tasks) {
2240
+ throw new Error(`Unknown category: ${category}. Available categories: ${Object.keys(categories).join(', ')}`);
2241
+ }
2242
+ return {
2243
+ category,
2244
+ tasks: tasks.map(task => {
2245
+ const template = task_templates_1.TaskTemplates.getTaskTemplate(task);
2246
+ return {
2247
+ task,
2248
+ description: template?.description || '',
2249
+ nodeType: template?.nodeType || ''
2250
+ };
2251
+ })
2252
+ };
2253
+ }
2254
+ const categories = task_templates_1.TaskTemplates.getTaskCategories();
2255
+ const result = {
2256
+ totalTasks: task_templates_1.TaskTemplates.getAllTasks().length,
2257
+ categories: {}
2258
+ };
2259
+ for (const [cat, tasks] of Object.entries(categories)) {
2260
+ result.categories[cat] = tasks.map(task => {
2261
+ const template = task_templates_1.TaskTemplates.getTaskTemplate(task);
2262
+ return {
2263
+ task,
2264
+ description: template?.description || '',
2265
+ nodeType: template?.nodeType || ''
2266
+ };
2267
+ });
2268
+ }
2269
+ return result;
2270
+ }
2271
+ async validateNodeConfig(nodeType, config, mode = 'operation', profile = 'ai-friendly') {
2272
+ await this.ensureInitialized();
2273
+ if (!this.repository)
2274
+ throw new Error('Repository not initialized');
2275
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
2276
+ let node = this.repository.getNode(normalizedType);
2277
+ if (!node && normalizedType !== nodeType) {
2278
+ node = this.repository.getNode(nodeType);
2279
+ }
2280
+ if (!node) {
2281
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
2282
+ for (const alt of alternatives) {
2283
+ const found = this.repository.getNode(alt);
2284
+ if (found) {
2285
+ node = found;
2286
+ break;
2287
+ }
2288
+ }
2289
+ }
2290
+ if (!node) {
2291
+ throw new Error(`Node ${nodeType} not found`);
2292
+ }
2293
+ const properties = node.properties || [];
2294
+ const configWithVersion = {
2295
+ '@version': node.version || 1,
2296
+ ...config
2297
+ };
2298
+ const validationResult = enhanced_config_validator_1.EnhancedConfigValidator.validateWithMode(node.nodeType, configWithVersion, properties, mode, profile);
2299
+ return {
2300
+ nodeType: node.nodeType,
2301
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package, node.nodeType),
2302
+ displayName: node.displayName,
2303
+ ...validationResult,
2304
+ summary: {
2305
+ hasErrors: !validationResult.valid,
2306
+ errorCount: validationResult.errors.length,
2307
+ warningCount: validationResult.warnings.length,
2308
+ suggestionCount: validationResult.suggestions.length
2309
+ }
2310
+ };
2311
+ }
2312
+ async getPropertyDependencies(nodeType, config) {
2313
+ await this.ensureInitialized();
2314
+ if (!this.repository)
2315
+ throw new Error('Repository not initialized');
2316
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
2317
+ let node = this.repository.getNode(normalizedType);
2318
+ if (!node && normalizedType !== nodeType) {
2319
+ node = this.repository.getNode(nodeType);
2320
+ }
2321
+ if (!node) {
2322
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
2323
+ for (const alt of alternatives) {
2324
+ const found = this.repository.getNode(alt);
2325
+ if (found) {
2326
+ node = found;
2327
+ break;
2328
+ }
2329
+ }
2330
+ }
2331
+ if (!node) {
2332
+ throw new Error(`Node ${nodeType} not found`);
2333
+ }
2334
+ const properties = node.properties || [];
2335
+ const analysis = property_dependencies_1.PropertyDependencies.analyze(properties);
2336
+ let visibilityImpact = null;
2337
+ if (config) {
2338
+ visibilityImpact = property_dependencies_1.PropertyDependencies.getVisibilityImpact(properties, config);
2339
+ }
2340
+ return {
2341
+ nodeType: node.nodeType,
2342
+ displayName: node.displayName,
2343
+ ...analysis,
2344
+ currentConfig: config ? {
2345
+ providedValues: config,
2346
+ visibilityImpact
2347
+ } : undefined
2348
+ };
2349
+ }
2350
+ async getNodeAsToolInfo(nodeType) {
2351
+ await this.ensureInitialized();
2352
+ if (!this.repository)
2353
+ throw new Error('Repository not initialized');
2354
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
2355
+ let node = this.repository.getNode(normalizedType);
2356
+ if (!node && normalizedType !== nodeType) {
2357
+ node = this.repository.getNode(nodeType);
2358
+ }
2359
+ if (!node) {
2360
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
2361
+ for (const alt of alternatives) {
2362
+ const found = this.repository.getNode(alt);
2363
+ if (found) {
2364
+ node = found;
2365
+ break;
2366
+ }
2367
+ }
2368
+ }
2369
+ if (!node) {
2370
+ throw new Error(`Node ${nodeType} not found`);
2371
+ }
2372
+ const commonUseCases = this.getCommonAIToolUseCases(node.nodeType);
2373
+ const aiToolCapabilities = {
2374
+ canBeUsedAsTool: true,
2375
+ hasUsableAsToolProperty: node.isAITool,
2376
+ requiresEnvironmentVariable: !node.isAITool && node.package !== 'n8n-nodes-base',
2377
+ connectionType: 'ai_tool',
2378
+ commonUseCases,
2379
+ requirements: {
2380
+ connection: 'Connect to the "ai_tool" port of an AI Agent node',
2381
+ environment: node.package !== 'n8n-nodes-base' ?
2382
+ 'Set N8N_COMMUNITY_PACKAGES_ALLOW_TOOL_USAGE=true for community nodes' :
2383
+ 'No special environment variables needed for built-in nodes'
2384
+ },
2385
+ examples: this.getAIToolExamples(node.nodeType),
2386
+ tips: [
2387
+ 'Give the tool a clear, descriptive name in the AI Agent settings',
2388
+ 'Write a detailed tool description to help the AI understand when to use it',
2389
+ 'Test the node independently before connecting it as a tool',
2390
+ node.isAITool ?
2391
+ 'This node is optimized for AI tool usage' :
2392
+ 'This is a regular node that can be used as an AI tool'
2393
+ ]
2394
+ };
2395
+ return {
2396
+ nodeType: node.nodeType,
2397
+ workflowNodeType: (0, node_utils_1.getWorkflowNodeType)(node.package, node.nodeType),
2398
+ displayName: node.displayName,
2399
+ description: node.description,
2400
+ package: node.package,
2401
+ isMarkedAsAITool: node.isAITool,
2402
+ aiToolCapabilities
2403
+ };
2404
+ }
2405
+ getOutputDescriptions(nodeType, outputName, index) {
2406
+ if (nodeType === 'nodes-base.splitInBatches') {
2407
+ if (outputName === 'done' && index === 0) {
2408
+ return {
2409
+ description: 'Final processed data after all iterations complete',
2410
+ connectionGuidance: 'Connect to nodes that should run AFTER the loop completes'
2411
+ };
2412
+ }
2413
+ else if (outputName === 'loop' && index === 1) {
2414
+ return {
2415
+ description: 'Current batch data for this iteration',
2416
+ connectionGuidance: 'Connect to nodes that process items INSIDE the loop (and connect their output back to this node)'
2417
+ };
2418
+ }
2419
+ }
2420
+ if (nodeType === 'nodes-base.if') {
2421
+ if (outputName === 'true' && index === 0) {
2422
+ return {
2423
+ description: 'Items that match the condition',
2424
+ connectionGuidance: 'Connect to nodes that handle the TRUE case'
2425
+ };
2426
+ }
2427
+ else if (outputName === 'false' && index === 1) {
2428
+ return {
2429
+ description: 'Items that do not match the condition',
2430
+ connectionGuidance: 'Connect to nodes that handle the FALSE case'
2431
+ };
2432
+ }
2433
+ }
2434
+ if (nodeType === 'nodes-base.switch') {
2435
+ return {
2436
+ description: `Output ${index}: ${outputName || 'Route ' + index}`,
2437
+ connectionGuidance: `Connect to nodes for the "${outputName || 'route ' + index}" case`
2438
+ };
2439
+ }
2440
+ return {
2441
+ description: outputName || `Output ${index}`,
2442
+ connectionGuidance: `Connect to downstream nodes`
2443
+ };
2444
+ }
2445
+ getCommonAIToolUseCases(nodeType) {
2446
+ const useCaseMap = {
2447
+ 'nodes-base.slack': [
2448
+ 'Send notifications about task completion',
2449
+ 'Post updates to channels',
2450
+ 'Send direct messages',
2451
+ 'Create alerts and reminders'
2452
+ ],
2453
+ 'nodes-base.googleSheets': [
2454
+ 'Read data for analysis',
2455
+ 'Log results and outputs',
2456
+ 'Update spreadsheet records',
2457
+ 'Create reports'
2458
+ ],
2459
+ 'nodes-base.gmail': [
2460
+ 'Send email notifications',
2461
+ 'Read and process emails',
2462
+ 'Send reports and summaries',
2463
+ 'Handle email-based workflows'
2464
+ ],
2465
+ 'nodes-base.httpRequest': [
2466
+ 'Call external APIs',
2467
+ 'Fetch data from web services',
2468
+ 'Send webhooks',
2469
+ 'Integrate with any REST API'
2470
+ ],
2471
+ 'nodes-base.postgres': [
2472
+ 'Query database for information',
2473
+ 'Store analysis results',
2474
+ 'Update records based on AI decisions',
2475
+ 'Generate reports from data'
2476
+ ],
2477
+ 'nodes-base.webhook': [
2478
+ 'Receive external triggers',
2479
+ 'Create callback endpoints',
2480
+ 'Handle incoming data',
2481
+ 'Integrate with external systems'
2482
+ ]
2483
+ };
2484
+ for (const [key, useCases] of Object.entries(useCaseMap)) {
2485
+ if (nodeType.includes(key)) {
2486
+ return useCases;
2487
+ }
2488
+ }
2489
+ return [
2490
+ 'Perform automated actions',
2491
+ 'Integrate with external services',
2492
+ 'Process and transform data',
2493
+ 'Extend AI agent capabilities'
2494
+ ];
2495
+ }
2496
+ buildToolVariantGuidance(node) {
2497
+ const isToolVariant = !!node.isToolVariant;
2498
+ const hasToolVariant = !!node.hasToolVariant;
2499
+ const toolVariantOf = node.toolVariantOf;
2500
+ if (!isToolVariant && !hasToolVariant) {
2501
+ return undefined;
2502
+ }
2503
+ if (isToolVariant) {
2504
+ return {
2505
+ isToolVariant: true,
2506
+ toolVariantOf,
2507
+ hasToolVariant: false,
2508
+ guidance: `This is the Tool variant for AI Agent integration. Use this node type when connecting to AI Agents. The base node is: ${toolVariantOf}`
2509
+ };
2510
+ }
2511
+ if (hasToolVariant && node.nodeType) {
2512
+ const toolVariantNodeType = `${node.nodeType}Tool`;
2513
+ return {
2514
+ isToolVariant: false,
2515
+ hasToolVariant: true,
2516
+ toolVariantNodeType,
2517
+ guidance: `To use this node with AI Agents, use the Tool variant: ${toolVariantNodeType}. The Tool variant has an additional 'toolDescription' property and outputs 'ai_tool' instead of 'main'.`
2518
+ };
2519
+ }
2520
+ return undefined;
2521
+ }
2522
+ getAIToolExamples(nodeType) {
2523
+ const exampleMap = {
2524
+ 'nodes-base.slack': {
2525
+ toolName: 'Send Slack Message',
2526
+ toolDescription: 'Sends a message to a specified Slack channel or user. Use this to notify team members about important events or results.',
2527
+ nodeConfig: {
2528
+ resource: 'message',
2529
+ operation: 'post',
2530
+ channel: '={{ $fromAI("channel", "The Slack channel to send to, e.g. #general") }}',
2531
+ text: '={{ $fromAI("message", "The message content to send") }}'
2532
+ }
2533
+ },
2534
+ 'nodes-base.googleSheets': {
2535
+ toolName: 'Update Google Sheet',
2536
+ toolDescription: 'Reads or updates data in a Google Sheets spreadsheet. Use this to log information, retrieve data, or update records.',
2537
+ nodeConfig: {
2538
+ operation: 'append',
2539
+ sheetId: 'your-sheet-id',
2540
+ range: 'A:Z',
2541
+ dataMode: 'autoMap'
2542
+ }
2543
+ },
2544
+ 'nodes-base.httpRequest': {
2545
+ toolName: 'Call API',
2546
+ toolDescription: 'Makes HTTP requests to external APIs. Use this to fetch data, trigger webhooks, or integrate with any web service.',
2547
+ nodeConfig: {
2548
+ method: '={{ $fromAI("method", "HTTP method: GET, POST, PUT, DELETE") }}',
2549
+ url: '={{ $fromAI("url", "The complete API endpoint URL") }}',
2550
+ sendBody: true,
2551
+ bodyContentType: 'json',
2552
+ jsonBody: '={{ $fromAI("body", "Request body as JSON object") }}'
2553
+ }
2554
+ }
2555
+ };
2556
+ for (const [key, example] of Object.entries(exampleMap)) {
2557
+ if (nodeType.includes(key)) {
2558
+ return example;
2559
+ }
2560
+ }
2561
+ return {
2562
+ toolName: 'Custom Tool',
2563
+ toolDescription: 'Performs specific operations. Describe what this tool does and when to use it.',
2564
+ nodeConfig: {
2565
+ note: 'Configure the node based on its specific requirements'
2566
+ }
2567
+ };
2568
+ }
2569
+ async validateNodeMinimal(nodeType, config) {
2570
+ await this.ensureInitialized();
2571
+ if (!this.repository)
2572
+ throw new Error('Repository not initialized');
2573
+ const normalizedType = node_type_normalizer_1.NodeTypeNormalizer.normalizeToFullForm(nodeType);
2574
+ let node = this.repository.getNode(normalizedType);
2575
+ if (!node && normalizedType !== nodeType) {
2576
+ node = this.repository.getNode(nodeType);
2577
+ }
2578
+ if (!node) {
2579
+ const alternatives = (0, node_utils_1.getNodeTypeAlternatives)(normalizedType);
2580
+ for (const alt of alternatives) {
2581
+ const found = this.repository.getNode(alt);
2582
+ if (found) {
2583
+ node = found;
2584
+ break;
2585
+ }
2586
+ }
2587
+ }
2588
+ if (!node) {
2589
+ throw new Error(`Node ${nodeType} not found`);
2590
+ }
2591
+ const properties = node.properties || [];
2592
+ const configWithVersion = {
2593
+ '@version': node.version || 1,
2594
+ ...(config || {})
2595
+ };
2596
+ const missingFields = [];
2597
+ for (const prop of properties) {
2598
+ if (!prop.required)
2599
+ continue;
2600
+ if (prop.displayOptions && !config_validator_1.ConfigValidator.isPropertyVisible(prop, configWithVersion)) {
2601
+ continue;
2602
+ }
2603
+ if (!config || !(prop.name in config)) {
2604
+ missingFields.push(prop.displayName || prop.name);
2605
+ }
2606
+ }
2607
+ return {
2608
+ nodeType: node.nodeType,
2609
+ displayName: node.displayName,
2610
+ valid: missingFields.length === 0,
2611
+ missingRequiredFields: missingFields
2612
+ };
2613
+ }
2614
+ async getToolsDocumentation(topic, depth = 'essentials') {
2615
+ if (!topic || topic === 'overview') {
2616
+ return (0, tools_documentation_1.getToolsOverview)(depth);
2617
+ }
2618
+ return (0, tools_documentation_1.getToolDocumentation)(topic, depth);
2619
+ }
2620
+ async connect(transport) {
2621
+ await this.ensureInitialized();
2622
+ await this.server.connect(transport);
2623
+ logger_1.logger.info('MCP Server connected', {
2624
+ transportType: transport.constructor.name
2625
+ });
2626
+ }
2627
+ async listTemplates(limit = 10, offset = 0, sortBy = 'views', includeMetadata = false) {
2628
+ await this.ensureInitialized();
2629
+ if (!this.templateService)
2630
+ throw new Error('Template service not initialized');
2631
+ const result = await this.templateService.listTemplates(limit, offset, sortBy, includeMetadata);
2632
+ return {
2633
+ ...result,
2634
+ tip: result.items.length > 0 ?
2635
+ `Use get_template(templateId) to get full workflow details. Total: ${result.total} templates available.` :
2636
+ "No templates found. Run 'npm run fetch:templates' to update template database"
2637
+ };
2638
+ }
2639
+ async listNodeTemplates(nodeTypes, limit = 10, offset = 0) {
2640
+ await this.ensureInitialized();
2641
+ if (!this.templateService)
2642
+ throw new Error('Template service not initialized');
2643
+ const result = await this.templateService.listNodeTemplates(nodeTypes, limit, offset);
2644
+ if (result.items.length === 0 && offset === 0) {
2645
+ return {
2646
+ ...result,
2647
+ message: `No templates found using nodes: ${nodeTypes.join(', ')}`,
2648
+ tip: "Try searching with more common nodes or run 'npm run fetch:templates' to update template database"
2649
+ };
2650
+ }
2651
+ return {
2652
+ ...result,
2653
+ tip: `Showing ${result.items.length} of ${result.total} templates. Use offset for pagination.`
2654
+ };
2655
+ }
2656
+ async getTemplate(templateId, mode = 'full') {
2657
+ await this.ensureInitialized();
2658
+ if (!this.templateService)
2659
+ throw new Error('Template service not initialized');
2660
+ const template = await this.templateService.getTemplate(templateId, mode);
2661
+ if (!template) {
2662
+ return {
2663
+ error: `Template ${templateId} not found`,
2664
+ tip: "Use list_templates, list_node_templates or search_templates to find available templates"
2665
+ };
2666
+ }
2667
+ const usage = mode === 'nodes_only' ? "Node list for quick overview" :
2668
+ mode === 'structure' ? "Workflow structure without full details" :
2669
+ "Complete workflow JSON ready to import into n8n";
2670
+ return {
2671
+ mode,
2672
+ template,
2673
+ usage
2674
+ };
2675
+ }
2676
+ async searchTemplates(query, limit = 20, offset = 0, fields) {
2677
+ await this.ensureInitialized();
2678
+ if (!this.templateService)
2679
+ throw new Error('Template service not initialized');
2680
+ const result = await this.templateService.searchTemplates(query, limit, offset, fields);
2681
+ if (result.items.length === 0 && offset === 0) {
2682
+ return {
2683
+ ...result,
2684
+ message: `No templates found matching: "${query}"`,
2685
+ tip: "Try different keywords or run 'npm run fetch:templates' to update template database"
2686
+ };
2687
+ }
2688
+ return {
2689
+ ...result,
2690
+ query,
2691
+ tip: `Found ${result.total} templates matching "${query}". Showing ${result.items.length}.`
2692
+ };
2693
+ }
2694
+ async getTemplatesForTask(task, limit = 10, offset = 0) {
2695
+ await this.ensureInitialized();
2696
+ if (!this.templateService)
2697
+ throw new Error('Template service not initialized');
2698
+ const result = await this.templateService.getTemplatesForTask(task, limit, offset);
2699
+ const availableTasks = this.templateService.listAvailableTasks();
2700
+ if (result.items.length === 0 && offset === 0) {
2701
+ return {
2702
+ ...result,
2703
+ message: `No templates found for task: ${task}`,
2704
+ availableTasks,
2705
+ tip: "Try a different task or use search_templates for custom searches"
2706
+ };
2707
+ }
2708
+ return {
2709
+ ...result,
2710
+ task,
2711
+ description: this.getTaskDescription(task),
2712
+ tip: `${result.total} templates available for ${task}. Showing ${result.items.length}.`
2713
+ };
2714
+ }
2715
+ async searchTemplatesByMetadata(filters, limit = 20, offset = 0) {
2716
+ await this.ensureInitialized();
2717
+ if (!this.templateService)
2718
+ throw new Error('Template service not initialized');
2719
+ const result = await this.templateService.searchTemplatesByMetadata(filters, limit, offset);
2720
+ const filterSummary = [];
2721
+ if (filters.category)
2722
+ filterSummary.push(`category: ${filters.category}`);
2723
+ if (filters.complexity)
2724
+ filterSummary.push(`complexity: ${filters.complexity}`);
2725
+ if (filters.maxSetupMinutes)
2726
+ filterSummary.push(`max setup: ${filters.maxSetupMinutes} min`);
2727
+ if (filters.minSetupMinutes)
2728
+ filterSummary.push(`min setup: ${filters.minSetupMinutes} min`);
2729
+ if (filters.requiredService)
2730
+ filterSummary.push(`service: ${filters.requiredService}`);
2731
+ if (filters.targetAudience)
2732
+ filterSummary.push(`audience: ${filters.targetAudience}`);
2733
+ if (result.items.length === 0 && offset === 0) {
2734
+ const availableCategories = await this.templateService.getAvailableCategories();
2735
+ const availableAudiences = await this.templateService.getAvailableTargetAudiences();
2736
+ return {
2737
+ ...result,
2738
+ message: `No templates found with filters: ${filterSummary.join(', ')}`,
2739
+ availableCategories: availableCategories.slice(0, 10),
2740
+ availableAudiences: availableAudiences.slice(0, 5),
2741
+ tip: "Try broader filters or different categories. Use list_templates to see all templates."
2742
+ };
2743
+ }
2744
+ return {
2745
+ ...result,
2746
+ filters,
2747
+ filterSummary: filterSummary.join(', '),
2748
+ tip: `Found ${result.total} templates matching filters. Showing ${result.items.length}. Each includes AI-generated metadata.`
2749
+ };
2750
+ }
2751
+ getTaskDescription(task) {
2752
+ const descriptions = {
2753
+ 'ai_automation': 'AI-powered workflows using OpenAI, LangChain, and other AI tools',
2754
+ 'data_sync': 'Synchronize data between databases, spreadsheets, and APIs',
2755
+ 'webhook_processing': 'Process incoming webhooks and trigger automated actions',
2756
+ 'email_automation': 'Send, receive, and process emails automatically',
2757
+ 'slack_integration': 'Integrate with Slack for notifications and bot interactions',
2758
+ 'data_transformation': 'Transform, clean, and manipulate data',
2759
+ 'file_processing': 'Handle file uploads, downloads, and transformations',
2760
+ 'scheduling': 'Schedule recurring tasks and time-based automations',
2761
+ 'api_integration': 'Connect to external APIs and web services',
2762
+ 'database_operations': 'Query, insert, update, and manage database records'
2763
+ };
2764
+ return descriptions[task] || 'Workflow templates for this task';
2765
+ }
2766
+ async validateWorkflow(workflow, options) {
2767
+ await this.ensureInitialized();
2768
+ if (!this.repository)
2769
+ throw new Error('Repository not initialized');
2770
+ logger_1.logger.info('Workflow validation requested', {
2771
+ hasWorkflow: !!workflow,
2772
+ workflowType: typeof workflow,
2773
+ hasNodes: workflow?.nodes !== undefined,
2774
+ nodesType: workflow?.nodes ? typeof workflow.nodes : 'undefined',
2775
+ nodesIsArray: Array.isArray(workflow?.nodes),
2776
+ nodesCount: Array.isArray(workflow?.nodes) ? workflow.nodes.length : 0,
2777
+ hasConnections: workflow?.connections !== undefined,
2778
+ connectionsType: workflow?.connections ? typeof workflow.connections : 'undefined',
2779
+ options: options
2780
+ });
2781
+ if (!workflow || typeof workflow !== 'object') {
2782
+ return {
2783
+ valid: false,
2784
+ errors: [{
2785
+ node: 'workflow',
2786
+ message: 'Workflow must be an object with nodes and connections',
2787
+ details: 'Expected format: ' + (0, workflow_examples_1.getWorkflowExampleString)()
2788
+ }],
2789
+ summary: { errorCount: 1 }
2790
+ };
2791
+ }
2792
+ if (!workflow.nodes || !Array.isArray(workflow.nodes)) {
2793
+ return {
2794
+ valid: false,
2795
+ errors: [{
2796
+ node: 'workflow',
2797
+ message: 'Workflow must have a nodes array',
2798
+ details: 'Expected: workflow.nodes = [array of node objects]. ' + (0, workflow_examples_1.getWorkflowExampleString)()
2799
+ }],
2800
+ summary: { errorCount: 1 }
2801
+ };
2802
+ }
2803
+ if (!workflow.connections || typeof workflow.connections !== 'object') {
2804
+ return {
2805
+ valid: false,
2806
+ errors: [{
2807
+ node: 'workflow',
2808
+ message: 'Workflow must have a connections object',
2809
+ details: 'Expected: workflow.connections = {} (can be empty object). ' + (0, workflow_examples_1.getWorkflowExampleString)()
2810
+ }],
2811
+ summary: { errorCount: 1 }
2812
+ };
2813
+ }
2814
+ const validator = new workflow_validator_1.WorkflowValidator(this.repository, enhanced_config_validator_1.EnhancedConfigValidator);
2815
+ try {
2816
+ const result = await validator.validateWorkflow(workflow, options);
2817
+ const response = {
2818
+ valid: result.valid,
2819
+ summary: {
2820
+ totalNodes: result.statistics.totalNodes,
2821
+ enabledNodes: result.statistics.enabledNodes,
2822
+ triggerNodes: result.statistics.triggerNodes,
2823
+ validConnections: result.statistics.validConnections,
2824
+ invalidConnections: result.statistics.invalidConnections,
2825
+ expressionsValidated: result.statistics.expressionsValidated,
2826
+ errorCount: result.errors.length,
2827
+ warningCount: result.warnings.length
2828
+ },
2829
+ errors: result.errors.map(e => ({
2830
+ node: e.nodeName || 'workflow',
2831
+ message: e.message,
2832
+ details: e.details
2833
+ })),
2834
+ warnings: result.warnings.map(w => ({
2835
+ node: w.nodeName || 'workflow',
2836
+ message: w.message,
2837
+ details: w.details
2838
+ }))
2839
+ };
2840
+ if (result.suggestions.length > 0) {
2841
+ response.suggestions = result.suggestions;
2842
+ }
2843
+ if (!result.valid && result.errors.length > 0) {
2844
+ result.errors.forEach(error => {
2845
+ telemetry_1.telemetry.trackValidationDetails(error.nodeName || 'workflow', error.type || 'validation_error', {
2846
+ message: error.message,
2847
+ nodeCount: workflow.nodes?.length ?? 0,
2848
+ hasConnections: Object.keys(workflow.connections || {}).length > 0
2849
+ });
2850
+ });
2851
+ }
2852
+ if (result.valid) {
2853
+ telemetry_1.telemetry.trackWorkflowCreation(workflow, true);
2854
+ }
2855
+ return response;
2856
+ }
2857
+ catch (error) {
2858
+ logger_1.logger.error('Error validating workflow:', error);
2859
+ return {
2860
+ valid: false,
2861
+ error: error instanceof Error ? error.message : 'Unknown error validating workflow',
2862
+ tip: 'Ensure the workflow JSON includes nodes array and connections object'
2863
+ };
2864
+ }
2865
+ }
2866
+ async validateWorkflowConnections(workflow) {
2867
+ await this.ensureInitialized();
2868
+ if (!this.repository)
2869
+ throw new Error('Repository not initialized');
2870
+ const validator = new workflow_validator_1.WorkflowValidator(this.repository, enhanced_config_validator_1.EnhancedConfigValidator);
2871
+ try {
2872
+ const result = await validator.validateWorkflow(workflow, {
2873
+ validateNodes: false,
2874
+ validateConnections: true,
2875
+ validateExpressions: false
2876
+ });
2877
+ const response = {
2878
+ valid: result.errors.length === 0,
2879
+ statistics: {
2880
+ totalNodes: result.statistics.totalNodes,
2881
+ triggerNodes: result.statistics.triggerNodes,
2882
+ validConnections: result.statistics.validConnections,
2883
+ invalidConnections: result.statistics.invalidConnections
2884
+ }
2885
+ };
2886
+ const connectionErrors = result.errors.filter(e => e.message.includes('connection') ||
2887
+ e.message.includes('cycle') ||
2888
+ e.message.includes('orphaned'));
2889
+ const connectionWarnings = result.warnings.filter(w => w.message.includes('connection') ||
2890
+ w.message.includes('orphaned') ||
2891
+ w.message.includes('trigger'));
2892
+ if (connectionErrors.length > 0) {
2893
+ response.errors = connectionErrors.map(e => ({
2894
+ node: e.nodeName || 'workflow',
2895
+ message: e.message
2896
+ }));
2897
+ }
2898
+ if (connectionWarnings.length > 0) {
2899
+ response.warnings = connectionWarnings.map(w => ({
2900
+ node: w.nodeName || 'workflow',
2901
+ message: w.message
2902
+ }));
2903
+ }
2904
+ return response;
2905
+ }
2906
+ catch (error) {
2907
+ logger_1.logger.error('Error validating workflow connections:', error);
2908
+ return {
2909
+ valid: false,
2910
+ error: error instanceof Error ? error.message : 'Unknown error validating connections'
2911
+ };
2912
+ }
2913
+ }
2914
+ async validateWorkflowExpressions(workflow) {
2915
+ await this.ensureInitialized();
2916
+ if (!this.repository)
2917
+ throw new Error('Repository not initialized');
2918
+ const validator = new workflow_validator_1.WorkflowValidator(this.repository, enhanced_config_validator_1.EnhancedConfigValidator);
2919
+ try {
2920
+ const result = await validator.validateWorkflow(workflow, {
2921
+ validateNodes: false,
2922
+ validateConnections: false,
2923
+ validateExpressions: true
2924
+ });
2925
+ const response = {
2926
+ valid: result.errors.length === 0,
2927
+ statistics: {
2928
+ totalNodes: result.statistics.totalNodes,
2929
+ expressionsValidated: result.statistics.expressionsValidated
2930
+ }
2931
+ };
2932
+ const expressionErrors = result.errors.filter(e => e.message.includes('Expression') ||
2933
+ e.message.includes('$') ||
2934
+ e.message.includes('{{'));
2935
+ const expressionWarnings = result.warnings.filter(w => w.message.includes('Expression') ||
2936
+ w.message.includes('$') ||
2937
+ w.message.includes('{{'));
2938
+ if (expressionErrors.length > 0) {
2939
+ response.errors = expressionErrors.map(e => ({
2940
+ node: e.nodeName || 'workflow',
2941
+ message: e.message
2942
+ }));
2943
+ }
2944
+ if (expressionWarnings.length > 0) {
2945
+ response.warnings = expressionWarnings.map(w => ({
2946
+ node: w.nodeName || 'workflow',
2947
+ message: w.message
2948
+ }));
2949
+ }
2950
+ if (expressionErrors.length > 0 || expressionWarnings.length > 0) {
2951
+ response.tips = [
2952
+ 'Use {{ }} to wrap expressions',
2953
+ 'Reference data with $json.propertyName',
2954
+ 'Reference other nodes with $node["Node Name"].json',
2955
+ 'Use $input.item for input data in loops'
2956
+ ];
2957
+ }
2958
+ return response;
2959
+ }
2960
+ catch (error) {
2961
+ logger_1.logger.error('Error validating workflow expressions:', error);
2962
+ return {
2963
+ valid: false,
2964
+ error: error instanceof Error ? error.message : 'Unknown error validating expressions'
2965
+ };
2966
+ }
2967
+ }
2968
+ async run() {
2969
+ await this.ensureInitialized();
2970
+ const transport = new stdio_js_1.StdioServerTransport();
2971
+ await this.server.connect(transport);
2972
+ if (!process.stdout.isTTY || process.env.IS_DOCKER) {
2973
+ const originalWrite = process.stdout.write.bind(process.stdout);
2974
+ process.stdout.write = function (chunk, encoding, callback) {
2975
+ const result = originalWrite(chunk, encoding, callback);
2976
+ process.stdout.emit('drain');
2977
+ return result;
2978
+ };
2979
+ }
2980
+ logger_1.logger.info('n8n Documentation MCP Server running on stdio transport');
2981
+ process.stdin.resume();
2982
+ }
2983
+ async shutdown() {
2984
+ logger_1.logger.info('Shutting down MCP server...');
2985
+ if (this.cache) {
2986
+ try {
2987
+ this.cache.destroy();
2988
+ logger_1.logger.info('Cache timers cleaned up');
2989
+ }
2990
+ catch (error) {
2991
+ logger_1.logger.error('Error cleaning up cache:', error);
2992
+ }
2993
+ }
2994
+ if (this.db) {
2995
+ try {
2996
+ await this.db.close();
2997
+ logger_1.logger.info('Database connection closed');
2998
+ }
2999
+ catch (error) {
3000
+ logger_1.logger.error('Error closing database:', error);
3001
+ }
3002
+ }
3003
+ }
3004
+ }
3005
+ exports.N8NDocumentationMCPServer = N8NDocumentationMCPServer;
3006
+ //# sourceMappingURL=server.js.map