frontmcp 0.12.2 → 1.0.0-beta.2

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 (264) hide show
  1. package/README.md +1 -1
  2. package/package.json +6 -5
  3. package/src/commands/build/bundler.js +1 -1
  4. package/src/commands/build/bundler.js.map +1 -1
  5. package/src/commands/build/exec/cli-runtime/cli-bundler.d.ts +17 -0
  6. package/src/commands/build/exec/cli-runtime/cli-bundler.js +75 -0
  7. package/src/commands/build/exec/cli-runtime/cli-bundler.js.map +1 -0
  8. package/src/commands/build/exec/cli-runtime/credential-store.d.ts +22 -0
  9. package/src/commands/build/exec/cli-runtime/credential-store.js +140 -0
  10. package/src/commands/build/exec/cli-runtime/credential-store.js.map +1 -0
  11. package/src/commands/build/exec/cli-runtime/daemon-client.d.ts +16 -0
  12. package/src/commands/build/exec/cli-runtime/daemon-client.js +169 -0
  13. package/src/commands/build/exec/cli-runtime/daemon-client.js.map +1 -0
  14. package/src/commands/build/exec/cli-runtime/generate-cli-entry.d.ts +37 -0
  15. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +1287 -0
  16. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -0
  17. package/src/commands/build/exec/cli-runtime/index.d.ts +9 -0
  18. package/src/commands/build/exec/cli-runtime/index.js +32 -0
  19. package/src/commands/build/exec/cli-runtime/index.js.map +1 -0
  20. package/src/commands/build/exec/cli-runtime/oauth-helper.d.ts +9 -0
  21. package/src/commands/build/exec/cli-runtime/oauth-helper.js +224 -0
  22. package/src/commands/build/exec/cli-runtime/oauth-helper.js.map +1 -0
  23. package/src/commands/build/exec/cli-runtime/output-formatter.d.ts +46 -0
  24. package/src/commands/build/exec/cli-runtime/output-formatter.js +168 -0
  25. package/src/commands/build/exec/cli-runtime/output-formatter.js.map +1 -0
  26. package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +57 -0
  27. package/src/commands/build/exec/cli-runtime/schema-extractor.js +129 -0
  28. package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -0
  29. package/src/commands/build/exec/cli-runtime/schema-to-commander.d.ts +38 -0
  30. package/src/commands/build/exec/cli-runtime/schema-to-commander.js +172 -0
  31. package/src/commands/build/exec/cli-runtime/schema-to-commander.js.map +1 -0
  32. package/src/commands/build/exec/cli-runtime/session-manager.d.ts +16 -0
  33. package/src/commands/build/exec/cli-runtime/session-manager.js +122 -0
  34. package/src/commands/build/exec/cli-runtime/session-manager.js.map +1 -0
  35. package/src/commands/build/exec/config.d.ts +25 -0
  36. package/src/commands/build/exec/config.js +0 -1
  37. package/src/commands/build/exec/config.js.map +1 -1
  38. package/src/commands/build/exec/esbuild-bundler.d.ts +4 -1
  39. package/src/commands/build/exec/esbuild-bundler.js +28 -9
  40. package/src/commands/build/exec/esbuild-bundler.js.map +1 -1
  41. package/src/commands/build/exec/index.d.ts +7 -2
  42. package/src/commands/build/exec/index.js +159 -9
  43. package/src/commands/build/exec/index.js.map +1 -1
  44. package/src/commands/build/exec/manifest.d.ts +14 -0
  45. package/src/commands/build/exec/manifest.js.map +1 -1
  46. package/src/commands/build/exec/runner-script.d.ts +1 -1
  47. package/src/commands/build/exec/runner-script.js +48 -5
  48. package/src/commands/build/exec/runner-script.js.map +1 -1
  49. package/src/commands/build/exec/sea-builder.d.ts +18 -0
  50. package/src/commands/build/exec/sea-builder.js +81 -0
  51. package/src/commands/build/exec/sea-builder.js.map +1 -0
  52. package/src/commands/build/exec/setup.js +0 -2
  53. package/src/commands/build/exec/setup.js.map +1 -1
  54. package/src/commands/build/index.d.ts +1 -1
  55. package/src/commands/build/index.js +3 -3
  56. package/src/commands/build/index.js.map +1 -1
  57. package/src/commands/build/register.d.ts +2 -0
  58. package/src/commands/build/register.js +21 -0
  59. package/src/commands/build/register.js.map +1 -0
  60. package/src/commands/{dev.d.ts → dev/dev.d.ts} +1 -1
  61. package/src/commands/{dev.js → dev/dev.js} +3 -3
  62. package/src/commands/dev/dev.js.map +1 -0
  63. package/src/commands/{doctor.js → dev/doctor.js} +5 -4
  64. package/src/commands/dev/doctor.js.map +1 -0
  65. package/src/commands/{inspector.js → dev/inspector.js} +1 -1
  66. package/src/commands/dev/inspector.js.map +1 -0
  67. package/src/commands/dev/register.d.ts +2 -0
  68. package/src/commands/dev/register.js +49 -0
  69. package/src/commands/dev/register.js.map +1 -0
  70. package/src/commands/{test.d.ts → dev/test.d.ts} +1 -1
  71. package/src/commands/{test.js → dev/test.js} +5 -5
  72. package/src/commands/dev/test.js.map +1 -0
  73. package/src/commands/{configure.d.ts → package/configure.d.ts} +1 -1
  74. package/src/commands/{configure.js → package/configure.js} +3 -3
  75. package/src/commands/package/configure.js.map +1 -0
  76. package/src/commands/package/esm-update.d.ts +19 -0
  77. package/src/commands/package/esm-update.js +93 -0
  78. package/src/commands/package/esm-update.js.map +1 -0
  79. package/src/commands/{install/index.d.ts → package/install.d.ts} +1 -1
  80. package/src/commands/{install/index.js → package/install.js} +8 -5
  81. package/src/commands/package/install.js.map +1 -0
  82. package/src/commands/{install → package}/questionnaire.js +2 -2
  83. package/src/commands/{install → package}/questionnaire.js.map +1 -1
  84. package/src/commands/package/register.d.ts +2 -0
  85. package/src/commands/package/register.js +35 -0
  86. package/src/commands/package/register.js.map +1 -0
  87. package/src/commands/{install → package}/registry.js +8 -6
  88. package/src/commands/package/registry.js.map +1 -0
  89. package/src/commands/{install → package}/sources/git.js +8 -1
  90. package/src/commands/package/sources/git.js.map +1 -0
  91. package/src/commands/{install → package}/sources/local.js.map +1 -1
  92. package/src/commands/{install → package}/sources/npm.js.map +1 -1
  93. package/src/commands/{install → package}/types.d.ts +7 -1
  94. package/src/commands/{install → package}/types.js +4 -0
  95. package/src/commands/package/types.js.map +1 -0
  96. package/src/commands/{uninstall.d.ts → package/uninstall.d.ts} +1 -1
  97. package/src/commands/{uninstall.js → package/uninstall.js} +2 -2
  98. package/src/commands/package/uninstall.js.map +1 -0
  99. package/src/{pm/pm.format.d.ts → commands/pm/format.d.ts} +1 -1
  100. package/src/{pm/pm.format.js → commands/pm/format.js} +2 -2
  101. package/src/commands/pm/format.js.map +1 -0
  102. package/src/{pm/pm.health.js → commands/pm/health.js} +1 -1
  103. package/src/commands/pm/health.js.map +1 -0
  104. package/src/commands/pm/index.d.ts +9 -0
  105. package/src/{pm → commands/pm}/index.js +32 -32
  106. package/src/commands/pm/index.js.map +1 -0
  107. package/src/commands/{list.d.ts → pm/list.d.ts} +1 -1
  108. package/src/commands/{list.js → pm/list.js} +3 -3
  109. package/src/commands/pm/list.js.map +1 -0
  110. package/src/{pm/pm.logs.js → commands/pm/log-utils.js} +9 -9
  111. package/src/commands/pm/log-utils.js.map +1 -0
  112. package/src/commands/{logs.d.ts → pm/logs.d.ts} +1 -1
  113. package/src/commands/{logs.js → pm/logs.js} +6 -6
  114. package/src/commands/pm/logs.js.map +1 -0
  115. package/src/{pm/pm.manager.d.ts → commands/pm/manager.d.ts} +1 -1
  116. package/src/{pm/pm.manager.js → commands/pm/manager.js} +21 -21
  117. package/src/commands/pm/manager.js.map +1 -0
  118. package/src/{pm/pm.paths.d.ts → commands/pm/paths.d.ts} +1 -0
  119. package/src/{pm/pm.paths.js → commands/pm/paths.js} +2 -1
  120. package/src/commands/pm/paths.js.map +1 -0
  121. package/src/{pm/pm.pidfile.d.ts → commands/pm/pidfile.d.ts} +1 -1
  122. package/src/{pm/pm.pidfile.js → commands/pm/pidfile.js} +8 -8
  123. package/src/commands/pm/pidfile.js.map +1 -0
  124. package/src/commands/pm/register.d.ts +2 -0
  125. package/src/commands/pm/register.js +83 -0
  126. package/src/commands/pm/register.js.map +1 -0
  127. package/src/commands/{restart.d.ts → pm/restart.d.ts} +1 -1
  128. package/src/commands/{restart.js → pm/restart.js} +4 -4
  129. package/src/commands/pm/restart.js.map +1 -0
  130. package/src/{pm/pm.service.d.ts → commands/pm/service-gen.d.ts} +1 -1
  131. package/src/{pm/pm.service.js → commands/pm/service-gen.js} +5 -5
  132. package/src/commands/pm/service-gen.js.map +1 -0
  133. package/src/commands/{service.d.ts → pm/service.d.ts} +1 -1
  134. package/src/commands/{service.js → pm/service.js} +6 -6
  135. package/src/commands/pm/service.js.map +1 -0
  136. package/src/commands/{socket.d.ts → pm/socket.d.ts} +1 -1
  137. package/src/commands/{socket.js → pm/socket.js} +3 -3
  138. package/src/commands/pm/socket.js.map +1 -0
  139. package/src/{pm/pm.spawn.d.ts → commands/pm/spawn.d.ts} +1 -1
  140. package/src/{pm/pm.spawn.js → commands/pm/spawn.js} +15 -15
  141. package/src/commands/pm/spawn.js.map +1 -0
  142. package/src/commands/{start.d.ts → pm/start.d.ts} +1 -1
  143. package/src/commands/{start.js → pm/start.js} +6 -6
  144. package/src/commands/pm/start.js.map +1 -0
  145. package/src/commands/{status.d.ts → pm/status.d.ts} +1 -1
  146. package/src/commands/{status.js → pm/status.js} +5 -5
  147. package/src/commands/pm/status.js.map +1 -0
  148. package/src/commands/{stop.d.ts → pm/stop.d.ts} +1 -1
  149. package/src/commands/{stop.js → pm/stop.js} +3 -3
  150. package/src/commands/pm/stop.js.map +1 -0
  151. package/src/{pm/pm.types.js → commands/pm/types.js} +1 -1
  152. package/src/commands/pm/types.js.map +1 -0
  153. package/src/commands/{create.js → scaffold/create.js} +91 -20
  154. package/src/commands/scaffold/create.js.map +1 -0
  155. package/src/commands/scaffold/register.d.ts +2 -0
  156. package/src/commands/scaffold/register.js +28 -0
  157. package/src/commands/scaffold/register.js.map +1 -0
  158. package/src/{args.d.ts → core/args.d.ts} +7 -1
  159. package/src/{args.js → core/args.js} +8 -0
  160. package/src/core/args.js.map +1 -0
  161. package/src/core/bridge.d.ts +9 -0
  162. package/src/core/bridge.js +75 -0
  163. package/src/core/bridge.js.map +1 -0
  164. package/src/core/cli.d.ts +8 -0
  165. package/src/core/cli.js +23 -0
  166. package/src/core/cli.js.map +1 -0
  167. package/src/core/colors.js.map +1 -0
  168. package/src/core/help.d.ts +7 -0
  169. package/src/core/help.js +83 -0
  170. package/src/core/help.js.map +1 -0
  171. package/src/core/index.d.ts +7 -0
  172. package/src/core/index.js +22 -0
  173. package/src/core/index.js.map +1 -0
  174. package/src/core/program.d.ts +2 -0
  175. package/src/core/program.js +23 -0
  176. package/src/core/program.js.map +1 -0
  177. package/src/core/tsconfig.js.map +1 -0
  178. package/src/{version.js → core/version.js} +1 -1
  179. package/src/core/version.js.map +1 -0
  180. package/src/index.d.ts +1 -1
  181. package/src/index.js +2 -5
  182. package/src/index.js.map +1 -1
  183. package/src/{utils → shared}/env.js +2 -2
  184. package/src/shared/env.js.map +1 -0
  185. package/src/{utils → shared}/fs.js +2 -2
  186. package/src/shared/fs.js.map +1 -0
  187. package/src/shared/index.d.ts +3 -0
  188. package/src/shared/index.js +14 -0
  189. package/src/shared/index.js.map +1 -0
  190. package/src/shared/prompts.js.map +1 -0
  191. package/src/args.js.map +0 -1
  192. package/src/cli.d.ts +0 -5
  193. package/src/cli.js +0 -241
  194. package/src/cli.js.map +0 -1
  195. package/src/colors.js.map +0 -1
  196. package/src/commands/configure.js.map +0 -1
  197. package/src/commands/create.js.map +0 -1
  198. package/src/commands/dev.js.map +0 -1
  199. package/src/commands/doctor.js.map +0 -1
  200. package/src/commands/inspector.js.map +0 -1
  201. package/src/commands/install/index.js.map +0 -1
  202. package/src/commands/install/registry.js.map +0 -1
  203. package/src/commands/install/sources/git.js.map +0 -1
  204. package/src/commands/install/types.js.map +0 -1
  205. package/src/commands/list.js.map +0 -1
  206. package/src/commands/logs.js.map +0 -1
  207. package/src/commands/restart.js.map +0 -1
  208. package/src/commands/service.js.map +0 -1
  209. package/src/commands/socket.js.map +0 -1
  210. package/src/commands/start.js.map +0 -1
  211. package/src/commands/status.js.map +0 -1
  212. package/src/commands/stop.js.map +0 -1
  213. package/src/commands/template.d.ts +0 -13
  214. package/src/commands/template.js +0 -193
  215. package/src/commands/template.js.map +0 -1
  216. package/src/commands/test.js.map +0 -1
  217. package/src/commands/uninstall.js.map +0 -1
  218. package/src/pm/index.d.ts +0 -9
  219. package/src/pm/index.js.map +0 -1
  220. package/src/pm/pm.format.js.map +0 -1
  221. package/src/pm/pm.health.js.map +0 -1
  222. package/src/pm/pm.logs.js.map +0 -1
  223. package/src/pm/pm.manager.js.map +0 -1
  224. package/src/pm/pm.paths.js.map +0 -1
  225. package/src/pm/pm.pidfile.js.map +0 -1
  226. package/src/pm/pm.service.js.map +0 -1
  227. package/src/pm/pm.spawn.js.map +0 -1
  228. package/src/pm/pm.types.js.map +0 -1
  229. package/src/templates/3rd-party-integration/src/http-client.d.ts +0 -20
  230. package/src/templates/3rd-party-integration/src/http-client.js +0 -105
  231. package/src/templates/3rd-party-integration/src/http-client.js.map +0 -1
  232. package/src/templates/3rd-party-integration/src/mcp-http-types.d.ts +0 -63
  233. package/src/templates/3rd-party-integration/src/mcp-http-types.js +0 -52
  234. package/src/templates/3rd-party-integration/src/mcp-http-types.js.map +0 -1
  235. package/src/templates/3rd-party-integration/src/tools/example.list.d.ts +0 -45
  236. package/src/templates/3rd-party-integration/src/tools/example.list.js +0 -85
  237. package/src/templates/3rd-party-integration/src/tools/example.list.js.map +0 -1
  238. package/src/tsconfig.js.map +0 -1
  239. package/src/utils/env.js.map +0 -1
  240. package/src/utils/fs.js.map +0 -1
  241. package/src/utils/prompts.js.map +0 -1
  242. package/src/version.js.map +0 -1
  243. /package/src/commands/{doctor.d.ts → dev/doctor.d.ts} +0 -0
  244. /package/src/commands/{inspector.d.ts → dev/inspector.d.ts} +0 -0
  245. /package/src/commands/{install → package}/questionnaire.d.ts +0 -0
  246. /package/src/commands/{install → package}/registry.d.ts +0 -0
  247. /package/src/commands/{install → package}/sources/git.d.ts +0 -0
  248. /package/src/commands/{install → package}/sources/local.d.ts +0 -0
  249. /package/src/commands/{install → package}/sources/local.js +0 -0
  250. /package/src/commands/{install → package}/sources/npm.d.ts +0 -0
  251. /package/src/commands/{install → package}/sources/npm.js +0 -0
  252. /package/src/{pm/pm.health.d.ts → commands/pm/health.d.ts} +0 -0
  253. /package/src/{pm/pm.logs.d.ts → commands/pm/log-utils.d.ts} +0 -0
  254. /package/src/{pm/pm.types.d.ts → commands/pm/types.d.ts} +0 -0
  255. /package/src/commands/{create.d.ts → scaffold/create.d.ts} +0 -0
  256. /package/src/{colors.d.ts → core/colors.d.ts} +0 -0
  257. /package/src/{colors.js → core/colors.js} +0 -0
  258. /package/src/{tsconfig.d.ts → core/tsconfig.d.ts} +0 -0
  259. /package/src/{tsconfig.js → core/tsconfig.js} +0 -0
  260. /package/src/{version.d.ts → core/version.d.ts} +0 -0
  261. /package/src/{utils → shared}/env.d.ts +0 -0
  262. /package/src/{utils → shared}/fs.d.ts +0 -0
  263. /package/src/{utils → shared}/prompts.d.ts +0 -0
  264. /package/src/{utils → shared}/prompts.js +0 -0
@@ -0,0 +1,1287 @@
1
+ "use strict";
2
+ /**
3
+ * Generates the CLI entry point TypeScript/JavaScript source code.
4
+ * This creates a commander.js-based CLI where each MCP tool is a subcommand.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.RESERVED_COMMANDS = void 0;
8
+ exports.resolveToolCommandName = resolveToolCommandName;
9
+ exports.generateCliEntry = generateCliEntry;
10
+ exports.extractTemplateParams = extractTemplateParams;
11
+ const schema_extractor_1 = require("./schema-extractor");
12
+ const schema_to_commander_1 = require("./schema-to-commander");
13
+ exports.RESERVED_COMMANDS = new Set([
14
+ 'resource', 'template', 'prompt', 'subscribe',
15
+ 'login', 'logout', 'connect', 'serve', 'daemon',
16
+ 'doctor', 'install', 'uninstall', 'sessions', 'help', 'version',
17
+ 'skills', 'job', 'workflow',
18
+ ]);
19
+ /**
20
+ * Resolve tool command name, appending '-tool' suffix if it conflicts with a built-in command.
21
+ * Returns { cmdName, wasRenamed } so the caller can log a warning at build time.
22
+ */
23
+ function resolveToolCommandName(toolName) {
24
+ const cmdName = (0, schema_to_commander_1.camelToKebab)(toolName).replace(/_/g, '-');
25
+ if (exports.RESERVED_COMMANDS.has(cmdName)) {
26
+ return { cmdName: `${cmdName}-tool`, wasRenamed: true };
27
+ }
28
+ return { cmdName, wasRenamed: false };
29
+ }
30
+ /**
31
+ * Generate the CLI entry source code (CJS module).
32
+ */
33
+ function generateCliEntry(options) {
34
+ const { appName, appVersion, description, serverBundleFilename, outputDefault, schema, excludeTools, oauthConfig, authRequired, } = options;
35
+ const capabilities = schema.capabilities;
36
+ const filteredTools = schema.tools.filter((t) => !excludeTools.includes(t.name) && !schema_extractor_1.SYSTEM_TOOL_NAMES.has(t.name));
37
+ const selfContained = !!options.selfContained;
38
+ const sections = [
39
+ generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained),
40
+ generateToolCommands(filteredTools, appName),
41
+ generateResourceCommands(schema),
42
+ generateTemplateCommands(schema.resourceTemplates),
43
+ generatePromptCommands(schema.prompts),
44
+ capabilities.skills ? generateSkillsCommands() : '',
45
+ capabilities.jobs ? generateJobCommands(schema.jobs) : '',
46
+ capabilities.workflows ? generateWorkflowCommands() : '',
47
+ generateSubscribeCommands(),
48
+ ...(authRequired ? [
49
+ generateLoginCommand(appName, oauthConfig),
50
+ generateLogoutCommand(appName),
51
+ generateSessionCommands(),
52
+ ] : []),
53
+ generateServeCommand(serverBundleFilename),
54
+ generateDoctorCommand(appName, options.nativeDeps),
55
+ generateInstallCommand(appName, options.nativeDeps, selfContained),
56
+ generateDaemonCommands(appName, serverBundleFilename),
57
+ generateFooter(),
58
+ ];
59
+ return sections.filter(Boolean).join('\n\n');
60
+ }
61
+ function generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained) {
62
+ const hasOAuth = !!oauthConfig;
63
+ // Build the group routing map dynamically
64
+ const skillsRouting = capabilities.skills ? `\n else if (name === 'skills') groups['Skills'].push(sub);` : '';
65
+ const jobsRouting = capabilities.jobs ? `\n else if (name === 'job') groups['Jobs'].push(sub);` : '';
66
+ const workflowsRouting = capabilities.workflows ? `\n else if (name === 'workflow') groups['Workflows'].push(sub);` : '';
67
+ const authRouting = authRequired ? `\n else if (['login', 'logout', 'sessions', 'connect'].indexOf(name) !== -1) groups['Auth'].push(sub);` : '';
68
+ // Build the groups object dynamically
69
+ const groupEntries = [
70
+ ` 'Tools': []`,
71
+ ` 'Resources & Prompts': []`,
72
+ ];
73
+ if (capabilities.skills)
74
+ groupEntries.push(` 'Skills': []`);
75
+ if (capabilities.jobs)
76
+ groupEntries.push(` 'Jobs': []`);
77
+ if (capabilities.workflows)
78
+ groupEntries.push(` 'Workflows': []`);
79
+ if (authRequired)
80
+ groupEntries.push(` 'Auth': []`);
81
+ groupEntries.push(` 'Subscriptions': []`);
82
+ groupEntries.push(` 'System': []`);
83
+ return `'use strict';
84
+
85
+ var { Command, Option } = require('commander');
86
+ var path = require('path');
87
+ var fs = require('fs');
88
+ var os = require('os');
89
+ var fmt = require('./output-formatter');
90
+ ${authRequired ? "var sessions = require('./session-manager');\nvar creds = require('./credential-store');" : ''}
91
+ ${hasOAuth ? "var oauthHelper = require('./oauth-helper');" : ''}
92
+
93
+ var APP_NAME = ${JSON.stringify(appName)};
94
+ var SCRIPT_DIR = __dirname;
95
+ var FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');
96
+ ${selfContained
97
+ ? `// Self-contained: server bundle and SDK are inlined by esbuild
98
+ var SERVER_BUNDLE = '../${serverBundleFilename}';`
99
+ : `var SERVER_BUNDLE = path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});`}
100
+
101
+ var _client = null;
102
+ async function getClient() {
103
+ if (_client) return _client;
104
+
105
+ // Try daemon first — Unix socket HTTP (~5-15ms vs ~420ms in-process)
106
+ var socketPath = path.join(FRONTMCP_HOME, 'sockets', APP_NAME + '.sock');
107
+ if (fs.existsSync(socketPath)) {
108
+ try {
109
+ var daemonClient = require('./daemon-client');
110
+ var dc = daemonClient.createDaemonClient(socketPath);
111
+ await dc.ping();
112
+ _client = dc;
113
+ return _client;
114
+ } catch (_) { /* daemon not available, fall through */ }
115
+ }
116
+
117
+ // Fallback: in-process connect (with CLI mode for faster init)
118
+ var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});
119
+ var configOrClass = mod.default || mod;
120
+ var sdk = require('@frontmcp/sdk');
121
+ var connect = sdk.connect || sdk.direct.connect;${authRequired ? `
122
+ var sessionName = sessions.getActiveSessionName();
123
+ var store = creds.createCredentialStore();
124
+ var credBlob = await store.get(sessionName);
125
+ var connectOpts = credBlob ? { authToken: credBlob.token, mode: 'cli' } : { mode: 'cli' };
126
+ _client = await connect(configOrClass, connectOpts);` : `
127
+ _client = await connect(configOrClass, { mode: 'cli' });`}
128
+ return _client;
129
+ }
130
+
131
+ var program = new Command();
132
+ program
133
+ .name(${JSON.stringify(appName)})
134
+ .version(${JSON.stringify(appVersion)})
135
+ .description(${JSON.stringify(description || `${appName} CLI`)})
136
+ .option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)});
137
+
138
+ program.configureHelp({
139
+ sortSubcommands: false,
140
+ formatHelp: function(cmd, helper) {
141
+ var groups = {
142
+ ${groupEntries.join(',\n')}
143
+ };
144
+ var toolCmdNames = cmd._toolCommandNames || [];
145
+ cmd.commands.forEach(function(sub) {
146
+ var name = sub.name();
147
+ if (toolCmdNames.indexOf(name) !== -1) groups['Tools'].push(sub);
148
+ else if (['resource', 'template', 'prompt'].indexOf(name) !== -1) groups['Resources & Prompts'].push(sub);${skillsRouting}${jobsRouting}${workflowsRouting}${authRouting}
149
+ else if (name === 'subscribe') groups['Subscriptions'].push(sub);
150
+ else groups['System'].push(sub);
151
+ });
152
+ var termWidth = helper.padWidth(cmd, helper);
153
+ var lines = [];
154
+ lines.push('Usage: ' + helper.commandUsage(cmd));
155
+ lines.push('');
156
+ var desc = helper.commandDescription(cmd);
157
+ if (desc) { lines.push(desc); lines.push(''); }
158
+ var globalOpts = helper.formatHelp ? helper.visibleOptions(cmd) : [];
159
+ if (globalOpts.length > 0) {
160
+ lines.push('Options:');
161
+ globalOpts.forEach(function(opt) {
162
+ lines.push(' ' + helper.optionTerm(opt).padEnd(termWidth) + ' ' + helper.optionDescription(opt));
163
+ });
164
+ lines.push('');
165
+ }
166
+ Object.keys(groups).forEach(function(groupName) {
167
+ var cmds = groups[groupName];
168
+ if (cmds.length === 0) return;
169
+ lines.push(groupName + ':');
170
+ cmds.forEach(function(sub) {
171
+ lines.push(' ' + helper.subcommandTerm(sub).padEnd(termWidth) + ' ' + helper.subcommandDescription(sub));
172
+ });
173
+ lines.push('');
174
+ });
175
+ return lines.join('\\n');
176
+ }
177
+ });
178
+
179
+ program.action(function() { program.outputHelp(); });`;
180
+ }
181
+ function generateToolCommands(tools, appName) {
182
+ if (tools.length === 0)
183
+ return '// No tools extracted\nprogram._toolCommandNames = [];';
184
+ const cmdNames = [];
185
+ const commands = tools.map((tool) => {
186
+ const { cmdName } = resolveToolCommandName(tool.name);
187
+ cmdNames.push(cmdName);
188
+ const { options } = (0, schema_to_commander_1.schemaToCommander)(tool.inputSchema);
189
+ const optionLines = options.map((o) => ` ${(0, schema_to_commander_1.generateOptionCode)(o)}`).join('\n');
190
+ return `program
191
+ .command(${JSON.stringify(cmdName)})
192
+ .description(${JSON.stringify(tool.description)})
193
+ ${optionLines}
194
+ .action(async function(opts) {
195
+ try {
196
+ var client = await getClient();
197
+ var args = {};
198
+ var rawOpts = this.opts();
199
+ ${generateArgMapping(tool)}
200
+ var result = await client.callTool(${JSON.stringify(tool.name)}, args);
201
+ var mode = program.opts().output || ${JSON.stringify('text')};
202
+ console.log(fmt.formatToolResult(result, mode));
203
+ } catch (err) {
204
+ var meta = err && err._meta ? err._meta : (err && err.data && err.data._meta ? err.data._meta : null);
205
+ if (meta && meta.authorization_required) {
206
+ console.error('Authorization required' + (meta.app ? ' for ' + meta.app : ''));
207
+ if (meta.auth_url) console.error('Authorize at: ' + meta.auth_url);
208
+ console.error('Or run: ' + ${JSON.stringify(appName)} + ' login');
209
+ } else {
210
+ console.error('Error:', err.message || err);
211
+ }
212
+ process.exitCode = 1;
213
+ }
214
+ });`;
215
+ });
216
+ return `program._toolCommandNames = ${JSON.stringify(cmdNames)};\n\n${commands.join('\n\n')}`;
217
+ }
218
+ function generateArgMapping(tool) {
219
+ const props = tool.inputSchema.properties;
220
+ if (!props)
221
+ return '';
222
+ const mappings = Object.keys(props).map((propName) => {
223
+ const propSchema = props[propName];
224
+ const kebab = (0, schema_to_commander_1.camelToKebab)(propName);
225
+ // Commander converts kebab-case flags to camelCase in opts()
226
+ const camel = kebabToCamel(kebab);
227
+ // Resolve type for object detection
228
+ let propType = propSchema?.type;
229
+ if (Array.isArray(propType)) {
230
+ propType = propType.find((t) => t !== 'null') || propType[0];
231
+ }
232
+ if (propType === 'object') {
233
+ return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {
234
+ try { args[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }
235
+ catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }
236
+ }`;
237
+ }
238
+ return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;
239
+ });
240
+ return mappings.join('\n ');
241
+ }
242
+ function generateJobArgMapping(inputSchema) {
243
+ const props = inputSchema.properties;
244
+ if (!props)
245
+ return '';
246
+ const mappings = Object.keys(props).map((propName) => {
247
+ const propSchema = props[propName];
248
+ const kebab = (0, schema_to_commander_1.camelToKebab)(propName);
249
+ const camel = kebabToCamel(kebab);
250
+ let propType = propSchema?.type;
251
+ if (Array.isArray(propType)) {
252
+ propType = propType.find((t) => t !== 'null') || propType[0];
253
+ }
254
+ if (propType === 'object') {
255
+ return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {
256
+ try { input[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }
257
+ catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }
258
+ }`;
259
+ }
260
+ return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) input[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;
261
+ });
262
+ return mappings.join('\n ');
263
+ }
264
+ function generateResourceCommands(_schema) {
265
+ return `var resourceCmd = program.command('resource').description('Resource operations');
266
+
267
+ resourceCmd
268
+ .command('list')
269
+ .description('List available resources')
270
+ .action(async function() {
271
+ try {
272
+ var client = await getClient();
273
+ var result = await client.listResources();
274
+ var mode = program.opts().output || 'text';
275
+ if (mode === 'json') {
276
+ console.log(JSON.stringify(result, null, 2));
277
+ } else {
278
+ var resources = result.resources || [];
279
+ if (resources.length === 0) { console.log('No resources available.'); return; }
280
+ resources.forEach(function(r) {
281
+ console.log(' ' + r.uri + (r.description ? ' - ' + r.description : ''));
282
+ });
283
+ }
284
+ } catch (err) {
285
+ console.error('Error:', err.message || err);
286
+ process.exitCode = 1;
287
+ }
288
+ });
289
+
290
+ resourceCmd
291
+ .command('read <uri>')
292
+ .description('Read a resource by URI')
293
+ .action(async function(uri) {
294
+ try {
295
+ var client = await getClient();
296
+ var result = await client.readResource(uri);
297
+ var mode = program.opts().output || 'text';
298
+ console.log(fmt.formatResourceResult(result, mode));
299
+ } catch (err) {
300
+ console.error('Error:', err.message || err);
301
+ process.exitCode = 1;
302
+ }
303
+ });`;
304
+ }
305
+ function generateTemplateCommands(templates) {
306
+ if (!templates || templates.length === 0)
307
+ return '// No resource templates extracted';
308
+ const subcommands = templates.map((tmpl) => {
309
+ const cmdName = (0, schema_to_commander_1.camelToKebab)(tmpl.name).replace(/_/g, '-');
310
+ // Extract {param} placeholders from URI template
311
+ const paramNames = extractTemplateParams(tmpl.uriTemplate);
312
+ const optionLines = paramNames
313
+ .map((p) => ` .requiredOption('--${(0, schema_to_commander_1.camelToKebab)(p)} <value>', 'Template parameter: ${p}')`)
314
+ .join('\n');
315
+ const paramMapping = paramNames
316
+ .map((p) => {
317
+ const camel = kebabToCamel((0, schema_to_commander_1.camelToKebab)(p));
318
+ return `uri = uri.replace('{${p}}', encodeURIComponent(rawOpts[${JSON.stringify(camel)}]));`;
319
+ })
320
+ .join('\n ');
321
+ return `templateCmd
322
+ .command(${JSON.stringify(cmdName)})
323
+ .description(${JSON.stringify(tmpl.description || `Read resource from template: ${tmpl.uriTemplate}`)})
324
+ ${optionLines}
325
+ .action(async function(opts) {
326
+ try {
327
+ var client = await getClient();
328
+ var rawOpts = this.opts();
329
+ var uri = ${JSON.stringify(tmpl.uriTemplate)};
330
+ ${paramMapping}
331
+ var result = await client.readResource(uri);
332
+ var mode = program.opts().output || 'text';
333
+ console.log(fmt.formatResourceResult(result, mode));
334
+ } catch (err) {
335
+ console.error('Error:', err.message || err);
336
+ process.exitCode = 1;
337
+ }
338
+ });`;
339
+ });
340
+ return `var templateCmd = program.command('template').description('Resource template operations');
341
+
342
+ templateCmd
343
+ .command('list')
344
+ .description('List available resource templates')
345
+ .action(async function() {
346
+ try {
347
+ var client = await getClient();
348
+ var result = await client.listResourceTemplates();
349
+ var mode = program.opts().output || 'text';
350
+ if (mode === 'json') {
351
+ console.log(JSON.stringify(result, null, 2));
352
+ } else {
353
+ var templates = result.resourceTemplates || [];
354
+ if (templates.length === 0) { console.log('No resource templates available.'); return; }
355
+ templates.forEach(function(t) {
356
+ console.log(' ' + t.uriTemplate + (t.description ? ' - ' + t.description : ''));
357
+ });
358
+ }
359
+ } catch (err) {
360
+ console.error('Error:', err.message || err);
361
+ process.exitCode = 1;
362
+ }
363
+ });
364
+
365
+ ${subcommands.join('\n\n')}`;
366
+ }
367
+ function generatePromptCommands(prompts) {
368
+ const subcommands = prompts.map((prompt) => {
369
+ const cmdName = (0, schema_to_commander_1.camelToKebab)(prompt.name).replace(/_/g, '-');
370
+ const argOptions = (prompt.arguments || [])
371
+ .map((a) => {
372
+ const flag = `--${(0, schema_to_commander_1.camelToKebab)(a.name)} <value>`;
373
+ const desc = a.description || '';
374
+ return a.required
375
+ ? ` .requiredOption('${flag}', '${escapeStr(desc)}')`
376
+ : ` .option('${flag}', '${escapeStr(desc)}')`;
377
+ })
378
+ .join('\n');
379
+ return `promptCmd
380
+ .command(${JSON.stringify(cmdName)})
381
+ .description(${JSON.stringify(prompt.description || '')})
382
+ ${argOptions}
383
+ .action(async function(opts) {
384
+ try {
385
+ var client = await getClient();
386
+ var args = {};
387
+ var rawOpts = this.opts();
388
+ ${(prompt.arguments || []).map((a) => {
389
+ const camel = kebabToCamel((0, schema_to_commander_1.camelToKebab)(a.name));
390
+ return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(a.name)}] = rawOpts[${JSON.stringify(camel)}];`;
391
+ }).join('\n ')}
392
+ var result = await client.getPrompt(${JSON.stringify(prompt.name)}, args);
393
+ var mode = program.opts().output || 'text';
394
+ console.log(fmt.formatPromptResult(result, mode));
395
+ } catch (err) {
396
+ console.error('Error:', err.message || err);
397
+ process.exitCode = 1;
398
+ }
399
+ });`;
400
+ });
401
+ return `var promptCmd = program.command('prompt').description('Prompt operations');
402
+
403
+ promptCmd
404
+ .command('list')
405
+ .description('List available prompts')
406
+ .action(async function() {
407
+ try {
408
+ var client = await getClient();
409
+ var result = await client.listPrompts();
410
+ var mode = program.opts().output || 'text';
411
+ if (mode === 'json') {
412
+ console.log(JSON.stringify(result, null, 2));
413
+ } else {
414
+ var prompts = result.prompts || [];
415
+ if (prompts.length === 0) { console.log('No prompts available.'); return; }
416
+ prompts.forEach(function(p) {
417
+ console.log(' ' + p.name + (p.description ? ' - ' + p.description : ''));
418
+ });
419
+ }
420
+ } catch (err) {
421
+ console.error('Error:', err.message || err);
422
+ process.exitCode = 1;
423
+ }
424
+ });
425
+
426
+ ${subcommands.join('\n\n')}`;
427
+ }
428
+ function generateSkillsCommands() {
429
+ return `var skillsCmd = program.command('skills').description('Skill operations');
430
+
431
+ skillsCmd
432
+ .command('search [query]')
433
+ .description('Search for skills')
434
+ .action(async function(query) {
435
+ try {
436
+ var client = await getClient();
437
+ var result = await client.searchSkills(query || '');
438
+ var mode = program.opts().output || 'text';
439
+ if (mode === 'json') {
440
+ console.log(JSON.stringify(result, null, 2));
441
+ } else {
442
+ var skills = result.skills || result || [];
443
+ if (Array.isArray(skills) && skills.length === 0) { console.log('No skills found.'); return; }
444
+ if (Array.isArray(skills)) {
445
+ skills.forEach(function(s) {
446
+ console.log(' ' + (s.name || s.id || JSON.stringify(s)));
447
+ });
448
+ } else {
449
+ console.log(JSON.stringify(result, null, 2));
450
+ }
451
+ }
452
+ } catch (err) {
453
+ console.error('Error:', err.message || err);
454
+ process.exitCode = 1;
455
+ }
456
+ });
457
+
458
+ skillsCmd
459
+ .command('load <ids...>')
460
+ .description('Load skills by ID')
461
+ .action(async function(ids) {
462
+ try {
463
+ var client = await getClient();
464
+ var result = await client.loadSkills(ids);
465
+ var mode = program.opts().output || 'text';
466
+ if (mode === 'json') {
467
+ console.log(JSON.stringify(result, null, 2));
468
+ } else {
469
+ console.log('Loaded ' + ids.length + ' skill(s).');
470
+ if (result && typeof result === 'object') {
471
+ console.log(JSON.stringify(result, null, 2));
472
+ }
473
+ }
474
+ } catch (err) {
475
+ console.error('Error:', err.message || err);
476
+ process.exitCode = 1;
477
+ }
478
+ });
479
+
480
+ skillsCmd
481
+ .command('list')
482
+ .description('List available skills')
483
+ .action(async function() {
484
+ try {
485
+ var client = await getClient();
486
+ var result = await client.listSkills();
487
+ var mode = program.opts().output || 'text';
488
+ if (mode === 'json') {
489
+ console.log(JSON.stringify(result, null, 2));
490
+ } else {
491
+ var skills = result.skills || result || [];
492
+ if (Array.isArray(skills) && skills.length === 0) { console.log('No skills available.'); return; }
493
+ if (Array.isArray(skills)) {
494
+ skills.forEach(function(s) {
495
+ console.log(' ' + (s.name || s.id || JSON.stringify(s)));
496
+ });
497
+ } else {
498
+ console.log(JSON.stringify(result, null, 2));
499
+ }
500
+ }
501
+ } catch (err) {
502
+ console.error('Error:', err.message || err);
503
+ process.exitCode = 1;
504
+ }
505
+ });`;
506
+ }
507
+ function generateJobCommands(jobs) {
508
+ // Generate typed 'run' subcommands for each known job
509
+ const runSubcommands = jobs.map((job) => {
510
+ const jobCmdName = (0, schema_to_commander_1.camelToKebab)(job.name).replace(/_/g, '-');
511
+ if (job.inputSchema) {
512
+ const { options } = (0, schema_to_commander_1.schemaToCommander)(job.inputSchema);
513
+ const optionLines = options.map((o) => ` ${(0, schema_to_commander_1.generateOptionCode)(o)}`).join('\n');
514
+ const argMapping = generateJobArgMapping(job.inputSchema);
515
+ return `jobRunCmd
516
+ .command(${JSON.stringify(jobCmdName)})
517
+ .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})
518
+ ${optionLines}
519
+ .option('--background', 'Run in background mode')
520
+ .action(async function(opts) {
521
+ try {
522
+ var client = await getClient();
523
+ var input = {};
524
+ var rawOpts = this.opts();
525
+ ${argMapping}
526
+ var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!rawOpts.background });
527
+ var mode = program.opts().output || 'text';
528
+ if (mode === 'json') {
529
+ console.log(JSON.stringify(result, null, 2));
530
+ } else {
531
+ if (rawOpts.background && result && result.runId) {
532
+ console.log('Job started. Run ID: ' + result.runId);
533
+ } else {
534
+ console.log(JSON.stringify(result, null, 2));
535
+ }
536
+ }
537
+ } catch (err) {
538
+ console.error('Error:', err.message || err);
539
+ process.exitCode = 1;
540
+ }
541
+ });`;
542
+ }
543
+ // No inputSchema — fall back to generic --input <json>
544
+ return `jobRunCmd
545
+ .command(${JSON.stringify(jobCmdName)})
546
+ .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})
547
+ .option('--input <json>', 'Job input as JSON string')
548
+ .option('--background', 'Run in background mode')
549
+ .action(async function(opts) {
550
+ try {
551
+ var client = await getClient();
552
+ var input = {};
553
+ if (opts.input) {
554
+ try { input = JSON.parse(opts.input); }
555
+ catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }
556
+ }
557
+ var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!opts.background });
558
+ var mode = program.opts().output || 'text';
559
+ if (mode === 'json') {
560
+ console.log(JSON.stringify(result, null, 2));
561
+ } else {
562
+ if (opts.background && result && result.runId) {
563
+ console.log('Job started. Run ID: ' + result.runId);
564
+ } else {
565
+ console.log(JSON.stringify(result, null, 2));
566
+ }
567
+ }
568
+ } catch (err) {
569
+ console.error('Error:', err.message || err);
570
+ process.exitCode = 1;
571
+ }
572
+ });`;
573
+ });
574
+ // Generic fallback 'run' for jobs not known at build time
575
+ const genericRun = `jobRunCmd
576
+ .command('_run <name>')
577
+ .description('Run a job by name (generic)')
578
+ .option('--input <json>', 'Job input as JSON string')
579
+ .option('--background', 'Run in background mode')
580
+ .action(async function(name, opts) {
581
+ try {
582
+ var client = await getClient();
583
+ var input = {};
584
+ if (opts.input) {
585
+ try { input = JSON.parse(opts.input); }
586
+ catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }
587
+ }
588
+ var result = await client.executeJob(name, input, { background: !!opts.background });
589
+ var mode = program.opts().output || 'text';
590
+ if (mode === 'json') {
591
+ console.log(JSON.stringify(result, null, 2));
592
+ } else {
593
+ if (opts.background && result && result.runId) {
594
+ console.log('Job started. Run ID: ' + result.runId);
595
+ } else {
596
+ console.log(JSON.stringify(result, null, 2));
597
+ }
598
+ }
599
+ } catch (err) {
600
+ console.error('Error:', err.message || err);
601
+ process.exitCode = 1;
602
+ }
603
+ });`;
604
+ return `var jobCmd = program.command('job').description('Job operations');
605
+
606
+ jobCmd
607
+ .command('list')
608
+ .description('List available jobs')
609
+ .action(async function() {
610
+ try {
611
+ var client = await getClient();
612
+ var result = await client.listJobs();
613
+ var mode = program.opts().output || 'text';
614
+ if (mode === 'json') {
615
+ console.log(JSON.stringify(result, null, 2));
616
+ } else {
617
+ var jobs = result.jobs || result || [];
618
+ if (Array.isArray(jobs) && jobs.length === 0) { console.log('No jobs available.'); return; }
619
+ if (Array.isArray(jobs)) {
620
+ jobs.forEach(function(j) {
621
+ console.log(' ' + (j.name || j.id || JSON.stringify(j)));
622
+ });
623
+ } else {
624
+ console.log(JSON.stringify(result, null, 2));
625
+ }
626
+ }
627
+ } catch (err) {
628
+ console.error('Error:', err.message || err);
629
+ process.exitCode = 1;
630
+ }
631
+ });
632
+
633
+ var jobRunCmd = jobCmd.command('run').description('Run a job');
634
+
635
+ ${runSubcommands.join('\n\n')}
636
+
637
+ ${jobs.length > 0 ? genericRun : `jobRunCmd
638
+ .argument('<name>', 'Job name')
639
+ .option('--input <json>', 'Job input as JSON string')
640
+ .option('--background', 'Run in background mode')
641
+ .action(async function(name, opts) {
642
+ try {
643
+ var client = await getClient();
644
+ var input = {};
645
+ if (opts.input) {
646
+ try { input = JSON.parse(opts.input); }
647
+ catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }
648
+ }
649
+ var result = await client.executeJob(name, input, { background: !!opts.background });
650
+ var mode = program.opts().output || 'text';
651
+ if (mode === 'json') {
652
+ console.log(JSON.stringify(result, null, 2));
653
+ } else {
654
+ if (opts.background && result && result.runId) {
655
+ console.log('Job started. Run ID: ' + result.runId);
656
+ } else {
657
+ console.log(JSON.stringify(result, null, 2));
658
+ }
659
+ }
660
+ } catch (err) {
661
+ console.error('Error:', err.message || err);
662
+ process.exitCode = 1;
663
+ }
664
+ });`}
665
+
666
+ jobCmd
667
+ .command('status <runId>')
668
+ .description('Get the status of a job run')
669
+ .action(async function(runId) {
670
+ try {
671
+ var client = await getClient();
672
+ var result = await client.getJobStatus(runId);
673
+ var mode = program.opts().output || 'text';
674
+ if (mode === 'json') {
675
+ console.log(JSON.stringify(result, null, 2));
676
+ } else {
677
+ console.log('Status: ' + (result.status || JSON.stringify(result)));
678
+ }
679
+ } catch (err) {
680
+ console.error('Error:', err.message || err);
681
+ process.exitCode = 1;
682
+ }
683
+ });`;
684
+ }
685
+ function generateWorkflowCommands() {
686
+ return `var workflowCmd = program.command('workflow').description('Workflow operations');
687
+
688
+ workflowCmd
689
+ .command('list')
690
+ .description('List available workflows')
691
+ .action(async function() {
692
+ try {
693
+ var client = await getClient();
694
+ var result = await client.listWorkflows();
695
+ var mode = program.opts().output || 'text';
696
+ if (mode === 'json') {
697
+ console.log(JSON.stringify(result, null, 2));
698
+ } else {
699
+ var workflows = result.workflows || result || [];
700
+ if (Array.isArray(workflows) && workflows.length === 0) { console.log('No workflows available.'); return; }
701
+ if (Array.isArray(workflows)) {
702
+ workflows.forEach(function(w) {
703
+ console.log(' ' + (w.name || w.id || JSON.stringify(w)));
704
+ });
705
+ } else {
706
+ console.log(JSON.stringify(result, null, 2));
707
+ }
708
+ }
709
+ } catch (err) {
710
+ console.error('Error:', err.message || err);
711
+ process.exitCode = 1;
712
+ }
713
+ });
714
+
715
+ workflowCmd
716
+ .command('run <name>')
717
+ .description('Run a workflow by name')
718
+ .option('--input <json>', 'Workflow input as JSON string')
719
+ .option('--background', 'Run in background mode')
720
+ .action(async function(name, opts) {
721
+ try {
722
+ var client = await getClient();
723
+ var input = {};
724
+ if (opts.input) {
725
+ try { input = JSON.parse(opts.input); }
726
+ catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }
727
+ }
728
+ var result = await client.executeWorkflow(name, input, { background: !!opts.background });
729
+ var mode = program.opts().output || 'text';
730
+ if (mode === 'json') {
731
+ console.log(JSON.stringify(result, null, 2));
732
+ } else {
733
+ if (opts.background && result && result.runId) {
734
+ console.log('Workflow started. Run ID: ' + result.runId);
735
+ } else {
736
+ console.log(JSON.stringify(result, null, 2));
737
+ }
738
+ }
739
+ } catch (err) {
740
+ console.error('Error:', err.message || err);
741
+ process.exitCode = 1;
742
+ }
743
+ });
744
+
745
+ workflowCmd
746
+ .command('status <runId>')
747
+ .description('Get the status of a workflow run')
748
+ .action(async function(runId) {
749
+ try {
750
+ var client = await getClient();
751
+ var result = await client.getWorkflowStatus(runId);
752
+ var mode = program.opts().output || 'text';
753
+ if (mode === 'json') {
754
+ console.log(JSON.stringify(result, null, 2));
755
+ } else {
756
+ console.log('Status: ' + (result.status || JSON.stringify(result)));
757
+ }
758
+ } catch (err) {
759
+ console.error('Error:', err.message || err);
760
+ process.exitCode = 1;
761
+ }
762
+ });`;
763
+ }
764
+ function generateSubscribeCommands() {
765
+ return `var subscribeCmd = program.command('subscribe').description('Subscribe to updates');
766
+
767
+ subscribeCmd
768
+ .command('resource <uri>')
769
+ .description('Stream resource updates (Ctrl+C to stop)')
770
+ .action(async function(uri) {
771
+ try {
772
+ var client = await getClient();
773
+ await client.subscribeResource(uri);
774
+ var mode = program.opts().output || 'text';
775
+ console.log('Subscribed to resource: ' + uri);
776
+ console.log('Waiting for updates... (Ctrl+C to stop)\\n');
777
+ client.onResourceUpdated(function(uri) {
778
+ console.log(fmt.formatSubscriptionEvent({ type: 'resource_updated', uri: uri, timestamp: new Date().toISOString() }, mode));
779
+ });
780
+ process.on('SIGINT', async function() {
781
+ console.log('\\nUnsubscribing...');
782
+ try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }
783
+ process.exit(0);
784
+ });
785
+ // Keep process alive
786
+ await new Promise(function() {});
787
+ } catch (err) {
788
+ console.error('Error:', err.message || err);
789
+ process.exitCode = 1;
790
+ }
791
+ });
792
+
793
+ subscribeCmd
794
+ .command('notification <name>')
795
+ .description('Stream notifications (Ctrl+C to stop)')
796
+ .action(async function(name) {
797
+ try {
798
+ var client = await getClient();
799
+ var mode = program.opts().output || 'text';
800
+ console.log('Listening for notification: ' + name);
801
+ console.log('Waiting for events... (Ctrl+C to stop)\\n');
802
+ client.onNotification(function(notification) {
803
+ if (notification.method === name || name === '*') {
804
+ console.log(fmt.formatSubscriptionEvent({ type: 'notification', method: notification.method, params: notification.params, timestamp: new Date().toISOString() }, mode));
805
+ }
806
+ });
807
+ process.on('SIGINT', function() {
808
+ console.log('\\nStopping...');
809
+ process.exit(0);
810
+ });
811
+ // Keep process alive
812
+ await new Promise(function() {});
813
+ } catch (err) {
814
+ console.error('Error:', err.message || err);
815
+ process.exitCode = 1;
816
+ }
817
+ });`;
818
+ }
819
+ function generateLoginCommand(appName, oauthConfig) {
820
+ const serverUrl = oauthConfig?.serverUrl || '';
821
+ const clientId = oauthConfig?.clientId || appName;
822
+ const defaultScope = oauthConfig?.defaultScope || '';
823
+ const portStart = oauthConfig?.portRange?.[0] ?? 17830;
824
+ const portEnd = oauthConfig?.portRange?.[1] ?? 17850;
825
+ const timeout = oauthConfig?.timeout ?? 120000;
826
+ return `program
827
+ .command('login')
828
+ .description('Authenticate via OAuth')
829
+ .option('--server <url>', 'Server URL for OAuth'${serverUrl ? `, ${JSON.stringify(serverUrl)}` : ''})
830
+ .option('--session <name>', 'Session name', 'default')
831
+ .option('--scope <scopes>', 'OAuth scopes'${defaultScope ? `, ${JSON.stringify(defaultScope)}` : ''})
832
+ .option('--no-browser', 'Print URL instead of opening browser')
833
+ .action(async function(opts) {
834
+ var serverUrl = opts.server || process.env.FRONTMCP_SERVER_URL || ${JSON.stringify(serverUrl)};
835
+ if (!serverUrl) {
836
+ console.error('Server URL required. Use --server <url> or set FRONTMCP_SERVER_URL.');
837
+ process.exitCode = 1;
838
+ return;
839
+ }
840
+ try {
841
+ var oauthHelper = require('./oauth-helper');
842
+ var result = await oauthHelper.startOAuthLogin({
843
+ serverUrl: serverUrl,
844
+ clientId: ${JSON.stringify(clientId)},
845
+ scope: opts.scope || ${JSON.stringify(defaultScope)},
846
+ portStart: ${portStart},
847
+ portEnd: ${portEnd},
848
+ timeout: ${timeout},
849
+ noBrowser: !opts.browser
850
+ });
851
+ var sessionName = opts.session || 'default';
852
+ var store = creds.createCredentialStore();
853
+ await store.set(sessionName, result);
854
+ sessions.getOrCreateSession(sessionName);
855
+ console.log('Logged in successfully. Session: ' + sessionName);
856
+ } catch (err) {
857
+ console.error('Login failed:', err.message || err);
858
+ process.exitCode = 1;
859
+ }
860
+ });`;
861
+ }
862
+ function generateLogoutCommand(_appName) {
863
+ return `program
864
+ .command('logout')
865
+ .description('Clear stored credentials')
866
+ .option('--session <name>', 'Session to log out')
867
+ .option('--all', 'Log out of all sessions')
868
+ .action(async function(opts) {
869
+ var store = creds.createCredentialStore();
870
+ if (opts.all) {
871
+ var allSessions = await store.list();
872
+ for (var i = 0; i < allSessions.length; i++) {
873
+ await store.delete(allSessions[i]);
874
+ }
875
+ console.log('Logged out of ' + allSessions.length + ' session(s).');
876
+ } else {
877
+ var sessionName = opts.session || sessions.getActiveSessionName();
878
+ await store.delete(sessionName);
879
+ console.log('Logged out of session: ' + sessionName);
880
+ }
881
+ });`;
882
+ }
883
+ function generateSessionCommands() {
884
+ return `var sessionsCmd = program.command('sessions').description('Session management');
885
+
886
+ sessionsCmd
887
+ .command('list')
888
+ .description('List all sessions')
889
+ .action(function() {
890
+ var list = sessions.listSessions();
891
+ if (list.length === 0) { console.log('No sessions.'); return; }
892
+ list.forEach(function(s) {
893
+ var marker = s.isActive ? ' (active)' : '';
894
+ console.log(' ' + s.name + marker + ' - last used: ' + s.lastUsedAt);
895
+ });
896
+ });
897
+
898
+ sessionsCmd
899
+ .command('switch <name>')
900
+ .description('Switch to a named session')
901
+ .action(function(name) {
902
+ sessions.switchSession(name);
903
+ console.log('Switched to session: ' + name);
904
+ });
905
+
906
+ sessionsCmd
907
+ .command('delete <name>')
908
+ .description('Delete a session')
909
+ .action(async function(name) {
910
+ var store = creds.createCredentialStore();
911
+ await store.delete(name);
912
+ sessions.deleteSession(name);
913
+ console.log('Deleted session: ' + name);
914
+ });
915
+
916
+ program
917
+ .command('connect')
918
+ .description('Authenticate and store credentials')
919
+ .option('--session <name>', 'Session name', 'default')
920
+ .option('--token <token>', 'Auth token (or pass via stdin)')
921
+ .action(async function(opts) {
922
+ var sessionName = opts.session || 'default';
923
+ var token = opts.token;
924
+ if (!token) {
925
+ console.log('Usage: ' + program.name() + ' connect --token <your-token>');
926
+ console.log(' Or pipe token: echo "tok_xxx" | ' + program.name() + ' connect');
927
+ process.exitCode = 1;
928
+ return;
929
+ }
930
+ var store = creds.createCredentialStore();
931
+ await store.set(sessionName, { token: token });
932
+ sessions.getOrCreateSession(sessionName);
933
+ console.log('Credentials stored for session: ' + sessionName);
934
+ });`;
935
+ }
936
+ function generateServeCommand(serverBundleFilename) {
937
+ return `program
938
+ .command('serve')
939
+ .description('Start the HTTP/SSE server')
940
+ .option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })
941
+ .action(async function(opts) {
942
+ var mod = require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}));
943
+ if (opts.port) process.env.PORT = String(opts.port);
944
+ // The server bundle should self-start when required
945
+ if (typeof mod.start === 'function') await mod.start();
946
+ else if (typeof mod.default?.start === 'function') await mod.default.start();
947
+ });`;
948
+ }
949
+ function generateDoctorCommand(appName, nativeDeps) {
950
+ const checks = [];
951
+ if (nativeDeps.brew?.length) {
952
+ for (const pkg of nativeDeps.brew) {
953
+ checks.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', check: 'brew list ${pkg}' }`);
954
+ }
955
+ }
956
+ if (nativeDeps.apt?.length) {
957
+ for (const pkg of nativeDeps.apt) {
958
+ checks.push(` { name: ${JSON.stringify(pkg)}, type: 'apt', check: 'dpkg -l ${pkg}' }`);
959
+ }
960
+ }
961
+ if (nativeDeps.npm?.length) {
962
+ for (const pkg of nativeDeps.npm) {
963
+ checks.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', check: 'npm ls ${pkg}' }`);
964
+ }
965
+ }
966
+ return `program
967
+ .command('doctor')
968
+ .description('Check system dependencies and configuration')
969
+ .option('--fix', 'Attempt to install missing dependencies')
970
+ .action(async function(opts) {
971
+ var exec = require('child_process').execSync;
972
+ var ok = true;
973
+
974
+ // Check Node.js version
975
+ var nodeMajor = parseInt(process.versions.node.split('.')[0], 10);
976
+ if (nodeMajor >= 22) {
977
+ console.log(' [ok] Node.js v' + process.versions.node);
978
+ } else {
979
+ console.log(' [!!] Node.js v' + process.versions.node + ' (>=22 required)');
980
+ ok = false;
981
+ }
982
+
983
+ var deps = [
984
+ ${checks.join(',\n')}
985
+ ];
986
+
987
+ for (var i = 0; i < deps.length; i++) {
988
+ var dep = deps[i];
989
+ try {
990
+ exec(dep.check, { stdio: 'ignore' });
991
+ console.log(' [ok] ' + dep.name + ' (' + dep.type + ')');
992
+ } catch (_) {
993
+ console.log(' [!!] ' + dep.name + ' (' + dep.type + ') - not found');
994
+ ok = false;
995
+ if (opts.fix) {
996
+ try {
997
+ var installCmd = dep.type === 'brew' ? 'brew install ' + dep.name
998
+ : dep.type === 'apt' ? 'sudo apt-get install -y ' + dep.name
999
+ : 'npm install ' + dep.name;
1000
+ console.log(' Installing: ' + installCmd);
1001
+ exec(installCmd, { stdio: 'inherit' });
1002
+ console.log(' [ok] Installed ' + dep.name);
1003
+ } catch (e) {
1004
+ console.log(' [!!] Failed to install ' + dep.name);
1005
+ }
1006
+ }
1007
+ }
1008
+ }
1009
+
1010
+ // Check FRONTMCP_HOME directory
1011
+ var fs = require('fs');
1012
+ var appDir = require('path').join(FRONTMCP_HOME, 'apps', ${JSON.stringify(appName)});
1013
+ if (fs.existsSync(appDir)) {
1014
+ console.log(' [ok] App directory: ' + appDir);
1015
+ } else {
1016
+ console.log(' [!!] App directory not found: ' + appDir);
1017
+ ok = false;
1018
+ }
1019
+
1020
+ if (ok) console.log('\\nAll checks passed.');
1021
+ else {
1022
+ console.log('\\nSome checks failed.' + (opts.fix ? '' : ' Run with --fix to attempt repairs.'));
1023
+ process.exitCode = 1;
1024
+ }
1025
+ });`;
1026
+ }
1027
+ function generateInstallCommand(appName, nativeDeps, selfContained) {
1028
+ const depEntries = [];
1029
+ if (nativeDeps.brew?.length) {
1030
+ for (const pkg of nativeDeps.brew) {
1031
+ depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', install: 'brew install ${pkg}', check: 'brew list ${pkg}' }`);
1032
+ }
1033
+ }
1034
+ if (nativeDeps.npm?.length) {
1035
+ for (const pkg of nativeDeps.npm) {
1036
+ depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', install: 'npm install ${pkg}', check: 'npm ls ${pkg}' }`);
1037
+ }
1038
+ }
1039
+ return `program
1040
+ .command('install')
1041
+ .description('Install to ~/.frontmcp/ and set up dependencies')
1042
+ .option('--prefix <path>', 'Installation prefix directory')
1043
+ .option('--bin-dir <path>', 'Directory for symlink (default: ~/.local/bin or /usr/local/bin)')
1044
+ .action(async function(opts) {
1045
+ var fs = require('fs');
1046
+ var pathMod = require('path');
1047
+ var os = require('os');
1048
+ var exec = require('child_process').execSync;
1049
+ var installBase = opts.prefix || FRONTMCP_HOME;
1050
+ var appDir = pathMod.join(installBase, 'apps', ${JSON.stringify(appName)});
1051
+ var dirs = ['', '/data', '/sessions', '/credentials'].map(function(s) { return appDir + s; });
1052
+
1053
+ console.log('Installing ${appName}...');
1054
+ dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });
1055
+
1056
+ // Copy bundle files
1057
+ var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {
1058
+ return f.endsWith('.js') || f.endsWith('.json')${selfContained ? " || f.endsWith('-bin')" : ''};
1059
+ });
1060
+ files.forEach(function(f) {
1061
+ fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));
1062
+ });
1063
+ console.log(' Copied ' + files.length + ' files to ' + appDir);
1064
+
1065
+ // Install native deps
1066
+ var deps = [
1067
+ ${depEntries.join(',\n')}
1068
+ ];
1069
+ for (var i = 0; i < deps.length; i++) {
1070
+ var dep = deps[i];
1071
+ try { exec(dep.check, { stdio: 'ignore' }); }
1072
+ catch (_) {
1073
+ console.log(' [' + (i + 1) + '/' + deps.length + '] Installing ' + dep.name + ' via ' + dep.type + '...');
1074
+ try { exec(dep.install, { stdio: 'inherit' }); }
1075
+ catch (e) { console.log(' Warning: Failed to install ' + dep.name); }
1076
+ }
1077
+ }
1078
+
1079
+ // Set execute permission on the entry point
1080
+ var entryFile = pathMod.join(appDir, ${JSON.stringify(selfContained ? `${appName}-cli-bin` : `${appName}-cli.bundle.js`)});
1081
+ try { fs.chmodSync(entryFile, 0o755); } catch (_) { /* ok */ }
1082
+
1083
+ // Create symlink
1084
+ var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];
1085
+ var linked = false;
1086
+ for (var j = 0; j < binDirs.length && !linked; j++) {
1087
+ try {
1088
+ fs.mkdirSync(binDirs[j], { recursive: true });
1089
+ var linkPath = pathMod.join(binDirs[j], ${JSON.stringify(appName)});
1090
+ try { fs.unlinkSync(linkPath); } catch (_) { /* ok */ }
1091
+ fs.symlinkSync(entryFile, linkPath);
1092
+ console.log(' Symlinked: ' + linkPath);
1093
+ linked = true;
1094
+ } catch (_) { /* try next */ }
1095
+ }
1096
+
1097
+ console.log('\\nInstalled. Run: ${appName} --help');
1098
+ });
1099
+
1100
+ program
1101
+ .command('uninstall')
1102
+ .description('Remove from ~/.frontmcp/ and clean up')
1103
+ .option('--prefix <path>', 'Installation prefix directory')
1104
+ .option('--bin-dir <path>', 'Directory where symlink was created')
1105
+ .action(async function(opts) {
1106
+ var fs = require('fs');
1107
+ var pathMod = require('path');
1108
+ var os = require('os');
1109
+ var uninstallBase = opts.prefix || FRONTMCP_HOME;
1110
+ var appDir = pathMod.join(uninstallBase, 'apps', ${JSON.stringify(appName)});
1111
+
1112
+ // Remove credentials (if auth is enabled)
1113
+ if (typeof creds !== 'undefined') {
1114
+ var store = creds.createCredentialStore();
1115
+ var credSessions = await store.list();
1116
+ for (var i = 0; i < credSessions.length; i++) {
1117
+ await store.delete(credSessions[i]);
1118
+ }
1119
+ }
1120
+
1121
+ // Remove symlink
1122
+ var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];
1123
+ binDirs.forEach(function(d) {
1124
+ try { fs.unlinkSync(pathMod.join(d, ${JSON.stringify(appName)})); } catch (_) { /* ok */ }
1125
+ });
1126
+
1127
+ // Remove app directory
1128
+ fs.rmSync(appDir, { recursive: true, force: true });
1129
+ console.log('Uninstalled ${appName}.');
1130
+ });`;
1131
+ }
1132
+ function generateDaemonCommands(appName, serverBundleFilename) {
1133
+ return `var daemonCmd = program.command('daemon').description('Daemon management');
1134
+
1135
+ daemonCmd
1136
+ .command('start')
1137
+ .description('Start as a background daemon (Unix socket)')
1138
+ .option('--idle-timeout <ms>', 'Auto-stop after idle period (ms, 0 to disable)', function(v) { return parseInt(v, 10); }, 300000)
1139
+ .action(async function(opts) {
1140
+ var { spawn } = require('child_process');
1141
+ var pathMod = require('path');
1142
+ var pidDir = pathMod.join(FRONTMCP_HOME, 'pids');
1143
+ var logDir = pathMod.join(FRONTMCP_HOME, 'logs');
1144
+ var socketDir = pathMod.join(FRONTMCP_HOME, 'sockets');
1145
+ fs.mkdirSync(pidDir, { recursive: true });
1146
+ fs.mkdirSync(logDir, { recursive: true });
1147
+ fs.mkdirSync(socketDir, { recursive: true });
1148
+
1149
+ var socketPath = pathMod.join(socketDir, ${JSON.stringify(appName)} + '.sock');
1150
+
1151
+ // Clean up stale socket file
1152
+ try { fs.unlinkSync(socketPath); } catch (_) { /* ok */ }
1153
+
1154
+ // Check if already running
1155
+ var pidPath = pathMod.join(pidDir, ${JSON.stringify(appName)} + '.pid');
1156
+ try {
1157
+ var existing = JSON.parse(fs.readFileSync(pidPath, 'utf8'));
1158
+ process.kill(existing.pid, 0);
1159
+ console.log('Daemon already running (PID: ' + existing.pid + ').');
1160
+ return;
1161
+ } catch (_) { /* not running, proceed */ }
1162
+
1163
+ var env = Object.assign({}, process.env, {
1164
+ FRONTMCP_DAEMON_SOCKET: socketPath,
1165
+ FRONTMCP_DAEMON_IDLE_TIMEOUT: String(opts.idleTimeout)
1166
+ });
1167
+
1168
+ var logPath = pathMod.join(logDir, ${JSON.stringify(appName)} + '.log');
1169
+ var out = fs.openSync(logPath, 'a');
1170
+ var err = fs.openSync(logPath, 'a');
1171
+
1172
+ // Start the daemon using runUnixSocket via a small wrapper script
1173
+ // Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)
1174
+ var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});
1175
+ var daemonScript = 'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +
1176
+ 'var sdk = require("@frontmcp/sdk");' +
1177
+ 'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +
1178
+ 'var config = mod.default || mod;' +
1179
+ 'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +
1180
+ '.then(function() { console.log("Daemon listening on " + ' + JSON.stringify(socketPath) + '); })' +
1181
+ '.catch(function(e) { console.error("Daemon failed:", e); process.exit(1); });';
1182
+
1183
+ var child = spawn('node', ['-e', daemonScript], {
1184
+ detached: true,
1185
+ stdio: ['ignore', out, err],
1186
+ env: env
1187
+ });
1188
+
1189
+ fs.writeFileSync(pidPath, JSON.stringify({
1190
+ pid: child.pid,
1191
+ socketPath: socketPath,
1192
+ startedAt: new Date().toISOString()
1193
+ }));
1194
+ child.unref();
1195
+
1196
+ // Wait for socket file to appear (max 5s)
1197
+ var waited = 0;
1198
+ while (!fs.existsSync(socketPath) && waited < 5000) {
1199
+ await new Promise(function(r) { setTimeout(r, 100); });
1200
+ waited += 100;
1201
+ }
1202
+
1203
+ if (fs.existsSync(socketPath)) {
1204
+ console.log('Daemon started (PID: ' + child.pid + '). Socket: ' + socketPath);
1205
+ console.log('Logs: ' + logPath);
1206
+ } else {
1207
+ console.log('Daemon started (PID: ' + child.pid + ') but socket not yet available.');
1208
+ console.log('Check logs: ' + logPath);
1209
+ }
1210
+ });
1211
+
1212
+ daemonCmd
1213
+ .command('stop')
1214
+ .description('Stop the daemon')
1215
+ .action(function() {
1216
+ var pathMod = require('path');
1217
+ var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');
1218
+ try {
1219
+ var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));
1220
+ process.kill(data.pid, 'SIGTERM');
1221
+ fs.unlinkSync(pidPath);
1222
+ // Clean up socket file
1223
+ if (data.socketPath) {
1224
+ try { fs.unlinkSync(data.socketPath); } catch (_) { /* ok */ }
1225
+ }
1226
+ console.log('Daemon stopped (PID: ' + data.pid + ').');
1227
+ } catch (e) {
1228
+ console.log('No running daemon found.');
1229
+ }
1230
+ });
1231
+
1232
+ daemonCmd
1233
+ .command('status')
1234
+ .description('Check daemon status')
1235
+ .action(function() {
1236
+ var pathMod = require('path');
1237
+ var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');
1238
+ try {
1239
+ var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));
1240
+ try {
1241
+ process.kill(data.pid, 0);
1242
+ var socketStatus = data.socketPath && fs.existsSync(data.socketPath) ? ', socket: active' : '';
1243
+ console.log('Running (PID: ' + data.pid + ', started: ' + data.startedAt + socketStatus + ')');
1244
+ } catch (_) {
1245
+ console.log('Not running (stale PID file).');
1246
+ fs.unlinkSync(pidPath);
1247
+ }
1248
+ } catch (_) { console.log('Not running.'); }
1249
+ });
1250
+
1251
+ daemonCmd
1252
+ .command('logs')
1253
+ .description('Tail daemon logs')
1254
+ .option('-n, --lines <n>', 'Number of lines', function(v) { return parseInt(v, 10); }, 50)
1255
+ .action(function(opts) {
1256
+ var pathMod = require('path');
1257
+ var logPath = pathMod.join(FRONTMCP_HOME, 'logs', ${JSON.stringify(appName)} + '.log');
1258
+ try {
1259
+ var content = fs.readFileSync(logPath, 'utf8');
1260
+ var lines = content.split('\\n');
1261
+ var start = Math.max(0, lines.length - opts.lines);
1262
+ console.log(lines.slice(start).join('\\n'));
1263
+ } catch (_) { console.log('No logs found.'); }
1264
+ });`;
1265
+ }
1266
+ function generateFooter() {
1267
+ return `program.parseAsync(process.argv).catch(function(err) {
1268
+ console.error('Fatal:', err.message || err);
1269
+ process.exit(1);
1270
+ });`;
1271
+ }
1272
+ /**
1273
+ * Extract {param} placeholders from a URI template string.
1274
+ */
1275
+ function extractTemplateParams(uriTemplate) {
1276
+ const matches = uriTemplate.match(/\{([^}]+)\}/g);
1277
+ if (!matches)
1278
+ return [];
1279
+ return matches.map((m) => m.slice(1, -1));
1280
+ }
1281
+ function kebabToCamel(str) {
1282
+ return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());
1283
+ }
1284
+ function escapeStr(s) {
1285
+ return s.replace(/\\/g, '\\\\').replace(/'/g, "\\'");
1286
+ }
1287
+ //# sourceMappingURL=generate-cli-entry.js.map