frontmcp 1.0.0-beta.5 → 1.0.0-beta.7
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.
- package/package.json +2 -2
- package/src/commands/build/exec/cli-runtime/daemon-client.js +1 -0
- package/src/commands/build/exec/cli-runtime/daemon-client.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +38 -7
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
- package/src/commands/scaffold/create.js +33 -4
- package/src/commands/scaffold/create.js.map +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.7",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@clack/prompts": "^0.10.0",
|
|
33
|
-
"@frontmcp/utils": "1.0.0-beta.
|
|
33
|
+
"@frontmcp/utils": "1.0.0-beta.7",
|
|
34
34
|
"commander": "^13.0.0",
|
|
35
35
|
"tslib": "^2.3.0",
|
|
36
36
|
"@rspack/core": "^1.7.6",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-client.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/daemon-client.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAQH,
|
|
1
|
+
{"version":3,"file":"daemon-client.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/daemon-client.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG;;AAQH,gEAqJC;AA3JD,0DAA0D;AAE1D;;;GAGG;AACH,SAAgB,0BAA0B;IACxC,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmJR,CAAC;AACF,CAAC","sourcesContent":["/**\n * Lightweight daemon client for CLI exec.\n *\n * Sends MCP JSON-RPC requests over a Unix socket using Node.js built-in http module.\n * This avoids the full FrontMCP SDK initialization (~420ms) by talking to an\n * already-running daemon process.\n *\n * NOTE: This file is used as a CJS runtime module — it gets bundled into the CLI\n * output by esbuild alongside the generated CLI entry. It must remain free of\n * TypeScript-only constructs at runtime (the .ts extension is for build-time only).\n */\n\n/* eslint-disable @typescript-eslint/no-require-imports */\n\n/**\n * Generate the daemon-client JavaScript source code (CJS module).\n * This is embedded into the CLI bundle at build time.\n */\nexport function generateDaemonClientSource(): string {\n return `'use strict';\n\nvar http = require('http');\n\n/**\n * Send a JSON-RPC request over a Unix socket.\n * @param {string} socketPath - Path to the Unix socket file.\n * @param {string} method - JSON-RPC method name.\n * @param {object} [params] - Method parameters.\n * @returns {Promise<object>} Parsed JSON-RPC result.\n */\nfunction rpcCall(socketPath, method, params) {\n return new Promise(function(resolve, reject) {\n var body = JSON.stringify({\n jsonrpc: '2.0',\n id: Date.now(),\n method: method,\n params: params || {}\n });\n\n var req = http.request({\n socketPath: socketPath,\n path: '/mcp',\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'Content-Length': Buffer.byteLength(body)\n },\n timeout: 10000\n }, function(res) {\n var chunks = [];\n res.on('data', function(chunk) { chunks.push(chunk); });\n res.on('end', function() {\n try {\n var json = JSON.parse(Buffer.concat(chunks).toString());\n if (json.error) {\n var err = new Error(json.error.message || 'RPC error');\n err.code = json.error.code;\n err.data = json.error.data;\n reject(err);\n } else {\n resolve(json.result);\n }\n } catch (e) {\n reject(new Error('Invalid JSON response from daemon'));\n }\n });\n });\n\n req.on('error', function(err) {\n reject(err);\n });\n\n req.on('timeout', function() {\n req.destroy();\n reject(new Error('Daemon request timed out'));\n });\n\n req.write(body);\n req.end();\n });\n}\n\n/**\n * Create a daemon client that implements the same interface as DirectClient.\n * @param {string} socketPath - Path to the Unix socket file.\n * @returns {object} Client object with MCP methods.\n */\nfunction createDaemonClient(socketPath) {\n function call(method, params) {\n return rpcCall(socketPath, method, params);\n }\n\n return {\n _isDaemon: true,\n ping: function() {\n return call('ping');\n },\n callTool: function(name, args) {\n return call('tools/call', { name: name, arguments: args || {} });\n },\n listTools: function() {\n return call('tools/list');\n },\n listResources: function() {\n return call('resources/list');\n },\n readResource: function(uri) {\n return call('resources/read', { uri: uri });\n },\n listResourceTemplates: function() {\n return call('resources/templates/list');\n },\n listPrompts: function() {\n return call('prompts/list');\n },\n getPrompt: function(name, args) {\n return call('prompts/get', { name: name, arguments: args || {} });\n },\n searchSkills: function(query) {\n return call('skills/search', { query: query || '' });\n },\n loadSkills: function(ids) {\n return call('skills/load', { ids: ids });\n },\n listSkills: function() {\n return call('skills/list');\n },\n listJobs: function() {\n return call('jobs/list');\n },\n executeJob: function(name, input, opts) {\n return call('jobs/execute', { name: name, input: input, options: opts });\n },\n getJobStatus: function(runId) {\n return call('jobs/status', { runId: runId });\n },\n listWorkflows: function() {\n return call('workflows/list');\n },\n executeWorkflow: function(name, input, opts) {\n return call('workflows/execute', { name: name, input: input, options: opts });\n },\n getWorkflowStatus: function(runId) {\n return call('workflows/status', { runId: runId });\n },\n subscribeResource: function(uri) {\n return call('resources/subscribe', { uri: uri });\n },\n unsubscribeResource: function(uri) {\n return call('resources/unsubscribe', { uri: uri });\n },\n onResourceUpdated: function() {\n console.warn('Resource subscriptions are not supported in daemon mode (HTTP-based, no push).');\n return function() {};\n },\n onNotification: function() {\n console.warn('Notifications are not supported in daemon mode (HTTP-based, no push).');\n return function() {};\n },\n close: function() {\n return Promise.resolve();\n }\n };\n}\n\nexports.createDaemonClient = createDaemonClient;\n`;\n}\n"]}
|
|
@@ -762,14 +762,33 @@ workflowCmd
|
|
|
762
762
|
});`;
|
|
763
763
|
}
|
|
764
764
|
function generateSubscribeCommands() {
|
|
765
|
-
return `
|
|
765
|
+
return `
|
|
766
|
+
// Subscribe commands need push support (onNotification/onResourceUpdated).
|
|
767
|
+
// Daemon HTTP cannot push, so we force in-process when daemon was used.
|
|
768
|
+
async function getSubscribeClient() {
|
|
769
|
+
var client = await getClient();
|
|
770
|
+
// If connected via daemon, the onNotification/onResourceUpdated are no-ops.
|
|
771
|
+
// Reconnect via in-process for push support.
|
|
772
|
+
if (client._isDaemon) {
|
|
773
|
+
_client = null; // clear cached daemon client
|
|
774
|
+
var mod = require(SERVER_BUNDLE);
|
|
775
|
+
var configOrClass = mod.default || mod;
|
|
776
|
+
var sdk = require('@frontmcp/sdk');
|
|
777
|
+
var connect = sdk.connect || sdk.direct.connect;
|
|
778
|
+
_client = await connect(configOrClass, { mode: 'cli' });
|
|
779
|
+
return _client;
|
|
780
|
+
}
|
|
781
|
+
return client;
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
var subscribeCmd = program.command('subscribe').description('Subscribe to updates');
|
|
766
785
|
|
|
767
786
|
subscribeCmd
|
|
768
787
|
.command('resource <uri>')
|
|
769
788
|
.description('Stream resource updates (Ctrl+C to stop)')
|
|
770
789
|
.action(async function(uri) {
|
|
771
790
|
try {
|
|
772
|
-
var client = await
|
|
791
|
+
var client = await getSubscribeClient();
|
|
773
792
|
await client.subscribeResource(uri);
|
|
774
793
|
var mode = program.opts().output || 'text';
|
|
775
794
|
console.log('Subscribed to resource: ' + uri);
|
|
@@ -782,7 +801,9 @@ subscribeCmd
|
|
|
782
801
|
try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }
|
|
783
802
|
process.exit(0);
|
|
784
803
|
});
|
|
785
|
-
// Keep process alive
|
|
804
|
+
// Keep process alive — setInterval creates an active event loop handle
|
|
805
|
+
// so Node.js won't exit even with InMemoryTransport (no persistent I/O)
|
|
806
|
+
setInterval(function() {}, 2147483647);
|
|
786
807
|
await new Promise(function() {});
|
|
787
808
|
} catch (err) {
|
|
788
809
|
console.error('Error:', err.message || err);
|
|
@@ -795,7 +816,7 @@ subscribeCmd
|
|
|
795
816
|
.description('Stream notifications (Ctrl+C to stop)')
|
|
796
817
|
.action(async function(name) {
|
|
797
818
|
try {
|
|
798
|
-
var client = await
|
|
819
|
+
var client = await getSubscribeClient();
|
|
799
820
|
var mode = program.opts().output || 'text';
|
|
800
821
|
console.log('Listening for notification: ' + name);
|
|
801
822
|
console.log('Waiting for events... (Ctrl+C to stop)\\n');
|
|
@@ -808,7 +829,9 @@ subscribeCmd
|
|
|
808
829
|
console.log('\\nStopping...');
|
|
809
830
|
process.exit(0);
|
|
810
831
|
});
|
|
811
|
-
// Keep process alive
|
|
832
|
+
// Keep process alive — setInterval creates an active event loop handle
|
|
833
|
+
// so Node.js won't exit even with InMemoryTransport (no persistent I/O)
|
|
834
|
+
setInterval(function() {}, 2147483647);
|
|
812
835
|
await new Promise(function() {});
|
|
813
836
|
} catch (err) {
|
|
814
837
|
console.error('Error:', err.message || err);
|
|
@@ -1015,6 +1038,10 @@ ${checks.join(',\n')}
|
|
|
1015
1038
|
} else {
|
|
1016
1039
|
console.log(' [!!] App directory not found: ' + appDir);
|
|
1017
1040
|
ok = false;
|
|
1041
|
+
if (opts.fix) {
|
|
1042
|
+
fs.mkdirSync(appDir, { recursive: true });
|
|
1043
|
+
console.log(' [fixed] Created ' + appDir);
|
|
1044
|
+
}
|
|
1018
1045
|
}
|
|
1019
1046
|
|
|
1020
1047
|
if (ok) console.log('\\nAll checks passed.');
|
|
@@ -1172,10 +1199,14 @@ daemonCmd
|
|
|
1172
1199
|
// Start the daemon using runUnixSocket via a small wrapper script
|
|
1173
1200
|
// Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)
|
|
1174
1201
|
var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});
|
|
1175
|
-
var daemonScript = '
|
|
1202
|
+
var daemonScript = 'require("reflect-metadata");' +
|
|
1203
|
+
'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +
|
|
1176
1204
|
'var sdk = require("@frontmcp/sdk");' +
|
|
1177
1205
|
'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +
|
|
1178
|
-
'var
|
|
1206
|
+
'var raw = mod.default || mod;' +
|
|
1207
|
+
// If the export is a @FrontMcp-decorated class, extract config via Reflect metadata
|
|
1208
|
+
'var config = (typeof raw === "function" && typeof Reflect !== "undefined" && Reflect.getMetadata) ' +
|
|
1209
|
+
' ? (Reflect.getMetadata("__frontmcp:config", raw) || raw) : raw;' +
|
|
1179
1210
|
'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +
|
|
1180
1211
|
'.then(function() { console.log("Daemon listening on " + ' + JSON.stringify(socketPath) + '); })' +
|
|
1181
1212
|
'.catch(function(e) { console.error("Daemon failed:", e); process.exit(1); });';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-cli-entry.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/generate-cli-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generates the CLI entry point TypeScript/JavaScript source code.\n * This creates a commander.js-based CLI where each MCP tool is a subcommand.\n */\n\nimport { CliConfig, OAuthConfig } from '../config';\nimport { ExtractedSchema, ExtractedTool, ExtractedPrompt, ExtractedResourceTemplate, ExtractedCapabilities, ExtractedJob, SYSTEM_TOOL_NAMES } from './schema-extractor';\nimport { schemaToCommander, generateOptionCode, camelToKebab } from './schema-to-commander';\n\nexport const RESERVED_COMMANDS = new Set([\n 'resource', 'template', 'prompt', 'subscribe',\n 'login', 'logout', 'connect', 'serve', 'daemon',\n 'doctor', 'install', 'uninstall', 'sessions', 'help', 'version',\n 'skills', 'job', 'workflow',\n]);\n\nexport interface CliEntryOptions {\n appName: string;\n appVersion: string;\n description: string;\n serverBundleFilename: string;\n outputDefault: 'text' | 'json';\n authRequired: boolean;\n excludeTools: string[];\n nativeDeps: NonNullable<CliConfig['nativeDeps']>;\n schema: ExtractedSchema;\n oauthConfig?: OAuthConfig;\n /** When true, generate static requires that esbuild can resolve (for SEA builds). */\n selfContained?: boolean;\n}\n\n/**\n * Resolve tool command name, appending '-tool' suffix if it conflicts with a built-in command.\n * Returns { cmdName, wasRenamed } so the caller can log a warning at build time.\n */\nexport function resolveToolCommandName(toolName: string): { cmdName: string; wasRenamed: boolean } {\n const cmdName = camelToKebab(toolName).replace(/_/g, '-');\n if (RESERVED_COMMANDS.has(cmdName)) {\n return { cmdName: `${cmdName}-tool`, wasRenamed: true };\n }\n return { cmdName, wasRenamed: false };\n}\n\n/**\n * Generate the CLI entry source code (CJS module).\n */\nexport function generateCliEntry(options: CliEntryOptions): string {\n const {\n appName,\n appVersion,\n description,\n serverBundleFilename,\n outputDefault,\n schema,\n excludeTools,\n oauthConfig,\n authRequired,\n } = options;\n\n const capabilities = schema.capabilities;\n\n const filteredTools = schema.tools.filter(\n (t) => !excludeTools.includes(t.name) && !SYSTEM_TOOL_NAMES.has(t.name),\n );\n\n const selfContained = !!options.selfContained;\n\n const sections: string[] = [\n generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained),\n generateToolCommands(filteredTools, appName),\n generateResourceCommands(schema),\n generateTemplateCommands(schema.resourceTemplates),\n generatePromptCommands(schema.prompts),\n capabilities.skills ? generateSkillsCommands() : '',\n capabilities.jobs ? generateJobCommands(schema.jobs) : '',\n capabilities.workflows ? generateWorkflowCommands() : '',\n generateSubscribeCommands(),\n ...(authRequired ? [\n generateLoginCommand(appName, oauthConfig),\n generateLogoutCommand(appName),\n generateSessionCommands(),\n ] : []),\n generateServeCommand(serverBundleFilename),\n generateDoctorCommand(appName, options.nativeDeps),\n generateInstallCommand(appName, options.nativeDeps, selfContained),\n generateDaemonCommands(appName, serverBundleFilename),\n generateFooter(),\n ];\n\n return sections.filter(Boolean).join('\\n\\n');\n}\n\nfunction generateHeader(\n appName: string,\n appVersion: string,\n description: string,\n serverBundleFilename: string,\n outputDefault: string,\n authRequired: boolean,\n capabilities: ExtractedCapabilities,\n oauthConfig?: OAuthConfig,\n selfContained?: boolean,\n): string {\n const hasOAuth = !!oauthConfig;\n\n // Build the group routing map dynamically\n const skillsRouting = capabilities.skills ? `\\n else if (name === 'skills') groups['Skills'].push(sub);` : '';\n const jobsRouting = capabilities.jobs ? `\\n else if (name === 'job') groups['Jobs'].push(sub);` : '';\n const workflowsRouting = capabilities.workflows ? `\\n else if (name === 'workflow') groups['Workflows'].push(sub);` : '';\n const authRouting = authRequired ? `\\n else if (['login', 'logout', 'sessions', 'connect'].indexOf(name) !== -1) groups['Auth'].push(sub);` : '';\n\n // Build the groups object dynamically\n const groupEntries: string[] = [\n ` 'Tools': []`,\n ` 'Resources & Prompts': []`,\n ];\n if (capabilities.skills) groupEntries.push(` 'Skills': []`);\n if (capabilities.jobs) groupEntries.push(` 'Jobs': []`);\n if (capabilities.workflows) groupEntries.push(` 'Workflows': []`);\n if (authRequired) groupEntries.push(` 'Auth': []`);\n groupEntries.push(` 'Subscriptions': []`);\n groupEntries.push(` 'System': []`);\n\n return `'use strict';\n\nvar { Command, Option } = require('commander');\nvar path = require('path');\nvar fs = require('fs');\nvar os = require('os');\nvar fmt = require('./output-formatter');\n${authRequired ? \"var sessions = require('./session-manager');\\nvar creds = require('./credential-store');\" : ''}\n${hasOAuth ? \"var oauthHelper = require('./oauth-helper');\" : ''}\n\nvar APP_NAME = ${JSON.stringify(appName)};\nvar SCRIPT_DIR = __dirname;\nvar FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');\n${selfContained\n ? `// Self-contained: server bundle and SDK are inlined by esbuild\nvar SERVER_BUNDLE = '../${serverBundleFilename}';`\n : `var SERVER_BUNDLE = path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});`}\n\nvar _client = null;\nasync function getClient() {\n if (_client) return _client;\n\n // Try daemon first — Unix socket HTTP (~5-15ms vs ~420ms in-process)\n var socketPath = path.join(FRONTMCP_HOME, 'sockets', APP_NAME + '.sock');\n if (fs.existsSync(socketPath)) {\n try {\n var daemonClient = require('./daemon-client');\n var dc = daemonClient.createDaemonClient(socketPath);\n await dc.ping();\n _client = dc;\n return _client;\n } catch (_) { /* daemon not available, fall through */ }\n }\n\n // Fallback: in-process connect (with CLI mode for faster init)\n var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;${authRequired ? `\n var sessionName = sessions.getActiveSessionName();\n var store = creds.createCredentialStore();\n var credBlob = await store.get(sessionName);\n var connectOpts = credBlob ? { authToken: credBlob.token, mode: 'cli' } : { mode: 'cli' };\n _client = await connect(configOrClass, connectOpts);` : `\n _client = await connect(configOrClass, { mode: 'cli' });`}\n return _client;\n}\n\nvar program = new Command();\nprogram\n .name(${JSON.stringify(appName)})\n .version(${JSON.stringify(appVersion)})\n .description(${JSON.stringify(description || `${appName} CLI`)})\n .option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)});\n\nprogram.configureHelp({\n sortSubcommands: false,\n formatHelp: function(cmd, helper) {\n var groups = {\n${groupEntries.join(',\\n')}\n };\n var toolCmdNames = cmd._toolCommandNames || [];\n cmd.commands.forEach(function(sub) {\n var name = sub.name();\n if (toolCmdNames.indexOf(name) !== -1) groups['Tools'].push(sub);\n else if (['resource', 'template', 'prompt'].indexOf(name) !== -1) groups['Resources & Prompts'].push(sub);${skillsRouting}${jobsRouting}${workflowsRouting}${authRouting}\n else if (name === 'subscribe') groups['Subscriptions'].push(sub);\n else groups['System'].push(sub);\n });\n var termWidth = helper.padWidth(cmd, helper);\n var lines = [];\n lines.push('Usage: ' + helper.commandUsage(cmd));\n lines.push('');\n var desc = helper.commandDescription(cmd);\n if (desc) { lines.push(desc); lines.push(''); }\n var globalOpts = helper.formatHelp ? helper.visibleOptions(cmd) : [];\n if (globalOpts.length > 0) {\n lines.push('Options:');\n globalOpts.forEach(function(opt) {\n lines.push(' ' + helper.optionTerm(opt).padEnd(termWidth) + ' ' + helper.optionDescription(opt));\n });\n lines.push('');\n }\n Object.keys(groups).forEach(function(groupName) {\n var cmds = groups[groupName];\n if (cmds.length === 0) return;\n lines.push(groupName + ':');\n cmds.forEach(function(sub) {\n lines.push(' ' + helper.subcommandTerm(sub).padEnd(termWidth) + ' ' + helper.subcommandDescription(sub));\n });\n lines.push('');\n });\n return lines.join('\\\\n');\n }\n});\n\nprogram.action(function() { program.outputHelp(); });`;\n}\n\nfunction generateToolCommands(tools: ExtractedTool[], appName: string): string {\n if (tools.length === 0) return '// No tools extracted\\nprogram._toolCommandNames = [];';\n\n const cmdNames: string[] = [];\n const commands = tools.map((tool) => {\n const { cmdName } = resolveToolCommandName(tool.name);\n cmdNames.push(cmdName);\n const { options } = schemaToCommander(tool.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n\n return `program\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tool.description)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${generateArgMapping(tool)}\n var result = await client.callTool(${JSON.stringify(tool.name)}, args);\n var mode = program.opts().output || ${JSON.stringify('text')};\n console.log(fmt.formatToolResult(result, mode));\n } catch (err) {\n var meta = err && err._meta ? err._meta : (err && err.data && err.data._meta ? err.data._meta : null);\n if (meta && meta.authorization_required) {\n console.error('Authorization required' + (meta.app ? ' for ' + meta.app : ''));\n if (meta.auth_url) console.error('Authorize at: ' + meta.auth_url);\n console.error('Or run: ' + ${JSON.stringify(appName)} + ' login');\n } else {\n console.error('Error:', err.message || err);\n }\n process.exitCode = 1;\n }\n });`;\n });\n\n return `program._toolCommandNames = ${JSON.stringify(cmdNames)};\\n\\n${commands.join('\\n\\n')}`;\n}\n\nfunction generateArgMapping(tool: ExtractedTool): string {\n const props = (tool.inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n // Commander converts kebab-case flags to camelCase in opts()\n const camel = kebabToCamel(kebab);\n\n // Resolve type for object detection\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { args[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateJobArgMapping(inputSchema: Record<string, unknown>): string {\n const props = (inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n const camel = kebabToCamel(kebab);\n\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { input[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) input[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateResourceCommands(_schema: ExtractedSchema): string {\n return `var resourceCmd = program.command('resource').description('Resource operations');\n\nresourceCmd\n .command('list')\n .description('List available resources')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResources();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var resources = result.resources || [];\n if (resources.length === 0) { console.log('No resources available.'); return; }\n resources.forEach(function(r) {\n console.log(' ' + r.uri + (r.description ? ' - ' + r.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nresourceCmd\n .command('read <uri>')\n .description('Read a resource by URI')\n .action(async function(uri) {\n try {\n var client = await getClient();\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateTemplateCommands(templates: ExtractedResourceTemplate[]): string {\n if (!templates || templates.length === 0) return '// No resource templates extracted';\n\n const subcommands = templates.map((tmpl) => {\n const cmdName = camelToKebab(tmpl.name).replace(/_/g, '-');\n // Extract {param} placeholders from URI template\n const paramNames = extractTemplateParams(tmpl.uriTemplate);\n const optionLines = paramNames\n .map((p) => ` .requiredOption('--${camelToKebab(p)} <value>', 'Template parameter: ${p}')`)\n .join('\\n');\n\n const paramMapping = paramNames\n .map((p) => {\n const camel = kebabToCamel(camelToKebab(p));\n return `uri = uri.replace('{${p}}', encodeURIComponent(rawOpts[${JSON.stringify(camel)}]));`;\n })\n .join('\\n ');\n\n return `templateCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tmpl.description || `Read resource from template: ${tmpl.uriTemplate}`)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var rawOpts = this.opts();\n var uri = ${JSON.stringify(tmpl.uriTemplate)};\n ${paramMapping}\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var templateCmd = program.command('template').description('Resource template operations');\n\ntemplateCmd\n .command('list')\n .description('List available resource templates')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResourceTemplates();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var templates = result.resourceTemplates || [];\n if (templates.length === 0) { console.log('No resource templates available.'); return; }\n templates.forEach(function(t) {\n console.log(' ' + t.uriTemplate + (t.description ? ' - ' + t.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generatePromptCommands(prompts: ExtractedPrompt[]): string {\n const subcommands = prompts.map((prompt) => {\n const cmdName = camelToKebab(prompt.name).replace(/_/g, '-');\n const argOptions = (prompt.arguments || [])\n .map((a) => {\n const flag = `--${camelToKebab(a.name)} <value>`;\n const desc = a.description || '';\n return a.required\n ? ` .requiredOption('${flag}', '${escapeStr(desc)}')`\n : ` .option('${flag}', '${escapeStr(desc)}')`;\n })\n .join('\\n');\n\n return `promptCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(prompt.description || '')})\n${argOptions}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${(prompt.arguments || []).map((a) => {\n const camel = kebabToCamel(camelToKebab(a.name));\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(a.name)}] = rawOpts[${JSON.stringify(camel)}];`;\n }).join('\\n ')}\n var result = await client.getPrompt(${JSON.stringify(prompt.name)}, args);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatPromptResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var promptCmd = program.command('prompt').description('Prompt operations');\n\npromptCmd\n .command('list')\n .description('List available prompts')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listPrompts();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var prompts = result.prompts || [];\n if (prompts.length === 0) { console.log('No prompts available.'); return; }\n prompts.forEach(function(p) {\n console.log(' ' + p.name + (p.description ? ' - ' + p.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generateSkillsCommands(): string {\n return `var skillsCmd = program.command('skills').description('Skill operations');\n\nskillsCmd\n .command('search [query]')\n .description('Search for skills')\n .action(async function(query) {\n try {\n var client = await getClient();\n var result = await client.searchSkills(query || '');\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills found.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('load <ids...>')\n .description('Load skills by ID')\n .action(async function(ids) {\n try {\n var client = await getClient();\n var result = await client.loadSkills(ids);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Loaded ' + ids.length + ' skill(s).');\n if (result && typeof result === 'object') {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('list')\n .description('List available skills')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listSkills();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills available.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateJobCommands(jobs: ExtractedJob[]): string {\n // Generate typed 'run' subcommands for each known job\n const runSubcommands = jobs.map((job) => {\n const jobCmdName = camelToKebab(job.name).replace(/_/g, '-');\n\n if (job.inputSchema) {\n const { options } = schemaToCommander(job.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n const argMapping = generateJobArgMapping(job.inputSchema);\n\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n${optionLines}\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n var rawOpts = this.opts();\n ${argMapping}\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!rawOpts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (rawOpts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n }\n\n // No inputSchema — fall back to generic --input <json>\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n // Generic fallback 'run' for jobs not known at build time\n const genericRun = `jobRunCmd\n .command('_run <name>')\n .description('Run a job by name (generic)')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n\n return `var jobCmd = program.command('job').description('Job operations');\n\njobCmd\n .command('list')\n .description('List available jobs')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listJobs();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var jobs = result.jobs || result || [];\n if (Array.isArray(jobs) && jobs.length === 0) { console.log('No jobs available.'); return; }\n if (Array.isArray(jobs)) {\n jobs.forEach(function(j) {\n console.log(' ' + (j.name || j.id || JSON.stringify(j)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nvar jobRunCmd = jobCmd.command('run').description('Run a job');\n\n${runSubcommands.join('\\n\\n')}\n\n${jobs.length > 0 ? genericRun : `jobRunCmd\n .argument('<name>', 'Job name')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`}\n\njobCmd\n .command('status <runId>')\n .description('Get the status of a job run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getJobStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateWorkflowCommands(): string {\n return `var workflowCmd = program.command('workflow').description('Workflow operations');\n\nworkflowCmd\n .command('list')\n .description('List available workflows')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listWorkflows();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var workflows = result.workflows || result || [];\n if (Array.isArray(workflows) && workflows.length === 0) { console.log('No workflows available.'); return; }\n if (Array.isArray(workflows)) {\n workflows.forEach(function(w) {\n console.log(' ' + (w.name || w.id || JSON.stringify(w)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('run <name>')\n .description('Run a workflow by name')\n .option('--input <json>', 'Workflow input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeWorkflow(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Workflow started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('status <runId>')\n .description('Get the status of a workflow run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getWorkflowStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateSubscribeCommands(): string {\n return `var subscribeCmd = program.command('subscribe').description('Subscribe to updates');\n\nsubscribeCmd\n .command('resource <uri>')\n .description('Stream resource updates (Ctrl+C to stop)')\n .action(async function(uri) {\n try {\n var client = await getClient();\n await client.subscribeResource(uri);\n var mode = program.opts().output || 'text';\n console.log('Subscribed to resource: ' + uri);\n console.log('Waiting for updates... (Ctrl+C to stop)\\\\n');\n client.onResourceUpdated(function(uri) {\n console.log(fmt.formatSubscriptionEvent({ type: 'resource_updated', uri: uri, timestamp: new Date().toISOString() }, mode));\n });\n process.on('SIGINT', async function() {\n console.log('\\\\nUnsubscribing...');\n try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }\n process.exit(0);\n });\n // Keep process alive\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nsubscribeCmd\n .command('notification <name>')\n .description('Stream notifications (Ctrl+C to stop)')\n .action(async function(name) {\n try {\n var client = await getClient();\n var mode = program.opts().output || 'text';\n console.log('Listening for notification: ' + name);\n console.log('Waiting for events... (Ctrl+C to stop)\\\\n');\n client.onNotification(function(notification) {\n if (notification.method === name || name === '*') {\n console.log(fmt.formatSubscriptionEvent({ type: 'notification', method: notification.method, params: notification.params, timestamp: new Date().toISOString() }, mode));\n }\n });\n process.on('SIGINT', function() {\n console.log('\\\\nStopping...');\n process.exit(0);\n });\n // Keep process alive\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLoginCommand(appName: string, oauthConfig?: OAuthConfig): string {\n const serverUrl = oauthConfig?.serverUrl || '';\n const clientId = oauthConfig?.clientId || appName;\n const defaultScope = oauthConfig?.defaultScope || '';\n const portStart = oauthConfig?.portRange?.[0] ?? 17830;\n const portEnd = oauthConfig?.portRange?.[1] ?? 17850;\n const timeout = oauthConfig?.timeout ?? 120000;\n\n return `program\n .command('login')\n .description('Authenticate via OAuth')\n .option('--server <url>', 'Server URL for OAuth'${serverUrl ? `, ${JSON.stringify(serverUrl)}` : ''})\n .option('--session <name>', 'Session name', 'default')\n .option('--scope <scopes>', 'OAuth scopes'${defaultScope ? `, ${JSON.stringify(defaultScope)}` : ''})\n .option('--no-browser', 'Print URL instead of opening browser')\n .action(async function(opts) {\n var serverUrl = opts.server || process.env.FRONTMCP_SERVER_URL || ${JSON.stringify(serverUrl)};\n if (!serverUrl) {\n console.error('Server URL required. Use --server <url> or set FRONTMCP_SERVER_URL.');\n process.exitCode = 1;\n return;\n }\n try {\n var oauthHelper = require('./oauth-helper');\n var result = await oauthHelper.startOAuthLogin({\n serverUrl: serverUrl,\n clientId: ${JSON.stringify(clientId)},\n scope: opts.scope || ${JSON.stringify(defaultScope)},\n portStart: ${portStart},\n portEnd: ${portEnd},\n timeout: ${timeout},\n noBrowser: !opts.browser\n });\n var sessionName = opts.session || 'default';\n var store = creds.createCredentialStore();\n await store.set(sessionName, result);\n sessions.getOrCreateSession(sessionName);\n console.log('Logged in successfully. Session: ' + sessionName);\n } catch (err) {\n console.error('Login failed:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLogoutCommand(_appName: string): string {\n return `program\n .command('logout')\n .description('Clear stored credentials')\n .option('--session <name>', 'Session to log out')\n .option('--all', 'Log out of all sessions')\n .action(async function(opts) {\n var store = creds.createCredentialStore();\n if (opts.all) {\n var allSessions = await store.list();\n for (var i = 0; i < allSessions.length; i++) {\n await store.delete(allSessions[i]);\n }\n console.log('Logged out of ' + allSessions.length + ' session(s).');\n } else {\n var sessionName = opts.session || sessions.getActiveSessionName();\n await store.delete(sessionName);\n console.log('Logged out of session: ' + sessionName);\n }\n });`;\n}\n\nfunction generateSessionCommands(): string {\n return `var sessionsCmd = program.command('sessions').description('Session management');\n\nsessionsCmd\n .command('list')\n .description('List all sessions')\n .action(function() {\n var list = sessions.listSessions();\n if (list.length === 0) { console.log('No sessions.'); return; }\n list.forEach(function(s) {\n var marker = s.isActive ? ' (active)' : '';\n console.log(' ' + s.name + marker + ' - last used: ' + s.lastUsedAt);\n });\n });\n\nsessionsCmd\n .command('switch <name>')\n .description('Switch to a named session')\n .action(function(name) {\n sessions.switchSession(name);\n console.log('Switched to session: ' + name);\n });\n\nsessionsCmd\n .command('delete <name>')\n .description('Delete a session')\n .action(async function(name) {\n var store = creds.createCredentialStore();\n await store.delete(name);\n sessions.deleteSession(name);\n console.log('Deleted session: ' + name);\n });\n\nprogram\n .command('connect')\n .description('Authenticate and store credentials')\n .option('--session <name>', 'Session name', 'default')\n .option('--token <token>', 'Auth token (or pass via stdin)')\n .action(async function(opts) {\n var sessionName = opts.session || 'default';\n var token = opts.token;\n if (!token) {\n console.log('Usage: ' + program.name() + ' connect --token <your-token>');\n console.log(' Or pipe token: echo \"tok_xxx\" | ' + program.name() + ' connect');\n process.exitCode = 1;\n return;\n }\n var store = creds.createCredentialStore();\n await store.set(sessionName, { token: token });\n sessions.getOrCreateSession(sessionName);\n console.log('Credentials stored for session: ' + sessionName);\n });`;\n}\n\nfunction generateServeCommand(serverBundleFilename: string): string {\n return `program\n .command('serve')\n .description('Start the HTTP/SSE server')\n .option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })\n .action(async function(opts) {\n var mod = require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}));\n if (opts.port) process.env.PORT = String(opts.port);\n // The server bundle should self-start when required\n if (typeof mod.start === 'function') await mod.start();\n else if (typeof mod.default?.start === 'function') await mod.default.start();\n });`;\n}\n\nfunction generateDoctorCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n): string {\n const checks: string[] = [];\n\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.apt?.length) {\n for (const pkg of nativeDeps.apt) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'apt', check: 'dpkg -l ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('doctor')\n .description('Check system dependencies and configuration')\n .option('--fix', 'Attempt to install missing dependencies')\n .action(async function(opts) {\n var exec = require('child_process').execSync;\n var ok = true;\n\n // Check Node.js version\n var nodeMajor = parseInt(process.versions.node.split('.')[0], 10);\n if (nodeMajor >= 22) {\n console.log(' [ok] Node.js v' + process.versions.node);\n } else {\n console.log(' [!!] Node.js v' + process.versions.node + ' (>=22 required)');\n ok = false;\n }\n\n var deps = [\n${checks.join(',\\n')}\n ];\n\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try {\n exec(dep.check, { stdio: 'ignore' });\n console.log(' [ok] ' + dep.name + ' (' + dep.type + ')');\n } catch (_) {\n console.log(' [!!] ' + dep.name + ' (' + dep.type + ') - not found');\n ok = false;\n if (opts.fix) {\n try {\n var installCmd = dep.type === 'brew' ? 'brew install ' + dep.name\n : dep.type === 'apt' ? 'sudo apt-get install -y ' + dep.name\n : 'npm install ' + dep.name;\n console.log(' Installing: ' + installCmd);\n exec(installCmd, { stdio: 'inherit' });\n console.log(' [ok] Installed ' + dep.name);\n } catch (e) {\n console.log(' [!!] Failed to install ' + dep.name);\n }\n }\n }\n }\n\n // Check FRONTMCP_HOME directory\n var fs = require('fs');\n var appDir = require('path').join(FRONTMCP_HOME, 'apps', ${JSON.stringify(appName)});\n if (fs.existsSync(appDir)) {\n console.log(' [ok] App directory: ' + appDir);\n } else {\n console.log(' [!!] App directory not found: ' + appDir);\n ok = false;\n }\n\n if (ok) console.log('\\\\nAll checks passed.');\n else {\n console.log('\\\\nSome checks failed.' + (opts.fix ? '' : ' Run with --fix to attempt repairs.'));\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateInstallCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n selfContained?: boolean,\n): string {\n const depEntries: string[] = [];\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', install: 'brew install ${pkg}', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', install: 'npm install ${pkg}', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('install')\n .description('Install to ~/.frontmcp/ and set up dependencies')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory for symlink (default: ~/.local/bin or /usr/local/bin)')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var exec = require('child_process').execSync;\n var installBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(installBase, 'apps', ${JSON.stringify(appName)});\n var dirs = ['', '/data', '/sessions', '/credentials'].map(function(s) { return appDir + s; });\n\n console.log('Installing ${appName}...');\n dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });\n\n // Copy bundle files\n var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {\n return f.endsWith('.js') || f.endsWith('.json')${selfContained ? \" || f.endsWith('-bin')\" : ''};\n });\n files.forEach(function(f) {\n fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));\n });\n console.log(' Copied ' + files.length + ' files to ' + appDir);\n\n // Install native deps\n var deps = [\n${depEntries.join(',\\n')}\n ];\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try { exec(dep.check, { stdio: 'ignore' }); }\n catch (_) {\n console.log(' [' + (i + 1) + '/' + deps.length + '] Installing ' + dep.name + ' via ' + dep.type + '...');\n try { exec(dep.install, { stdio: 'inherit' }); }\n catch (e) { console.log(' Warning: Failed to install ' + dep.name); }\n }\n }\n\n // Set execute permission on the entry point\n var entryFile = pathMod.join(appDir, ${JSON.stringify(selfContained ? `${appName}-cli-bin` : `${appName}-cli.bundle.js`)});\n try { fs.chmodSync(entryFile, 0o755); } catch (_) { /* ok */ }\n\n // Create symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n var linked = false;\n for (var j = 0; j < binDirs.length && !linked; j++) {\n try {\n fs.mkdirSync(binDirs[j], { recursive: true });\n var linkPath = pathMod.join(binDirs[j], ${JSON.stringify(appName)});\n try { fs.unlinkSync(linkPath); } catch (_) { /* ok */ }\n fs.symlinkSync(entryFile, linkPath);\n console.log(' Symlinked: ' + linkPath);\n linked = true;\n } catch (_) { /* try next */ }\n }\n\n console.log('\\\\nInstalled. Run: ${appName} --help');\n });\n\nprogram\n .command('uninstall')\n .description('Remove from ~/.frontmcp/ and clean up')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory where symlink was created')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var uninstallBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(uninstallBase, 'apps', ${JSON.stringify(appName)});\n\n // Remove credentials (if auth is enabled)\n if (typeof creds !== 'undefined') {\n var store = creds.createCredentialStore();\n var credSessions = await store.list();\n for (var i = 0; i < credSessions.length; i++) {\n await store.delete(credSessions[i]);\n }\n }\n\n // Remove symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n binDirs.forEach(function(d) {\n try { fs.unlinkSync(pathMod.join(d, ${JSON.stringify(appName)})); } catch (_) { /* ok */ }\n });\n\n // Remove app directory\n fs.rmSync(appDir, { recursive: true, force: true });\n console.log('Uninstalled ${appName}.');\n });`;\n}\n\nfunction generateDaemonCommands(appName: string, serverBundleFilename: string): string {\n return `var daemonCmd = program.command('daemon').description('Daemon management');\n\ndaemonCmd\n .command('start')\n .description('Start as a background daemon (Unix socket)')\n .option('--idle-timeout <ms>', 'Auto-stop after idle period (ms, 0 to disable)', function(v) { return parseInt(v, 10); }, 300000)\n .action(async function(opts) {\n var { spawn } = require('child_process');\n var pathMod = require('path');\n var pidDir = pathMod.join(FRONTMCP_HOME, 'pids');\n var logDir = pathMod.join(FRONTMCP_HOME, 'logs');\n var socketDir = pathMod.join(FRONTMCP_HOME, 'sockets');\n fs.mkdirSync(pidDir, { recursive: true });\n fs.mkdirSync(logDir, { recursive: true });\n fs.mkdirSync(socketDir, { recursive: true });\n\n var socketPath = pathMod.join(socketDir, ${JSON.stringify(appName)} + '.sock');\n\n // Clean up stale socket file\n try { fs.unlinkSync(socketPath); } catch (_) { /* ok */ }\n\n // Check if already running\n var pidPath = pathMod.join(pidDir, ${JSON.stringify(appName)} + '.pid');\n try {\n var existing = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(existing.pid, 0);\n console.log('Daemon already running (PID: ' + existing.pid + ').');\n return;\n } catch (_) { /* not running, proceed */ }\n\n var env = Object.assign({}, process.env, {\n FRONTMCP_DAEMON_SOCKET: socketPath,\n FRONTMCP_DAEMON_IDLE_TIMEOUT: String(opts.idleTimeout)\n });\n\n var logPath = pathMod.join(logDir, ${JSON.stringify(appName)} + '.log');\n var out = fs.openSync(logPath, 'a');\n var err = fs.openSync(logPath, 'a');\n\n // Start the daemon using runUnixSocket via a small wrapper script\n // Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)\n var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});\n var daemonScript = 'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +\n 'var sdk = require(\"@frontmcp/sdk\");' +\n 'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +\n 'var config = mod.default || mod;' +\n 'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +\n '.then(function() { console.log(\"Daemon listening on \" + ' + JSON.stringify(socketPath) + '); })' +\n '.catch(function(e) { console.error(\"Daemon failed:\", e); process.exit(1); });';\n\n var child = spawn('node', ['-e', daemonScript], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });\n\n fs.writeFileSync(pidPath, JSON.stringify({\n pid: child.pid,\n socketPath: socketPath,\n startedAt: new Date().toISOString()\n }));\n child.unref();\n\n // Wait for socket file to appear (max 5s)\n var waited = 0;\n while (!fs.existsSync(socketPath) && waited < 5000) {\n await new Promise(function(r) { setTimeout(r, 100); });\n waited += 100;\n }\n\n if (fs.existsSync(socketPath)) {\n console.log('Daemon started (PID: ' + child.pid + '). Socket: ' + socketPath);\n console.log('Logs: ' + logPath);\n } else {\n console.log('Daemon started (PID: ' + child.pid + ') but socket not yet available.');\n console.log('Check logs: ' + logPath);\n }\n });\n\ndaemonCmd\n .command('stop')\n .description('Stop the daemon')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(data.pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n // Clean up socket file\n if (data.socketPath) {\n try { fs.unlinkSync(data.socketPath); } catch (_) { /* ok */ }\n }\n console.log('Daemon stopped (PID: ' + data.pid + ').');\n } catch (e) {\n console.log('No running daemon found.');\n }\n });\n\ndaemonCmd\n .command('status')\n .description('Check daemon status')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n try {\n process.kill(data.pid, 0);\n var socketStatus = data.socketPath && fs.existsSync(data.socketPath) ? ', socket: active' : '';\n console.log('Running (PID: ' + data.pid + ', started: ' + data.startedAt + socketStatus + ')');\n } catch (_) {\n console.log('Not running (stale PID file).');\n fs.unlinkSync(pidPath);\n }\n } catch (_) { console.log('Not running.'); }\n });\n\ndaemonCmd\n .command('logs')\n .description('Tail daemon logs')\n .option('-n, --lines <n>', 'Number of lines', function(v) { return parseInt(v, 10); }, 50)\n .action(function(opts) {\n var pathMod = require('path');\n var logPath = pathMod.join(FRONTMCP_HOME, 'logs', ${JSON.stringify(appName)} + '.log');\n try {\n var content = fs.readFileSync(logPath, 'utf8');\n var lines = content.split('\\\\n');\n var start = Math.max(0, lines.length - opts.lines);\n console.log(lines.slice(start).join('\\\\n'));\n } catch (_) { console.log('No logs found.'); }\n });`;\n}\n\nfunction generateFooter(): string {\n return `program.parseAsync(process.argv).catch(function(err) {\n console.error('Fatal:', err.message || err);\n process.exit(1);\n});`;\n}\n\n/**\n * Extract {param} placeholders from a URI template string.\n */\nexport function extractTemplateParams(uriTemplate: string): string[] {\n const matches = uriTemplate.match(/\\{([^}]+)\\}/g);\n if (!matches) return [];\n return matches.map((m) => m.slice(1, -1));\n}\n\nfunction kebabToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n\nfunction escapeStr(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"]}
|
|
1
|
+
{"version":3,"file":"generate-cli-entry.js","sourceRoot":"","sources":["../../../../../../src/commands/build/exec/cli-runtime/generate-cli-entry.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Generates the CLI entry point TypeScript/JavaScript source code.\n * This creates a commander.js-based CLI where each MCP tool is a subcommand.\n */\n\nimport { CliConfig, OAuthConfig } from '../config';\nimport { ExtractedSchema, ExtractedTool, ExtractedPrompt, ExtractedResourceTemplate, ExtractedCapabilities, ExtractedJob, SYSTEM_TOOL_NAMES } from './schema-extractor';\nimport { schemaToCommander, generateOptionCode, camelToKebab } from './schema-to-commander';\n\nexport const RESERVED_COMMANDS = new Set([\n 'resource', 'template', 'prompt', 'subscribe',\n 'login', 'logout', 'connect', 'serve', 'daemon',\n 'doctor', 'install', 'uninstall', 'sessions', 'help', 'version',\n 'skills', 'job', 'workflow',\n]);\n\nexport interface CliEntryOptions {\n appName: string;\n appVersion: string;\n description: string;\n serverBundleFilename: string;\n outputDefault: 'text' | 'json';\n authRequired: boolean;\n excludeTools: string[];\n nativeDeps: NonNullable<CliConfig['nativeDeps']>;\n schema: ExtractedSchema;\n oauthConfig?: OAuthConfig;\n /** When true, generate static requires that esbuild can resolve (for SEA builds). */\n selfContained?: boolean;\n}\n\n/**\n * Resolve tool command name, appending '-tool' suffix if it conflicts with a built-in command.\n * Returns { cmdName, wasRenamed } so the caller can log a warning at build time.\n */\nexport function resolveToolCommandName(toolName: string): { cmdName: string; wasRenamed: boolean } {\n const cmdName = camelToKebab(toolName).replace(/_/g, '-');\n if (RESERVED_COMMANDS.has(cmdName)) {\n return { cmdName: `${cmdName}-tool`, wasRenamed: true };\n }\n return { cmdName, wasRenamed: false };\n}\n\n/**\n * Generate the CLI entry source code (CJS module).\n */\nexport function generateCliEntry(options: CliEntryOptions): string {\n const {\n appName,\n appVersion,\n description,\n serverBundleFilename,\n outputDefault,\n schema,\n excludeTools,\n oauthConfig,\n authRequired,\n } = options;\n\n const capabilities = schema.capabilities;\n\n const filteredTools = schema.tools.filter(\n (t) => !excludeTools.includes(t.name) && !SYSTEM_TOOL_NAMES.has(t.name),\n );\n\n const selfContained = !!options.selfContained;\n\n const sections: string[] = [\n generateHeader(appName, appVersion, description, serverBundleFilename, outputDefault, authRequired, capabilities, oauthConfig, selfContained),\n generateToolCommands(filteredTools, appName),\n generateResourceCommands(schema),\n generateTemplateCommands(schema.resourceTemplates),\n generatePromptCommands(schema.prompts),\n capabilities.skills ? generateSkillsCommands() : '',\n capabilities.jobs ? generateJobCommands(schema.jobs) : '',\n capabilities.workflows ? generateWorkflowCommands() : '',\n generateSubscribeCommands(),\n ...(authRequired ? [\n generateLoginCommand(appName, oauthConfig),\n generateLogoutCommand(appName),\n generateSessionCommands(),\n ] : []),\n generateServeCommand(serverBundleFilename),\n generateDoctorCommand(appName, options.nativeDeps),\n generateInstallCommand(appName, options.nativeDeps, selfContained),\n generateDaemonCommands(appName, serverBundleFilename),\n generateFooter(),\n ];\n\n return sections.filter(Boolean).join('\\n\\n');\n}\n\nfunction generateHeader(\n appName: string,\n appVersion: string,\n description: string,\n serverBundleFilename: string,\n outputDefault: string,\n authRequired: boolean,\n capabilities: ExtractedCapabilities,\n oauthConfig?: OAuthConfig,\n selfContained?: boolean,\n): string {\n const hasOAuth = !!oauthConfig;\n\n // Build the group routing map dynamically\n const skillsRouting = capabilities.skills ? `\\n else if (name === 'skills') groups['Skills'].push(sub);` : '';\n const jobsRouting = capabilities.jobs ? `\\n else if (name === 'job') groups['Jobs'].push(sub);` : '';\n const workflowsRouting = capabilities.workflows ? `\\n else if (name === 'workflow') groups['Workflows'].push(sub);` : '';\n const authRouting = authRequired ? `\\n else if (['login', 'logout', 'sessions', 'connect'].indexOf(name) !== -1) groups['Auth'].push(sub);` : '';\n\n // Build the groups object dynamically\n const groupEntries: string[] = [\n ` 'Tools': []`,\n ` 'Resources & Prompts': []`,\n ];\n if (capabilities.skills) groupEntries.push(` 'Skills': []`);\n if (capabilities.jobs) groupEntries.push(` 'Jobs': []`);\n if (capabilities.workflows) groupEntries.push(` 'Workflows': []`);\n if (authRequired) groupEntries.push(` 'Auth': []`);\n groupEntries.push(` 'Subscriptions': []`);\n groupEntries.push(` 'System': []`);\n\n return `'use strict';\n\nvar { Command, Option } = require('commander');\nvar path = require('path');\nvar fs = require('fs');\nvar os = require('os');\nvar fmt = require('./output-formatter');\n${authRequired ? \"var sessions = require('./session-manager');\\nvar creds = require('./credential-store');\" : ''}\n${hasOAuth ? \"var oauthHelper = require('./oauth-helper');\" : ''}\n\nvar APP_NAME = ${JSON.stringify(appName)};\nvar SCRIPT_DIR = __dirname;\nvar FRONTMCP_HOME = process.env.FRONTMCP_HOME || path.join(os.homedir(), '.frontmcp');\n${selfContained\n ? `// Self-contained: server bundle and SDK are inlined by esbuild\nvar SERVER_BUNDLE = '../${serverBundleFilename}';`\n : `var SERVER_BUNDLE = path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});`}\n\nvar _client = null;\nasync function getClient() {\n if (_client) return _client;\n\n // Try daemon first — Unix socket HTTP (~5-15ms vs ~420ms in-process)\n var socketPath = path.join(FRONTMCP_HOME, 'sockets', APP_NAME + '.sock');\n if (fs.existsSync(socketPath)) {\n try {\n var daemonClient = require('./daemon-client');\n var dc = daemonClient.createDaemonClient(socketPath);\n await dc.ping();\n _client = dc;\n return _client;\n } catch (_) { /* daemon not available, fall through */ }\n }\n\n // Fallback: in-process connect (with CLI mode for faster init)\n var mod = require(${selfContained ? `'../${serverBundleFilename}'` : 'SERVER_BUNDLE'});\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;${authRequired ? `\n var sessionName = sessions.getActiveSessionName();\n var store = creds.createCredentialStore();\n var credBlob = await store.get(sessionName);\n var connectOpts = credBlob ? { authToken: credBlob.token, mode: 'cli' } : { mode: 'cli' };\n _client = await connect(configOrClass, connectOpts);` : `\n _client = await connect(configOrClass, { mode: 'cli' });`}\n return _client;\n}\n\nvar program = new Command();\nprogram\n .name(${JSON.stringify(appName)})\n .version(${JSON.stringify(appVersion)})\n .description(${JSON.stringify(description || `${appName} CLI`)})\n .option('--output <mode>', 'Output format: text or json', ${JSON.stringify(outputDefault)});\n\nprogram.configureHelp({\n sortSubcommands: false,\n formatHelp: function(cmd, helper) {\n var groups = {\n${groupEntries.join(',\\n')}\n };\n var toolCmdNames = cmd._toolCommandNames || [];\n cmd.commands.forEach(function(sub) {\n var name = sub.name();\n if (toolCmdNames.indexOf(name) !== -1) groups['Tools'].push(sub);\n else if (['resource', 'template', 'prompt'].indexOf(name) !== -1) groups['Resources & Prompts'].push(sub);${skillsRouting}${jobsRouting}${workflowsRouting}${authRouting}\n else if (name === 'subscribe') groups['Subscriptions'].push(sub);\n else groups['System'].push(sub);\n });\n var termWidth = helper.padWidth(cmd, helper);\n var lines = [];\n lines.push('Usage: ' + helper.commandUsage(cmd));\n lines.push('');\n var desc = helper.commandDescription(cmd);\n if (desc) { lines.push(desc); lines.push(''); }\n var globalOpts = helper.formatHelp ? helper.visibleOptions(cmd) : [];\n if (globalOpts.length > 0) {\n lines.push('Options:');\n globalOpts.forEach(function(opt) {\n lines.push(' ' + helper.optionTerm(opt).padEnd(termWidth) + ' ' + helper.optionDescription(opt));\n });\n lines.push('');\n }\n Object.keys(groups).forEach(function(groupName) {\n var cmds = groups[groupName];\n if (cmds.length === 0) return;\n lines.push(groupName + ':');\n cmds.forEach(function(sub) {\n lines.push(' ' + helper.subcommandTerm(sub).padEnd(termWidth) + ' ' + helper.subcommandDescription(sub));\n });\n lines.push('');\n });\n return lines.join('\\\\n');\n }\n});\n\nprogram.action(function() { program.outputHelp(); });`;\n}\n\nfunction generateToolCommands(tools: ExtractedTool[], appName: string): string {\n if (tools.length === 0) return '// No tools extracted\\nprogram._toolCommandNames = [];';\n\n const cmdNames: string[] = [];\n const commands = tools.map((tool) => {\n const { cmdName } = resolveToolCommandName(tool.name);\n cmdNames.push(cmdName);\n const { options } = schemaToCommander(tool.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n\n return `program\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tool.description)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${generateArgMapping(tool)}\n var result = await client.callTool(${JSON.stringify(tool.name)}, args);\n var mode = program.opts().output || ${JSON.stringify('text')};\n console.log(fmt.formatToolResult(result, mode));\n } catch (err) {\n var meta = err && err._meta ? err._meta : (err && err.data && err.data._meta ? err.data._meta : null);\n if (meta && meta.authorization_required) {\n console.error('Authorization required' + (meta.app ? ' for ' + meta.app : ''));\n if (meta.auth_url) console.error('Authorize at: ' + meta.auth_url);\n console.error('Or run: ' + ${JSON.stringify(appName)} + ' login');\n } else {\n console.error('Error:', err.message || err);\n }\n process.exitCode = 1;\n }\n });`;\n });\n\n return `program._toolCommandNames = ${JSON.stringify(cmdNames)};\\n\\n${commands.join('\\n\\n')}`;\n}\n\nfunction generateArgMapping(tool: ExtractedTool): string {\n const props = (tool.inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n // Commander converts kebab-case flags to camelCase in opts()\n const camel = kebabToCamel(kebab);\n\n // Resolve type for object detection\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { args[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateJobArgMapping(inputSchema: Record<string, unknown>): string {\n const props = (inputSchema as Record<string, unknown>).properties as Record<string, Record<string, unknown>> | undefined;\n if (!props) return '';\n\n const mappings = Object.keys(props).map((propName) => {\n const propSchema = props[propName];\n const kebab = camelToKebab(propName);\n const camel = kebabToCamel(kebab);\n\n let propType = propSchema?.type as string | string[] | undefined;\n if (Array.isArray(propType)) {\n propType = propType.find((t: string) => t !== 'null') || propType[0];\n }\n\n if (propType === 'object') {\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) {\n try { input[${JSON.stringify(propName)}] = JSON.parse(rawOpts[${JSON.stringify(camel)}]); }\n catch (_jsonErr) { console.error('Invalid JSON for --${kebab}'); process.exitCode = 1; return; }\n }`;\n }\n\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) input[${JSON.stringify(propName)}] = rawOpts[${JSON.stringify(camel)}];`;\n });\n\n return mappings.join('\\n ');\n}\n\nfunction generateResourceCommands(_schema: ExtractedSchema): string {\n return `var resourceCmd = program.command('resource').description('Resource operations');\n\nresourceCmd\n .command('list')\n .description('List available resources')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResources();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var resources = result.resources || [];\n if (resources.length === 0) { console.log('No resources available.'); return; }\n resources.forEach(function(r) {\n console.log(' ' + r.uri + (r.description ? ' - ' + r.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nresourceCmd\n .command('read <uri>')\n .description('Read a resource by URI')\n .action(async function(uri) {\n try {\n var client = await getClient();\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateTemplateCommands(templates: ExtractedResourceTemplate[]): string {\n if (!templates || templates.length === 0) return '// No resource templates extracted';\n\n const subcommands = templates.map((tmpl) => {\n const cmdName = camelToKebab(tmpl.name).replace(/_/g, '-');\n // Extract {param} placeholders from URI template\n const paramNames = extractTemplateParams(tmpl.uriTemplate);\n const optionLines = paramNames\n .map((p) => ` .requiredOption('--${camelToKebab(p)} <value>', 'Template parameter: ${p}')`)\n .join('\\n');\n\n const paramMapping = paramNames\n .map((p) => {\n const camel = kebabToCamel(camelToKebab(p));\n return `uri = uri.replace('{${p}}', encodeURIComponent(rawOpts[${JSON.stringify(camel)}]));`;\n })\n .join('\\n ');\n\n return `templateCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(tmpl.description || `Read resource from template: ${tmpl.uriTemplate}`)})\n${optionLines}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var rawOpts = this.opts();\n var uri = ${JSON.stringify(tmpl.uriTemplate)};\n ${paramMapping}\n var result = await client.readResource(uri);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatResourceResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var templateCmd = program.command('template').description('Resource template operations');\n\ntemplateCmd\n .command('list')\n .description('List available resource templates')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listResourceTemplates();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var templates = result.resourceTemplates || [];\n if (templates.length === 0) { console.log('No resource templates available.'); return; }\n templates.forEach(function(t) {\n console.log(' ' + t.uriTemplate + (t.description ? ' - ' + t.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generatePromptCommands(prompts: ExtractedPrompt[]): string {\n const subcommands = prompts.map((prompt) => {\n const cmdName = camelToKebab(prompt.name).replace(/_/g, '-');\n const argOptions = (prompt.arguments || [])\n .map((a) => {\n const flag = `--${camelToKebab(a.name)} <value>`;\n const desc = a.description || '';\n return a.required\n ? ` .requiredOption('${flag}', '${escapeStr(desc)}')`\n : ` .option('${flag}', '${escapeStr(desc)}')`;\n })\n .join('\\n');\n\n return `promptCmd\n .command(${JSON.stringify(cmdName)})\n .description(${JSON.stringify(prompt.description || '')})\n${argOptions}\n .action(async function(opts) {\n try {\n var client = await getClient();\n var args = {};\n var rawOpts = this.opts();\n ${(prompt.arguments || []).map((a) => {\n const camel = kebabToCamel(camelToKebab(a.name));\n return `if (rawOpts[${JSON.stringify(camel)}] !== undefined) args[${JSON.stringify(a.name)}] = rawOpts[${JSON.stringify(camel)}];`;\n }).join('\\n ')}\n var result = await client.getPrompt(${JSON.stringify(prompt.name)}, args);\n var mode = program.opts().output || 'text';\n console.log(fmt.formatPromptResult(result, mode));\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n return `var promptCmd = program.command('prompt').description('Prompt operations');\n\npromptCmd\n .command('list')\n .description('List available prompts')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listPrompts();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var prompts = result.prompts || [];\n if (prompts.length === 0) { console.log('No prompts available.'); return; }\n prompts.forEach(function(p) {\n console.log(' ' + p.name + (p.description ? ' - ' + p.description : ''));\n });\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\n${subcommands.join('\\n\\n')}`;\n}\n\nfunction generateSkillsCommands(): string {\n return `var skillsCmd = program.command('skills').description('Skill operations');\n\nskillsCmd\n .command('search [query]')\n .description('Search for skills')\n .action(async function(query) {\n try {\n var client = await getClient();\n var result = await client.searchSkills(query || '');\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills found.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('load <ids...>')\n .description('Load skills by ID')\n .action(async function(ids) {\n try {\n var client = await getClient();\n var result = await client.loadSkills(ids);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Loaded ' + ids.length + ' skill(s).');\n if (result && typeof result === 'object') {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nskillsCmd\n .command('list')\n .description('List available skills')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listSkills();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var skills = result.skills || result || [];\n if (Array.isArray(skills) && skills.length === 0) { console.log('No skills available.'); return; }\n if (Array.isArray(skills)) {\n skills.forEach(function(s) {\n console.log(' ' + (s.name || s.id || JSON.stringify(s)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateJobCommands(jobs: ExtractedJob[]): string {\n // Generate typed 'run' subcommands for each known job\n const runSubcommands = jobs.map((job) => {\n const jobCmdName = camelToKebab(job.name).replace(/_/g, '-');\n\n if (job.inputSchema) {\n const { options } = schemaToCommander(job.inputSchema);\n const optionLines = options.map((o) => ` ${generateOptionCode(o)}`).join('\\n');\n const argMapping = generateJobArgMapping(job.inputSchema);\n\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n${optionLines}\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n var rawOpts = this.opts();\n ${argMapping}\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!rawOpts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (rawOpts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n }\n\n // No inputSchema — fall back to generic --input <json>\n return `jobRunCmd\n .command(${JSON.stringify(jobCmdName)})\n .description(${JSON.stringify(job.description || `Run the ${job.name} job`)})\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(${JSON.stringify(job.name)}, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n });\n\n // Generic fallback 'run' for jobs not known at build time\n const genericRun = `jobRunCmd\n .command('_run <name>')\n .description('Run a job by name (generic)')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n\n return `var jobCmd = program.command('job').description('Job operations');\n\njobCmd\n .command('list')\n .description('List available jobs')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listJobs();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var jobs = result.jobs || result || [];\n if (Array.isArray(jobs) && jobs.length === 0) { console.log('No jobs available.'); return; }\n if (Array.isArray(jobs)) {\n jobs.forEach(function(j) {\n console.log(' ' + (j.name || j.id || JSON.stringify(j)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nvar jobRunCmd = jobCmd.command('run').description('Run a job');\n\n${runSubcommands.join('\\n\\n')}\n\n${jobs.length > 0 ? genericRun : `jobRunCmd\n .argument('<name>', 'Job name')\n .option('--input <json>', 'Job input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeJob(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Job started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`}\n\njobCmd\n .command('status <runId>')\n .description('Get the status of a job run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getJobStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateWorkflowCommands(): string {\n return `var workflowCmd = program.command('workflow').description('Workflow operations');\n\nworkflowCmd\n .command('list')\n .description('List available workflows')\n .action(async function() {\n try {\n var client = await getClient();\n var result = await client.listWorkflows();\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n var workflows = result.workflows || result || [];\n if (Array.isArray(workflows) && workflows.length === 0) { console.log('No workflows available.'); return; }\n if (Array.isArray(workflows)) {\n workflows.forEach(function(w) {\n console.log(' ' + (w.name || w.id || JSON.stringify(w)));\n });\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('run <name>')\n .description('Run a workflow by name')\n .option('--input <json>', 'Workflow input as JSON string')\n .option('--background', 'Run in background mode')\n .action(async function(name, opts) {\n try {\n var client = await getClient();\n var input = {};\n if (opts.input) {\n try { input = JSON.parse(opts.input); }\n catch (_) { console.error('Invalid JSON for --input'); process.exitCode = 1; return; }\n }\n var result = await client.executeWorkflow(name, input, { background: !!opts.background });\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n if (opts.background && result && result.runId) {\n console.log('Workflow started. Run ID: ' + result.runId);\n } else {\n console.log(JSON.stringify(result, null, 2));\n }\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nworkflowCmd\n .command('status <runId>')\n .description('Get the status of a workflow run')\n .action(async function(runId) {\n try {\n var client = await getClient();\n var result = await client.getWorkflowStatus(runId);\n var mode = program.opts().output || 'text';\n if (mode === 'json') {\n console.log(JSON.stringify(result, null, 2));\n } else {\n console.log('Status: ' + (result.status || JSON.stringify(result)));\n }\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateSubscribeCommands(): string {\n return `\n// Subscribe commands need push support (onNotification/onResourceUpdated).\n// Daemon HTTP cannot push, so we force in-process when daemon was used.\nasync function getSubscribeClient() {\n var client = await getClient();\n // If connected via daemon, the onNotification/onResourceUpdated are no-ops.\n // Reconnect via in-process for push support.\n if (client._isDaemon) {\n _client = null; // clear cached daemon client\n var mod = require(SERVER_BUNDLE);\n var configOrClass = mod.default || mod;\n var sdk = require('@frontmcp/sdk');\n var connect = sdk.connect || sdk.direct.connect;\n _client = await connect(configOrClass, { mode: 'cli' });\n return _client;\n }\n return client;\n}\n\nvar subscribeCmd = program.command('subscribe').description('Subscribe to updates');\n\nsubscribeCmd\n .command('resource <uri>')\n .description('Stream resource updates (Ctrl+C to stop)')\n .action(async function(uri) {\n try {\n var client = await getSubscribeClient();\n await client.subscribeResource(uri);\n var mode = program.opts().output || 'text';\n console.log('Subscribed to resource: ' + uri);\n console.log('Waiting for updates... (Ctrl+C to stop)\\\\n');\n client.onResourceUpdated(function(uri) {\n console.log(fmt.formatSubscriptionEvent({ type: 'resource_updated', uri: uri, timestamp: new Date().toISOString() }, mode));\n });\n process.on('SIGINT', async function() {\n console.log('\\\\nUnsubscribing...');\n try { await client.unsubscribeResource(uri); } catch (_) { /* ok */ }\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });\n\nsubscribeCmd\n .command('notification <name>')\n .description('Stream notifications (Ctrl+C to stop)')\n .action(async function(name) {\n try {\n var client = await getSubscribeClient();\n var mode = program.opts().output || 'text';\n console.log('Listening for notification: ' + name);\n console.log('Waiting for events... (Ctrl+C to stop)\\\\n');\n client.onNotification(function(notification) {\n if (notification.method === name || name === '*') {\n console.log(fmt.formatSubscriptionEvent({ type: 'notification', method: notification.method, params: notification.params, timestamp: new Date().toISOString() }, mode));\n }\n });\n process.on('SIGINT', function() {\n console.log('\\\\nStopping...');\n process.exit(0);\n });\n // Keep process alive — setInterval creates an active event loop handle\n // so Node.js won't exit even with InMemoryTransport (no persistent I/O)\n setInterval(function() {}, 2147483647);\n await new Promise(function() {});\n } catch (err) {\n console.error('Error:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLoginCommand(appName: string, oauthConfig?: OAuthConfig): string {\n const serverUrl = oauthConfig?.serverUrl || '';\n const clientId = oauthConfig?.clientId || appName;\n const defaultScope = oauthConfig?.defaultScope || '';\n const portStart = oauthConfig?.portRange?.[0] ?? 17830;\n const portEnd = oauthConfig?.portRange?.[1] ?? 17850;\n const timeout = oauthConfig?.timeout ?? 120000;\n\n return `program\n .command('login')\n .description('Authenticate via OAuth')\n .option('--server <url>', 'Server URL for OAuth'${serverUrl ? `, ${JSON.stringify(serverUrl)}` : ''})\n .option('--session <name>', 'Session name', 'default')\n .option('--scope <scopes>', 'OAuth scopes'${defaultScope ? `, ${JSON.stringify(defaultScope)}` : ''})\n .option('--no-browser', 'Print URL instead of opening browser')\n .action(async function(opts) {\n var serverUrl = opts.server || process.env.FRONTMCP_SERVER_URL || ${JSON.stringify(serverUrl)};\n if (!serverUrl) {\n console.error('Server URL required. Use --server <url> or set FRONTMCP_SERVER_URL.');\n process.exitCode = 1;\n return;\n }\n try {\n var oauthHelper = require('./oauth-helper');\n var result = await oauthHelper.startOAuthLogin({\n serverUrl: serverUrl,\n clientId: ${JSON.stringify(clientId)},\n scope: opts.scope || ${JSON.stringify(defaultScope)},\n portStart: ${portStart},\n portEnd: ${portEnd},\n timeout: ${timeout},\n noBrowser: !opts.browser\n });\n var sessionName = opts.session || 'default';\n var store = creds.createCredentialStore();\n await store.set(sessionName, result);\n sessions.getOrCreateSession(sessionName);\n console.log('Logged in successfully. Session: ' + sessionName);\n } catch (err) {\n console.error('Login failed:', err.message || err);\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateLogoutCommand(_appName: string): string {\n return `program\n .command('logout')\n .description('Clear stored credentials')\n .option('--session <name>', 'Session to log out')\n .option('--all', 'Log out of all sessions')\n .action(async function(opts) {\n var store = creds.createCredentialStore();\n if (opts.all) {\n var allSessions = await store.list();\n for (var i = 0; i < allSessions.length; i++) {\n await store.delete(allSessions[i]);\n }\n console.log('Logged out of ' + allSessions.length + ' session(s).');\n } else {\n var sessionName = opts.session || sessions.getActiveSessionName();\n await store.delete(sessionName);\n console.log('Logged out of session: ' + sessionName);\n }\n });`;\n}\n\nfunction generateSessionCommands(): string {\n return `var sessionsCmd = program.command('sessions').description('Session management');\n\nsessionsCmd\n .command('list')\n .description('List all sessions')\n .action(function() {\n var list = sessions.listSessions();\n if (list.length === 0) { console.log('No sessions.'); return; }\n list.forEach(function(s) {\n var marker = s.isActive ? ' (active)' : '';\n console.log(' ' + s.name + marker + ' - last used: ' + s.lastUsedAt);\n });\n });\n\nsessionsCmd\n .command('switch <name>')\n .description('Switch to a named session')\n .action(function(name) {\n sessions.switchSession(name);\n console.log('Switched to session: ' + name);\n });\n\nsessionsCmd\n .command('delete <name>')\n .description('Delete a session')\n .action(async function(name) {\n var store = creds.createCredentialStore();\n await store.delete(name);\n sessions.deleteSession(name);\n console.log('Deleted session: ' + name);\n });\n\nprogram\n .command('connect')\n .description('Authenticate and store credentials')\n .option('--session <name>', 'Session name', 'default')\n .option('--token <token>', 'Auth token (or pass via stdin)')\n .action(async function(opts) {\n var sessionName = opts.session || 'default';\n var token = opts.token;\n if (!token) {\n console.log('Usage: ' + program.name() + ' connect --token <your-token>');\n console.log(' Or pipe token: echo \"tok_xxx\" | ' + program.name() + ' connect');\n process.exitCode = 1;\n return;\n }\n var store = creds.createCredentialStore();\n await store.set(sessionName, { token: token });\n sessions.getOrCreateSession(sessionName);\n console.log('Credentials stored for session: ' + sessionName);\n });`;\n}\n\nfunction generateServeCommand(serverBundleFilename: string): string {\n return `program\n .command('serve')\n .description('Start the HTTP/SSE server')\n .option('-p, --port <port>', 'Port number', function(v) { return parseInt(v, 10); })\n .action(async function(opts) {\n var mod = require(path.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)}));\n if (opts.port) process.env.PORT = String(opts.port);\n // The server bundle should self-start when required\n if (typeof mod.start === 'function') await mod.start();\n else if (typeof mod.default?.start === 'function') await mod.default.start();\n });`;\n}\n\nfunction generateDoctorCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n): string {\n const checks: string[] = [];\n\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.apt?.length) {\n for (const pkg of nativeDeps.apt) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'apt', check: 'dpkg -l ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n checks.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('doctor')\n .description('Check system dependencies and configuration')\n .option('--fix', 'Attempt to install missing dependencies')\n .action(async function(opts) {\n var exec = require('child_process').execSync;\n var ok = true;\n\n // Check Node.js version\n var nodeMajor = parseInt(process.versions.node.split('.')[0], 10);\n if (nodeMajor >= 22) {\n console.log(' [ok] Node.js v' + process.versions.node);\n } else {\n console.log(' [!!] Node.js v' + process.versions.node + ' (>=22 required)');\n ok = false;\n }\n\n var deps = [\n${checks.join(',\\n')}\n ];\n\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try {\n exec(dep.check, { stdio: 'ignore' });\n console.log(' [ok] ' + dep.name + ' (' + dep.type + ')');\n } catch (_) {\n console.log(' [!!] ' + dep.name + ' (' + dep.type + ') - not found');\n ok = false;\n if (opts.fix) {\n try {\n var installCmd = dep.type === 'brew' ? 'brew install ' + dep.name\n : dep.type === 'apt' ? 'sudo apt-get install -y ' + dep.name\n : 'npm install ' + dep.name;\n console.log(' Installing: ' + installCmd);\n exec(installCmd, { stdio: 'inherit' });\n console.log(' [ok] Installed ' + dep.name);\n } catch (e) {\n console.log(' [!!] Failed to install ' + dep.name);\n }\n }\n }\n }\n\n // Check FRONTMCP_HOME directory\n var fs = require('fs');\n var appDir = require('path').join(FRONTMCP_HOME, 'apps', ${JSON.stringify(appName)});\n if (fs.existsSync(appDir)) {\n console.log(' [ok] App directory: ' + appDir);\n } else {\n console.log(' [!!] App directory not found: ' + appDir);\n ok = false;\n if (opts.fix) {\n fs.mkdirSync(appDir, { recursive: true });\n console.log(' [fixed] Created ' + appDir);\n }\n }\n\n if (ok) console.log('\\\\nAll checks passed.');\n else {\n console.log('\\\\nSome checks failed.' + (opts.fix ? '' : ' Run with --fix to attempt repairs.'));\n process.exitCode = 1;\n }\n });`;\n}\n\nfunction generateInstallCommand(\n appName: string,\n nativeDeps: NonNullable<CliConfig['nativeDeps']>,\n selfContained?: boolean,\n): string {\n const depEntries: string[] = [];\n if (nativeDeps.brew?.length) {\n for (const pkg of nativeDeps.brew) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'brew', install: 'brew install ${pkg}', check: 'brew list ${pkg}' }`);\n }\n }\n if (nativeDeps.npm?.length) {\n for (const pkg of nativeDeps.npm) {\n depEntries.push(` { name: ${JSON.stringify(pkg)}, type: 'npm', install: 'npm install ${pkg}', check: 'npm ls ${pkg}' }`);\n }\n }\n\n return `program\n .command('install')\n .description('Install to ~/.frontmcp/ and set up dependencies')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory for symlink (default: ~/.local/bin or /usr/local/bin)')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var exec = require('child_process').execSync;\n var installBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(installBase, 'apps', ${JSON.stringify(appName)});\n var dirs = ['', '/data', '/sessions', '/credentials'].map(function(s) { return appDir + s; });\n\n console.log('Installing ${appName}...');\n dirs.forEach(function(d) { fs.mkdirSync(d, { recursive: true }); });\n\n // Copy bundle files\n var files = fs.readdirSync(SCRIPT_DIR).filter(function(f) {\n return f.endsWith('.js') || f.endsWith('.json')${selfContained ? \" || f.endsWith('-bin')\" : ''};\n });\n files.forEach(function(f) {\n fs.copyFileSync(pathMod.join(SCRIPT_DIR, f), pathMod.join(appDir, f));\n });\n console.log(' Copied ' + files.length + ' files to ' + appDir);\n\n // Install native deps\n var deps = [\n${depEntries.join(',\\n')}\n ];\n for (var i = 0; i < deps.length; i++) {\n var dep = deps[i];\n try { exec(dep.check, { stdio: 'ignore' }); }\n catch (_) {\n console.log(' [' + (i + 1) + '/' + deps.length + '] Installing ' + dep.name + ' via ' + dep.type + '...');\n try { exec(dep.install, { stdio: 'inherit' }); }\n catch (e) { console.log(' Warning: Failed to install ' + dep.name); }\n }\n }\n\n // Set execute permission on the entry point\n var entryFile = pathMod.join(appDir, ${JSON.stringify(selfContained ? `${appName}-cli-bin` : `${appName}-cli.bundle.js`)});\n try { fs.chmodSync(entryFile, 0o755); } catch (_) { /* ok */ }\n\n // Create symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n var linked = false;\n for (var j = 0; j < binDirs.length && !linked; j++) {\n try {\n fs.mkdirSync(binDirs[j], { recursive: true });\n var linkPath = pathMod.join(binDirs[j], ${JSON.stringify(appName)});\n try { fs.unlinkSync(linkPath); } catch (_) { /* ok */ }\n fs.symlinkSync(entryFile, linkPath);\n console.log(' Symlinked: ' + linkPath);\n linked = true;\n } catch (_) { /* try next */ }\n }\n\n console.log('\\\\nInstalled. Run: ${appName} --help');\n });\n\nprogram\n .command('uninstall')\n .description('Remove from ~/.frontmcp/ and clean up')\n .option('--prefix <path>', 'Installation prefix directory')\n .option('--bin-dir <path>', 'Directory where symlink was created')\n .action(async function(opts) {\n var fs = require('fs');\n var pathMod = require('path');\n var os = require('os');\n var uninstallBase = opts.prefix || FRONTMCP_HOME;\n var appDir = pathMod.join(uninstallBase, 'apps', ${JSON.stringify(appName)});\n\n // Remove credentials (if auth is enabled)\n if (typeof creds !== 'undefined') {\n var store = creds.createCredentialStore();\n var credSessions = await store.list();\n for (var i = 0; i < credSessions.length; i++) {\n await store.delete(credSessions[i]);\n }\n }\n\n // Remove symlink\n var binDirs = opts.binDir ? [opts.binDir] : ['/usr/local/bin', pathMod.join(os.homedir(), '.local', 'bin')];\n binDirs.forEach(function(d) {\n try { fs.unlinkSync(pathMod.join(d, ${JSON.stringify(appName)})); } catch (_) { /* ok */ }\n });\n\n // Remove app directory\n fs.rmSync(appDir, { recursive: true, force: true });\n console.log('Uninstalled ${appName}.');\n });`;\n}\n\nfunction generateDaemonCommands(appName: string, serverBundleFilename: string): string {\n return `var daemonCmd = program.command('daemon').description('Daemon management');\n\ndaemonCmd\n .command('start')\n .description('Start as a background daemon (Unix socket)')\n .option('--idle-timeout <ms>', 'Auto-stop after idle period (ms, 0 to disable)', function(v) { return parseInt(v, 10); }, 300000)\n .action(async function(opts) {\n var { spawn } = require('child_process');\n var pathMod = require('path');\n var pidDir = pathMod.join(FRONTMCP_HOME, 'pids');\n var logDir = pathMod.join(FRONTMCP_HOME, 'logs');\n var socketDir = pathMod.join(FRONTMCP_HOME, 'sockets');\n fs.mkdirSync(pidDir, { recursive: true });\n fs.mkdirSync(logDir, { recursive: true });\n fs.mkdirSync(socketDir, { recursive: true });\n\n var socketPath = pathMod.join(socketDir, ${JSON.stringify(appName)} + '.sock');\n\n // Clean up stale socket file\n try { fs.unlinkSync(socketPath); } catch (_) { /* ok */ }\n\n // Check if already running\n var pidPath = pathMod.join(pidDir, ${JSON.stringify(appName)} + '.pid');\n try {\n var existing = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(existing.pid, 0);\n console.log('Daemon already running (PID: ' + existing.pid + ').');\n return;\n } catch (_) { /* not running, proceed */ }\n\n var env = Object.assign({}, process.env, {\n FRONTMCP_DAEMON_SOCKET: socketPath,\n FRONTMCP_DAEMON_IDLE_TIMEOUT: String(opts.idleTimeout)\n });\n\n var logPath = pathMod.join(logDir, ${JSON.stringify(appName)} + '.log');\n var out = fs.openSync(logPath, 'a');\n var err = fs.openSync(logPath, 'a');\n\n // Start the daemon using runUnixSocket via a small wrapper script\n // Always use absolute path for the server bundle (SCRIPT_DIR resolves to __dirname at runtime)\n var serverBundlePath = pathMod.join(SCRIPT_DIR, ${JSON.stringify(serverBundleFilename)});\n var daemonScript = 'require(\"reflect-metadata\");' +\n 'var mod = require(' + JSON.stringify(serverBundlePath) + ');' +\n 'var sdk = require(\"@frontmcp/sdk\");' +\n 'var FrontMcpInstance = sdk.FrontMcpInstance || sdk.default.FrontMcpInstance;' +\n 'var raw = mod.default || mod;' +\n // If the export is a @FrontMcp-decorated class, extract config via Reflect metadata\n 'var config = (typeof raw === \"function\" && typeof Reflect !== \"undefined\" && Reflect.getMetadata) ' +\n ' ? (Reflect.getMetadata(\"__frontmcp:config\", raw) || raw) : raw;' +\n 'FrontMcpInstance.runUnixSocket(Object.assign({}, config, { socketPath: ' + JSON.stringify(socketPath) + ' }))' +\n '.then(function() { console.log(\"Daemon listening on \" + ' + JSON.stringify(socketPath) + '); })' +\n '.catch(function(e) { console.error(\"Daemon failed:\", e); process.exit(1); });';\n\n var child = spawn('node', ['-e', daemonScript], {\n detached: true,\n stdio: ['ignore', out, err],\n env: env\n });\n\n fs.writeFileSync(pidPath, JSON.stringify({\n pid: child.pid,\n socketPath: socketPath,\n startedAt: new Date().toISOString()\n }));\n child.unref();\n\n // Wait for socket file to appear (max 5s)\n var waited = 0;\n while (!fs.existsSync(socketPath) && waited < 5000) {\n await new Promise(function(r) { setTimeout(r, 100); });\n waited += 100;\n }\n\n if (fs.existsSync(socketPath)) {\n console.log('Daemon started (PID: ' + child.pid + '). Socket: ' + socketPath);\n console.log('Logs: ' + logPath);\n } else {\n console.log('Daemon started (PID: ' + child.pid + ') but socket not yet available.');\n console.log('Check logs: ' + logPath);\n }\n });\n\ndaemonCmd\n .command('stop')\n .description('Stop the daemon')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n process.kill(data.pid, 'SIGTERM');\n fs.unlinkSync(pidPath);\n // Clean up socket file\n if (data.socketPath) {\n try { fs.unlinkSync(data.socketPath); } catch (_) { /* ok */ }\n }\n console.log('Daemon stopped (PID: ' + data.pid + ').');\n } catch (e) {\n console.log('No running daemon found.');\n }\n });\n\ndaemonCmd\n .command('status')\n .description('Check daemon status')\n .action(function() {\n var pathMod = require('path');\n var pidPath = pathMod.join(FRONTMCP_HOME, 'pids', ${JSON.stringify(appName)} + '.pid');\n try {\n var data = JSON.parse(fs.readFileSync(pidPath, 'utf8'));\n try {\n process.kill(data.pid, 0);\n var socketStatus = data.socketPath && fs.existsSync(data.socketPath) ? ', socket: active' : '';\n console.log('Running (PID: ' + data.pid + ', started: ' + data.startedAt + socketStatus + ')');\n } catch (_) {\n console.log('Not running (stale PID file).');\n fs.unlinkSync(pidPath);\n }\n } catch (_) { console.log('Not running.'); }\n });\n\ndaemonCmd\n .command('logs')\n .description('Tail daemon logs')\n .option('-n, --lines <n>', 'Number of lines', function(v) { return parseInt(v, 10); }, 50)\n .action(function(opts) {\n var pathMod = require('path');\n var logPath = pathMod.join(FRONTMCP_HOME, 'logs', ${JSON.stringify(appName)} + '.log');\n try {\n var content = fs.readFileSync(logPath, 'utf8');\n var lines = content.split('\\\\n');\n var start = Math.max(0, lines.length - opts.lines);\n console.log(lines.slice(start).join('\\\\n'));\n } catch (_) { console.log('No logs found.'); }\n });`;\n}\n\nfunction generateFooter(): string {\n return `program.parseAsync(process.argv).catch(function(err) {\n console.error('Fatal:', err.message || err);\n process.exit(1);\n});`;\n}\n\n/**\n * Extract {param} placeholders from a URI template string.\n */\nexport function extractTemplateParams(uriTemplate: string): string[] {\n const matches = uriTemplate.match(/\\{([^}]+)\\}/g);\n if (!matches) return [];\n return matches.map((m) => m.slice(1, -1));\n}\n\nfunction kebabToCamel(str: string): string {\n return str.replace(/-([a-z])/g, (_, c) => c.toUpperCase());\n}\n\nfunction escapeStr(s: string): string {\n return s.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n"]}
|
|
@@ -4,7 +4,6 @@ exports.runCreate = runCreate;
|
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
6
|
const module_1 = require("module");
|
|
7
|
-
const fs_1 = require("fs");
|
|
8
7
|
const colors_1 = require("../../core/colors");
|
|
9
8
|
const utils_1 = require("@frontmcp/utils");
|
|
10
9
|
const tsconfig_1 = require("../../core/tsconfig");
|
|
@@ -74,7 +73,7 @@ async function scaffoldFileIfMissing(baseDir, p, content) {
|
|
|
74
73
|
return;
|
|
75
74
|
}
|
|
76
75
|
await (0, utils_1.ensureDir)(path.dirname(p));
|
|
77
|
-
await
|
|
76
|
+
await (0, utils_1.writeFile)(p, content.replace(/^\n/, ''));
|
|
78
77
|
console.log((0, colors_1.c)('green', `✓ created ${path.relative(baseDir, p)}`));
|
|
79
78
|
}
|
|
80
79
|
const TEMPLATE_MAIN_TS = `
|
|
@@ -120,6 +119,13 @@ export default class AddTool extends ToolContext {
|
|
|
120
119
|
const TEMPLATE_E2E_TEST_TS = `
|
|
121
120
|
import { test, expect } from '@frontmcp/testing';
|
|
122
121
|
|
|
122
|
+
/**
|
|
123
|
+
* E2E tests for the MCP server.
|
|
124
|
+
*
|
|
125
|
+
* Run with:
|
|
126
|
+
* frontmcp test # recommended
|
|
127
|
+
* npm run test:e2e # alternative
|
|
128
|
+
*/
|
|
123
129
|
test.describe('Server E2E', () => {
|
|
124
130
|
test.use({
|
|
125
131
|
server: './src/main.ts',
|
|
@@ -140,6 +146,11 @@ test.describe('Server E2E', () => {
|
|
|
140
146
|
const result = await mcp.tools.call('add', { a: 2, b: 3 });
|
|
141
147
|
expect(result).toBeSuccessful();
|
|
142
148
|
});
|
|
149
|
+
|
|
150
|
+
test('should list resources', async ({ mcp }) => {
|
|
151
|
+
const resources = await mcp.resources.list();
|
|
152
|
+
expect(resources).toBeDefined();
|
|
153
|
+
});
|
|
143
154
|
});
|
|
144
155
|
`;
|
|
145
156
|
const TEMPLATE_GITIGNORE = `
|
|
@@ -452,6 +463,10 @@ services:
|
|
|
452
463
|
|
|
453
464
|
volumes:
|
|
454
465
|
redis-data:
|
|
466
|
+
|
|
467
|
+
# Selective rebuild:
|
|
468
|
+
# docker compose -f ci/docker-compose.yml up --build app # rebuild only the app
|
|
469
|
+
# docker compose -f ci/docker-compose.yml up --build # rebuild everything
|
|
455
470
|
`;
|
|
456
471
|
}
|
|
457
472
|
function generateDockerComposeNoRedis() {
|
|
@@ -466,6 +481,9 @@ services:
|
|
|
466
481
|
environment:
|
|
467
482
|
- NODE_ENV=\${NODE_ENV:-development}
|
|
468
483
|
- PORT=\${PORT:-3000}
|
|
484
|
+
|
|
485
|
+
# Selective rebuild:
|
|
486
|
+
# docker compose -f ci/docker-compose.yml up --build app # rebuild only the app
|
|
469
487
|
`;
|
|
470
488
|
}
|
|
471
489
|
const TEMPLATE_ENV_DOCKER_CI = `
|
|
@@ -1334,8 +1352,8 @@ async function scaffoldProject(options) {
|
|
|
1334
1352
|
const targetDir = path.resolve(process.cwd(), folder);
|
|
1335
1353
|
// Validate directory
|
|
1336
1354
|
try {
|
|
1337
|
-
const
|
|
1338
|
-
if (!
|
|
1355
|
+
const targetStat = await (0, utils_1.stat)(targetDir);
|
|
1356
|
+
if (!targetStat.isDirectory()) {
|
|
1339
1357
|
console.error((0, colors_1.c)('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), targetDir)}`));
|
|
1340
1358
|
console.log((0, colors_1.c)('gray', 'Pick a different project name or remove/rename the existing file.'));
|
|
1341
1359
|
process.exit(1);
|
|
@@ -1388,6 +1406,17 @@ async function scaffoldProject(options) {
|
|
|
1388
1406
|
}
|
|
1389
1407
|
// Dynamic README
|
|
1390
1408
|
await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'README.md'), generateReadme(options));
|
|
1409
|
+
// Initialize git repository
|
|
1410
|
+
try {
|
|
1411
|
+
const { execSync } = await import('child_process');
|
|
1412
|
+
execSync('git init', { cwd: targetDir, stdio: 'ignore' });
|
|
1413
|
+
execSync('git add -A', { cwd: targetDir, stdio: 'ignore' });
|
|
1414
|
+
execSync('git commit -m "Initial commit"', { cwd: targetDir, stdio: 'ignore' });
|
|
1415
|
+
console.log(`${(0, colors_1.c)('green', '✓')} Initialized git repository`);
|
|
1416
|
+
}
|
|
1417
|
+
catch {
|
|
1418
|
+
// git may not be installed — silently skip
|
|
1419
|
+
}
|
|
1391
1420
|
// Print next steps
|
|
1392
1421
|
printNextSteps(folder, deploymentTarget, redisSetup, enableGitHubActions, packageManager);
|
|
1393
1422
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/commands/scaffold/create.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { createRequire } from 'module';\nimport { promises as fsp } from 'fs';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, isDirEmpty, writeJSON, readJSON, runCmd, stat } from '@frontmcp/utils';\nimport { runInit } from '../../core/tsconfig';\nimport { getSelfVersion } from '../../core/version';\nimport { clack } from '../../shared/prompts';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type DeploymentTarget = 'node' | 'vercel' | 'lambda' | 'cloudflare';\nexport type RedisSetup = 'docker' | 'existing' | 'none';\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n packageManager: PackageManager;\n nxScaffolded?: boolean;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n pm?: PackageManager;\n nx?: boolean;\n}\n\ninterface PmConfig {\n lockfileCopy: string;\n installAll: string;\n pruneDevDeps: string;\n run: string;\n userInstall: string;\n ghCache: string;\n ghInstallCmd: string;\n engines: { node: string; npm?: string };\n}\n\nconst PM_CONFIG: Record<PackageManager, PmConfig> = {\n npm: {\n lockfileCopy: 'COPY package*.json package-lock.json* ./',\n installAll: 'RUN npm ci',\n pruneDevDeps: 'RUN npm prune --omit=dev',\n run: 'npm run',\n userInstall: 'npm install',\n ghCache: 'npm',\n ghInstallCmd: 'npm ci',\n engines: { node: '>=22', npm: '>=10' },\n },\n yarn: {\n lockfileCopy: 'COPY package.json yarn.lock* ./',\n installAll: 'RUN yarn install --frozen-lockfile',\n pruneDevDeps: 'RUN yarn install --frozen-lockfile --production',\n run: 'yarn',\n userInstall: 'yarn install',\n ghCache: 'yarn',\n ghInstallCmd: 'yarn install --frozen-lockfile',\n engines: { node: '>=22' },\n },\n pnpm: {\n lockfileCopy: 'COPY package.json pnpm-lock.yaml* ./',\n installAll: 'RUN pnpm install --frozen-lockfile',\n pruneDevDeps: 'RUN pnpm prune --prod',\n run: 'pnpm run',\n userInstall: 'pnpm install',\n ghCache: 'pnpm',\n ghInstallCmd: 'pnpm install --frozen-lockfile',\n engines: { node: '>=22' },\n },\n};\n\ninterface PackageJson {\n name?: string;\n version?: string;\n private?: boolean;\n type?: string;\n main?: string;\n scripts?: Record<string, string>;\n engines?: { node?: string; npm?: string };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nfunction sanitizeForFolder(name: string): string {\n const seg = name.startsWith('@') && name.includes('/') ? name.split('/')[1] : name;\n return (\n seg\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nfunction sanitizeForNpm(name: string): string {\n if (name.startsWith('@') && name.includes('/')) {\n const [scope, pkg] = name.split('/');\n const s = scope.replace(/[^a-z0-9-]/gi, '').toLowerCase();\n const p = pkg.replace(/[^a-z0-9._-]/gi, '-').toLowerCase();\n return `@${s}/${p || 'frontmcp-app'}`;\n }\n return name.replace(/[^a-z0-9._-]/gi, '-').toLowerCase() || 'frontmcp-app';\n}\n\nfunction pkgNameFromCwd(cwd: string) {\n return (\n path\n .basename(cwd)\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nasync function scaffoldFileIfMissing(baseDir: string, p: string, content: string) {\n if (await fileExists(p)) {\n console.log(c('gray', `skip: ${path.relative(baseDir, p)} already exists`));\n return;\n }\n await ensureDir(path.dirname(p));\n await fsp.writeFile(p, content.replace(/^\\n/, ''), 'utf8');\n console.log(c('green', `✓ created ${path.relative(baseDir, p)}`));\n}\n\nconst TEMPLATE_MAIN_TS = `\nimport 'reflect-metadata';\nimport { FrontMcp } from '@frontmcp/sdk';\nimport { CalcApp } from './calc.app';\n\n@FrontMcp({\n info: { name: 'Demo 🚀', version: '0.1.0' },\n apps: [CalcApp],\n})\nexport default class Server {}\n`;\n\nconst TEMPLATE_CALC_APP_TS = `\nimport { App } from '@frontmcp/sdk';\nimport AddTool from './tools/add.tool';\n\n@App({\n id: 'calc',\n name: 'Calculator',\n tools: [AddTool],\n})\nexport class CalcApp {}\n`;\n\nconst TEMPLATE_ADD_TOOL_TS = `\nimport {Tool, ToolContext} from \"@frontmcp/sdk\";\nimport {z} from \"zod\";\n\n@Tool({\n name: 'add',\n description: 'Add two numbers',\n inputSchema: {a: z.number(), b: z.number()},\n outputSchema: {result: z.number()}\n})\nexport default class AddTool extends ToolContext {\n async execute(input: { a: number, b: number }) {\n return {\n result: input.a + input.b,\n };\n }\n}\n`;\n\nconst TEMPLATE_E2E_TEST_TS = `\nimport { test, expect } from '@frontmcp/testing';\n\ntest.describe('Server E2E', () => {\n test.use({\n server: './src/main.ts',\n port: 3100,\n });\n\n test('should connect and initialize', async ({ mcp }) => {\n expect(mcp.isConnected()).toBe(true);\n expect(mcp.serverInfo.name).toBeDefined();\n });\n\n test('should list tools', async ({ mcp }) => {\n const tools = await mcp.tools.list();\n expect(tools.length).toBeGreaterThanOrEqual(0);\n });\n\n test('should call add tool', async ({ mcp }) => {\n const result = await mcp.tools.call('add', { a: 2, b: 3 });\n expect(result).toBeSuccessful();\n });\n});\n`;\n\nconst TEMPLATE_GITIGNORE = `\n# Dependencies\nnode_modules/\n\n# Build output\ndist/\n*.tsbuildinfo\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS files\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Environment variables\n.env\n.env.local\n.env.*.local\n\n# FrontMCP development keys (contains private keys - never commit!)\n.frontmcp/\n\n# Coverage\ncoverage/\n\n# Test output\ntest-output/\n`;\n\nconst TEMPLATE_DOCKERIGNORE = `\nnode_modules\ndist\n.git\ncoverage\ntest-output\n*.tsbuildinfo\n.idea\n.vscode\n.DS_Store\nThumbs.db\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n.env\n.env.local\n.env.*.local\n.frontmcp\ne2e\n*.md\nLICENSE\n`;\n\nconst TEMPLATE_JEST_E2E_CONFIG = `\n/* eslint-disable */\nexport default {\n displayName: 'e2e',\n testEnvironment: 'node',\n testMatch: ['<rootDir>/e2e/**/*.e2e.spec.ts'],\n testTimeout: 60000,\n setupFilesAfterEnv: ['@frontmcp/testing/setup'],\n transform: {\n '^.+\\\\\\\\.[tj]s$': [\n '@swc/jest',\n {\n jsc: {\n target: 'es2022',\n parser: {\n syntax: 'typescript',\n decorators: true,\n dynamicImport: true,\n },\n transform: {\n decoratorMetadata: true,\n legacyDecorator: true,\n },\n keepClassNames: true,\n externalHelpers: true,\n loose: true,\n },\n module: {\n type: 'es6',\n },\n sourceMaps: true,\n swcrc: false,\n },\n ],\n },\n moduleFileExtensions: ['ts', 'js', 'html'],\n transformIgnorePatterns: ['node_modules/(?!(jose)/)'],\n};\n`;\n\nconst TEMPLATE_TSCONFIG_E2E = `\n{\n \"extends\": \"./tsconfig.json\",\n \"compilerOptions\": {\n \"types\": [\"node\", \"jest\"]\n },\n \"include\": [\"e2e/**/*.ts\", \"jest.e2e.config.ts\"]\n}\n`;\n\nconst TEMPLATE_ENV_EXAMPLE = `\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis (recommended for development, required for production)\nREDIS_HOST=localhost\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\n\n# Optional: Redis TLS (enable for production)\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_ENV_DOCKER = `\n# Docker-specific environment\n# Copy this to .env when running with docker compose\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_README = `\n# FrontMCP Server\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n\n## Development with Docker\n\n### Prerequisites\n- Docker & Docker Compose installed\n\n### Quick Start\n\n\\`\\`\\`bash\n# Start Redis and app in development mode\ndocker compose up\n\n# Start only Redis (for local development)\ndocker compose up redis -d\n\n# Stop all services\ndocker compose down\n\\`\\`\\`\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n\n## Redis Configuration\n\n### Development\nRedis is **recommended** for development to enable caching and session persistence.\nUse the included \\`docker-compose.yml\\` to run Redis locally:\n\n\\`\\`\\`bash\ndocker compose up redis -d\n\\`\\`\\`\n\n### Production\nRedis is **required** in production for:\n- Session storage (multi-instance deployments)\n- Caching (performance optimization)\n- Rate limiting (if enabled)\n\nSee the [Redis Setup Guide](https://docs.agentfront.dev/docs/deployment/redis-setup) for production configuration.\n\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n\n## Project Structure\n\n\\`\\`\\`\n├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n├── docker-compose.yml # Docker services config\n├── Dockerfile # Container build config\n├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n// =============================================================================\n// Deployment Target Templates\n// =============================================================================\n\n// Docker templates (moved to ci/ folder)\nfunction generateDockerfile(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n const corepack = pm !== 'npm' ? '\\nRUN corepack enable\\n' : '';\n return `\n# Build stage\nFROM node:24-slim AS builder\n\nWORKDIR /app\n${corepack}\n# Install all dependencies (including devDependencies for build)\n${cfg.lockfileCopy}\n${cfg.installAll}\n\n# Copy source and build\nCOPY . .\nRUN ${cfg.run} build\n\n# Prune devDependencies so only production deps remain\n${cfg.pruneDevDeps}\n\n# Production stage\nFROM node:24-slim AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n}\n\nfunction generateDockerComposeWithRedis(): string {\n return `\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 3s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: ..\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - PORT=\\${PORT:-3000}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n\nvolumes:\n redis-data:\n`;\n}\n\nfunction generateDockerComposeNoRedis(): string {\n return `\nservices:\n app:\n build:\n context: ..\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - PORT=\\${PORT:-3000}\n`;\n}\n\nconst TEMPLATE_ENV_DOCKER_CI = `\n# Docker-specific environment\n# Use with: docker compose -f ci/docker-compose.yml --env-file ci/.env.docker up\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\n// Vercel template\nconst TEMPLATE_VERCEL_JSON = (projectName: string) =>\n JSON.stringify(\n {\n $schema: 'https://openapi.vercel.sh/vercel.json',\n name: projectName,\n version: 2,\n builds: [\n {\n src: 'dist/main.js',\n use: '@vercel/node',\n },\n ],\n routes: [\n {\n src: '/(.*)',\n dest: '/dist/main.js',\n },\n ],\n env: {\n NODE_ENV: 'production',\n },\n },\n null,\n 2,\n );\n\n// AWS Lambda SAM template\nconst TEMPLATE_SAM_YAML = (projectName: string) => `\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: ${projectName} - FrontMCP Lambda Function\n\nGlobals:\n Function:\n Timeout: 30\n Runtime: nodejs22.x\n MemorySize: 256\n\nResources:\n FrontMCPFunction:\n Type: AWS::Serverless::Function\n Properties:\n CodeUri: ../dist/\n Handler: main.handler\n Events:\n ApiEvent:\n Type: HttpApi\n Properties:\n Path: /{proxy+}\n Method: ANY\n\nOutputs:\n ApiEndpoint:\n Description: API Gateway endpoint URL\n Value: !Sub \"https://\\${ServerlessHttpApi}.execute-api.\\${AWS::Region}.amazonaws.com\"\n`;\n\n// Cloudflare Workers template\nconst TEMPLATE_WRANGLER_TOML = (projectName: string) => `\nname = \"${projectName}\"\nmain = \"dist/main.js\"\ncompatibility_date = \"2024-01-01\"\n\n[vars]\nNODE_ENV = \"production\"\n\n# Uncomment to enable KV namespace for caching\n# [[kv_namespaces]]\n# binding = \"CACHE\"\n# id = \"your-kv-namespace-id\"\n`;\n\n// =============================================================================\n// GitHub Actions Templates\n// =============================================================================\n\nfunction generatePmSetupSteps(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n if (pm === 'pnpm') {\n return `\n - name: Setup pnpm\n uses: pnpm/action-setup@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '24'\n cache: '${cfg.ghCache}'\n\n - name: Install dependencies\n run: ${cfg.ghInstallCmd}`;\n }\n return `\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '24'\n cache: '${cfg.ghCache}'\n\n - name: Install dependencies\n run: ${cfg.ghInstallCmd}`;\n}\n\nfunction generateGhCi(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: CI\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n lint-and-test:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Type check\n run: npx tsc --noEmit\n\n - name: Run tests\n run: ${cfg.run} test\n`;\n}\n\nfunction generateGhE2e(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: E2E Tests\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n e2e:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Run E2E tests\n run: ${cfg.run} test:e2e\n`;\n}\n\nconst TEMPLATE_GH_DEPLOY_DOCKER = `\nname: Build and Push Docker Image\n\non:\n push:\n branches: [main]\n tags: ['v*']\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: \\${{ github.repository }}\n\njobs:\n build-and-push:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n packages: write\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Log in to Container Registry\n uses: docker/login-action@v3\n with:\n registry: \\${{ env.REGISTRY }}\n username: \\${{ github.actor }}\n password: \\${{ secrets.GITHUB_TOKEN }}\n\n - name: Extract metadata\n id: meta\n uses: docker/metadata-action@v5\n with:\n images: \\${{ env.REGISTRY }}/\\${{ env.IMAGE_NAME }}\n\n - name: Build and push\n uses: docker/build-push-action@v5\n with:\n context: .\n file: ./ci/Dockerfile\n push: true\n tags: \\${{ steps.meta.outputs.tags }}\n labels: \\${{ steps.meta.outputs.labels }}\n`;\n\nfunction generateGhDeployVercel(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to Vercel\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Deploy to Vercel\n uses: amondnet/vercel-action@v25\n with:\n vercel-token: \\${{ secrets.VERCEL_TOKEN }}\n vercel-org-id: \\${{ secrets.VERCEL_ORG_ID }}\n vercel-project-id: \\${{ secrets.VERCEL_PROJECT_ID }}\n vercel-args: '--prod'\n`;\n}\n\nfunction generateGhDeployLambda(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to AWS Lambda\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Configure AWS credentials\n uses: aws-actions/configure-aws-credentials@v4\n with:\n aws-access-key-id: \\${{ secrets.AWS_ACCESS_KEY_ID }}\n aws-secret-access-key: \\${{ secrets.AWS_SECRET_ACCESS_KEY }}\n aws-region: \\${{ secrets.AWS_REGION }}\n\n - name: Setup SAM\n uses: aws-actions/setup-sam@v2\n\n - name: Deploy with SAM\n run: |\n cd ci\n sam build\n sam deploy --no-confirm-changeset --no-fail-on-empty-changeset\n`;\n}\n\nfunction generateGhDeployCloudflare(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to Cloudflare Workers\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Deploy to Cloudflare\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: \\${{ secrets.CLOUDFLARE_API_TOKEN }}\n`;\n}\n\n// =============================================================================\n// Dynamic README Templates\n// =============================================================================\n\nfunction generateReadme(options: CreateOptions): string {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions, packageManager } = options;\n const cfg = PM_CONFIG[packageManager];\n\n let readme = `# ${projectName}\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n`;\n\n // Add CI badge if GitHub Actions enabled\n if (enableGitHubActions) {\n readme += `\n\n`;\n }\n\n readme += `\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\n${cfg.userInstall}\n\n# Start development server\n${cfg.run} dev\n\n# Run MCP Inspector\n${cfg.run} inspect\n\\`\\`\\`\n`;\n\n // Deployment-specific sections\n if (deploymentTarget === 'node') {\n readme += `\n## Docker Development\n\n\\`\\`\\`bash\n# Start all services${redisSetup === 'docker' ? ' (includes Redis)' : ''}\n${cfg.run} docker:up\n\n# Stop all services\n${cfg.run} docker:down\n\n# Rebuild Docker image\n${cfg.run} docker:build\n\\`\\`\\`\n`;\n\n if (redisSetup === 'docker') {\n readme += `\n### Redis\n\nRedis is included in the Docker Compose setup. For local development without Docker:\n\n\\`\\`\\`bash\n# Start only Redis\ndocker compose -f ci/docker-compose.yml up redis -d\n\\`\\`\\`\n`;\n }\n\n readme += `\n## Production Deployment\n\nBuild and push the Docker image:\n\n\\`\\`\\`bash\ndocker build -f ci/Dockerfile -t ${projectName}:latest .\ndocker push your-registry/${projectName}:latest\n\\`\\`\\`\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `\n## Deploy to Vercel\n\n\\`\\`\\`bash\n# Build for production\n${cfg.run} build\n\n# Deploy using Vercel CLI\nnpx vercel --prod\n\\`\\`\\`\n\nOr connect your repository to Vercel for automatic deployments.\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `\n## Deploy to AWS Lambda\n\n\\`\\`\\`bash\n# Build the project\n${cfg.run} build\n\n# Deploy using AWS SAM\n${cfg.run} deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- AWS CLI configured with appropriate credentials\n- AWS SAM CLI installed (\\`brew install aws-sam-cli\\` or \\`pip install aws-sam-cli\\`)\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `\n## Deploy to Cloudflare Workers\n\n\\`\\`\\`bash\n# Build the project\n${cfg.run} build\n\n# Deploy using Wrangler\n${cfg.run} deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- Wrangler CLI installed (\\`npm install -g wrangler\\`)\n- Cloudflare account configured (\\`wrangler login\\`)\n`;\n }\n\n // Environment variables section\n readme += `\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n`;\n\n if (deploymentTarget === 'node' && redisSetup !== 'none') {\n readme += `| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n| \\`REDIS_PASSWORD\\` | - | Redis password (set in production) |\n`;\n }\n\n // GitHub Actions section\n if (enableGitHubActions) {\n readme += `\n## CI/CD\n\nThis project includes GitHub Actions workflows:\n\n- **ci.yml**: Runs on every push/PR - type checking and tests\n- **e2e.yml**: Runs E2E tests\n- **deploy.yml**: Deploys to ${\n deploymentTarget === 'node'\n ? 'GitHub Container Registry'\n : deploymentTarget === 'vercel'\n ? 'Vercel'\n : deploymentTarget === 'lambda'\n ? 'AWS Lambda'\n : 'Cloudflare Workers'\n }\n\n### Required Secrets\n`;\n\n if (deploymentTarget === 'vercel') {\n readme += `\n- \\`VERCEL_TOKEN\\`: Vercel API token\n- \\`VERCEL_ORG_ID\\`: Vercel organization ID\n- \\`VERCEL_PROJECT_ID\\`: Vercel project ID\n`;\n } else if (deploymentTarget === 'lambda') {\n readme += `\n- \\`AWS_ACCESS_KEY_ID\\`: AWS access key\n- \\`AWS_SECRET_ACCESS_KEY\\`: AWS secret key\n- \\`AWS_REGION\\`: AWS region (e.g., us-east-1)\n`;\n } else if (deploymentTarget === 'cloudflare') {\n readme += `\n- \\`CLOUDFLARE_API_TOKEN\\`: Cloudflare API token with Workers permissions\n`;\n } else {\n readme += `\nNo additional secrets required - uses \\`GITHUB_TOKEN\\` for GHCR.\n`;\n }\n }\n\n readme += `\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`${cfg.run} dev\\` | Start development server with hot reload |\n| \\`${cfg.run} build\\` | Build for production |\n| \\`${cfg.run} inspect\\` | Launch MCP Inspector |\n| \\`${cfg.run} doctor\\` | Check project configuration |\n| \\`${cfg.run} test\\` | Run unit tests |\n| \\`${cfg.run} test:e2e\\` | Run E2E tests |\n`;\n\n if (deploymentTarget === 'node') {\n readme += `| \\`${cfg.run} docker:up\\` | Start Docker services |\n| \\`${cfg.run} docker:down\\` | Stop Docker services |\n| \\`${cfg.run} docker:build\\` | Rebuild Docker image |\n`;\n }\n\n if (deploymentTarget === 'lambda' || deploymentTarget === 'cloudflare') {\n readme += `| \\`${cfg.run} deploy\\` | Deploy to ${deploymentTarget === 'lambda' ? 'AWS Lambda' : 'Cloudflare Workers'} |\n`;\n }\n\n readme += `\n## Project Structure\n\n\\`\\`\\`\n`;\n\n // Dynamic project structure based on options\n readme += `├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n`;\n\n if (deploymentTarget === 'node') {\n readme += `├── .dockerignore # Docker build context exclusions\n├── ci/\n│ ├── Dockerfile # Container build config\n│ ├── docker-compose.yml # Docker services config\n│ └── .env.docker # Docker-specific env vars\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `├── vercel.json # Vercel deployment config\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `├── ci/\n│ └── template.yaml # AWS SAM template\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `├── wrangler.toml # Cloudflare Workers config\n`;\n }\n\n if (enableGitHubActions) {\n readme += `├── .github/workflows/\n│ ├── ci.yml # CI workflow\n│ ├── e2e.yml # E2E test workflow\n│ └── deploy.yml # Deployment workflow\n`;\n }\n\n readme += `├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Scaling to a Monorepo\n\nTo migrate to an Nx monorepo with multiple apps and shared libraries:\n\n\\`\\`\\`bash\nnpx frontmcp create my-workspace --nx\n\\`\\`\\`\n\nThis scaffolds an Nx workspace with generators for tools, resources, prompts, and more.\nSee the [FrontMCP Nx Plugin docs](https://docs.agentfront.dev) for details.\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n return readme;\n}\n\n// =============================================================================\n// Scaffolding Functions\n// =============================================================================\n\nfunction getDefaults(projectArg?: string): CreateOptions {\n return {\n projectName: projectArg || 'frontmcp-app',\n deploymentTarget: 'node',\n redisSetup: 'docker',\n enableGitHubActions: true,\n packageManager: 'npm',\n };\n}\n\nfunction getInstallCommand(pm: PackageManager): { cmd: string; args: string[] } {\n switch (pm) {\n case 'npm':\n return { cmd: 'npm', args: ['install'] };\n case 'yarn':\n return { cmd: 'yarn', args: ['install'] };\n case 'pnpm':\n return { cmd: 'pnpm', args: ['install'] };\n }\n}\n\nasync function scaffoldNxWorkspace(projectName: string, flags?: CreateFlags): Promise<void> {\n const pm = flags?.pm ?? 'npm';\n const folder = sanitizeForFolder(projectName);\n const projectDir = path.resolve(process.cwd(), folder);\n\n // Validate target directory\n try {\n const s = await stat(projectDir);\n if (!s.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), projectDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(projectDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), projectDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(projectDir);\n } else {\n throw e;\n }\n }\n\n try {\n // Step 1: Write bootstrap package.json with nx tooling\n const selfVersion = getSelfVersion();\n await writeJSON(path.join(projectDir, 'package.json'), {\n name: folder,\n version: '0.0.1',\n private: true,\n devDependencies: {\n nx: '22.3.3',\n '@nx/devkit': '22.3.3',\n '@frontmcp/nx': `~${selfVersion}`,\n },\n });\n\n // Step 2: Install nx tooling\n console.log(c('cyan', `\\nInstalling Nx tooling in ./${folder}...\\n`));\n const install = getInstallCommand(pm);\n await runCmd(install.cmd, install.args, { cwd: projectDir });\n\n // Step 3: Load nx and @frontmcp/nx from the installed location\n const localRequire = createRequire(path.join(projectDir, 'package.json'));\n const { FsTree, flushChanges } = localRequire('nx/src/generators/tree.js');\n const { workspaceGenerator } = localRequire('@frontmcp/nx');\n\n // Step 4: Run the workspace generator\n console.log(c('cyan', `\\nScaffolding Nx monorepo: ${projectName}...\\n`));\n const tree = new FsTree(process.cwd(), false);\n const callback = await workspaceGenerator(tree, {\n name: folder,\n packageManager: pm,\n skipInstall: true,\n skipGit: false,\n createSampleApp: true,\n });\n\n flushChanges(tree.root, tree.listChanges());\n\n if (callback) {\n await callback();\n }\n\n // Step 5: Install full project dependencies\n console.log(c('cyan', '\\nInstalling project dependencies...\\n'));\n await runCmd(install.cmd, install.args, { cwd: projectDir });\n\n console.log(c('green', `\\n✅ Nx monorepo created at ./${folder}\\n`));\n console.log(c('dim', 'Next steps:'));\n console.log(c('dim', ` cd ${folder}`));\n console.log(c('dim', ' nx g @frontmcp/nx:app my-app # Add an app'));\n console.log(c('dim', ' nx g @frontmcp/nx:lib my-lib # Add a library'));\n console.log(c('dim', ' nx g @frontmcp/nx:tool my-tool # Add a tool to an app'));\n console.log(c('dim', ' nx dev demo # Start dev server'));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (\n message.includes('Cannot find module') ||\n message.includes('Cannot find package') ||\n message.includes('MODULE_NOT_FOUND')\n ) {\n console.error(c('red', '\\nFailed to install Nx tooling.'));\n console.log(c('dim', 'Check your network connection and try again.'));\n console.log(c('dim', 'You can also install manually:'));\n console.log(c('bold', ` cd ${folder} && ${pm} install`));\n } else {\n console.error(c('red', `\\nFailed to scaffold Nx workspace: ${message}`));\n }\n process.exit(1);\n }\n}\n\nasync function collectOptions(projectArg?: string, flags?: CreateFlags): Promise<CreateOptions> {\n const p = await clack();\n\n // Project name\n let projectName = projectArg;\n if (!projectName) {\n const result = await p.text({\n message: 'Project name',\n validate: (val) => {\n if (!val.trim()) return 'Project name is required';\n return undefined;\n },\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n projectName = result;\n }\n\n if (!flags?.yes) {\n const projectType = await p.select({\n message: 'Project type',\n options: [\n { label: 'Standalone project (recommended)', value: 'standalone' as const },\n { label: 'Nx monorepo (advanced)', value: 'nx' as const },\n ],\n initialValue: 'standalone' as const,\n });\n if (p.isCancel(projectType)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n if (projectType === 'nx') {\n await scaffoldNxWorkspace(projectName, flags);\n return {\n projectName,\n deploymentTarget: 'node',\n redisSetup: 'none',\n enableGitHubActions: false,\n packageManager: flags?.pm ?? 'npm',\n nxScaffolded: true,\n };\n }\n }\n\n // Deployment target\n let deploymentTarget = flags?.target;\n if (!deploymentTarget) {\n const result = await p.select({\n message: 'Select deployment target',\n options: [\n { label: 'Node.js (Docker) - Recommended for production', value: 'node' as DeploymentTarget },\n { label: 'Vercel (Serverless)', value: 'vercel' as DeploymentTarget },\n { label: 'AWS Lambda', value: 'lambda' as DeploymentTarget },\n { label: 'Cloudflare Workers', value: 'cloudflare' as DeploymentTarget },\n ],\n initialValue: 'node' as DeploymentTarget,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n deploymentTarget = result;\n }\n\n // Redis setup (only for Node.js/Docker)\n let redisSetup: RedisSetup = 'none';\n if (deploymentTarget === 'node') {\n if (flags?.redis) {\n redisSetup = flags.redis;\n } else {\n const result = await p.select({\n message: 'Redis setup',\n options: [\n { label: 'Docker Compose (recommended for development)', value: 'docker' as RedisSetup },\n { label: 'Existing Redis (I have my own Redis)', value: 'existing' as RedisSetup },\n { label: 'None (skip Redis)', value: 'none' as RedisSetup },\n ],\n initialValue: 'docker' as RedisSetup,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n redisSetup = result;\n }\n }\n\n // Package manager\n let packageManager = flags?.pm;\n if (!packageManager) {\n const result = await p.select({\n message: 'Package manager',\n options: [\n { label: 'npm (default)', value: 'npm' as PackageManager },\n { label: 'yarn', value: 'yarn' as PackageManager },\n { label: 'pnpm', value: 'pnpm' as PackageManager },\n ],\n initialValue: 'npm' as PackageManager,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n packageManager = result;\n }\n\n // GitHub Actions\n let enableGitHubActions = flags?.cicd;\n if (enableGitHubActions === undefined) {\n const result = await p.confirm({\n message: 'Set up GitHub Actions CI/CD?',\n initialValue: true,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n enableGitHubActions = result;\n }\n\n return {\n projectName,\n deploymentTarget,\n redisSetup,\n enableGitHubActions,\n packageManager,\n };\n}\n\nasync function scaffoldDeploymentFiles(targetDir: string, options: CreateOptions): Promise<void> {\n const { deploymentTarget, redisSetup, projectName } = options;\n\n switch (deploymentTarget) {\n case 'node': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(\n targetDir,\n path.join(ciDir, 'Dockerfile'),\n generateDockerfile(options.packageManager),\n );\n\n const dockerCompose = redisSetup === 'docker' ? generateDockerComposeWithRedis() : generateDockerComposeNoRedis();\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'docker-compose.yml'), dockerCompose);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, '.env.docker'), TEMPLATE_ENV_DOCKER_CI);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.dockerignore'), TEMPLATE_DOCKERIGNORE);\n break;\n }\n\n case 'vercel':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'vercel.json'),\n TEMPLATE_VERCEL_JSON(sanitizeForFolder(projectName)),\n );\n break;\n\n case 'lambda': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'template.yaml'), TEMPLATE_SAM_YAML(projectName));\n break;\n }\n\n case 'cloudflare':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'wrangler.toml'),\n TEMPLATE_WRANGLER_TOML(sanitizeForFolder(projectName)),\n );\n break;\n }\n\n // Always create .env.example at root\n const envExample =\n deploymentTarget === 'node' && redisSetup !== 'none' ? TEMPLATE_ENV_EXAMPLE : TEMPLATE_ENV_EXAMPLE_BASIC;\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.env.example'), envExample);\n}\n\n// Basic .env.example without Redis\nconst TEMPLATE_ENV_EXAMPLE_BASIC = `\n# Application\nPORT=3000\nNODE_ENV=development\n`;\n\nasync function scaffoldGitHubActions(\n targetDir: string,\n deploymentTarget: DeploymentTarget,\n pm: PackageManager,\n): Promise<void> {\n const workflowDir = path.join(targetDir, '.github', 'workflows');\n await ensureDir(workflowDir);\n\n // Always create CI and E2E workflows\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'ci.yml'), generateGhCi(pm));\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'e2e.yml'), generateGhE2e(pm));\n\n // Create deployment workflow based on target\n const deployTemplate = getDeployWorkflowTemplate(deploymentTarget, pm);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'deploy.yml'), deployTemplate);\n}\n\nfunction getDeployWorkflowTemplate(target: DeploymentTarget, pm: PackageManager): string {\n switch (target) {\n case 'node':\n return TEMPLATE_GH_DEPLOY_DOCKER;\n case 'vercel':\n return generateGhDeployVercel(pm);\n case 'lambda':\n return generateGhDeployLambda(pm);\n case 'cloudflare':\n return generateGhDeployCloudflare(pm);\n }\n}\n\nasync function scaffoldProject(options: CreateOptions): Promise<void> {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions, packageManager } = options;\n\n const folder = sanitizeForFolder(projectName);\n const pkgName = sanitizeForNpm(projectName);\n const targetDir = path.resolve(process.cwd(), folder);\n\n // Validate directory\n try {\n const stat = await fsp.stat(targetDir);\n if (!stat.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(targetDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(targetDir);\n } else {\n throw e;\n }\n }\n\n console.log(`\\n${c('cyan', '[create]')} Creating project in ${c('bold', './' + folder)}`);\n console.log(c('gray', ` Deployment: ${deploymentTarget}`));\n if (deploymentTarget === 'node') {\n console.log(c('gray', ` Redis: ${redisSetup}`));\n }\n console.log(c('gray', ` Package manager: ${packageManager}`));\n console.log(c('gray', ` GitHub Actions: ${enableGitHubActions ? 'Yes' : 'No'}`));\n console.log('');\n\n process.chdir(targetDir);\n\n // Initialize tsconfig\n await runInit(targetDir);\n\n // Create package.json with deployment-specific scripts\n const selfVersion = getSelfVersion();\n await upsertPackageJsonWithTarget(targetDir, pkgName, selfVersion, deploymentTarget, packageManager);\n\n // Scaffold base files\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'main.ts'), TEMPLATE_MAIN_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'calc.app.ts'), TEMPLATE_CALC_APP_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'tools', 'add.tool.ts'), TEMPLATE_ADD_TOOL_TS);\n\n // E2E scaffolding\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.spec.ts'), TEMPLATE_E2E_TEST_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'jest.e2e.config.ts'), TEMPLATE_JEST_E2E_CONFIG);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'tsconfig.e2e.json'), TEMPLATE_TSCONFIG_E2E);\n\n // Git configuration\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.gitignore'), TEMPLATE_GITIGNORE);\n\n // Node version\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.nvmrc'), '24\\n');\n\n // Deployment-specific files\n await scaffoldDeploymentFiles(targetDir, options);\n\n // GitHub Actions\n if (enableGitHubActions) {\n await scaffoldGitHubActions(targetDir, deploymentTarget, packageManager);\n }\n\n // Dynamic README\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'README.md'), generateReadme(options));\n\n // Print next steps\n printNextSteps(folder, deploymentTarget, redisSetup, enableGitHubActions, packageManager);\n}\n\nfunction printNextSteps(\n folder: string,\n deploymentTarget: DeploymentTarget,\n redisSetup: RedisSetup,\n enableGitHubActions: boolean,\n pm: PackageManager,\n): void {\n const cfg = PM_CONFIG[pm];\n console.log('\\nNext steps:');\n console.log(` 1) cd ${folder}`);\n console.log(` 2) ${cfg.userInstall}`);\n console.log(` 3) ${cfg.run} dev `, c('gray', '# tsx watcher + async tsc type-check'));\n console.log(` 4) ${cfg.run} inspect `, c('gray', '# launch MCP Inspector'));\n console.log(` 5) ${cfg.run} build `, c('gray', '# compile with tsc via frontmcp build'));\n console.log(` 6) ${cfg.run} test:e2e `, c('gray', '# run E2E tests'));\n\n if (deploymentTarget === 'node') {\n console.log('');\n console.log(c('cyan', 'Docker:'));\n console.log(\n ` ${cfg.run} docker:up `,\n c('gray', `# start${redisSetup === 'docker' ? ' Redis +' : ''} app in Docker`),\n );\n console.log(` ${cfg.run} docker:down `, c('gray', '# stop Docker services'));\n }\n\n if (deploymentTarget === 'vercel') {\n console.log('');\n console.log(c('cyan', 'Deploy to Vercel:'));\n console.log(' npx vercel ', c('gray', '# deploy to Vercel'));\n }\n\n if (deploymentTarget === 'lambda') {\n console.log('');\n console.log(c('cyan', 'Deploy to AWS Lambda:'));\n console.log(` ${cfg.run} deploy `, c('gray', '# deploy with SAM'));\n }\n\n if (deploymentTarget === 'cloudflare') {\n console.log('');\n console.log(c('cyan', 'Deploy to Cloudflare:'));\n console.log(` ${cfg.run} deploy `, c('gray', '# deploy with Wrangler'));\n }\n\n if (enableGitHubActions) {\n console.log('');\n console.log(c('cyan', 'GitHub Actions:'));\n console.log(' .github/workflows/ ', c('gray', '# CI, E2E, and deploy workflows ready'));\n }\n}\n\n// =============================================================================\n// Package.json with Target-Specific Scripts\n// =============================================================================\n\nasync function upsertPackageJsonWithTarget(\n cwd: string,\n nameOverride: string | undefined,\n selfVersion: string,\n deploymentTarget: DeploymentTarget,\n pm: PackageManager = 'npm',\n) {\n const pkgPath = path.join(cwd, 'package.json');\n const existing = await readJSON<PackageJson>(pkgPath);\n\n const frontmcpLibRange = `~${selfVersion}`;\n\n const baseScripts: Record<string, string> = {\n dev: 'frontmcp dev',\n build: 'frontmcp build',\n inspect: 'frontmcp inspector',\n doctor: 'frontmcp doctor',\n test: 'frontmcp test',\n 'test:e2e': 'jest --config jest.e2e.config.ts --runInBand',\n };\n\n // Add target-specific scripts\n if (deploymentTarget === 'node') {\n baseScripts['docker:up'] = 'docker compose -f ci/docker-compose.yml up';\n baseScripts['docker:down'] = 'docker compose -f ci/docker-compose.yml down';\n baseScripts['docker:build'] = 'docker compose -f ci/docker-compose.yml build';\n }\n\n if (deploymentTarget === 'lambda') {\n baseScripts['deploy'] = 'cd ci && sam build && sam deploy';\n }\n\n if (deploymentTarget === 'cloudflare') {\n baseScripts['deploy'] = 'wrangler deploy';\n }\n\n const base = {\n name: nameOverride ?? pkgNameFromCwd(cwd),\n version: '0.1.0',\n private: true,\n type: 'commonjs',\n main: 'src/main.ts',\n scripts: baseScripts,\n engines: PM_CONFIG[pm].engines,\n dependencies: {\n '@frontmcp/sdk': frontmcpLibRange,\n '@frontmcp/plugins': frontmcpLibRange,\n '@frontmcp/adapters': frontmcpLibRange,\n frontmcp: selfVersion,\n tslib: '^2.5.0',\n zod: '^4.0.0',\n 'reflect-metadata': '^0.2.2',\n },\n devDependencies: {\n '@frontmcp/testing': frontmcpLibRange,\n '@swc/core': '^1.11.29',\n '@swc/jest': '^0.2.37',\n jest: '^29.7.0',\n '@types/jest': '^29.5.14',\n tsx: '^4.20.6',\n '@types/node': '^24.0.0',\n typescript: '^5.5.3',\n },\n };\n\n if (!existing) {\n await writeJSON(pkgPath, base);\n console.log(c('green', '✅ Created package.json (synced @frontmcp libs to CLI version + exact frontmcp)'));\n return;\n }\n\n const merged: PackageJson = { ...base, ...existing };\n\n merged.name = existing.name || base.name;\n merged.main = existing.main || base.main;\n merged.type = existing.type || base.type;\n\n // Preserve user scripts, add base scripts only if missing\n merged.scripts = {\n ...baseScripts,\n ...(existing.scripts || {}),\n };\n\n merged.engines = {\n ...(existing.engines || {}),\n ...base.engines,\n };\n\n merged.dependencies = {\n ...(existing.dependencies || {}),\n ...base.dependencies,\n };\n\n merged.devDependencies = {\n ...(existing.devDependencies || {}),\n ...base.devDependencies,\n };\n\n await writeJSON(pkgPath, merged);\n console.log(c('green', '✅ Updated package.json (synced @frontmcp libs + frontmcp to current CLI version)'));\n}\n\n// =============================================================================\n// Main Entry Point\n// =============================================================================\n\nexport async function runCreate(projectArg?: string, flags?: CreateFlags): Promise<void> {\n // Nx monorepo mode (non-interactive with --nx flag)\n if (flags?.nx) {\n const name = projectArg || 'frontmcp-app';\n await scaffoldNxWorkspace(name, flags);\n return;\n }\n\n // Non-interactive mode: use --yes flag or non-TTY environment\n if (flags?.yes || !isInteractive()) {\n const options = getDefaults(projectArg);\n // Override defaults with any provided flags\n if (flags?.target) options.deploymentTarget = flags.target;\n if (flags?.redis) options.redisSetup = flags.redis;\n if (flags?.cicd !== undefined) options.enableGitHubActions = flags.cicd;\n if (flags?.pm) options.packageManager = flags.pm;\n if (projectArg) options.projectName = projectArg;\n\n if (!options.projectName) {\n console.error(c('red', 'Error: project name is required in non-interactive mode.\\n'));\n console.log(`Usage: ${c('bold', 'npx frontmcp create <project-name> --yes')}`);\n process.exit(1);\n }\n\n await scaffoldProject(options);\n return;\n }\n\n // Interactive mode\n const p = await clack();\n p.intro('Create a new FrontMCP project');\n\n const options = await collectOptions(projectArg, flags);\n if (!options.nxScaffolded) await scaffoldProject(options);\n\n p.outro('Done!');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/commands/scaffold/create.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { createRequire } from 'module';\nimport { c } from '../../core/colors';\nimport { ensureDir, fileExists, isDirEmpty, writeFile, writeJSON, readJSON, runCmd, stat } from '@frontmcp/utils';\nimport { runInit } from '../../core/tsconfig';\nimport { getSelfVersion } from '../../core/version';\nimport { clack } from '../../shared/prompts';\n\n// =============================================================================\n// Types\n// =============================================================================\n\nexport type DeploymentTarget = 'node' | 'vercel' | 'lambda' | 'cloudflare';\nexport type RedisSetup = 'docker' | 'existing' | 'none';\nexport type PackageManager = 'npm' | 'yarn' | 'pnpm';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n packageManager: PackageManager;\n nxScaffolded?: boolean;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n pm?: PackageManager;\n nx?: boolean;\n}\n\ninterface PmConfig {\n lockfileCopy: string;\n installAll: string;\n pruneDevDeps: string;\n run: string;\n userInstall: string;\n ghCache: string;\n ghInstallCmd: string;\n engines: { node: string; npm?: string };\n}\n\nconst PM_CONFIG: Record<PackageManager, PmConfig> = {\n npm: {\n lockfileCopy: 'COPY package*.json package-lock.json* ./',\n installAll: 'RUN npm ci',\n pruneDevDeps: 'RUN npm prune --omit=dev',\n run: 'npm run',\n userInstall: 'npm install',\n ghCache: 'npm',\n ghInstallCmd: 'npm ci',\n engines: { node: '>=22', npm: '>=10' },\n },\n yarn: {\n lockfileCopy: 'COPY package.json yarn.lock* ./',\n installAll: 'RUN yarn install --frozen-lockfile',\n pruneDevDeps: 'RUN yarn install --frozen-lockfile --production',\n run: 'yarn',\n userInstall: 'yarn install',\n ghCache: 'yarn',\n ghInstallCmd: 'yarn install --frozen-lockfile',\n engines: { node: '>=22' },\n },\n pnpm: {\n lockfileCopy: 'COPY package.json pnpm-lock.yaml* ./',\n installAll: 'RUN pnpm install --frozen-lockfile',\n pruneDevDeps: 'RUN pnpm prune --prod',\n run: 'pnpm run',\n userInstall: 'pnpm install',\n ghCache: 'pnpm',\n ghInstallCmd: 'pnpm install --frozen-lockfile',\n engines: { node: '>=22' },\n },\n};\n\ninterface PackageJson {\n name?: string;\n version?: string;\n private?: boolean;\n type?: string;\n main?: string;\n scripts?: Record<string, string>;\n engines?: { node?: string; npm?: string };\n dependencies?: Record<string, string>;\n devDependencies?: Record<string, string>;\n [key: string]: unknown;\n}\n\nfunction isInteractive(): boolean {\n return process.stdin.isTTY === true;\n}\n\nfunction sanitizeForFolder(name: string): string {\n const seg = name.startsWith('@') && name.includes('/') ? name.split('/')[1] : name;\n return (\n seg\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nfunction sanitizeForNpm(name: string): string {\n if (name.startsWith('@') && name.includes('/')) {\n const [scope, pkg] = name.split('/');\n const s = scope.replace(/[^a-z0-9-]/gi, '').toLowerCase();\n const p = pkg.replace(/[^a-z0-9._-]/gi, '-').toLowerCase();\n return `@${s}/${p || 'frontmcp-app'}`;\n }\n return name.replace(/[^a-z0-9._-]/gi, '-').toLowerCase() || 'frontmcp-app';\n}\n\nfunction pkgNameFromCwd(cwd: string) {\n return (\n path\n .basename(cwd)\n .replace(/[^a-zA-Z0-9._-]/g, '-')\n .toLowerCase() || 'frontmcp-app'\n );\n}\n\nasync function scaffoldFileIfMissing(baseDir: string, p: string, content: string) {\n if (await fileExists(p)) {\n console.log(c('gray', `skip: ${path.relative(baseDir, p)} already exists`));\n return;\n }\n await ensureDir(path.dirname(p));\n await writeFile(p, content.replace(/^\\n/, ''));\n console.log(c('green', `✓ created ${path.relative(baseDir, p)}`));\n}\n\nconst TEMPLATE_MAIN_TS = `\nimport 'reflect-metadata';\nimport { FrontMcp } from '@frontmcp/sdk';\nimport { CalcApp } from './calc.app';\n\n@FrontMcp({\n info: { name: 'Demo 🚀', version: '0.1.0' },\n apps: [CalcApp],\n})\nexport default class Server {}\n`;\n\nconst TEMPLATE_CALC_APP_TS = `\nimport { App } from '@frontmcp/sdk';\nimport AddTool from './tools/add.tool';\n\n@App({\n id: 'calc',\n name: 'Calculator',\n tools: [AddTool],\n})\nexport class CalcApp {}\n`;\n\nconst TEMPLATE_ADD_TOOL_TS = `\nimport {Tool, ToolContext} from \"@frontmcp/sdk\";\nimport {z} from \"zod\";\n\n@Tool({\n name: 'add',\n description: 'Add two numbers',\n inputSchema: {a: z.number(), b: z.number()},\n outputSchema: {result: z.number()}\n})\nexport default class AddTool extends ToolContext {\n async execute(input: { a: number, b: number }) {\n return {\n result: input.a + input.b,\n };\n }\n}\n`;\n\nconst TEMPLATE_E2E_TEST_TS = `\nimport { test, expect } from '@frontmcp/testing';\n\n/**\n * E2E tests for the MCP server.\n *\n * Run with:\n * frontmcp test # recommended\n * npm run test:e2e # alternative\n */\ntest.describe('Server E2E', () => {\n test.use({\n server: './src/main.ts',\n port: 3100,\n });\n\n test('should connect and initialize', async ({ mcp }) => {\n expect(mcp.isConnected()).toBe(true);\n expect(mcp.serverInfo.name).toBeDefined();\n });\n\n test('should list tools', async ({ mcp }) => {\n const tools = await mcp.tools.list();\n expect(tools.length).toBeGreaterThanOrEqual(0);\n });\n\n test('should call add tool', async ({ mcp }) => {\n const result = await mcp.tools.call('add', { a: 2, b: 3 });\n expect(result).toBeSuccessful();\n });\n\n test('should list resources', async ({ mcp }) => {\n const resources = await mcp.resources.list();\n expect(resources).toBeDefined();\n });\n});\n`;\n\nconst TEMPLATE_GITIGNORE = `\n# Dependencies\nnode_modules/\n\n# Build output\ndist/\n*.tsbuildinfo\n\n# IDE\n.idea/\n.vscode/\n*.swp\n*.swo\n\n# OS files\n.DS_Store\nThumbs.db\n\n# Logs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n\n# Environment variables\n.env\n.env.local\n.env.*.local\n\n# FrontMCP development keys (contains private keys - never commit!)\n.frontmcp/\n\n# Coverage\ncoverage/\n\n# Test output\ntest-output/\n`;\n\nconst TEMPLATE_DOCKERIGNORE = `\nnode_modules\ndist\n.git\ncoverage\ntest-output\n*.tsbuildinfo\n.idea\n.vscode\n.DS_Store\nThumbs.db\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\n.env\n.env.local\n.env.*.local\n.frontmcp\ne2e\n*.md\nLICENSE\n`;\n\nconst TEMPLATE_JEST_E2E_CONFIG = `\n/* eslint-disable */\nexport default {\n displayName: 'e2e',\n testEnvironment: 'node',\n testMatch: ['<rootDir>/e2e/**/*.e2e.spec.ts'],\n testTimeout: 60000,\n setupFilesAfterEnv: ['@frontmcp/testing/setup'],\n transform: {\n '^.+\\\\\\\\.[tj]s$': [\n '@swc/jest',\n {\n jsc: {\n target: 'es2022',\n parser: {\n syntax: 'typescript',\n decorators: true,\n dynamicImport: true,\n },\n transform: {\n decoratorMetadata: true,\n legacyDecorator: true,\n },\n keepClassNames: true,\n externalHelpers: true,\n loose: true,\n },\n module: {\n type: 'es6',\n },\n sourceMaps: true,\n swcrc: false,\n },\n ],\n },\n moduleFileExtensions: ['ts', 'js', 'html'],\n transformIgnorePatterns: ['node_modules/(?!(jose)/)'],\n};\n`;\n\nconst TEMPLATE_TSCONFIG_E2E = `\n{\n \"extends\": \"./tsconfig.json\",\n \"compilerOptions\": {\n \"types\": [\"node\", \"jest\"]\n },\n \"include\": [\"e2e/**/*.ts\", \"jest.e2e.config.ts\"]\n}\n`;\n\nconst TEMPLATE_ENV_EXAMPLE = `\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis (recommended for development, required for production)\nREDIS_HOST=localhost\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\n\n# Optional: Redis TLS (enable for production)\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_ENV_DOCKER = `\n# Docker-specific environment\n# Copy this to .env when running with docker compose\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\nconst TEMPLATE_README = `\n# FrontMCP Server\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\nnpm install\n\n# Start development server\nnpm run dev\n\n# Run MCP Inspector\nnpm run inspect\n\\`\\`\\`\n\n## Development with Docker\n\n### Prerequisites\n- Docker & Docker Compose installed\n\n### Quick Start\n\n\\`\\`\\`bash\n# Start Redis and app in development mode\ndocker compose up\n\n# Start only Redis (for local development)\ndocker compose up redis -d\n\n# Stop all services\ndocker compose down\n\\`\\`\\`\n\n### Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n\n## Redis Configuration\n\n### Development\nRedis is **recommended** for development to enable caching and session persistence.\nUse the included \\`docker-compose.yml\\` to run Redis locally:\n\n\\`\\`\\`bash\ndocker compose up redis -d\n\\`\\`\\`\n\n### Production\nRedis is **required** in production for:\n- Session storage (multi-instance deployments)\n- Caching (performance optimization)\n- Rate limiting (if enabled)\n\nSee the [Redis Setup Guide](https://docs.agentfront.dev/docs/deployment/redis-setup) for production configuration.\n\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`npm run dev\\` | Start development server with hot reload |\n| \\`npm run build\\` | Build for production |\n| \\`npm run inspect\\` | Launch MCP Inspector |\n| \\`npm run doctor\\` | Check project configuration |\n| \\`npm run test\\` | Run unit tests |\n| \\`npm run test:e2e\\` | Run E2E tests |\n\n## Project Structure\n\n\\`\\`\\`\n├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n├── docker-compose.yml # Docker services config\n├── Dockerfile # Container build config\n├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n// =============================================================================\n// Deployment Target Templates\n// =============================================================================\n\n// Docker templates (moved to ci/ folder)\nfunction generateDockerfile(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n const corepack = pm !== 'npm' ? '\\nRUN corepack enable\\n' : '';\n return `\n# Build stage\nFROM node:24-slim AS builder\n\nWORKDIR /app\n${corepack}\n# Install all dependencies (including devDependencies for build)\n${cfg.lockfileCopy}\n${cfg.installAll}\n\n# Copy source and build\nCOPY . .\nRUN ${cfg.run} build\n\n# Prune devDependencies so only production deps remain\n${cfg.pruneDevDeps}\n\n# Production stage\nFROM node:24-slim AS runner\n\nWORKDIR /app\nENV NODE_ENV=production\n\nCOPY --from=builder /app/node_modules ./node_modules\nCOPY --from=builder /app/dist ./dist\nCOPY --from=builder /app/package.json ./\n\nEXPOSE 3000\n\nCMD [\"node\", \"dist/main.js\"]\n`;\n}\n\nfunction generateDockerComposeWithRedis(): string {\n return `\nservices:\n redis:\n image: redis:7-alpine\n ports:\n - '6379:6379'\n volumes:\n - redis-data:/data\n command: redis-server --appendonly yes\n healthcheck:\n test: ['CMD', 'redis-cli', 'ping']\n interval: 3s\n timeout: 5s\n retries: 3\n\n app:\n build:\n context: ..\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - PORT=\\${PORT:-3000}\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n depends_on:\n redis:\n condition: service_healthy\n\nvolumes:\n redis-data:\n\n# Selective rebuild:\n# docker compose -f ci/docker-compose.yml up --build app # rebuild only the app\n# docker compose -f ci/docker-compose.yml up --build # rebuild everything\n`;\n}\n\nfunction generateDockerComposeNoRedis(): string {\n return `\nservices:\n app:\n build:\n context: ..\n dockerfile: ci/Dockerfile\n ports:\n - '\\${PORT:-3000}:3000'\n environment:\n - NODE_ENV=\\${NODE_ENV:-development}\n - PORT=\\${PORT:-3000}\n\n# Selective rebuild:\n# docker compose -f ci/docker-compose.yml up --build app # rebuild only the app\n`;\n}\n\nconst TEMPLATE_ENV_DOCKER_CI = `\n# Docker-specific environment\n# Use with: docker compose -f ci/docker-compose.yml --env-file ci/.env.docker up\n\n# Application\nPORT=3000\nNODE_ENV=development\n\n# Redis - use 'redis' (service name) as host inside Docker network\nREDIS_HOST=redis\nREDIS_PORT=6379\n# SECURITY: Set a strong password in production\nREDIS_PASSWORD=\nREDIS_DB=0\nREDIS_TLS=false\n`;\n\n// Vercel template\nconst TEMPLATE_VERCEL_JSON = (projectName: string) =>\n JSON.stringify(\n {\n $schema: 'https://openapi.vercel.sh/vercel.json',\n name: projectName,\n version: 2,\n builds: [\n {\n src: 'dist/main.js',\n use: '@vercel/node',\n },\n ],\n routes: [\n {\n src: '/(.*)',\n dest: '/dist/main.js',\n },\n ],\n env: {\n NODE_ENV: 'production',\n },\n },\n null,\n 2,\n );\n\n// AWS Lambda SAM template\nconst TEMPLATE_SAM_YAML = (projectName: string) => `\nAWSTemplateFormatVersion: '2010-09-09'\nTransform: AWS::Serverless-2016-10-31\nDescription: ${projectName} - FrontMCP Lambda Function\n\nGlobals:\n Function:\n Timeout: 30\n Runtime: nodejs22.x\n MemorySize: 256\n\nResources:\n FrontMCPFunction:\n Type: AWS::Serverless::Function\n Properties:\n CodeUri: ../dist/\n Handler: main.handler\n Events:\n ApiEvent:\n Type: HttpApi\n Properties:\n Path: /{proxy+}\n Method: ANY\n\nOutputs:\n ApiEndpoint:\n Description: API Gateway endpoint URL\n Value: !Sub \"https://\\${ServerlessHttpApi}.execute-api.\\${AWS::Region}.amazonaws.com\"\n`;\n\n// Cloudflare Workers template\nconst TEMPLATE_WRANGLER_TOML = (projectName: string) => `\nname = \"${projectName}\"\nmain = \"dist/main.js\"\ncompatibility_date = \"2024-01-01\"\n\n[vars]\nNODE_ENV = \"production\"\n\n# Uncomment to enable KV namespace for caching\n# [[kv_namespaces]]\n# binding = \"CACHE\"\n# id = \"your-kv-namespace-id\"\n`;\n\n// =============================================================================\n// GitHub Actions Templates\n// =============================================================================\n\nfunction generatePmSetupSteps(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n if (pm === 'pnpm') {\n return `\n - name: Setup pnpm\n uses: pnpm/action-setup@v4\n\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '24'\n cache: '${cfg.ghCache}'\n\n - name: Install dependencies\n run: ${cfg.ghInstallCmd}`;\n }\n return `\n - name: Setup Node.js\n uses: actions/setup-node@v4\n with:\n node-version: '24'\n cache: '${cfg.ghCache}'\n\n - name: Install dependencies\n run: ${cfg.ghInstallCmd}`;\n}\n\nfunction generateGhCi(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: CI\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n lint-and-test:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Type check\n run: npx tsc --noEmit\n\n - name: Run tests\n run: ${cfg.run} test\n`;\n}\n\nfunction generateGhE2e(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: E2E Tests\n\non:\n push:\n branches: [main]\n pull_request:\n branches: [main]\n\njobs:\n e2e:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Run E2E tests\n run: ${cfg.run} test:e2e\n`;\n}\n\nconst TEMPLATE_GH_DEPLOY_DOCKER = `\nname: Build and Push Docker Image\n\non:\n push:\n branches: [main]\n tags: ['v*']\n\nenv:\n REGISTRY: ghcr.io\n IMAGE_NAME: \\${{ github.repository }}\n\njobs:\n build-and-push:\n runs-on: ubuntu-latest\n permissions:\n contents: read\n packages: write\n\n steps:\n - uses: actions/checkout@v4\n\n - name: Log in to Container Registry\n uses: docker/login-action@v3\n with:\n registry: \\${{ env.REGISTRY }}\n username: \\${{ github.actor }}\n password: \\${{ secrets.GITHUB_TOKEN }}\n\n - name: Extract metadata\n id: meta\n uses: docker/metadata-action@v5\n with:\n images: \\${{ env.REGISTRY }}/\\${{ env.IMAGE_NAME }}\n\n - name: Build and push\n uses: docker/build-push-action@v5\n with:\n context: .\n file: ./ci/Dockerfile\n push: true\n tags: \\${{ steps.meta.outputs.tags }}\n labels: \\${{ steps.meta.outputs.labels }}\n`;\n\nfunction generateGhDeployVercel(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to Vercel\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Deploy to Vercel\n uses: amondnet/vercel-action@v25\n with:\n vercel-token: \\${{ secrets.VERCEL_TOKEN }}\n vercel-org-id: \\${{ secrets.VERCEL_ORG_ID }}\n vercel-project-id: \\${{ secrets.VERCEL_PROJECT_ID }}\n vercel-args: '--prod'\n`;\n}\n\nfunction generateGhDeployLambda(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to AWS Lambda\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Configure AWS credentials\n uses: aws-actions/configure-aws-credentials@v4\n with:\n aws-access-key-id: \\${{ secrets.AWS_ACCESS_KEY_ID }}\n aws-secret-access-key: \\${{ secrets.AWS_SECRET_ACCESS_KEY }}\n aws-region: \\${{ secrets.AWS_REGION }}\n\n - name: Setup SAM\n uses: aws-actions/setup-sam@v2\n\n - name: Deploy with SAM\n run: |\n cd ci\n sam build\n sam deploy --no-confirm-changeset --no-fail-on-empty-changeset\n`;\n}\n\nfunction generateGhDeployCloudflare(pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `\nname: Deploy to Cloudflare Workers\n\non:\n push:\n branches: [main]\n\njobs:\n deploy:\n runs-on: ubuntu-latest\n\n steps:\n - uses: actions/checkout@v4\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Deploy to Cloudflare\n uses: cloudflare/wrangler-action@v3\n with:\n apiToken: \\${{ secrets.CLOUDFLARE_API_TOKEN }}\n`;\n}\n\n// =============================================================================\n// Dynamic README Templates\n// =============================================================================\n\nfunction generateReadme(options: CreateOptions): string {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions, packageManager } = options;\n const cfg = PM_CONFIG[packageManager];\n\n let readme = `# ${projectName}\n\nA TypeScript MCP server built with [FrontMCP](https://github.com/agentfront/frontmcp).\n`;\n\n // Add CI badge if GitHub Actions enabled\n if (enableGitHubActions) {\n readme += `\n\n`;\n }\n\n readme += `\n## Quick Start\n\n\\`\\`\\`bash\n# Install dependencies\n${cfg.userInstall}\n\n# Start development server\n${cfg.run} dev\n\n# Run MCP Inspector\n${cfg.run} inspect\n\\`\\`\\`\n`;\n\n // Deployment-specific sections\n if (deploymentTarget === 'node') {\n readme += `\n## Docker Development\n\n\\`\\`\\`bash\n# Start all services${redisSetup === 'docker' ? ' (includes Redis)' : ''}\n${cfg.run} docker:up\n\n# Stop all services\n${cfg.run} docker:down\n\n# Rebuild Docker image\n${cfg.run} docker:build\n\\`\\`\\`\n`;\n\n if (redisSetup === 'docker') {\n readme += `\n### Redis\n\nRedis is included in the Docker Compose setup. For local development without Docker:\n\n\\`\\`\\`bash\n# Start only Redis\ndocker compose -f ci/docker-compose.yml up redis -d\n\\`\\`\\`\n`;\n }\n\n readme += `\n## Production Deployment\n\nBuild and push the Docker image:\n\n\\`\\`\\`bash\ndocker build -f ci/Dockerfile -t ${projectName}:latest .\ndocker push your-registry/${projectName}:latest\n\\`\\`\\`\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `\n## Deploy to Vercel\n\n\\`\\`\\`bash\n# Build for production\n${cfg.run} build\n\n# Deploy using Vercel CLI\nnpx vercel --prod\n\\`\\`\\`\n\nOr connect your repository to Vercel for automatic deployments.\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `\n## Deploy to AWS Lambda\n\n\\`\\`\\`bash\n# Build the project\n${cfg.run} build\n\n# Deploy using AWS SAM\n${cfg.run} deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- AWS CLI configured with appropriate credentials\n- AWS SAM CLI installed (\\`brew install aws-sam-cli\\` or \\`pip install aws-sam-cli\\`)\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `\n## Deploy to Cloudflare Workers\n\n\\`\\`\\`bash\n# Build the project\n${cfg.run} build\n\n# Deploy using Wrangler\n${cfg.run} deploy\n\\`\\`\\`\n\n### Prerequisites\n\n- Wrangler CLI installed (\\`npm install -g wrangler\\`)\n- Cloudflare account configured (\\`wrangler login\\`)\n`;\n }\n\n // Environment variables section\n readme += `\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| \\`PORT\\` | 3000 | Application port |\n| \\`NODE_ENV\\` | development | Environment mode |\n`;\n\n if (deploymentTarget === 'node' && redisSetup !== 'none') {\n readme += `| \\`REDIS_HOST\\` | localhost | Redis host (use \\`redis\\` in Docker) |\n| \\`REDIS_PORT\\` | 6379 | Redis port |\n| \\`REDIS_PASSWORD\\` | - | Redis password (set in production) |\n`;\n }\n\n // GitHub Actions section\n if (enableGitHubActions) {\n readme += `\n## CI/CD\n\nThis project includes GitHub Actions workflows:\n\n- **ci.yml**: Runs on every push/PR - type checking and tests\n- **e2e.yml**: Runs E2E tests\n- **deploy.yml**: Deploys to ${\n deploymentTarget === 'node'\n ? 'GitHub Container Registry'\n : deploymentTarget === 'vercel'\n ? 'Vercel'\n : deploymentTarget === 'lambda'\n ? 'AWS Lambda'\n : 'Cloudflare Workers'\n }\n\n### Required Secrets\n`;\n\n if (deploymentTarget === 'vercel') {\n readme += `\n- \\`VERCEL_TOKEN\\`: Vercel API token\n- \\`VERCEL_ORG_ID\\`: Vercel organization ID\n- \\`VERCEL_PROJECT_ID\\`: Vercel project ID\n`;\n } else if (deploymentTarget === 'lambda') {\n readme += `\n- \\`AWS_ACCESS_KEY_ID\\`: AWS access key\n- \\`AWS_SECRET_ACCESS_KEY\\`: AWS secret key\n- \\`AWS_REGION\\`: AWS region (e.g., us-east-1)\n`;\n } else if (deploymentTarget === 'cloudflare') {\n readme += `\n- \\`CLOUDFLARE_API_TOKEN\\`: Cloudflare API token with Workers permissions\n`;\n } else {\n readme += `\nNo additional secrets required - uses \\`GITHUB_TOKEN\\` for GHCR.\n`;\n }\n }\n\n readme += `\n## Scripts\n\n| Script | Description |\n|--------|-------------|\n| \\`${cfg.run} dev\\` | Start development server with hot reload |\n| \\`${cfg.run} build\\` | Build for production |\n| \\`${cfg.run} inspect\\` | Launch MCP Inspector |\n| \\`${cfg.run} doctor\\` | Check project configuration |\n| \\`${cfg.run} test\\` | Run unit tests |\n| \\`${cfg.run} test:e2e\\` | Run E2E tests |\n`;\n\n if (deploymentTarget === 'node') {\n readme += `| \\`${cfg.run} docker:up\\` | Start Docker services |\n| \\`${cfg.run} docker:down\\` | Stop Docker services |\n| \\`${cfg.run} docker:build\\` | Rebuild Docker image |\n`;\n }\n\n if (deploymentTarget === 'lambda' || deploymentTarget === 'cloudflare') {\n readme += `| \\`${cfg.run} deploy\\` | Deploy to ${deploymentTarget === 'lambda' ? 'AWS Lambda' : 'Cloudflare Workers'} |\n`;\n }\n\n readme += `\n## Project Structure\n\n\\`\\`\\`\n`;\n\n // Dynamic project structure based on options\n readme += `├── .env.example # Environment variables template\n├── .gitignore # Git ignore rules\n`;\n\n if (deploymentTarget === 'node') {\n readme += `├── .dockerignore # Docker build context exclusions\n├── ci/\n│ ├── Dockerfile # Container build config\n│ ├── docker-compose.yml # Docker services config\n│ └── .env.docker # Docker-specific env vars\n`;\n }\n\n if (deploymentTarget === 'vercel') {\n readme += `├── vercel.json # Vercel deployment config\n`;\n }\n\n if (deploymentTarget === 'lambda') {\n readme += `├── ci/\n│ └── template.yaml # AWS SAM template\n`;\n }\n\n if (deploymentTarget === 'cloudflare') {\n readme += `├── wrangler.toml # Cloudflare Workers config\n`;\n }\n\n if (enableGitHubActions) {\n readme += `├── .github/workflows/\n│ ├── ci.yml # CI workflow\n│ ├── e2e.yml # E2E test workflow\n│ └── deploy.yml # Deployment workflow\n`;\n }\n\n readme += `├── e2e/ # E2E tests\n├── jest.e2e.config.ts # Jest E2E configuration\n├── package.json # Dependencies and scripts\n├── src/\n│ ├── main.ts # Server entry point\n│ ├── calc.app.ts # Example app\n│ └── tools/\n│ └── add.tool.ts # Example tool\n├── tsconfig.json # TypeScript config\n└── tsconfig.e2e.json # TypeScript config for E2E tests\n\\`\\`\\`\n\n## Scaling to a Monorepo\n\nTo migrate to an Nx monorepo with multiple apps and shared libraries:\n\n\\`\\`\\`bash\nnpx frontmcp create my-workspace --nx\n\\`\\`\\`\n\nThis scaffolds an Nx workspace with generators for tools, resources, prompts, and more.\nSee the [FrontMCP Nx Plugin docs](https://docs.agentfront.dev) for details.\n\n## Learn More\n\n- [FrontMCP Documentation](https://docs.agentfront.dev)\n- [MCP Specification](https://modelcontextprotocol.io)\n`;\n\n return readme;\n}\n\n// =============================================================================\n// Scaffolding Functions\n// =============================================================================\n\nfunction getDefaults(projectArg?: string): CreateOptions {\n return {\n projectName: projectArg || 'frontmcp-app',\n deploymentTarget: 'node',\n redisSetup: 'docker',\n enableGitHubActions: true,\n packageManager: 'npm',\n };\n}\n\nfunction getInstallCommand(pm: PackageManager): { cmd: string; args: string[] } {\n switch (pm) {\n case 'npm':\n return { cmd: 'npm', args: ['install'] };\n case 'yarn':\n return { cmd: 'yarn', args: ['install'] };\n case 'pnpm':\n return { cmd: 'pnpm', args: ['install'] };\n }\n}\n\nasync function scaffoldNxWorkspace(projectName: string, flags?: CreateFlags): Promise<void> {\n const pm = flags?.pm ?? 'npm';\n const folder = sanitizeForFolder(projectName);\n const projectDir = path.resolve(process.cwd(), folder);\n\n // Validate target directory\n try {\n const s = await stat(projectDir);\n if (!s.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), projectDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(projectDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), projectDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(projectDir);\n } else {\n throw e;\n }\n }\n\n try {\n // Step 1: Write bootstrap package.json with nx tooling\n const selfVersion = getSelfVersion();\n await writeJSON(path.join(projectDir, 'package.json'), {\n name: folder,\n version: '0.0.1',\n private: true,\n devDependencies: {\n nx: '22.3.3',\n '@nx/devkit': '22.3.3',\n '@frontmcp/nx': `~${selfVersion}`,\n },\n });\n\n // Step 2: Install nx tooling\n console.log(c('cyan', `\\nInstalling Nx tooling in ./${folder}...\\n`));\n const install = getInstallCommand(pm);\n await runCmd(install.cmd, install.args, { cwd: projectDir });\n\n // Step 3: Load nx and @frontmcp/nx from the installed location\n const localRequire = createRequire(path.join(projectDir, 'package.json'));\n const { FsTree, flushChanges } = localRequire('nx/src/generators/tree.js');\n const { workspaceGenerator } = localRequire('@frontmcp/nx');\n\n // Step 4: Run the workspace generator\n console.log(c('cyan', `\\nScaffolding Nx monorepo: ${projectName}...\\n`));\n const tree = new FsTree(process.cwd(), false);\n const callback = await workspaceGenerator(tree, {\n name: folder,\n packageManager: pm,\n skipInstall: true,\n skipGit: false,\n createSampleApp: true,\n });\n\n flushChanges(tree.root, tree.listChanges());\n\n if (callback) {\n await callback();\n }\n\n // Step 5: Install full project dependencies\n console.log(c('cyan', '\\nInstalling project dependencies...\\n'));\n await runCmd(install.cmd, install.args, { cwd: projectDir });\n\n console.log(c('green', `\\n✅ Nx monorepo created at ./${folder}\\n`));\n console.log(c('dim', 'Next steps:'));\n console.log(c('dim', ` cd ${folder}`));\n console.log(c('dim', ' nx g @frontmcp/nx:app my-app # Add an app'));\n console.log(c('dim', ' nx g @frontmcp/nx:lib my-lib # Add a library'));\n console.log(c('dim', ' nx g @frontmcp/nx:tool my-tool # Add a tool to an app'));\n console.log(c('dim', ' nx dev demo # Start dev server'));\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err);\n if (\n message.includes('Cannot find module') ||\n message.includes('Cannot find package') ||\n message.includes('MODULE_NOT_FOUND')\n ) {\n console.error(c('red', '\\nFailed to install Nx tooling.'));\n console.log(c('dim', 'Check your network connection and try again.'));\n console.log(c('dim', 'You can also install manually:'));\n console.log(c('bold', ` cd ${folder} && ${pm} install`));\n } else {\n console.error(c('red', `\\nFailed to scaffold Nx workspace: ${message}`));\n }\n process.exit(1);\n }\n}\n\nasync function collectOptions(projectArg?: string, flags?: CreateFlags): Promise<CreateOptions> {\n const p = await clack();\n\n // Project name\n let projectName = projectArg;\n if (!projectName) {\n const result = await p.text({\n message: 'Project name',\n validate: (val) => {\n if (!val.trim()) return 'Project name is required';\n return undefined;\n },\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n projectName = result;\n }\n\n if (!flags?.yes) {\n const projectType = await p.select({\n message: 'Project type',\n options: [\n { label: 'Standalone project (recommended)', value: 'standalone' as const },\n { label: 'Nx monorepo (advanced)', value: 'nx' as const },\n ],\n initialValue: 'standalone' as const,\n });\n if (p.isCancel(projectType)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n if (projectType === 'nx') {\n await scaffoldNxWorkspace(projectName, flags);\n return {\n projectName,\n deploymentTarget: 'node',\n redisSetup: 'none',\n enableGitHubActions: false,\n packageManager: flags?.pm ?? 'npm',\n nxScaffolded: true,\n };\n }\n }\n\n // Deployment target\n let deploymentTarget = flags?.target;\n if (!deploymentTarget) {\n const result = await p.select({\n message: 'Select deployment target',\n options: [\n { label: 'Node.js (Docker) - Recommended for production', value: 'node' as DeploymentTarget },\n { label: 'Vercel (Serverless)', value: 'vercel' as DeploymentTarget },\n { label: 'AWS Lambda', value: 'lambda' as DeploymentTarget },\n { label: 'Cloudflare Workers', value: 'cloudflare' as DeploymentTarget },\n ],\n initialValue: 'node' as DeploymentTarget,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n deploymentTarget = result;\n }\n\n // Redis setup (only for Node.js/Docker)\n let redisSetup: RedisSetup = 'none';\n if (deploymentTarget === 'node') {\n if (flags?.redis) {\n redisSetup = flags.redis;\n } else {\n const result = await p.select({\n message: 'Redis setup',\n options: [\n { label: 'Docker Compose (recommended for development)', value: 'docker' as RedisSetup },\n { label: 'Existing Redis (I have my own Redis)', value: 'existing' as RedisSetup },\n { label: 'None (skip Redis)', value: 'none' as RedisSetup },\n ],\n initialValue: 'docker' as RedisSetup,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n redisSetup = result;\n }\n }\n\n // Package manager\n let packageManager = flags?.pm;\n if (!packageManager) {\n const result = await p.select({\n message: 'Package manager',\n options: [\n { label: 'npm (default)', value: 'npm' as PackageManager },\n { label: 'yarn', value: 'yarn' as PackageManager },\n { label: 'pnpm', value: 'pnpm' as PackageManager },\n ],\n initialValue: 'npm' as PackageManager,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n packageManager = result;\n }\n\n // GitHub Actions\n let enableGitHubActions = flags?.cicd;\n if (enableGitHubActions === undefined) {\n const result = await p.confirm({\n message: 'Set up GitHub Actions CI/CD?',\n initialValue: true,\n });\n if (p.isCancel(result)) {\n p.cancel('Cancelled.');\n process.exit(0);\n }\n enableGitHubActions = result;\n }\n\n return {\n projectName,\n deploymentTarget,\n redisSetup,\n enableGitHubActions,\n packageManager,\n };\n}\n\nasync function scaffoldDeploymentFiles(targetDir: string, options: CreateOptions): Promise<void> {\n const { deploymentTarget, redisSetup, projectName } = options;\n\n switch (deploymentTarget) {\n case 'node': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(\n targetDir,\n path.join(ciDir, 'Dockerfile'),\n generateDockerfile(options.packageManager),\n );\n\n const dockerCompose = redisSetup === 'docker' ? generateDockerComposeWithRedis() : generateDockerComposeNoRedis();\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'docker-compose.yml'), dockerCompose);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, '.env.docker'), TEMPLATE_ENV_DOCKER_CI);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.dockerignore'), TEMPLATE_DOCKERIGNORE);\n break;\n }\n\n case 'vercel':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'vercel.json'),\n TEMPLATE_VERCEL_JSON(sanitizeForFolder(projectName)),\n );\n break;\n\n case 'lambda': {\n const ciDir = path.join(targetDir, 'ci');\n await ensureDir(ciDir);\n await scaffoldFileIfMissing(targetDir, path.join(ciDir, 'template.yaml'), TEMPLATE_SAM_YAML(projectName));\n break;\n }\n\n case 'cloudflare':\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'wrangler.toml'),\n TEMPLATE_WRANGLER_TOML(sanitizeForFolder(projectName)),\n );\n break;\n }\n\n // Always create .env.example at root\n const envExample =\n deploymentTarget === 'node' && redisSetup !== 'none' ? TEMPLATE_ENV_EXAMPLE : TEMPLATE_ENV_EXAMPLE_BASIC;\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.env.example'), envExample);\n}\n\n// Basic .env.example without Redis\nconst TEMPLATE_ENV_EXAMPLE_BASIC = `\n# Application\nPORT=3000\nNODE_ENV=development\n`;\n\nasync function scaffoldGitHubActions(\n targetDir: string,\n deploymentTarget: DeploymentTarget,\n pm: PackageManager,\n): Promise<void> {\n const workflowDir = path.join(targetDir, '.github', 'workflows');\n await ensureDir(workflowDir);\n\n // Always create CI and E2E workflows\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'ci.yml'), generateGhCi(pm));\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'e2e.yml'), generateGhE2e(pm));\n\n // Create deployment workflow based on target\n const deployTemplate = getDeployWorkflowTemplate(deploymentTarget, pm);\n await scaffoldFileIfMissing(targetDir, path.join(workflowDir, 'deploy.yml'), deployTemplate);\n}\n\nfunction getDeployWorkflowTemplate(target: DeploymentTarget, pm: PackageManager): string {\n switch (target) {\n case 'node':\n return TEMPLATE_GH_DEPLOY_DOCKER;\n case 'vercel':\n return generateGhDeployVercel(pm);\n case 'lambda':\n return generateGhDeployLambda(pm);\n case 'cloudflare':\n return generateGhDeployCloudflare(pm);\n }\n}\n\nasync function scaffoldProject(options: CreateOptions): Promise<void> {\n const { projectName, deploymentTarget, redisSetup, enableGitHubActions, packageManager } = options;\n\n const folder = sanitizeForFolder(projectName);\n const pkgName = sanitizeForNpm(projectName);\n const targetDir = path.resolve(process.cwd(), folder);\n\n // Validate directory\n try {\n const targetStat = await stat(targetDir);\n if (!targetStat.isDirectory()) {\n console.error(\n c('red', `Refusing to scaffold into non-directory path: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different project name or remove/rename the existing file.'));\n process.exit(1);\n }\n if (!(await isDirEmpty(targetDir))) {\n console.error(\n c('red', `Refusing to scaffold into non-empty directory: ${path.relative(process.cwd(), targetDir)}`),\n );\n console.log(c('gray', 'Pick a different name or start with an empty folder.'));\n process.exit(1);\n }\n } catch (e: unknown) {\n if (e && typeof e === 'object' && 'code' in e && e.code === 'ENOENT') {\n await ensureDir(targetDir);\n } else {\n throw e;\n }\n }\n\n console.log(`\\n${c('cyan', '[create]')} Creating project in ${c('bold', './' + folder)}`);\n console.log(c('gray', ` Deployment: ${deploymentTarget}`));\n if (deploymentTarget === 'node') {\n console.log(c('gray', ` Redis: ${redisSetup}`));\n }\n console.log(c('gray', ` Package manager: ${packageManager}`));\n console.log(c('gray', ` GitHub Actions: ${enableGitHubActions ? 'Yes' : 'No'}`));\n console.log('');\n\n process.chdir(targetDir);\n\n // Initialize tsconfig\n await runInit(targetDir);\n\n // Create package.json with deployment-specific scripts\n const selfVersion = getSelfVersion();\n await upsertPackageJsonWithTarget(targetDir, pkgName, selfVersion, deploymentTarget, packageManager);\n\n // Scaffold base files\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'main.ts'), TEMPLATE_MAIN_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'calc.app.ts'), TEMPLATE_CALC_APP_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'src', 'tools', 'add.tool.ts'), TEMPLATE_ADD_TOOL_TS);\n\n // E2E scaffolding\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.spec.ts'), TEMPLATE_E2E_TEST_TS);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'jest.e2e.config.ts'), TEMPLATE_JEST_E2E_CONFIG);\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'tsconfig.e2e.json'), TEMPLATE_TSCONFIG_E2E);\n\n // Git configuration\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.gitignore'), TEMPLATE_GITIGNORE);\n\n // Node version\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, '.nvmrc'), '24\\n');\n\n // Deployment-specific files\n await scaffoldDeploymentFiles(targetDir, options);\n\n // GitHub Actions\n if (enableGitHubActions) {\n await scaffoldGitHubActions(targetDir, deploymentTarget, packageManager);\n }\n\n // Dynamic README\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'README.md'), generateReadme(options));\n\n // Initialize git repository\n try {\n const { execSync } = await import('child_process');\n execSync('git init', { cwd: targetDir, stdio: 'ignore' });\n execSync('git add -A', { cwd: targetDir, stdio: 'ignore' });\n execSync('git commit -m \"Initial commit\"', { cwd: targetDir, stdio: 'ignore' });\n console.log(`${c('green', '✓')} Initialized git repository`);\n } catch {\n // git may not be installed — silently skip\n }\n\n // Print next steps\n printNextSteps(folder, deploymentTarget, redisSetup, enableGitHubActions, packageManager);\n}\n\nfunction printNextSteps(\n folder: string,\n deploymentTarget: DeploymentTarget,\n redisSetup: RedisSetup,\n enableGitHubActions: boolean,\n pm: PackageManager,\n): void {\n const cfg = PM_CONFIG[pm];\n console.log('\\nNext steps:');\n console.log(` 1) cd ${folder}`);\n console.log(` 2) ${cfg.userInstall}`);\n console.log(` 3) ${cfg.run} dev `, c('gray', '# tsx watcher + async tsc type-check'));\n console.log(` 4) ${cfg.run} inspect `, c('gray', '# launch MCP Inspector'));\n console.log(` 5) ${cfg.run} build `, c('gray', '# compile with tsc via frontmcp build'));\n console.log(` 6) ${cfg.run} test:e2e `, c('gray', '# run E2E tests'));\n\n if (deploymentTarget === 'node') {\n console.log('');\n console.log(c('cyan', 'Docker:'));\n console.log(\n ` ${cfg.run} docker:up `,\n c('gray', `# start${redisSetup === 'docker' ? ' Redis +' : ''} app in Docker`),\n );\n console.log(` ${cfg.run} docker:down `, c('gray', '# stop Docker services'));\n }\n\n if (deploymentTarget === 'vercel') {\n console.log('');\n console.log(c('cyan', 'Deploy to Vercel:'));\n console.log(' npx vercel ', c('gray', '# deploy to Vercel'));\n }\n\n if (deploymentTarget === 'lambda') {\n console.log('');\n console.log(c('cyan', 'Deploy to AWS Lambda:'));\n console.log(` ${cfg.run} deploy `, c('gray', '# deploy with SAM'));\n }\n\n if (deploymentTarget === 'cloudflare') {\n console.log('');\n console.log(c('cyan', 'Deploy to Cloudflare:'));\n console.log(` ${cfg.run} deploy `, c('gray', '# deploy with Wrangler'));\n }\n\n if (enableGitHubActions) {\n console.log('');\n console.log(c('cyan', 'GitHub Actions:'));\n console.log(' .github/workflows/ ', c('gray', '# CI, E2E, and deploy workflows ready'));\n }\n}\n\n// =============================================================================\n// Package.json with Target-Specific Scripts\n// =============================================================================\n\nasync function upsertPackageJsonWithTarget(\n cwd: string,\n nameOverride: string | undefined,\n selfVersion: string,\n deploymentTarget: DeploymentTarget,\n pm: PackageManager = 'npm',\n) {\n const pkgPath = path.join(cwd, 'package.json');\n const existing = await readJSON<PackageJson>(pkgPath);\n\n const frontmcpLibRange = `~${selfVersion}`;\n\n const baseScripts: Record<string, string> = {\n dev: 'frontmcp dev',\n build: 'frontmcp build',\n inspect: 'frontmcp inspector',\n doctor: 'frontmcp doctor',\n test: 'frontmcp test',\n 'test:e2e': 'jest --config jest.e2e.config.ts --runInBand',\n };\n\n // Add target-specific scripts\n if (deploymentTarget === 'node') {\n baseScripts['docker:up'] = 'docker compose -f ci/docker-compose.yml up';\n baseScripts['docker:down'] = 'docker compose -f ci/docker-compose.yml down';\n baseScripts['docker:build'] = 'docker compose -f ci/docker-compose.yml build';\n }\n\n if (deploymentTarget === 'lambda') {\n baseScripts['deploy'] = 'cd ci && sam build && sam deploy';\n }\n\n if (deploymentTarget === 'cloudflare') {\n baseScripts['deploy'] = 'wrangler deploy';\n }\n\n const base = {\n name: nameOverride ?? pkgNameFromCwd(cwd),\n version: '0.1.0',\n private: true,\n type: 'commonjs',\n main: 'src/main.ts',\n scripts: baseScripts,\n engines: PM_CONFIG[pm].engines,\n dependencies: {\n '@frontmcp/sdk': frontmcpLibRange,\n '@frontmcp/plugins': frontmcpLibRange,\n '@frontmcp/adapters': frontmcpLibRange,\n frontmcp: selfVersion,\n tslib: '^2.5.0',\n zod: '^4.0.0',\n 'reflect-metadata': '^0.2.2',\n },\n devDependencies: {\n '@frontmcp/testing': frontmcpLibRange,\n '@swc/core': '^1.11.29',\n '@swc/jest': '^0.2.37',\n jest: '^29.7.0',\n '@types/jest': '^29.5.14',\n tsx: '^4.20.6',\n '@types/node': '^24.0.0',\n typescript: '^5.5.3',\n },\n };\n\n if (!existing) {\n await writeJSON(pkgPath, base);\n console.log(c('green', '✅ Created package.json (synced @frontmcp libs to CLI version + exact frontmcp)'));\n return;\n }\n\n const merged: PackageJson = { ...base, ...existing };\n\n merged.name = existing.name || base.name;\n merged.main = existing.main || base.main;\n merged.type = existing.type || base.type;\n\n // Preserve user scripts, add base scripts only if missing\n merged.scripts = {\n ...baseScripts,\n ...(existing.scripts || {}),\n };\n\n merged.engines = {\n ...(existing.engines || {}),\n ...base.engines,\n };\n\n merged.dependencies = {\n ...(existing.dependencies || {}),\n ...base.dependencies,\n };\n\n merged.devDependencies = {\n ...(existing.devDependencies || {}),\n ...base.devDependencies,\n };\n\n await writeJSON(pkgPath, merged);\n console.log(c('green', '✅ Updated package.json (synced @frontmcp libs + frontmcp to current CLI version)'));\n}\n\n// =============================================================================\n// Main Entry Point\n// =============================================================================\n\nexport async function runCreate(projectArg?: string, flags?: CreateFlags): Promise<void> {\n // Nx monorepo mode (non-interactive with --nx flag)\n if (flags?.nx) {\n const name = projectArg || 'frontmcp-app';\n await scaffoldNxWorkspace(name, flags);\n return;\n }\n\n // Non-interactive mode: use --yes flag or non-TTY environment\n if (flags?.yes || !isInteractive()) {\n const options = getDefaults(projectArg);\n // Override defaults with any provided flags\n if (flags?.target) options.deploymentTarget = flags.target;\n if (flags?.redis) options.redisSetup = flags.redis;\n if (flags?.cicd !== undefined) options.enableGitHubActions = flags.cicd;\n if (flags?.pm) options.packageManager = flags.pm;\n if (projectArg) options.projectName = projectArg;\n\n if (!options.projectName) {\n console.error(c('red', 'Error: project name is required in non-interactive mode.\\n'));\n console.log(`Usage: ${c('bold', 'npx frontmcp create <project-name> --yes')}`);\n process.exit(1);\n }\n\n await scaffoldProject(options);\n return;\n }\n\n // Interactive mode\n const p = await clack();\n p.intro('Create a new FrontMCP project');\n\n const options = await collectOptions(projectArg, flags);\n if (!options.nxScaffolded) await scaffoldProject(options);\n\n p.outro('Done!');\n}\n"]}
|