n8n-mcp 2.21.0 → 2.22.5

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 (277) hide show
  1. package/README.md +1 -0
  2. package/data/nodes.db +0 -0
  3. package/dist/database/node-repository.d.ts +62 -0
  4. package/dist/database/node-repository.d.ts.map +1 -1
  5. package/dist/database/node-repository.js +276 -0
  6. package/dist/database/node-repository.js.map +1 -1
  7. package/dist/mcp/absolute-minimal.d.ts +4 -0
  8. package/dist/mcp/absolute-minimal.d.ts.map +1 -0
  9. package/dist/mcp/absolute-minimal.js +34 -0
  10. package/dist/mcp/absolute-minimal.js.map +1 -0
  11. package/dist/mcp/fixed-protocol.d.ts +17 -0
  12. package/dist/mcp/fixed-protocol.d.ts.map +1 -0
  13. package/dist/mcp/fixed-protocol.js +162 -0
  14. package/dist/mcp/fixed-protocol.js.map +1 -0
  15. package/dist/mcp/handlers-documentation.d.ts +18 -0
  16. package/dist/mcp/handlers-documentation.d.ts.map +1 -0
  17. package/dist/mcp/handlers-documentation.js +113 -0
  18. package/dist/mcp/handlers-documentation.js.map +1 -0
  19. package/dist/mcp/handlers-n8n-manager.d.ts +2 -1
  20. package/dist/mcp/handlers-n8n-manager.d.ts.map +1 -1
  21. package/dist/mcp/handlers-n8n-manager.js +193 -5
  22. package/dist/mcp/handlers-n8n-manager.js.map +1 -1
  23. package/dist/mcp/handlers-workflow-diff.d.ts +2 -1
  24. package/dist/mcp/handlers-workflow-diff.d.ts.map +1 -1
  25. package/dist/mcp/handlers-workflow-diff.js +30 -2
  26. package/dist/mcp/handlers-workflow-diff.js.map +1 -1
  27. package/dist/mcp/index.js +0 -0
  28. package/dist/mcp/minimal-test.d.ts +3 -0
  29. package/dist/mcp/minimal-test.d.ts.map +1 -0
  30. package/dist/mcp/minimal-test.js +83 -0
  31. package/dist/mcp/minimal-test.js.map +1 -0
  32. package/dist/mcp/server.d.ts.map +1 -1
  33. package/dist/mcp/server.js +5 -2
  34. package/dist/mcp/server.js.map +1 -1
  35. package/dist/mcp/stderr-test.d.ts +2 -0
  36. package/dist/mcp/stderr-test.d.ts.map +1 -0
  37. package/dist/mcp/stderr-test.js +32 -0
  38. package/dist/mcp/stderr-test.js.map +1 -0
  39. package/dist/mcp/tool-docs/special/code-node-guide.d.ts +3 -0
  40. package/dist/mcp/tool-docs/special/code-node-guide.d.ts.map +1 -0
  41. package/dist/mcp/tool-docs/special/code-node-guide.js +61 -0
  42. package/dist/mcp/tool-docs/special/code-node-guide.js.map +1 -0
  43. package/dist/mcp/tool-docs/special/index.d.ts +2 -0
  44. package/dist/mcp/tool-docs/special/index.d.ts.map +1 -0
  45. package/dist/mcp/tool-docs/special/index.js +6 -0
  46. package/dist/mcp/tool-docs/special/index.js.map +1 -0
  47. package/dist/mcp/tool-docs/templates/get-node-for-task.d.ts +3 -0
  48. package/dist/mcp/tool-docs/templates/get-node-for-task.d.ts.map +1 -0
  49. package/dist/mcp/tool-docs/templates/get-node-for-task.js +50 -0
  50. package/dist/mcp/tool-docs/templates/get-node-for-task.js.map +1 -0
  51. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.d.ts.map +1 -1
  52. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.js +47 -11
  53. package/dist/mcp/tool-docs/workflow_management/n8n-autofix-workflow.js.map +1 -1
  54. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.d.ts.map +1 -1
  55. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js +6 -0
  56. package/dist/mcp/tool-docs/workflow_management/n8n-update-partial-workflow.js.map +1 -1
  57. package/dist/mcp/tools-documentation-new.d.ts +6 -0
  58. package/dist/mcp/tools-documentation-new.d.ts.map +1 -0
  59. package/dist/mcp/tools-documentation-new.js +163 -0
  60. package/dist/mcp/tools-documentation-new.js.map +1 -0
  61. package/dist/mcp/tools-n8n-manager.d.ts.map +1 -1
  62. package/dist/mcp/tools-n8n-manager.js +55 -1
  63. package/dist/mcp/tools-n8n-manager.js.map +1 -1
  64. package/dist/mcp/ultra-minimal.d.ts +8 -0
  65. package/dist/mcp/ultra-minimal.d.ts.map +1 -0
  66. package/dist/mcp/ultra-minimal.js +93 -0
  67. package/dist/mcp/ultra-minimal.js.map +1 -0
  68. package/dist/mcp/working-test.d.ts +3 -0
  69. package/dist/mcp/working-test.d.ts.map +1 -0
  70. package/dist/mcp/working-test.js +48 -0
  71. package/dist/mcp/working-test.js.map +1 -0
  72. package/dist/mcp/wrapper.sh +28 -0
  73. package/dist/scripts/debug-n8n-auth.d.ts +3 -0
  74. package/dist/scripts/debug-n8n-auth.d.ts.map +1 -0
  75. package/dist/scripts/debug-n8n-auth.js +97 -0
  76. package/dist/scripts/debug-n8n-auth.js.map +1 -0
  77. package/dist/scripts/debug-node.d.ts +3 -0
  78. package/dist/scripts/debug-node.d.ts.map +1 -0
  79. package/dist/scripts/debug-node.js +59 -0
  80. package/dist/scripts/debug-node.js.map +1 -0
  81. package/dist/scripts/generate-metadata-only.d.ts +3 -0
  82. package/dist/scripts/generate-metadata-only.d.ts.map +1 -0
  83. package/dist/scripts/generate-metadata-only.js +146 -0
  84. package/dist/scripts/generate-metadata-only.js.map +1 -0
  85. package/dist/scripts/generate-metadata-sync.d.ts +3 -0
  86. package/dist/scripts/generate-metadata-sync.d.ts.map +1 -0
  87. package/dist/scripts/generate-metadata-sync.js +136 -0
  88. package/dist/scripts/generate-metadata-sync.js.map +1 -0
  89. package/dist/scripts/test-ai-workflow-validation.d.ts +3 -0
  90. package/dist/scripts/test-ai-workflow-validation.d.ts.map +1 -0
  91. package/dist/scripts/test-ai-workflow-validation.js +191 -0
  92. package/dist/scripts/test-ai-workflow-validation.js.map +1 -0
  93. package/dist/scripts/test-api-headers.d.ts +3 -0
  94. package/dist/scripts/test-api-headers.d.ts.map +1 -0
  95. package/dist/scripts/test-api-headers.js +35 -0
  96. package/dist/scripts/test-api-headers.js.map +1 -0
  97. package/dist/scripts/test-autofix-workflow.js +3 -3
  98. package/dist/scripts/test-autofix-workflow.js.map +1 -1
  99. package/dist/scripts/test-batch-processing.d.ts +3 -0
  100. package/dist/scripts/test-batch-processing.d.ts.map +1 -0
  101. package/dist/scripts/test-batch-processing.js +144 -0
  102. package/dist/scripts/test-batch-processing.js.map +1 -0
  103. package/dist/scripts/test-docker-config-simulation.d.ts +3 -0
  104. package/dist/scripts/test-docker-config-simulation.d.ts.map +1 -0
  105. package/dist/scripts/test-docker-config-simulation.js +74 -0
  106. package/dist/scripts/test-docker-config-simulation.js.map +1 -0
  107. package/dist/scripts/test-enhanced-validation.d.ts +3 -0
  108. package/dist/scripts/test-enhanced-validation.d.ts.map +1 -0
  109. package/dist/scripts/test-enhanced-validation.js +117 -0
  110. package/dist/scripts/test-enhanced-validation.js.map +1 -0
  111. package/dist/scripts/test-error-handling-validation.d.ts +3 -0
  112. package/dist/scripts/test-error-handling-validation.d.ts.map +1 -0
  113. package/dist/scripts/test-error-handling-validation.js +340 -0
  114. package/dist/scripts/test-error-handling-validation.js.map +1 -0
  115. package/dist/scripts/test-issue-45-fix.d.ts +3 -0
  116. package/dist/scripts/test-issue-45-fix.d.ts.map +1 -0
  117. package/dist/scripts/test-issue-45-fix.js +136 -0
  118. package/dist/scripts/test-issue-45-fix.js.map +1 -0
  119. package/dist/scripts/test-issue-74.d.ts +3 -0
  120. package/dist/scripts/test-issue-74.d.ts.map +1 -0
  121. package/dist/scripts/test-issue-74.js +112 -0
  122. package/dist/scripts/test-issue-74.js.map +1 -0
  123. package/dist/scripts/test-lazy-config.d.ts +3 -0
  124. package/dist/scripts/test-lazy-config.d.ts.map +1 -0
  125. package/dist/scripts/test-lazy-config.js +60 -0
  126. package/dist/scripts/test-lazy-config.js.map +1 -0
  127. package/dist/scripts/test-limited-results.d.ts +3 -0
  128. package/dist/scripts/test-limited-results.d.ts.map +1 -0
  129. package/dist/scripts/test-limited-results.js +76 -0
  130. package/dist/scripts/test-limited-results.js.map +1 -0
  131. package/dist/scripts/test-mcp-n8n-update-partial.d.ts +3 -0
  132. package/dist/scripts/test-mcp-n8n-update-partial.d.ts.map +1 -0
  133. package/dist/scripts/test-mcp-n8n-update-partial.js +138 -0
  134. package/dist/scripts/test-mcp-n8n-update-partial.js.map +1 -0
  135. package/dist/scripts/test-mcp-tools.d.ts +3 -0
  136. package/dist/scripts/test-mcp-tools.d.ts.map +1 -0
  137. package/dist/scripts/test-mcp-tools.js +36 -0
  138. package/dist/scripts/test-mcp-tools.js.map +1 -0
  139. package/dist/scripts/test-metadata-generation.d.ts +3 -0
  140. package/dist/scripts/test-metadata-generation.d.ts.map +1 -0
  141. package/dist/scripts/test-metadata-generation.js +96 -0
  142. package/dist/scripts/test-metadata-generation.js.map +1 -0
  143. package/dist/scripts/test-n8n-manager-integration.d.ts +3 -0
  144. package/dist/scripts/test-n8n-manager-integration.d.ts.map +1 -0
  145. package/dist/scripts/test-n8n-manager-integration.js +122 -0
  146. package/dist/scripts/test-n8n-manager-integration.js.map +1 -0
  147. package/dist/scripts/test-n8n-validate-workflow.d.ts +3 -0
  148. package/dist/scripts/test-n8n-validate-workflow.d.ts.map +1 -0
  149. package/dist/scripts/test-n8n-validate-workflow.js +125 -0
  150. package/dist/scripts/test-n8n-validate-workflow.js.map +1 -0
  151. package/dist/scripts/test-node-level-properties.d.ts +3 -0
  152. package/dist/scripts/test-node-level-properties.d.ts.map +1 -0
  153. package/dist/scripts/test-node-level-properties.js +196 -0
  154. package/dist/scripts/test-node-level-properties.js.map +1 -0
  155. package/dist/scripts/test-node-suggestions.js +1 -1
  156. package/dist/scripts/test-node-suggestions.js.map +1 -1
  157. package/dist/scripts/test-nodes.d.ts +3 -0
  158. package/dist/scripts/test-nodes.d.ts.map +1 -0
  159. package/dist/scripts/test-nodes.js +91 -0
  160. package/dist/scripts/test-nodes.js.map +1 -0
  161. package/dist/scripts/test-single-workflow.d.ts +3 -0
  162. package/dist/scripts/test-single-workflow.d.ts.map +1 -0
  163. package/dist/scripts/test-single-workflow.js +112 -0
  164. package/dist/scripts/test-single-workflow.js.map +1 -0
  165. package/dist/scripts/test-template-validation.d.ts +3 -0
  166. package/dist/scripts/test-template-validation.d.ts.map +1 -0
  167. package/dist/scripts/test-template-validation.js +142 -0
  168. package/dist/scripts/test-template-validation.js.map +1 -0
  169. package/dist/scripts/test-templates.d.ts +4 -0
  170. package/dist/scripts/test-templates.d.ts.map +1 -0
  171. package/dist/scripts/test-templates.js +99 -0
  172. package/dist/scripts/test-templates.js.map +1 -0
  173. package/dist/scripts/test-tools-documentation.d.ts +2 -0
  174. package/dist/scripts/test-tools-documentation.d.ts.map +1 -0
  175. package/dist/scripts/test-tools-documentation.js +41 -0
  176. package/dist/scripts/test-tools-documentation.js.map +1 -0
  177. package/dist/scripts/test-transactional-diff.d.ts +2 -0
  178. package/dist/scripts/test-transactional-diff.d.ts.map +1 -0
  179. package/dist/scripts/test-transactional-diff.js +240 -0
  180. package/dist/scripts/test-transactional-diff.js.map +1 -0
  181. package/dist/scripts/test-update-partial-debug.d.ts +3 -0
  182. package/dist/scripts/test-update-partial-debug.d.ts.map +1 -0
  183. package/dist/scripts/test-update-partial-debug.js +92 -0
  184. package/dist/scripts/test-update-partial-debug.js.map +1 -0
  185. package/dist/scripts/test-updatenode-null-fix.d.ts +3 -0
  186. package/dist/scripts/test-updatenode-null-fix.d.ts.map +1 -0
  187. package/dist/scripts/test-updatenode-null-fix.js +156 -0
  188. package/dist/scripts/test-updatenode-null-fix.js.map +1 -0
  189. package/dist/scripts/test-validation-parity.d.ts +2 -0
  190. package/dist/scripts/test-validation-parity.d.ts.map +1 -0
  191. package/dist/scripts/test-validation-parity.js +153 -0
  192. package/dist/scripts/test-validation-parity.js.map +1 -0
  193. package/dist/scripts/test-version-extraction.d.ts +2 -0
  194. package/dist/scripts/test-version-extraction.d.ts.map +1 -0
  195. package/dist/scripts/test-version-extraction.js +74 -0
  196. package/dist/scripts/test-version-extraction.js.map +1 -0
  197. package/dist/scripts/test-webhook-autofix.js +1 -1
  198. package/dist/scripts/test-webhook-autofix.js.map +1 -1
  199. package/dist/scripts/test-workflow-diff.d.ts +3 -0
  200. package/dist/scripts/test-workflow-diff.d.ts.map +1 -0
  201. package/dist/scripts/test-workflow-diff.js +328 -0
  202. package/dist/scripts/test-workflow-diff.js.map +1 -0
  203. package/dist/scripts/test-workflow-validation.d.ts +3 -0
  204. package/dist/scripts/test-workflow-validation.d.ts.map +1 -0
  205. package/dist/scripts/test-workflow-validation.js +238 -0
  206. package/dist/scripts/test-workflow-validation.js.map +1 -0
  207. package/dist/services/breaking-change-detector.d.ts +38 -0
  208. package/dist/services/breaking-change-detector.d.ts.map +1 -0
  209. package/dist/services/breaking-change-detector.js +184 -0
  210. package/dist/services/breaking-change-detector.js.map +1 -0
  211. package/dist/services/breaking-changes-registry.d.ts +28 -0
  212. package/dist/services/breaking-changes-registry.d.ts.map +1 -0
  213. package/dist/services/breaking-changes-registry.js +200 -0
  214. package/dist/services/breaking-changes-registry.js.map +1 -0
  215. package/dist/services/enhanced-config-validator.d.ts.map +1 -1
  216. package/dist/services/enhanced-config-validator.js +32 -0
  217. package/dist/services/enhanced-config-validator.js.map +1 -1
  218. package/dist/services/n8n-api-client.d.ts +1 -0
  219. package/dist/services/n8n-api-client.d.ts.map +1 -1
  220. package/dist/services/n8n-api-client.js +26 -4
  221. package/dist/services/n8n-api-client.js.map +1 -1
  222. package/dist/services/n8n-validation.d.ts +144 -6
  223. package/dist/services/n8n-validation.d.ts.map +1 -1
  224. package/dist/services/n8n-validation.js +12 -5
  225. package/dist/services/n8n-validation.js.map +1 -1
  226. package/dist/services/node-migration-service.d.ts +44 -0
  227. package/dist/services/node-migration-service.d.ts.map +1 -0
  228. package/dist/services/node-migration-service.js +231 -0
  229. package/dist/services/node-migration-service.js.map +1 -0
  230. package/dist/services/node-version-service.d.ts +63 -0
  231. package/dist/services/node-version-service.d.ts.map +1 -0
  232. package/dist/services/node-version-service.js +215 -0
  233. package/dist/services/node-version-service.js.map +1 -0
  234. package/dist/services/post-update-validator.d.ts +59 -0
  235. package/dist/services/post-update-validator.d.ts.map +1 -0
  236. package/dist/services/post-update-validator.js +231 -0
  237. package/dist/services/post-update-validator.js.map +1 -0
  238. package/dist/services/workflow-auto-fixer.d.ts +10 -2
  239. package/dist/services/workflow-auto-fixer.d.ts.map +1 -1
  240. package/dist/services/workflow-auto-fixer.js +124 -3
  241. package/dist/services/workflow-auto-fixer.js.map +1 -1
  242. package/dist/services/workflow-diff-engine.d.ts +1 -0
  243. package/dist/services/workflow-diff-engine.d.ts.map +1 -1
  244. package/dist/services/workflow-diff-engine.js +23 -1
  245. package/dist/services/workflow-diff-engine.js.map +1 -1
  246. package/dist/services/workflow-ownership.d.ts +35 -0
  247. package/dist/services/workflow-ownership.d.ts.map +1 -0
  248. package/dist/services/workflow-ownership.js +195 -0
  249. package/dist/services/workflow-ownership.js.map +1 -0
  250. package/dist/services/workflow-versioning-service.d.ts +102 -0
  251. package/dist/services/workflow-versioning-service.d.ts.map +1 -0
  252. package/dist/services/workflow-versioning-service.js +264 -0
  253. package/dist/services/workflow-versioning-service.js.map +1 -0
  254. package/dist/sse-server.d.ts +8 -0
  255. package/dist/sse-server.d.ts.map +1 -0
  256. package/dist/sse-server.js +652 -0
  257. package/dist/sse-server.js.map +1 -0
  258. package/dist/types/session-restoration.d.ts +25 -0
  259. package/dist/types/session-restoration.d.ts.map +1 -0
  260. package/dist/types/session-restoration.js +3 -0
  261. package/dist/types/session-restoration.js.map +1 -0
  262. package/dist/types/sse.d.ts +42 -0
  263. package/dist/types/sse.d.ts.map +1 -0
  264. package/dist/types/sse.js +3 -0
  265. package/dist/types/sse.js.map +1 -0
  266. package/dist/types/workflow-diff.d.ts +1 -0
  267. package/dist/types/workflow-diff.d.ts.map +1 -1
  268. package/dist/types/workflow-diff.js.map +1 -1
  269. package/dist/utils/sse-session-manager.d.ts +23 -0
  270. package/dist/utils/sse-session-manager.d.ts.map +1 -0
  271. package/dist/utils/sse-session-manager.js +178 -0
  272. package/dist/utils/sse-session-manager.js.map +1 -0
  273. package/dist/utils/version-utils.d.ts +16 -0
  274. package/dist/utils/version-utils.d.ts.map +1 -0
  275. package/dist/utils/version-utils.js +129 -0
  276. package/dist/utils/version-utils.js.map +1 -0
  277. package/package.json +1 -10
@@ -0,0 +1,652 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ var __importDefault = (this && this.__importDefault) || function (mod) {
4
+ return (mod && mod.__esModule) ? mod : { "default": mod };
5
+ };
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.startSSEServer = startSSEServer;
8
+ const express_1 = __importDefault(require("express"));
9
+ const server_1 = require("./mcp/server");
10
+ const sse_session_manager_1 = require("./utils/sse-session-manager");
11
+ const logger_1 = require("./utils/logger");
12
+ const version_1 = require("./utils/version");
13
+ const tools_1 = require("./mcp/tools");
14
+ const tools_n8n_manager_1 = require("./mcp/tools-n8n-manager");
15
+ const n8n_api_1 = require("./config/n8n-api");
16
+ const http_server_1 = require("./http-server");
17
+ const types_js_1 = require("@modelcontextprotocol/sdk/types.js");
18
+ const dotenv_1 = __importDefault(require("dotenv"));
19
+ dotenv_1.default.config();
20
+ let expressServer;
21
+ let authToken = null;
22
+ let sessionManager;
23
+ let mcpServer;
24
+ function validateEnvironment() {
25
+ authToken = (0, http_server_1.loadAuthToken)();
26
+ if (!authToken || authToken.trim() === '') {
27
+ logger_1.logger.error('No authentication token found or token is empty');
28
+ console.error('ERROR: AUTH_TOKEN is required for SSE mode and cannot be empty');
29
+ console.error('Set AUTH_TOKEN environment variable or AUTH_TOKEN_FILE pointing to a file containing the token');
30
+ console.error('Generate AUTH_TOKEN with: openssl rand -base64 32');
31
+ process.exit(1);
32
+ }
33
+ authToken = authToken.trim();
34
+ if (authToken.length < 32) {
35
+ logger_1.logger.warn('AUTH_TOKEN should be at least 32 characters for security');
36
+ console.warn('WARNING: AUTH_TOKEN should be at least 32 characters for security');
37
+ }
38
+ }
39
+ async function shutdown() {
40
+ logger_1.logger.info('Shutting down SSE server...');
41
+ console.log('Shutting down SSE server...');
42
+ if (sessionManager) {
43
+ sessionManager.shutdown();
44
+ }
45
+ if (expressServer) {
46
+ expressServer.close(() => {
47
+ logger_1.logger.info('SSE server closed');
48
+ console.log('SSE server closed');
49
+ process.exit(0);
50
+ });
51
+ setTimeout(() => {
52
+ logger_1.logger.error('Forced shutdown after timeout');
53
+ process.exit(1);
54
+ }, 10000);
55
+ }
56
+ else {
57
+ process.exit(0);
58
+ }
59
+ }
60
+ async function startSSEServer() {
61
+ validateEnvironment();
62
+ const app = (0, express_1.default)();
63
+ sessionManager = new sse_session_manager_1.SSESessionManager();
64
+ mcpServer = new server_1.N8NDocumentationMCPServer();
65
+ const trustProxy = process.env.TRUST_PROXY ? Number(process.env.TRUST_PROXY) : 0;
66
+ if (trustProxy > 0) {
67
+ app.set('trust proxy', trustProxy);
68
+ logger_1.logger.info(`Trust proxy enabled with ${trustProxy} hop(s)`);
69
+ }
70
+ app.use(express_1.default.json());
71
+ app.use((req, res, next) => {
72
+ res.setHeader('X-Content-Type-Options', 'nosniff');
73
+ res.setHeader('X-Frame-Options', 'DENY');
74
+ res.setHeader('X-XSS-Protection', '1; mode=block');
75
+ res.setHeader('Strict-Transport-Security', 'max-age=31536000; includeSubDomains');
76
+ next();
77
+ });
78
+ app.use((req, res, next) => {
79
+ const allowedOrigin = process.env.CORS_ORIGIN || '*';
80
+ res.setHeader('Access-Control-Allow-Origin', allowedOrigin);
81
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
82
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, Accept, X-Client-ID, X-Auth-Token, X-API-Key');
83
+ res.setHeader('Access-Control-Max-Age', '86400');
84
+ res.setHeader('Access-Control-Allow-Credentials', 'true');
85
+ if (req.method === 'OPTIONS') {
86
+ logger_1.logger.info('OPTIONS preflight request', {
87
+ path: req.path,
88
+ origin: req.headers.origin,
89
+ headers: req.headers
90
+ });
91
+ res.sendStatus(204);
92
+ return;
93
+ }
94
+ next();
95
+ });
96
+ app.use((req, res, next) => {
97
+ const logData = {
98
+ method: req.method,
99
+ path: req.path,
100
+ url: req.url,
101
+ ip: req.ip,
102
+ userAgent: req.get('user-agent'),
103
+ contentLength: req.get('content-length'),
104
+ headers: process.env.LOG_LEVEL === 'debug' ? req.headers : undefined,
105
+ query: req.query,
106
+ isSSERequest: req.headers.accept?.includes('text/event-stream') || false
107
+ };
108
+ logger_1.logger.info(`${req.method} ${req.path}`, logData);
109
+ if (req.path.includes('/sse') || req.path === '/mcp' || req.headers.accept?.includes('text/event-stream')) {
110
+ logger_1.logger.info('SSE connection attempt detected', {
111
+ path: req.path,
112
+ acceptHeader: req.headers.accept,
113
+ authHeader: req.headers.authorization ? 'present' : 'missing'
114
+ });
115
+ }
116
+ next();
117
+ });
118
+ const authenticateRequest = (req, res, next) => {
119
+ let token = null;
120
+ let authMethod = null;
121
+ logger_1.logger.debug('Authentication attempt', {
122
+ path: req.path,
123
+ headers: Object.keys(req.headers),
124
+ hasAuthHeader: !!req.headers.authorization,
125
+ hasQuery: !!req.query.token
126
+ });
127
+ const authHeader = req.headers.authorization;
128
+ if (authHeader && authHeader.startsWith('Bearer ')) {
129
+ token = authHeader.slice(7).trim();
130
+ authMethod = 'Bearer';
131
+ logger_1.logger.debug('Using Bearer authentication');
132
+ }
133
+ if (!token) {
134
+ const customHeaderName = process.env.AUTH_HEADER_NAME || 'x-auth-token';
135
+ const customHeaderValue = req.headers[customHeaderName.toLowerCase()];
136
+ if (customHeaderValue && typeof customHeaderValue === 'string') {
137
+ token = customHeaderValue.trim();
138
+ authMethod = `Custom header (${customHeaderName})`;
139
+ logger_1.logger.debug(`Using custom header authentication: ${customHeaderName}`);
140
+ }
141
+ }
142
+ if (!token && req.query.token) {
143
+ token = req.query.token;
144
+ authMethod = 'Query parameter';
145
+ logger_1.logger.debug('Using query parameter authentication');
146
+ }
147
+ if (!token && req.headers['x-api-key']) {
148
+ token = req.headers['x-api-key'];
149
+ authMethod = 'API key header';
150
+ logger_1.logger.debug('Using API key header authentication');
151
+ }
152
+ if (!token) {
153
+ logger_1.logger.warn('Authentication failed: No token provided', {
154
+ ip: req.ip,
155
+ path: req.path,
156
+ headers: Object.keys(req.headers),
157
+ availableAuthMethods: ['Bearer', 'x-auth-token', 'query.token', 'x-api-key']
158
+ });
159
+ res.status(401).json({
160
+ error: 'Unauthorized',
161
+ message: 'No authentication token provided',
162
+ hint: 'Use Bearer token, x-auth-token header, query parameter ?token=, or x-api-key header'
163
+ });
164
+ return;
165
+ }
166
+ if (token !== authToken) {
167
+ logger_1.logger.warn('Authentication failed: Invalid token', {
168
+ ip: req.ip,
169
+ path: req.path,
170
+ authMethod: authMethod,
171
+ tokenReceived: true
172
+ });
173
+ res.status(401).json({
174
+ error: 'Unauthorized',
175
+ message: 'Invalid authentication token'
176
+ });
177
+ return;
178
+ }
179
+ logger_1.logger.debug('Authentication successful', {
180
+ path: req.path,
181
+ authMethod: authMethod
182
+ });
183
+ next();
184
+ };
185
+ app.get('/health', (req, res) => {
186
+ res.json({
187
+ status: 'ok',
188
+ mode: 'sse',
189
+ version: version_1.PROJECT_VERSION,
190
+ uptime: Math.floor(process.uptime()),
191
+ activeSessions: sessionManager.getActiveClientCount(),
192
+ memory: {
193
+ used: Math.round(process.memoryUsage().heapUsed / 1024 / 1024),
194
+ total: Math.round(process.memoryUsage().heapTotal / 1024 / 1024),
195
+ unit: 'MB'
196
+ },
197
+ timestamp: new Date().toISOString()
198
+ });
199
+ });
200
+ const handleSSE = (req, res) => {
201
+ const path = req.params.path || 'default';
202
+ logger_1.logger.info('SSE endpoint handler invoked', {
203
+ endpoint: req.path,
204
+ method: req.method,
205
+ acceptHeader: req.headers.accept,
206
+ userAgent: req.headers['user-agent'],
207
+ path: path
208
+ });
209
+ let clientId;
210
+ try {
211
+ clientId = sessionManager.registerClient(res);
212
+ }
213
+ catch (error) {
214
+ logger_1.logger.error('Failed to register SSE client:', error);
215
+ res.status(503).json({
216
+ error: 'Service Unavailable',
217
+ message: error instanceof Error ? error.message : 'Failed to establish SSE connection'
218
+ });
219
+ return;
220
+ }
221
+ logger_1.logger.info(`New SSE connection established: ${clientId} (path: ${path})`, {
222
+ totalClients: sessionManager.getActiveClientCount(),
223
+ headers: {
224
+ accept: req.headers.accept,
225
+ 'content-type': req.headers['content-type'],
226
+ 'user-agent': req.headers['user-agent']
227
+ }
228
+ });
229
+ const getStringParam = (value) => {
230
+ if (typeof value === 'string')
231
+ return value;
232
+ if (Array.isArray(value) && value.length > 0)
233
+ return String(value[0]);
234
+ return undefined;
235
+ };
236
+ const workflowContext = {
237
+ workflowId: req.headers['x-workflow-id'] || getStringParam(req.query.workflowId),
238
+ executionId: req.headers['x-execution-id'] || getStringParam(req.query.executionId),
239
+ nodeId: req.headers['x-node-id'] || getStringParam(req.query.nodeId),
240
+ nodeName: req.headers['x-node-name'] || getStringParam(req.query.nodeName),
241
+ runId: req.headers['x-run-id'] || getStringParam(req.query.runId),
242
+ };
243
+ const cleanContext = {};
244
+ for (const [key, value] of Object.entries(workflowContext)) {
245
+ if (value !== undefined) {
246
+ cleanContext[key] = value;
247
+ }
248
+ }
249
+ if (Object.keys(cleanContext).length > 0) {
250
+ sessionManager.updateWorkflowContext(clientId, cleanContext);
251
+ logger_1.logger.info(`Workflow context for client ${clientId}:`, cleanContext);
252
+ }
253
+ logger_1.logger.debug('Sending endpoint event', { clientId });
254
+ sessionManager.sendToClient(clientId, {
255
+ event: 'endpoint',
256
+ data: `/messages?session_id=${clientId}`
257
+ });
258
+ const pingInterval = setInterval(() => {
259
+ if (!sessionManager.hasClient(clientId)) {
260
+ clearInterval(pingInterval);
261
+ return;
262
+ }
263
+ sessionManager.sendPing(clientId);
264
+ }, 30000);
265
+ req.on('close', () => {
266
+ clearInterval(pingInterval);
267
+ logger_1.logger.info(`SSE connection closed: ${clientId}`, {
268
+ path: path,
269
+ remainingClients: sessionManager.getActiveClientCount() - 1
270
+ });
271
+ });
272
+ };
273
+ app.get('/sse', authenticateRequest, handleSSE);
274
+ app.get('/mcp', authenticateRequest, handleSSE);
275
+ app.get('/mcp/:path/sse', authenticateRequest, handleSSE);
276
+ const handleMessage = async (req, res) => {
277
+ const sessionId = req.query.session_id;
278
+ logger_1.logger.info('Message endpoint called', {
279
+ path: req.path,
280
+ sessionId,
281
+ headers: Object.keys(req.headers),
282
+ body: req.body
283
+ });
284
+ const clientId = sessionId;
285
+ if (!clientId || !sessionManager.hasClient(clientId)) {
286
+ res.status(400).json({
287
+ error: 'Invalid session',
288
+ message: 'Client ID not found or session expired'
289
+ });
290
+ return;
291
+ }
292
+ try {
293
+ const jsonRpcRequest = req.body;
294
+ const workflowContext = sessionManager.getWorkflowContext(clientId);
295
+ logger_1.logger.debug('Received MCP message:', {
296
+ clientId,
297
+ method: jsonRpcRequest.method,
298
+ id: jsonRpcRequest.id,
299
+ workflowContext
300
+ });
301
+ let response;
302
+ switch (jsonRpcRequest.method) {
303
+ case 'initialize':
304
+ response = {
305
+ jsonrpc: '2.0',
306
+ result: {
307
+ protocolVersion: types_js_1.DEFAULT_NEGOTIATED_PROTOCOL_VERSION,
308
+ capabilities: {
309
+ tools: {},
310
+ resources: {},
311
+ prompts: {}
312
+ },
313
+ serverInfo: {
314
+ name: 'n8n-documentation-mcp',
315
+ version: version_1.PROJECT_VERSION
316
+ }
317
+ },
318
+ id: jsonRpcRequest.id
319
+ };
320
+ break;
321
+ case 'tools/list':
322
+ const tools = [...tools_1.n8nDocumentationToolsFinal];
323
+ if ((0, n8n_api_1.isN8nApiConfigured)()) {
324
+ tools.push(...tools_n8n_manager_1.n8nManagementTools);
325
+ }
326
+ response = {
327
+ jsonrpc: '2.0',
328
+ result: {
329
+ tools
330
+ },
331
+ id: jsonRpcRequest.id
332
+ };
333
+ break;
334
+ case 'tools/call':
335
+ const toolName = jsonRpcRequest.params?.name;
336
+ const toolArgs = jsonRpcRequest.params?.arguments || {};
337
+ logger_1.logger.debug('Tool call details:', {
338
+ toolName,
339
+ toolArgs,
340
+ toolArgsType: typeof toolArgs,
341
+ toolArgsKeys: Object.keys(toolArgs),
342
+ rawParams: jsonRpcRequest.params
343
+ });
344
+ try {
345
+ const result = await mcpServer.executeTool(toolName, toolArgs);
346
+ response = {
347
+ jsonrpc: '2.0',
348
+ result: {
349
+ content: [
350
+ {
351
+ type: 'text',
352
+ text: JSON.stringify(result, null, 2)
353
+ }
354
+ ]
355
+ },
356
+ id: jsonRpcRequest.id
357
+ };
358
+ }
359
+ catch (error) {
360
+ logger_1.logger.error(`Error executing tool ${toolName}:`, error);
361
+ response = {
362
+ jsonrpc: '2.0',
363
+ error: {
364
+ code: -32603,
365
+ message: `Error executing tool ${toolName}: ${error instanceof Error ? error.message : String(error)}`
366
+ },
367
+ id: jsonRpcRequest.id
368
+ };
369
+ }
370
+ break;
371
+ case 'resources/list':
372
+ response = {
373
+ jsonrpc: '2.0',
374
+ result: {
375
+ resources: []
376
+ },
377
+ id: jsonRpcRequest.id
378
+ };
379
+ break;
380
+ case 'resources/read':
381
+ response = {
382
+ jsonrpc: '2.0',
383
+ error: {
384
+ code: -32601,
385
+ message: 'Resource reading not implemented'
386
+ },
387
+ id: jsonRpcRequest.id
388
+ };
389
+ break;
390
+ case 'prompts/list':
391
+ response = {
392
+ jsonrpc: '2.0',
393
+ result: {
394
+ prompts: []
395
+ },
396
+ id: jsonRpcRequest.id
397
+ };
398
+ break;
399
+ case 'prompts/get':
400
+ response = {
401
+ jsonrpc: '2.0',
402
+ error: {
403
+ code: -32601,
404
+ message: 'Prompt retrieval not implemented'
405
+ },
406
+ id: jsonRpcRequest.id
407
+ };
408
+ break;
409
+ default:
410
+ response = {
411
+ jsonrpc: '2.0',
412
+ error: {
413
+ code: -32601,
414
+ message: `Method not found: ${jsonRpcRequest.method}`
415
+ },
416
+ id: jsonRpcRequest.id
417
+ };
418
+ }
419
+ sessionManager.sendMCPMessage(clientId, response);
420
+ res.json({
421
+ status: 'ok',
422
+ messageId: jsonRpcRequest.id
423
+ });
424
+ }
425
+ catch (error) {
426
+ logger_1.logger.error('Error processing MCP message:', error);
427
+ res.status(500).json({
428
+ error: 'Internal server error',
429
+ message: error instanceof Error ? error.message : 'Unknown error'
430
+ });
431
+ }
432
+ };
433
+ const handleLegacyMCP = async (req, res) => {
434
+ try {
435
+ const jsonRpcRequest = req.body;
436
+ logger_1.logger.debug('Received legacy MCP request:', { method: jsonRpcRequest.method });
437
+ let response;
438
+ switch (jsonRpcRequest.method) {
439
+ case 'initialize':
440
+ response = {
441
+ jsonrpc: '2.0',
442
+ result: {
443
+ protocolVersion: types_js_1.DEFAULT_NEGOTIATED_PROTOCOL_VERSION,
444
+ capabilities: {
445
+ tools: {},
446
+ resources: {},
447
+ prompts: {}
448
+ },
449
+ serverInfo: {
450
+ name: 'n8n-documentation-mcp',
451
+ version: version_1.PROJECT_VERSION
452
+ }
453
+ },
454
+ id: jsonRpcRequest.id
455
+ };
456
+ break;
457
+ case 'tools/list':
458
+ const tools = [...tools_1.n8nDocumentationToolsFinal];
459
+ if ((0, n8n_api_1.isN8nApiConfigured)()) {
460
+ tools.push(...tools_n8n_manager_1.n8nManagementTools);
461
+ }
462
+ response = {
463
+ jsonrpc: '2.0',
464
+ result: {
465
+ tools
466
+ },
467
+ id: jsonRpcRequest.id
468
+ };
469
+ break;
470
+ case 'tools/call':
471
+ const toolName = jsonRpcRequest.params?.name;
472
+ const toolArgs = jsonRpcRequest.params?.arguments || {};
473
+ logger_1.logger.debug('Tool call details:', {
474
+ toolName,
475
+ toolArgs,
476
+ toolArgsType: typeof toolArgs,
477
+ toolArgsKeys: Object.keys(toolArgs),
478
+ rawParams: jsonRpcRequest.params
479
+ });
480
+ try {
481
+ const result = await mcpServer.executeTool(toolName, toolArgs);
482
+ response = {
483
+ jsonrpc: '2.0',
484
+ result: {
485
+ content: [
486
+ {
487
+ type: 'text',
488
+ text: JSON.stringify(result, null, 2)
489
+ }
490
+ ]
491
+ },
492
+ id: jsonRpcRequest.id
493
+ };
494
+ }
495
+ catch (error) {
496
+ logger_1.logger.error(`Error executing tool ${toolName}:`, error);
497
+ response = {
498
+ jsonrpc: '2.0',
499
+ error: {
500
+ code: -32603,
501
+ message: `Error executing tool ${toolName}: ${error instanceof Error ? error.message : String(error)}`
502
+ },
503
+ id: jsonRpcRequest.id
504
+ };
505
+ }
506
+ break;
507
+ case 'resources/list':
508
+ response = {
509
+ jsonrpc: '2.0',
510
+ result: {
511
+ resources: []
512
+ },
513
+ id: jsonRpcRequest.id
514
+ };
515
+ break;
516
+ case 'resources/read':
517
+ response = {
518
+ jsonrpc: '2.0',
519
+ error: {
520
+ code: -32601,
521
+ message: 'Resource reading not implemented'
522
+ },
523
+ id: jsonRpcRequest.id
524
+ };
525
+ break;
526
+ case 'prompts/list':
527
+ response = {
528
+ jsonrpc: '2.0',
529
+ result: {
530
+ prompts: []
531
+ },
532
+ id: jsonRpcRequest.id
533
+ };
534
+ break;
535
+ case 'prompts/get':
536
+ response = {
537
+ jsonrpc: '2.0',
538
+ error: {
539
+ code: -32601,
540
+ message: 'Prompt retrieval not implemented'
541
+ },
542
+ id: jsonRpcRequest.id
543
+ };
544
+ break;
545
+ default:
546
+ response = {
547
+ jsonrpc: '2.0',
548
+ error: {
549
+ code: -32601,
550
+ message: `Method not found: ${jsonRpcRequest.method}`
551
+ },
552
+ id: jsonRpcRequest.id
553
+ };
554
+ }
555
+ res.json(response);
556
+ }
557
+ catch (error) {
558
+ logger_1.logger.error('Legacy MCP request error:', error);
559
+ res.status(500).json({
560
+ jsonrpc: '2.0',
561
+ error: {
562
+ code: -32603,
563
+ message: 'Internal server error',
564
+ data: error instanceof Error ? error.message : undefined
565
+ },
566
+ id: null
567
+ });
568
+ }
569
+ };
570
+ app.post('/messages', authenticateRequest, handleMessage);
571
+ app.post('/mcp/message', authenticateRequest, handleMessage);
572
+ app.post('/mcp/:path/message', authenticateRequest, handleMessage);
573
+ app.post('/mcp', authenticateRequest, handleLegacyMCP);
574
+ app.post('/mcp/:path', authenticateRequest, handleLegacyMCP);
575
+ app.post('/sse', authenticateRequest, handleLegacyMCP);
576
+ app.use((req, res, next) => {
577
+ const isKnownRoute = ['/health', '/sse', '/mcp', '/mcp/message'].some(route => req.path === route || req.path.startsWith(route + '/'));
578
+ if (!isKnownRoute) {
579
+ logger_1.logger.warn('Unmatched request', {
580
+ method: req.method,
581
+ path: req.path,
582
+ url: req.url,
583
+ headers: Object.keys(req.headers),
584
+ hasAuth: !!req.headers.authorization,
585
+ ip: req.ip
586
+ });
587
+ }
588
+ next();
589
+ });
590
+ app.use((req, res) => {
591
+ res.status(404).json({
592
+ error: 'Not found',
593
+ message: `Cannot ${req.method} ${req.path}`
594
+ });
595
+ });
596
+ app.use((err, req, res, next) => {
597
+ logger_1.logger.error('Express error handler:', err);
598
+ if (!res.headersSent) {
599
+ res.status(500).json({
600
+ error: 'Internal server error',
601
+ message: process.env.NODE_ENV === 'development' ? err.message : 'An error occurred'
602
+ });
603
+ }
604
+ });
605
+ const port = parseInt(process.env.PORT || '3000');
606
+ const host = process.env.HOST || '0.0.0.0';
607
+ expressServer = app.listen(port, host, () => {
608
+ logger_1.logger.info(`n8n MCP SSE Server started`, { port, host });
609
+ console.log(`n8n MCP SSE Server running on ${host}:${port}`);
610
+ console.log(`Health check: http://localhost:${port}/health`);
611
+ console.log(`SSE endpoints:`);
612
+ console.log(` - http://localhost:${port}/sse`);
613
+ console.log(` - http://localhost:${port}/mcp`);
614
+ console.log(` - http://localhost:${port}/mcp/{path}/sse`);
615
+ console.log(`Message endpoints:`);
616
+ console.log(` - http://localhost:${port}/messages?session_id={session_id}`);
617
+ console.log(` - http://localhost:${port}/mcp/message (legacy)`);
618
+ console.log('\nPress Ctrl+C to stop the server');
619
+ });
620
+ expressServer.on('error', (error) => {
621
+ if (error.code === 'EADDRINUSE') {
622
+ logger_1.logger.error(`Port ${port} is already in use`);
623
+ console.error(`ERROR: Port ${port} is already in use`);
624
+ process.exit(1);
625
+ }
626
+ else {
627
+ logger_1.logger.error('Server error:', error);
628
+ console.error('Server error:', error);
629
+ process.exit(1);
630
+ }
631
+ });
632
+ process.on('SIGTERM', shutdown);
633
+ process.on('SIGINT', shutdown);
634
+ process.on('uncaughtException', (error) => {
635
+ logger_1.logger.error('Uncaught exception:', error);
636
+ console.error('Uncaught exception:', error);
637
+ shutdown();
638
+ });
639
+ process.on('unhandledRejection', (reason, promise) => {
640
+ logger_1.logger.error('Unhandled rejection:', reason);
641
+ console.error('Unhandled rejection at:', promise, 'reason:', reason);
642
+ shutdown();
643
+ });
644
+ }
645
+ if (require.main === module) {
646
+ startSSEServer().catch(error => {
647
+ logger_1.logger.error('Failed to start SSE server:', error);
648
+ console.error('Failed to start SSE server:', error);
649
+ process.exit(1);
650
+ });
651
+ }
652
+ //# sourceMappingURL=sse-server.js.map