@fnet/cli 0.133.0 → 0.133.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 (182) hide show
  1. package/dist/fbin/index.js +14 -1
  2. package/dist/fnet/index.0jcm9pn5.js +1 -0
  3. package/dist/fnet/index.2084z2ed.js +2 -0
  4. package/dist/fnet/index.33f1ggpr.js +1 -0
  5. package/dist/fnet/index.3exge2js.js +1 -0
  6. package/dist/fnet/index.3kfx538h.js +1 -0
  7. package/dist/fnet/index.490y87nc.js +1 -0
  8. package/dist/fnet/index.4g9yezkq.js +1 -0
  9. package/dist/fnet/index.4jkat7r4.js +1 -0
  10. package/dist/fnet/index.7crx8ky1.js +1 -0
  11. package/dist/fnet/index.7vw06nrn.js +1 -0
  12. package/dist/fnet/index.9567fa9x.js +1 -0
  13. package/dist/fnet/index.gh75wt1m.js +1 -0
  14. package/dist/fnet/index.hzsfswvp.js +1 -0
  15. package/dist/fnet/index.jgpc3grc.js +1 -0
  16. package/dist/fnet/index.js +19 -1
  17. package/dist/fnet/index.p0zb7e1b.js +1 -0
  18. package/dist/fnet/index.r19p3bpa.js +2 -0
  19. package/dist/fnet/index.r82rtnmz.js +1 -0
  20. package/dist/fnet/index.s662t98v.js +1 -0
  21. package/dist/fnet/index.w74dpnpn.js +1 -0
  22. package/dist/fnet/index.xeaw5xa9.js +1 -0
  23. package/dist/fnet/index.zm4kesg6.js +1 -0
  24. package/dist/fnode/index.05n3mvs9.js +2 -0
  25. package/dist/fnode/index.2hc9tbyx.js +1 -0
  26. package/dist/fnode/index.2pnjg6dc.js +1 -0
  27. package/dist/fnode/index.9qgtmxq3.js +2 -0
  28. package/dist/fnode/index.b1q7y05p.js +1 -0
  29. package/dist/fnode/index.bhapgrs7.js +1 -0
  30. package/dist/fnode/index.cvxrf34y.js +2 -0
  31. package/dist/fnode/index.dp9wyahp.js +1 -0
  32. package/dist/fnode/index.eqxmcpdc.js +1 -0
  33. package/dist/fnode/index.f2tb0x3t.js +1 -0
  34. package/dist/fnode/index.fbzv6wwf.js +1 -0
  35. package/dist/fnode/index.gazd9raq.js +1 -0
  36. package/dist/fnode/index.hv4s25f0.js +3 -0
  37. package/dist/fnode/index.j5z7dtsx.js +1 -0
  38. package/dist/fnode/index.js +9 -1
  39. package/dist/fnode/index.kb4e4bxf.js +1 -0
  40. package/dist/fnode/index.qn0schqp.js +1 -0
  41. package/dist/fnode/index.rht29phd.js +1 -0
  42. package/dist/fnode/index.rzsfmek6.js +3 -0
  43. package/dist/fnode/index.s0nk6cv8.js +4 -0
  44. package/dist/fnode/index.s66v6wt4.js +1 -0
  45. package/dist/fnode/index.sv7v0y60.js +1 -0
  46. package/dist/fnode/index.tgkhgnrp.js +1 -0
  47. package/dist/fnode/index.vq706f75.js +1 -0
  48. package/dist/fnode/index.y8pvdcny.js +1 -0
  49. package/dist/fnode/index.z4vz93ww.js +1 -0
  50. package/dist/frun/index.js +1 -1
  51. package/dist/fservice/index.js +18 -1
  52. package/dist/fservice/index.q01yvaz0.js +2 -0
  53. package/package.json +21 -18
  54. package/readme.md +62 -15
  55. package/template/fnet/core/object.js +10 -10
  56. package/template/fnet/node/package.json.njk +6 -3
  57. package/template/fnet/node/src/cli/index.js.njk +5 -315
  58. package/template/fnet/node/src/cli/index.js.v1.njk +318 -0
  59. package/template/fnet/node/src/cli/v2/core/args-parser.njk +10 -0
  60. package/template/fnet/node/src/cli/v2/core/imports.njk +31 -0
  61. package/template/fnet/node/src/cli/v2/core/run-wrapper.njk +25 -0
  62. package/template/fnet/node/src/cli/v2/index.js.njk +184 -0
  63. package/template/fnet/node/src/cli/v2/modes/default/extend.njk +11 -0
  64. package/template/fnet/node/src/cli/v2/modes/default/standard.njk +20 -0
  65. package/template/fnet/node/src/cli/v2/modes/http/builtin.njk +66 -0
  66. package/template/fnet/node/src/cli/v2/modes/http/imports.njk +9 -0
  67. package/template/fnet/node/src/cli/v2/modes/http/index.njk +12 -0
  68. package/template/fnet/node/src/cli/v2/modes/mcp/imports.njk +33 -0
  69. package/template/fnet/node/src/cli/v2/modes/mcp/index.njk +30 -0
  70. package/template/fnet/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
  71. package/template/fnet/node/src/cli/v2/modes/mcp/tool-handlers.njk +46 -0
  72. package/template/fnet/node/src/cli/v2/modes/mcp/transport-http.njk +222 -0
  73. package/template/fnet/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
  74. package/template/fnet/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
  75. package/template/fnet/node/src/cli/v2/modes/pipeline/index.njk +113 -0
  76. package/template/fnet/node/src/cli/v2/modes/webhook/imports.njk +9 -0
  77. package/template/fnet/node/src/cli/v2/modes/webhook/index.njk +127 -0
  78. package/template/fnet/node/src/cli/v2/modes/websocket/imports.njk +15 -0
  79. package/template/fnet/node/src/cli/v2/modes/websocket/index.njk +104 -0
  80. package/template/fnet/node/src/default/blocks/assign.js.njk +10 -48
  81. package/template/fnet/node/src/default/blocks/call.js.njk +110 -156
  82. package/template/fnet/node/src/default/blocks/for.js.njk +58 -74
  83. package/template/fnet/node/src/default/blocks/form.js.njk +21 -59
  84. package/template/fnet/node/src/default/blocks/http.js.njk +135 -0
  85. package/template/fnet/node/src/default/blocks/modules.js.njk +10 -52
  86. package/template/fnet/node/src/default/blocks/new.js.njk +40 -85
  87. package/template/fnet/node/src/default/blocks/next.js.njk +10 -32
  88. package/template/fnet/node/src/default/blocks/output.js.njk +10 -48
  89. package/template/fnet/node/src/default/blocks/parallel.js.njk +64 -0
  90. package/template/fnet/node/src/default/blocks/pipeline.js.njk +109 -0
  91. package/template/fnet/node/src/default/blocks/raise.js.njk +9 -25
  92. package/template/fnet/node/src/default/blocks/retry.js.njk +70 -0
  93. package/template/fnet/node/src/default/blocks/return.js.njk +13 -25
  94. package/template/fnet/node/src/default/blocks/schedule.js.njk +66 -0
  95. package/template/fnet/node/src/default/blocks/signal.js.njk +10 -32
  96. package/template/fnet/node/src/default/blocks/steps.js.njk +32 -48
  97. package/template/fnet/node/src/default/blocks/switch.js.njk +37 -67
  98. package/template/fnet/node/src/default/blocks/tryexcept.js.njk +58 -52
  99. package/template/fnet/node/src/default/blocks/wait.js.njk +10 -30
  100. package/template/fnet/node/src/default/input.args.js.njk +5 -2
  101. package/template/fnet/node/src/default/macros/block-body-header.js.njk +1 -1
  102. package/template/fnet/node/src/default/macros/block-header.js.njk +0 -3
  103. package/template/fnet/node/src/default/macros/block-next.js.njk +1 -1
  104. package/template/fnet/node/src/default/macros/block-run-footer.js.njk +1 -1
  105. package/template/fnet/node/src/default/macros/block-run-header.js.njk +14 -2
  106. package/template/fnet/node/src/default/macros/page.js.njk +1 -1
  107. package/template/fnet/node/src/default/types/block.js.njk +133 -0
  108. package/template/fnet/node/src/default/workflow.js.njk +8 -6
  109. package/template/fnode/node/package.json.njk +5 -4
  110. package/template/fnode/node/src/cli/index.js.njk +3 -397
  111. package/template/fnode/node/src/cli/index.js.v1.njk +464 -0
  112. package/template/fnode/node/src/cli/v2/core/args-parser.njk +10 -0
  113. package/template/fnode/node/src/cli/v2/core/imports.njk +29 -0
  114. package/template/fnode/node/src/cli/v2/core/run-wrapper.njk +25 -0
  115. package/template/fnode/node/src/cli/v2/index.js.njk +184 -0
  116. package/template/fnode/node/src/cli/v2/modes/default/extend.njk +11 -0
  117. package/template/fnode/node/src/cli/v2/modes/default/standard.njk +19 -0
  118. package/template/fnode/node/src/cli/v2/modes/http/builtin.njk +61 -0
  119. package/template/fnode/node/src/cli/v2/modes/http/imports.njk +9 -0
  120. package/template/fnode/node/src/cli/v2/modes/http/index.njk +12 -0
  121. package/template/fnode/node/src/cli/v2/modes/mcp/imports.njk +33 -0
  122. package/template/fnode/node/src/cli/v2/modes/mcp/index.njk +30 -0
  123. package/template/fnode/node/src/cli/v2/modes/mcp/server-setup.njk +15 -0
  124. package/template/fnode/node/src/cli/v2/modes/mcp/tool-handlers.njk +41 -0
  125. package/template/fnode/node/src/cli/v2/modes/mcp/transport-http.njk +212 -0
  126. package/template/fnode/node/src/cli/v2/modes/mcp/transport-stdio.njk +9 -0
  127. package/template/fnode/node/src/cli/v2/modes/pipeline/imports.njk +9 -0
  128. package/template/fnode/node/src/cli/v2/modes/pipeline/index.njk +103 -0
  129. package/template/fnode/node/src/cli/v2/modes/webhook/imports.njk +9 -0
  130. package/template/fnode/node/src/cli/v2/modes/webhook/index.njk +122 -0
  131. package/template/fnode/node/src/cli/v2/modes/websocket/imports.njk +15 -0
  132. package/template/fnode/node/src/cli/v2/modes/websocket/index.njk +99 -0
  133. package/template/fnode/node/src/default/input.args.js.njk +6 -2
  134. package/dist/fnet/index.-SGbq2cI.js +0 -1
  135. package/dist/fnet/index.B5XE4ChJ.js +0 -1
  136. package/dist/fnet/index.Bft2w7m3.js +0 -1
  137. package/dist/fnet/index.BuYxdKtK.js +0 -1
  138. package/dist/fnet/index.C0YpfQ5j.js +0 -1
  139. package/dist/fnet/index.C2S9JYhS.js +0 -1
  140. package/dist/fnet/index.C7saWH6d.js +0 -1
  141. package/dist/fnet/index.CDct_kkF.js +0 -1
  142. package/dist/fnet/index.CMC8mlye.js +0 -1
  143. package/dist/fnet/index.CmMM-Ek9.js +0 -1
  144. package/dist/fnet/index.CuMyez3E.js +0 -1
  145. package/dist/fnet/index.CzAV0S36.js +0 -1
  146. package/dist/fnet/index.D2N9YZmA.js +0 -1
  147. package/dist/fnet/index.D3p7pncT.js +0 -1
  148. package/dist/fnet/index.DG8TqL-1.js +0 -1
  149. package/dist/fnet/index.DI3yyTtl.js +0 -1
  150. package/dist/fnet/index.DOYkqsYT.js +0 -1
  151. package/dist/fnet/index.DWpw12No.js +0 -1
  152. package/dist/fnet/index.DrwlOzAe.js +0 -1
  153. package/dist/fnet/index.Q-CYRcna.js +0 -1
  154. package/dist/fnet/index.W6RYgypK.js +0 -1
  155. package/dist/fnet/index.xd8c7XMr.js +0 -1
  156. package/dist/fnode/index.-SGbq2cI.js +0 -1
  157. package/dist/fnode/index.B5XE4ChJ.js +0 -1
  158. package/dist/fnode/index.B8gal9up.js +0 -1
  159. package/dist/fnode/index.BU1440aO.js +0 -1
  160. package/dist/fnode/index.BcGYSPne.js +0 -1
  161. package/dist/fnode/index.Bft2w7m3.js +0 -1
  162. package/dist/fnode/index.BuYxdKtK.js +0 -1
  163. package/dist/fnode/index.C2S9JYhS.js +0 -1
  164. package/dist/fnode/index.C7saWH6d.js +0 -1
  165. package/dist/fnode/index.CDct_kkF.js +0 -1
  166. package/dist/fnode/index.CMC8mlye.js +0 -1
  167. package/dist/fnode/index.CmMM-Ek9.js +0 -1
  168. package/dist/fnode/index.CuMyez3E.js +0 -1
  169. package/dist/fnode/index.CzAV0S36.js +0 -1
  170. package/dist/fnode/index.D2N9YZmA.js +0 -1
  171. package/dist/fnode/index.D3p7pncT.js +0 -1
  172. package/dist/fnode/index.DG8TqL-1.js +0 -1
  173. package/dist/fnode/index.DI3yyTtl.js +0 -1
  174. package/dist/fnode/index.DWpw12No.js +0 -1
  175. package/dist/fnode/index.DrwlOzAe.js +0 -1
  176. package/dist/fnode/index.N_a5FdgA.js +0 -1
  177. package/dist/fnode/index.Q-CYRcna.js +0 -1
  178. package/dist/fnode/index.UNoFg95r.js +0 -1
  179. package/dist/fnode/index.W6RYgypK.js +0 -1
  180. package/dist/fnode/index.xd8c7XMr.js +0 -1
  181. package/template/fnet/core/print.js +0 -1
  182. package/template/fnet/node/src/default/macros/workflow-header.js.njk +0 -7
@@ -0,0 +1,184 @@
1
+ {# ============================================================================
2
+ CLI TEMPLATE V2 - MODULAR ARCHITECTURE
3
+ ============================================================================
4
+
5
+ This template uses a modular, registry-based approach for maximum
6
+ extensibility. New modes, transports, and output formats can be added
7
+ without modifying the core template structure.
8
+
9
+ Architecture:
10
+ - core/ : Base imports, argument parsing, error handling
11
+ - modes/ : CLI execution modes (default, mcp, http, pipeline, etc.)
12
+ - output/ : Output formatters (json, yaml, table, etc.)
13
+
14
+ Each mode is self-contained and can be enabled/disabled via feature flags.
15
+
16
+ Supports:
17
+ - ESM and CJS formats
18
+ - Standard and Extend modes
19
+ - Multiple CLI modes (default, mcp, http)
20
+
21
+ ============================================================================ #}
22
+
23
+ {% if atom.doc.features.cli.enabled===true %}
24
+
25
+ {# --------------------------------------------------------------------------
26
+ CORE IMPORTS
27
+ -------------------------------------------------------------------------- #}
28
+ {% include "./core/imports.njk" %}
29
+
30
+ {# --------------------------------------------------------------------------
31
+ SHARED IMPORTS
32
+ --------------------------------------------------------------------------
33
+ Shared dependencies used by multiple modes
34
+ Prevents duplicate imports when multiple modes are enabled
35
+ -------------------------------------------------------------------------- #}
36
+ {% if atom.doc.features.cli.http.enabled===true or atom.doc.features.cli.webhook.enabled===true %}
37
+ // Shared: http module (used by HTTP and Webhook modes)
38
+ {% if atom.doc.features.project.format==='esm' %}
39
+ import http from 'http';
40
+ {% elif atom.doc.features.project.format==='cjs' %}
41
+ const http = require('http');
42
+ {% endif %}
43
+ {% endif %}
44
+
45
+ {% if atom.doc.features.cli.mcp.enabled === true or atom.doc.features.cli.webhook.enabled===true %}
46
+ // Shared: crypto module (used by MCP and Webhook modes)
47
+ {% if atom.doc.features.project.format==='esm' %}
48
+ import crypto from 'crypto';
49
+ {% elif atom.doc.features.project.format==='cjs' %}
50
+ const crypto = require('crypto');
51
+ {% endif %}
52
+ {% endif %}
53
+
54
+ {# --------------------------------------------------------------------------
55
+ MODE-SPECIFIC IMPORTS
56
+ --------------------------------------------------------------------------
57
+ Import dependencies for ALL enabled CLI modes
58
+ Multiple modes can be enabled simultaneously
59
+ -------------------------------------------------------------------------- #}
60
+ {% if atom.doc.features.cli.mcp.enabled === true %}
61
+ {% include "./modes/mcp/imports.njk" %}
62
+ {% endif %}
63
+
64
+ {% if atom.doc.features.cli.http.enabled===true %}
65
+ {% include "./modes/http/imports.njk" %}
66
+ {% endif %}
67
+
68
+ {% if atom.doc.features.cli.pipeline.enabled===true %}
69
+ {% include "./modes/pipeline/imports.njk" %}
70
+ {% endif %}
71
+
72
+ {% if atom.doc.features.cli.websocket.enabled===true %}
73
+ {% include "./modes/websocket/imports.njk" %}
74
+ {% endif %}
75
+
76
+ {% if atom.doc.features.cli.webhook.enabled===true %}
77
+ {% include "./modes/webhook/imports.njk" %}
78
+ {% endif %}
79
+
80
+ {# --------------------------------------------------------------------------
81
+ ARGUMENT PARSER
82
+ -------------------------------------------------------------------------- #}
83
+ {% include "./core/args-parser.njk" %}
84
+
85
+ {# --------------------------------------------------------------------------
86
+ MAIN RUN FUNCTION
87
+ --------------------------------------------------------------------------
88
+ Mode registry: Each mode is self-contained and handles its own logic
89
+ -------------------------------------------------------------------------- #}
90
+ const run = async () => {
91
+ const args = parseArgs();
92
+ const cliMode = args['cli-mode'] || args.cli_mode || 'default';
93
+
94
+ {# --------------------------------------------------------------------------
95
+ DEFAULT MODE
96
+ --------------------------------------------------------------------------
97
+ Standard or extended mode based on CLI configuration
98
+ -------------------------------------------------------------------------- #}
99
+ {% if atom.doc.features.cli.extend===true %}
100
+ {% include "./modes/default/extend.njk" %}
101
+ {% else %}
102
+ {% include "./modes/default/standard.njk" %}
103
+ {% endif %}
104
+
105
+ {# --------------------------------------------------------------------------
106
+ MCP MODE
107
+ --------------------------------------------------------------------------
108
+ Model Context Protocol server with multiple transport options
109
+ -------------------------------------------------------------------------- #}
110
+ {% if atom.doc.features.cli.mcp.enabled === true %}
111
+ {% include "./modes/mcp/index.njk" %}
112
+ {% endif %}
113
+
114
+ {# --------------------------------------------------------------------------
115
+ HTTP MODE
116
+ --------------------------------------------------------------------------
117
+ REST API server using built-in http module
118
+ -------------------------------------------------------------------------- #}
119
+ {% if atom.doc.features.cli.http.enabled===true %}
120
+ {% include "./modes/http/index.njk" %}
121
+ {% endif %}
122
+
123
+ {# --------------------------------------------------------------------------
124
+ PIPELINE MODE
125
+ --------------------------------------------------------------------------
126
+ Unix pipeline integration via stdin/stdout
127
+ -------------------------------------------------------------------------- #}
128
+ {% if atom.doc.features.cli.pipeline.enabled===true %}
129
+ {% include "./modes/pipeline/index.njk" %}
130
+ {% endif %}
131
+
132
+ {# --------------------------------------------------------------------------
133
+ WEBSOCKET MODE
134
+ --------------------------------------------------------------------------
135
+ Real-time bidirectional communication
136
+ -------------------------------------------------------------------------- #}
137
+ {% if atom.doc.features.cli.websocket.enabled===true %}
138
+ {% include "./modes/websocket/index.njk" %}
139
+ {% endif %}
140
+
141
+ {# --------------------------------------------------------------------------
142
+ WEBHOOK MODE
143
+ --------------------------------------------------------------------------
144
+ Event-driven HTTP with HMAC signature verification
145
+ -------------------------------------------------------------------------- #}
146
+ {% if atom.doc.features.cli.webhook.enabled===true %}
147
+ {% include "./modes/webhook/index.njk" %}
148
+ {% endif %}
149
+
150
+ {# --------------------------------------------------------------------------
151
+ FUTURE MODES
152
+ --------------------------------------------------------------------------
153
+ Add new modes here by simply including their index.njk
154
+
155
+ Examples:
156
+ - gRPC mode for high-performance RPC
157
+ - GraphQL mode for flexible APIs
158
+ - SSE mode for server-sent events
159
+ -------------------------------------------------------------------------- #}
160
+
161
+ {# {% if atom.doc.features.cli.webhook.enabled===true %}
162
+ {% include "./modes/webhook/index.njk" %}
163
+ {% endif %} #}
164
+
165
+ {# {% if atom.doc.features.cli.grpc.enabled===true %}
166
+ {% include "./modes/grpc/index.njk" %}
167
+ {% endif %} #}
168
+
169
+ {# --------------------------------------------------------------------------
170
+ UNKNOWN MODE HANDLER
171
+ -------------------------------------------------------------------------- #}
172
+ console.error(`Unknown CLI mode: ${cliMode}`);
173
+ console.error(`Available modes: default{% if atom.doc.features.cli.mcp.enabled === true %}, mcp{% endif %}{% if atom.doc.features.cli.http.enabled===true %}, http{% endif %}{% if atom.doc.features.cli.pipeline.enabled===true %}, pipeline{% endif %}{% if atom.doc.features.cli.websocket.enabled===true %}, websocket{% endif %}{% if atom.doc.features.cli.webhook.enabled===true %}, webhook{% endif %}`);
174
+ process.exit(1);
175
+ };
176
+
177
+ {# --------------------------------------------------------------------------
178
+ ERROR HANDLER & RUN
179
+ -------------------------------------------------------------------------- #}
180
+ {% include "./core/run-wrapper.njk" %}
181
+
182
+ {% endif %}
183
+ {# End of cli.enabled check #}
184
+
@@ -0,0 +1,11 @@
1
+ {# ============================================================================
2
+ DEFAULT MODE - EXTEND
3
+ ============================================================================
4
+ Extended CLI mode that returns result directly (for CLI wrapper usage)
5
+ ============================================================================ #}
6
+
7
+ if (cliMode === 'default') {
8
+ // Default mode code
9
+ return await Node(await argv());
10
+ }
11
+
@@ -0,0 +1,19 @@
1
+ {# ============================================================================
2
+ DEFAULT MODE - STANDARD
3
+ ============================================================================
4
+ Standard CLI mode that executes the Node function and prints result
5
+ ============================================================================ #}
6
+
7
+ if (cliMode === 'default') {
8
+ // Default mode code
9
+ const result = await Node(await argv());
10
+
11
+ if (typeof result !== 'undefined') {
12
+ const stdout_format = args['stdout-format'] || args.stdout_format || null;
13
+
14
+ if (stdout_format === 'json') console.log(JSON.stringify(result, null, 2));
15
+ else console.log(result);
16
+ }
17
+ return;
18
+ }
19
+
@@ -0,0 +1,61 @@
1
+ {# ============================================================================
2
+ HTTP MODE - BUILT-IN (Native Node.js HTTP)
3
+ ============================================================================
4
+ Simple REST API server using Node.js built-in http module
5
+ No external dependencies required
6
+ ============================================================================ #}
7
+
8
+ const server = http.createServer(async (req, res) => {
9
+ // CORS headers
10
+ res.setHeader('Access-Control-Allow-Origin', '*');
11
+ res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
12
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
13
+
14
+ // Handle OPTIONS preflight
15
+ if (req.method === 'OPTIONS') {
16
+ res.writeHead(200);
17
+ res.end();
18
+ return;
19
+ }
20
+
21
+ // Only accept POST requests
22
+ if (req.method !== 'POST') {
23
+ res.writeHead(405, { 'Content-Type': 'application/json' });
24
+ res.end(JSON.stringify({ error: 'Method not allowed' }));
25
+ return;
26
+ }
27
+
28
+ // Check path
29
+ const path = '/{{atom.doc.features.cli.http.path or atom.doc.name}}';
30
+ if (req.url !== path) {
31
+ res.writeHead(404, { 'Content-Type': 'application/json' });
32
+ res.end(JSON.stringify({ error: 'Not found' }));
33
+ return;
34
+ }
35
+
36
+ // Parse request body
37
+ let body = '';
38
+ req.on('data', chunk => {
39
+ body += chunk.toString();
40
+ });
41
+
42
+ req.on('end', async () => {
43
+ try {
44
+ const data = JSON.parse(body);
45
+ const result = await Node(data);
46
+
47
+ res.writeHead(200, { 'Content-Type': 'application/json' });
48
+ res.end(JSON.stringify(result));
49
+ } catch (error) {
50
+ res.writeHead(500, { 'Content-Type': 'application/json' });
51
+ res.end(JSON.stringify({ error: error.message }));
52
+ }
53
+ });
54
+ });
55
+
56
+ const port = args['cli-port'] || args.cli_port || 3000;
57
+ server.listen(port, () => {
58
+ console.log(`HTTP server started on port ${port} (native http)`);
59
+ });
60
+ return;
61
+
@@ -0,0 +1,9 @@
1
+ {# ============================================================================
2
+ HTTP MODE - IMPORTS
3
+ ============================================================================
4
+ No mode-specific imports needed
5
+ http module is imported in shared imports section
6
+ ============================================================================ #}
7
+
8
+ {# http module imported in shared section #}
9
+
@@ -0,0 +1,12 @@
1
+ {# ============================================================================
2
+ HTTP MODE - MAIN
3
+ ============================================================================
4
+ HTTP REST API mode using Node.js built-in http module
5
+ Zero dependencies, simple and fast
6
+ ============================================================================ #}
7
+
8
+ if (cliMode === 'http') {
9
+ // HTTP mode code
10
+ {% include "./builtin.njk" %}
11
+ }
12
+
@@ -0,0 +1,33 @@
1
+ {# ============================================================================
2
+ MCP MODE - IMPORTS
3
+ ============================================================================
4
+ MCP SDK dependencies for Model Context Protocol support
5
+ Supports both ESM and CJS formats
6
+ ============================================================================ #}
7
+
8
+ {% if atom.doc.features.project.format==='esm' %}
9
+ {# ESM Format #}
10
+ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
11
+ import { ListToolsRequestSchema, CallToolRequestSchema } from "@modelcontextprotocol/sdk/types.js";
12
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
13
+ import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js";
14
+ import express from "express";
15
+ {% if atom.doc.features.cli.mcp.ws===true %}
16
+ import expressWs from "express-ws";
17
+ {% endif %}
18
+ {# crypto imported in shared section #}
19
+
20
+ {% elif atom.doc.features.project.format==='cjs' %}
21
+ {# CJS Format #}
22
+ const { Server } = require("@modelcontextprotocol/sdk/server/index.js");
23
+ const { ListToolsRequestSchema, CallToolRequestSchema } = require("@modelcontextprotocol/sdk/types.js");
24
+ const { StdioServerTransport } = require("@modelcontextprotocol/sdk/server/stdio.js");
25
+ const { StreamableHTTPServerTransport } = require("@modelcontextprotocol/sdk/server/streamableHttp.js");
26
+ const express = require("express");
27
+ {% if atom.doc.features.cli.mcp.ws===true %}
28
+ const expressWs = require("express-ws");
29
+ {% endif %}
30
+ {# crypto imported in shared section #}
31
+
32
+ {% endif %}
33
+
@@ -0,0 +1,30 @@
1
+ {# ============================================================================
2
+ MCP MODE - MAIN
3
+ ============================================================================
4
+ Model Context Protocol mode orchestrator
5
+ Supports multiple transports: STDIO, HTTP (future: WebSocket, SSE, gRPC)
6
+ ============================================================================ #}
7
+
8
+ if (cliMode === 'mcp') {
9
+ // MCP mode code
10
+ {% include "./server-setup.njk" %}
11
+ {% include "./tool-handlers.njk" %}
12
+
13
+ // Get transport type from arguments
14
+ const transportType = args['mcp-transport'] || args.mcp_transport || 'stdio';
15
+ let transport;
16
+
17
+ if (transportType === 'stdio') {
18
+ {% include "./transport-stdio.njk" %}
19
+ } else if (transportType === 'http') {
20
+ {% include "./transport-http.njk" %}
21
+ } else {
22
+ console.error(`Unknown MCP transport type: ${transportType}`);
23
+ console.error(`Supported types: stdio, http`);
24
+ process.exit(1);
25
+ }
26
+
27
+ await server.connect(transport);
28
+ return;
29
+ }
30
+
@@ -0,0 +1,15 @@
1
+ {# ============================================================================
2
+ MCP MODE - SERVER SETUP
3
+ ============================================================================
4
+ Initialize MCP server with capabilities
5
+ ============================================================================ #}
6
+
7
+ const server = new Server({
8
+ name: "{{atom.doc.features.cli.mcp.name or atom.doc.name}}",
9
+ version: "{{atom.doc.version or '0.0.1'}}"
10
+ }, {
11
+ capabilities: {
12
+ tools: {}
13
+ }
14
+ });
15
+
@@ -0,0 +1,41 @@
1
+ {# ============================================================================
2
+ MCP MODE - TOOL HANDLERS
3
+ ============================================================================
4
+ Register MCP tool handlers for listing and executing tools
5
+ ============================================================================ #}
6
+
7
+ // Define available tools
8
+ server.setRequestHandler(ListToolsRequestSchema, async () => {
9
+ return {
10
+ tools: [{
11
+ name: "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}",
12
+ description: `{{atom.doc.features.cli.mcp.tool.description or atom.doc.description}}`,
13
+ inputSchema: inputSchema
14
+ }]
15
+ };
16
+ });
17
+
18
+ // Handle tool execution
19
+ server.setRequestHandler(CallToolRequestSchema, async (request) => {
20
+ if (request.params.name === "{{atom.doc.features.cli.mcp.tool.name or atom.doc.name}}") {
21
+ try {
22
+ const result = await Node(request.params.arguments);
23
+ return {
24
+ content: [{
25
+ type: "text",
26
+ text: JSON.stringify(result)
27
+ }]
28
+ };
29
+ } catch (error) {
30
+ return {
31
+ content: [{
32
+ type: "text",
33
+ text: `Error: ${error.message}`
34
+ }],
35
+ isError: true
36
+ };
37
+ }
38
+ }
39
+ throw new Error("Tool not found");
40
+ });
41
+
@@ -0,0 +1,212 @@
1
+ {# ============================================================================
2
+ MCP MODE - HTTP TRANSPORT
3
+ ============================================================================
4
+ Streamable HTTP transport for MCP protocol with session management
5
+ Official transport as of MCP 2025-03-26
6
+ ============================================================================ #}
7
+
8
+ // Use Streamable HTTP transport (official transport as of MCP 2025-03-26)
9
+ const app = express();
10
+ {% if atom.doc.features.cli.mcp.ws===true %}
11
+ // Enable WebSocket support
12
+ expressWs(app);
13
+ {% endif %}
14
+ app.use(express.json());
15
+
16
+ const port = args['cli-port'] || args.cli_port || 3000;
17
+ const host = args['cli-host'] || args.cli_host || '0.0.0.0';
18
+ const basePath = '{{atom.doc.features.cli.mcp.path or 'mcp'}}';
19
+ const mcpEndpoint = `/${basePath}`; // MCP protocol endpoint
20
+ const verbose = args['cli-verbose'] || args.cli_verbose || false;
21
+
22
+ // Optional endpoints (enabled via config)
23
+ const httpEnabled = {{atom.doc.features.cli.mcp.http or false}};
24
+ const wsEnabled = {{atom.doc.features.cli.mcp.ws or false}};
25
+ const httpEndpoint = `/${basePath}/input`; // HTTP input endpoint
26
+ const wsEndpoint = `/${basePath}/ws`; // WebSocket endpoint
27
+
28
+ // Verbose logging helper
29
+ const log = (...args) => {
30
+ if (verbose) {
31
+ console.log('[MCP]', new Date().toISOString(), ...args);
32
+ }
33
+ };
34
+
35
+ // Map to store transports by session ID
36
+ const transports = {};
37
+
38
+ // Handle POST requests for client-to-server communication
39
+ app.post(mcpEndpoint, async (req, res) => {
40
+ // Check for existing session ID
41
+ const sessionId = req.get('Mcp-Session-Id');
42
+
43
+ log('POST request received');
44
+ log('Session ID:', sessionId || 'none');
45
+ log('Request body:', JSON.stringify(req.body, null, 2));
46
+
47
+ let transport;
48
+
49
+ if (sessionId && transports[sessionId]) {
50
+ // Reuse existing transport
51
+ log('Reusing existing transport for session:', sessionId);
52
+ transport = transports[sessionId];
53
+ } else if (!sessionId && req.body && (req.body.method === 'initialize' ||
54
+ (Array.isArray(req.body) && req.body.some(item => item.method === 'initialize')))) {
55
+ // New initialization request
56
+ log('Creating new transport for initialization');
57
+ transport = new StreamableHTTPServerTransport({
58
+ sessionIdGenerator: () => {
59
+ // Generate cryptographically secure session ID
60
+ return crypto.randomBytes(16).toString('hex');
61
+ },
62
+ onsessioninitialized: (sessionId) => {
63
+ // Store the transport by session ID
64
+ log('Session initialized:', sessionId);
65
+ transports[sessionId] = transport;
66
+ }
67
+ });
68
+
69
+ // Clean up transport when closed
70
+ transport.onclose = () => {
71
+ if (transport.sessionId) {
72
+ log('Transport closed, cleaning up session:', transport.sessionId);
73
+ delete transports[transport.sessionId];
74
+ }
75
+ };
76
+
77
+ // Connect to the MCP server
78
+ await server.connect(transport);
79
+ log('Server connected to transport');
80
+ } else {
81
+ // Invalid request
82
+ log('Invalid request - no valid session ID');
83
+ return res.status(400).json({
84
+ jsonrpc: '2.0',
85
+ error: {
86
+ code: -32000,
87
+ message: 'Bad Request: No valid session ID provided'
88
+ },
89
+ id: null
90
+ });
91
+ }
92
+
93
+ // Handle the request
94
+ log('Handling request with transport');
95
+ await transport.handleRequest(req, res, req.body);
96
+ });
97
+
98
+ // Reusable handler for GET and DELETE requests
99
+ const handleSessionRequest = async (req, res) => {
100
+ const sessionId = req.get('Mcp-Session-Id');
101
+ log(`${req.method} request received for session:`, sessionId || 'none');
102
+
103
+ if (!sessionId || !transports[sessionId]) {
104
+ log('Invalid or missing session ID');
105
+ return res.status(400).send('Invalid or missing session ID');
106
+ }
107
+
108
+ const transport = transports[sessionId];
109
+ log('Handling request with existing transport');
110
+ await transport.handleRequest(req, res);
111
+ };
112
+
113
+ // Handle GET requests for server-to-client notifications via SSE
114
+ app.get(mcpEndpoint, handleSessionRequest);
115
+
116
+ // Handle DELETE requests for session termination
117
+ app.delete(mcpEndpoint, handleSessionRequest);
118
+
119
+ {% if atom.doc.features.cli.mcp.http===true %}
120
+ // HTTP input endpoint (enabled via config: cli.mcp.http: true)
121
+ app.post(httpEndpoint, async (req, res) => {
122
+ log('HTTP input request received');
123
+ log('Request body:', JSON.stringify(req.body, null, 2));
124
+
125
+ try {
126
+ // Call the Node function directly with the request body
127
+ const result = await Node(req.body);
128
+
129
+ log('HTTP input processed successfully');
130
+ log('Result:', JSON.stringify(result, null, 2));
131
+
132
+ // Return the result as JSON
133
+ res.json(result);
134
+ } catch (error) {
135
+ log('HTTP input processing error:', error.message);
136
+
137
+ // Return error response
138
+ res.status(500).json({
139
+ error: error.message,
140
+ stack: verbose ? error.stack : undefined
141
+ });
142
+ }
143
+ });
144
+ {% endif %}
145
+
146
+ {% if atom.doc.features.cli.mcp.ws===true %}
147
+ // WebSocket endpoint (enabled via config: cli.mcp.ws: true)
148
+ // Map to store WebSocket clients
149
+ const wsClients = new Set();
150
+
151
+ app.ws(wsEndpoint, (ws, req) => {
152
+ log('WebSocket connection established');
153
+ wsClients.add(ws);
154
+
155
+ // Handle incoming messages
156
+ ws.on('message', async (message) => {
157
+ log('WebSocket message received:', message);
158
+
159
+ try {
160
+ // Parse JSON message
161
+ const data = JSON.parse(message);
162
+
163
+ // Call the Node function
164
+ const result = await Node(data);
165
+
166
+ log('WebSocket message processed successfully');
167
+ log('Result:', JSON.stringify(result, null, 2));
168
+
169
+ // Send result back to client
170
+ ws.send(JSON.stringify(result));
171
+ } catch (error) {
172
+ log('WebSocket message processing error:', error.message);
173
+
174
+ // Send error response
175
+ ws.send(JSON.stringify({
176
+ error: error.message,
177
+ stack: verbose ? error.stack : undefined
178
+ }));
179
+ }
180
+ });
181
+
182
+ // Handle connection close
183
+ ws.on('close', () => {
184
+ log('WebSocket connection closed');
185
+ wsClients.delete(ws);
186
+ });
187
+
188
+ // Handle errors
189
+ ws.on('error', (error) => {
190
+ log('WebSocket error:', error.message);
191
+ wsClients.delete(ws);
192
+ });
193
+ });
194
+ {% endif %}
195
+
196
+ app.listen(port, host, () => {
197
+ console.log(`MCP server started with Streamable HTTP transport`);
198
+ console.log(`MCP endpoint: http://${host}:${port}${mcpEndpoint}`);
199
+ {% if atom.doc.features.cli.mcp.http===true %}
200
+ console.log(`HTTP endpoint: http://${host}:${port}${httpEndpoint}`);
201
+ {% endif %}
202
+ {% if atom.doc.features.cli.mcp.ws===true %}
203
+ console.log(`WebSocket endpoint: ws://${host}:${port}${wsEndpoint}`);
204
+ {% endif %}
205
+ console.log(`Listening on ${host}:${port}`);
206
+ if (verbose) {
207
+ console.log(`Verbose logging enabled`);
208
+ }
209
+ });
210
+
211
+ return;
212
+
@@ -0,0 +1,9 @@
1
+ {# ============================================================================
2
+ MCP MODE - STDIO TRANSPORT
3
+ ============================================================================
4
+ Standard input/output transport for MCP protocol
5
+ ============================================================================ #}
6
+
7
+ // Use stdio transport
8
+ transport = new StdioServerTransport();
9
+
@@ -0,0 +1,9 @@
1
+ {# ============================================================================
2
+ PIPELINE MODE - IMPORTS
3
+ ============================================================================
4
+ No external dependencies needed - uses native Node.js streams
5
+ stdin/stdout are available globally
6
+ ============================================================================ #}
7
+
8
+ {# No imports needed for pipeline mode - stdin/stdout are native #}
9
+