frontmcp 1.3.0 → 1.4.0
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/README.md +38 -29
- package/package.json +4 -4
- package/src/commands/build/exec/runner-script.js +16 -4
- package/src/commands/build/exec/runner-script.js.map +1 -1
- package/src/commands/dev/dev.d.ts +16 -0
- package/src/commands/dev/dev.js +35 -1
- package/src/commands/dev/dev.js.map +1 -1
- package/src/commands/scaffold/create.js +8 -8
- package/src/commands/scaffold/create.js.map +1 -1
- package/src/core/tsconfig.d.ts +20 -0
- package/src/core/tsconfig.js +41 -2
- package/src/core/tsconfig.js.map +1 -1
package/README.md
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
</picture>
|
|
8
8
|
<hr>
|
|
9
9
|
|
|
10
|
-
**The TypeScript
|
|
10
|
+
**The production-grade, TypeScript-first framework for building MCP servers — decorators, DI, auth, and Streamable HTTP, batteries included.**
|
|
11
11
|
|
|
12
12
|
[](https://www.npmjs.com/package/@frontmcp/sdk)
|
|
13
|
-
[](https://nodejs.org)
|
|
14
14
|
[](https://github.com/agentfront/frontmcp/blob/main/LICENSE)
|
|
15
15
|
[](https://snyk.io/test/github/agentfront/frontmcp)
|
|
16
16
|
|
|
@@ -20,12 +20,17 @@
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
-
FrontMCP
|
|
24
|
-
|
|
23
|
+
FrontMCP turns the [Model Context Protocol](https://modelcontextprotocol.io) into a
|
|
24
|
+
typed, declarative framework. You write clean `@Tool`, `@Resource`, and `@App`
|
|
25
|
+
classes; FrontMCP handles the protocol, transport, dependency injection, sessions,
|
|
26
|
+
auth, and execution flow — and the **same server runs locally and ships to
|
|
27
|
+
production unchanged**.
|
|
25
28
|
|
|
26
29
|
```ts
|
|
27
30
|
import 'reflect-metadata';
|
|
31
|
+
|
|
28
32
|
import { FrontMcp, LogLevel } from '@frontmcp/sdk';
|
|
33
|
+
|
|
29
34
|
import HelloApp from './hello.app';
|
|
30
35
|
|
|
31
36
|
@FrontMcp({
|
|
@@ -37,6 +42,14 @@ import HelloApp from './hello.app';
|
|
|
37
42
|
export default class Server {}
|
|
38
43
|
```
|
|
39
44
|
|
|
45
|
+
## Why FrontMCP
|
|
46
|
+
|
|
47
|
+
- **Typed by default** — decorators + Zod schemas give end-to-end types from input to output, with editor autocomplete and compile-time checks.
|
|
48
|
+
- **Batteries included** — auth (OAuth/JWKS/DCR), sessions, transport, discovery, and DI are built in, not bolted on.
|
|
49
|
+
- **Ship anywhere** — one codebase deploys to Node, Vercel, AWS Lambda, Cloudflare Workers, or a serverless bundle.
|
|
50
|
+
- **Production-minded** — stateful/stateless sessions, high-availability transport, structured observability, and a 95%+ tested core.
|
|
51
|
+
- **Extensible** — plugins, lifecycle hooks, OpenAPI adapters, and external MCP sub-apps when you outgrow the defaults.
|
|
52
|
+
|
|
40
53
|
## Installation
|
|
41
54
|
|
|
42
55
|
**Node.js 24+** required.
|
|
@@ -50,34 +63,30 @@ npm i -D frontmcp @types/node@^24
|
|
|
50
63
|
npx frontmcp init
|
|
51
64
|
```
|
|
52
65
|
|
|
53
|
-
> Full setup guide: [Installation][docs-install]
|
|
66
|
+
> Full setup guide: [Installation][docs-install] · [Quickstart][docs-quickstart]
|
|
54
67
|
|
|
55
68
|
## Capabilities
|
|
56
69
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
| **Testing** | E2E fixtures, matchers, HTTP mocking for MCP servers | [Testing][docs-testing] |
|
|
78
|
-
| **UI Library** | HTML/React widgets, SSR, MCP Bridge, web components | [UI][docs-ui] |
|
|
79
|
-
| **CLI** | `create`, `init`, `dev`, `build`, `inspector`, `doctor` | [CLI][docs-install] |
|
|
80
|
-
| **Deployment** | Local dev, production builds, version alignment | [Deployment][docs-deploy] |
|
|
70
|
+
**Build** — decorator-configured [`@FrontMcp` server][docs-server] and [`@App`][docs-apps]
|
|
71
|
+
domains; typed [`@Tool`][docs-tools], [`@Resource`][docs-resources], and
|
|
72
|
+
[`@Prompt`][docs-prompts] primitives; [`@Agent`][docs-agents] multi-step chains; and
|
|
73
|
+
scoped [Providers / DI][docs-providers].
|
|
74
|
+
|
|
75
|
+
**Secure** — [Remote & Local OAuth, JWKS, DCR, per-app auth][docs-auth] with
|
|
76
|
+
stateful / stateless [sessions][docs-server] (JWT or UUID transport IDs).
|
|
77
|
+
|
|
78
|
+
**Connect & operate** — [Streamable HTTP + SSE transport][docs-transport],
|
|
79
|
+
capability [discovery][docs-discovery], [elicitation][docs-elicitation],
|
|
80
|
+
[hooks][docs-hooks], HTTP-discoverable [skills][docs-skills],
|
|
81
|
+
[external MCP sub-apps][docs-ext-apps], an in-process [Direct Client][docs-direct]
|
|
82
|
+
(`connectOpenAI` / `connectClaude`), and first-class [deployment][docs-deploy].
|
|
83
|
+
|
|
84
|
+
**Extend & tooling** — official [plugins][docs-plugins] (Cache, Remember, CodeCall,
|
|
85
|
+
Dashboard), the [OpenAPI adapter][docs-adapters], a [UI library][docs-ui] (HTML/React
|
|
86
|
+
widgets, SSR, MCP Bridge), an [E2E testing framework][docs-testing], and a
|
|
87
|
+
[CLI][docs-install] (`create`, `init`, `dev`, `build`, `inspect`, `doctor`).
|
|
88
|
+
|
|
89
|
+
→ Full reference: **[docs.agentfront.dev/frontmcp][docs-home]**
|
|
81
90
|
|
|
82
91
|
## Packages
|
|
83
92
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frontmcp",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "FrontMCP command line interface",
|
|
5
5
|
"author": "AgentFront <info@agentfront.dev>",
|
|
6
6
|
"homepage": "https://docs.agentfront.dev",
|
|
@@ -31,9 +31,9 @@
|
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
33
|
"@clack/prompts": "^0.10.0",
|
|
34
|
-
"@frontmcp/lazy-zod": "1.
|
|
35
|
-
"@frontmcp/utils": "1.
|
|
36
|
-
"@frontmcp/skills": "1.
|
|
34
|
+
"@frontmcp/lazy-zod": "1.4.0",
|
|
35
|
+
"@frontmcp/utils": "1.4.0",
|
|
36
|
+
"@frontmcp/skills": "1.4.0",
|
|
37
37
|
"commander": "^13.0.0",
|
|
38
38
|
"tslib": "^2.3.0",
|
|
39
39
|
"vectoriadb": "^2.2.0",
|
|
@@ -33,16 +33,20 @@ case "\${1:-}" in
|
|
|
33
33
|
cat <<EOF
|
|
34
34
|
${name} v${version} — FrontMCP server
|
|
35
35
|
|
|
36
|
-
This binary starts a long-running MCP HTTP server.
|
|
36
|
+
This binary starts a long-running MCP HTTP server, or an MCP stdio server with --stdio.
|
|
37
37
|
|
|
38
38
|
Usage:
|
|
39
|
-
${name} Start the server
|
|
39
|
+
${name} Start the HTTP server
|
|
40
|
+
${name} --stdio Serve over stdio (stdin/stdout JSON-RPC); binds no TCP port
|
|
40
41
|
${name} --help Show this help
|
|
41
42
|
${name} --version Show version
|
|
42
43
|
${name} --print-manifest Print the deployment manifest as JSON
|
|
43
44
|
|
|
44
45
|
Configure via environment variables, .env, or frontmcp.config.
|
|
45
46
|
|
|
47
|
+
Use --stdio for local MCP clients (Claude Desktop, Cursor). Example config:
|
|
48
|
+
{ "command": "${name}", "args": ["--stdio"] }
|
|
49
|
+
|
|
46
50
|
For a CLI-style binary that exposes tools/resources/prompts as subcommands,
|
|
47
51
|
build with: frontmcp build --target cli
|
|
48
52
|
EOF
|
|
@@ -56,10 +60,18 @@ EOF
|
|
|
56
60
|
cat "\${SCRIPT_DIR}/${name}.manifest.json"
|
|
57
61
|
exit 0
|
|
58
62
|
;;
|
|
63
|
+
--stdio)
|
|
64
|
+
# Serve over stdio (stdin/stdout JSON-RPC) instead of starting the HTTP
|
|
65
|
+
# server. FRONTMCP_STDIO=1 makes the @FrontMcp decorator connect the stdio
|
|
66
|
+
# transport and bind no TCP port (#448, #451); logs go to stderr and
|
|
67
|
+
# ~/.frontmcp/logs. Drop the flag and fall through to the exec below.
|
|
68
|
+
export FRONTMCP_STDIO=1
|
|
69
|
+
shift
|
|
70
|
+
;;
|
|
59
71
|
--*)
|
|
60
72
|
echo "Error: unsupported flag '\${1}' on the server runner."
|
|
61
|
-
echo "This binary is a long-running HTTP server; flag-style invocation is reserved." >&2
|
|
62
|
-
echo "Run with no args to start, or build with --target cli for a CLI binary." >&2
|
|
73
|
+
echo "This binary is a long-running HTTP server; flag-style invocation is reserved (except --stdio)." >&2
|
|
74
|
+
echo "Run with no args to start, --stdio to serve over stdio, or build with --target cli for a CLI binary." >&2
|
|
63
75
|
exit 2
|
|
64
76
|
;;
|
|
65
77
|
esac
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runner-script.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/runner-script.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAWH,oDAGC;AAED,
|
|
1
|
+
{"version":3,"file":"runner-script.js","sourceRoot":"","sources":["../../../../../src/commands/build/exec/runner-script.ts"],"names":[],"mappings":";AAAA;;;GAGG;;AAWH,oDAGC;AAED,oDAyJC;AArKD;;;;;;GAMG;AACH,SAAgB,oBAAoB,CAAC,KAAa;IAChD,0EAA0E;IAC1E,OAAO,KAAK,CAAC,OAAO,CAAC,mBAAmB,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,SAAgB,oBAAoB,CAAC,MAA0B,EAAE,OAAiB,EAAE,OAAiB;IACnG,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;IACzB,MAAM,OAAO,GAAG,oBAAoB,CAAC,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,CAAC;IAEhE,yEAAyE;IACzE,6EAA6E;IAC7E,wEAAwE;IACxE,wEAAwE;IACxE,wBAAwB;IACxB,MAAM,eAAe,GAAG,CAAC,OAAO;QAC9B,CAAC,CAAC;;;;;EAKJ,IAAI,KAAK,OAAO;;;;;IAKd,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;IACJ,IAAI;;;;;kBAKU,IAAI;;;;;;;;YAQV,IAAI,IAAI,OAAO;;;;0BAID,IAAI;;;;;;;;;;;;;;;;;;CAkB7B;QACG,CAAC,CAAC,EAAE,CAAC;IAEP,0DAA0D;IAC1D,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,IAAI,UAAU,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,CAAC;QAC3D,MAAM,OAAO,GAAG,OAAO;YACrB,CAAC,CAAC,KAAK,IAAI,qCAAqC;YAChD,CAAC,CAAC,KAAK,IAAI,wCAAwC,CAAC;QAEtD,OAAO;;;EAGT,OAAO;yCACgC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM;;;yBAGxC,MAAM;;;;;;EAM7B,eAAe;;;;;;;;;;;CAWhB,CAAC;IACA,CAAC;IAED,MAAM,WAAW,GAAG,MAAM,CAAC,WAAW,IAAI,UAAU,CAAC;IACrD,MAAM,YAAY,GAAG,eAAe,CAAC,WAAW,CAAC,CAAC;IAElD,MAAM,MAAM,GAAG,OAAO;QACpB,CAAC,CAAC,kBAAkB,IAAI,gBAAgB;QACxC,CAAC,CAAC,kBAAkB,IAAI,YAAY,CAAC;IAEvC,MAAM,OAAO,GAAG,OAAO;QACrB,CAAC,CAAC,KAAK,IAAI,4BAA4B;QACvC,CAAC,CAAC,KAAK,IAAI,2BAA2B,CAAC;IAEzC,OAAO;;;EAGP,OAAO;yCACgC,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM;;;UAG5D,MAAM;EACd,eAAe;;;;0BAIS,WAAW;;;;;6BAKR,YAAY;yBAChB,WAAW;;;;;;;uCAOG,OAAO,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM;;;;;;;;;;;;;;8CActB,IAAI;;;;;;CAMjD,CAAC;AACF,CAAC;AAED,SAAS,eAAe,CAAC,OAAe;IACtC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC7C,CAAC","sourcesContent":["/**\n * Bash runner script generation.\n * The runner checks Node.js, loads .env, and runs the bundle.\n */\n\nimport { type FrontmcpExecConfig } from './config';\n\n/**\n * Defense-in-depth: scrub anything outside `[a-zA-Z0-9._+-]` from values that\n * the runner / installer scripts interpolate into bash. The user owns\n * `frontmcp.config`, so a malicious value would be self-inflicted, but the\n * generated scripts are committed into repos and downloaded by end-users —\n * so we keep them safe to copy/paste regardless of upstream config hygiene.\n */\nexport function sanitizeShellLiteral(value: string): string {\n // `-` placed last in the character class is literal, so no escape needed.\n return value.replace(/[^A-Za-z0-9._+-]/g, '_');\n}\n\nexport function generateRunnerScript(config: FrontmcpExecConfig, cliMode?: boolean, seaMode?: boolean): string {\n const name = config.name;\n const version = sanitizeShellLiteral(config.version || '0.0.0');\n\n // #377 — `--target node` runner used to silently exec the bundle for any\n // flag, so `./frontegg-bin --help` quietly booted the HTTP server. Intercept\n // help/version here so server-mode runners behave like a normal CLI for\n // those flags. CLI-mode runners pass everything through to the bundle's\n // own commander parser.\n const helpInterceptor = !cliMode\n ? `\n# Intercept standard CLI flags before booting the long-running server.\ncase \"\\${1:-}\" in\n -h|--help)\n cat <<EOF\n${name} v${version} — FrontMCP server\n\nThis binary starts a long-running MCP HTTP server, or an MCP stdio server with --stdio.\n\nUsage:\n ${name} Start the HTTP server\n ${name} --stdio Serve over stdio (stdin/stdout JSON-RPC); binds no TCP port\n ${name} --help Show this help\n ${name} --version Show version\n ${name} --print-manifest Print the deployment manifest as JSON\n\nConfigure via environment variables, .env, or frontmcp.config.\n\nUse --stdio for local MCP clients (Claude Desktop, Cursor). Example config:\n { \"command\": \"${name}\", \"args\": [\"--stdio\"] }\n\nFor a CLI-style binary that exposes tools/resources/prompts as subcommands,\nbuild with: frontmcp build --target cli\nEOF\n exit 0\n ;;\n --version)\n echo \"${name} ${version}\"\n exit 0\n ;;\n --print-manifest)\n cat \"\\${SCRIPT_DIR}/${name}.manifest.json\"\n exit 0\n ;;\n --stdio)\n # Serve over stdio (stdin/stdout JSON-RPC) instead of starting the HTTP\n # server. FRONTMCP_STDIO=1 makes the @FrontMcp decorator connect the stdio\n # transport and bind no TCP port (#448, #451); logs go to stderr and\n # ~/.frontmcp/logs. Drop the flag and fall through to the exec below.\n export FRONTMCP_STDIO=1\n shift\n ;;\n --*)\n echo \"Error: unsupported flag '\\${1}' on the server runner.\"\n echo \"This binary is a long-running HTTP server; flag-style invocation is reserved (except --stdio).\" >&2\n echo \"Run with no args to start, --stdio to serve over stdio, or build with --target cli for a CLI binary.\" >&2\n exit 2\n ;;\nesac\n`\n : '';\n\n // SEA mode: binary is self-contained, no Node.js required\n if (seaMode) {\n const binary = cliMode ? `${name}-cli-bin` : `${name}-bin`;\n const comment = cliMode\n ? `# ${name} — FrontMCP CLI (single executable)`\n : `# ${name} — FrontMCP Server (single executable)`;\n\n return `#!/usr/bin/env bash\nset -euo pipefail\n\n${comment}\n# Generated by frontmcp build --target ${cliMode ? 'cli' : 'node'}\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nBINARY=\"\\${SCRIPT_DIR}/${binary}\"\n\nif [ ! -f \"\\${BINARY}\" ]; then\n echo \"Error: Binary not found at \\${BINARY}\"\n exit 1\nfi\n${helpInterceptor}\n# Load .env if present\nENV_FILE=\"\\${SCRIPT_DIR}/.env\"\nif [ -f \"\\${ENV_FILE}\" ]; then\n set -a\n # shellcheck disable=SC1090\n source \"\\${ENV_FILE}\"\n set +a\nfi\n\nexec \"\\${BINARY}\" \"$@\"\n`;\n }\n\n const nodeVersion = config.nodeVersion || '>=22.0.0';\n const minNodeMajor = extractMinMajor(nodeVersion);\n\n const bundle = cliMode\n ? `\\${SCRIPT_DIR}/${name}-cli.bundle.js`\n : `\\${SCRIPT_DIR}/${name}.bundle.js`;\n\n const comment = cliMode\n ? `# ${name} — FrontMCP CLI Executable`\n : `# ${name} — FrontMCP Server Runner`;\n\n return `#!/usr/bin/env bash\nset -euo pipefail\n\n${comment}\n# Generated by frontmcp build --target ${cliMode ? 'cli --js' : 'node'}\n\nSCRIPT_DIR=\"$(cd \"$(dirname \"\\${BASH_SOURCE[0]}\")\" && pwd)\"\nBUNDLE=\"${bundle}\"\n${helpInterceptor}\n# Check Node.js\nif ! command -v node &> /dev/null; then\n echo \"Error: Node.js is required but not installed.\"\n echo \"Install Node.js ${nodeVersion}: https://nodejs.org\"\n exit 1\nfi\n\nNODE_MAJOR=$(node -e \"console.log(process.versions.node.split('.')[0])\")\nif [ \"\\${NODE_MAJOR}\" -lt \"${minNodeMajor}\" ]; then\n echo \"Error: Node.js ${nodeVersion} required, found v$(node -v)\"\n exit 1\nfi\n\n# Check bundle exists\nif [ ! -f \"\\${BUNDLE}\" ]; then\n echo \"Error: Bundle not found at \\${BUNDLE}\"\n echo \"Run 'frontmcp build --target ${cliMode ? 'cli --js' : 'node'}' to create it.\"\n exit 1\nfi\n\n# Load .env if present\nENV_FILE=\"\\${SCRIPT_DIR}/.env\"\nif [ -f \"\\${ENV_FILE}\" ]; then\n set -a\n # shellcheck disable=SC1090\n source \"\\${ENV_FILE}\"\n set +a\nfi\n\n# Enable Node.js compile cache for faster startup on warm runs\nCOMPILE_CACHE_DIR=\"\\${HOME}/.cache/frontmcp/${name}\"\nmkdir -p \"\\${COMPILE_CACHE_DIR}\" 2>/dev/null || true\nexport NODE_COMPILE_CACHE=\"\\${COMPILE_CACHE_DIR}\"\n\n# Run\nexec node \"\\${BUNDLE}\" \"$@\"\n`;\n}\n\nfunction extractMinMajor(version: string): number {\n const match = version.match(/(\\d+)/);\n return match ? parseInt(match[1], 10) : 22;\n}\n"]}
|
|
@@ -16,4 +16,20 @@ export declare function resolveDevPort(opts: {
|
|
|
16
16
|
exit?: (code: number) => never;
|
|
17
17
|
log?: (msg: string) => void;
|
|
18
18
|
}): Promise<number>;
|
|
19
|
+
/**
|
|
20
|
+
* Build the environment handed to the spawned dev child.
|
|
21
|
+
*
|
|
22
|
+
* The resolved port is exported as `PORT`, and the configured
|
|
23
|
+
* `transport.http.path` (when set) as `FRONTMCP_HTTP_ENTRY_PATH` so the server
|
|
24
|
+
* mounts the MCP endpoint where the generated client URLs point (#446). Both are
|
|
25
|
+
* applied AFTER the inherited env so the dev-resolved values win for this run —
|
|
26
|
+
* the same precedence as `PORT`. A hard-coded `@FrontMcp({ http: { entryPath } })`
|
|
27
|
+
* in metadata still wins over the env (the SDK only reads it as a default).
|
|
28
|
+
*/
|
|
29
|
+
export declare function buildDevChildEnv(params: {
|
|
30
|
+
effectiveEnv: NodeJS.ProcessEnv;
|
|
31
|
+
baseEnv: NodeJS.ProcessEnv;
|
|
32
|
+
port: number;
|
|
33
|
+
configHttpPath?: string;
|
|
34
|
+
}): NodeJS.ProcessEnv;
|
|
19
35
|
export declare function runDev(opts: ParsedArgs): Promise<void>;
|
package/src/commands/dev/dev.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.resolveDevPort = resolveDevPort;
|
|
4
|
+
exports.buildDevChildEnv = buildDevChildEnv;
|
|
4
5
|
exports.runDev = runDev;
|
|
5
6
|
const tslib_1 = require("tslib");
|
|
6
7
|
const child_process_1 = require("child_process");
|
|
@@ -70,6 +71,25 @@ async function resolveDevPort(opts) {
|
|
|
70
71
|
log(line);
|
|
71
72
|
return exit(1);
|
|
72
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Build the environment handed to the spawned dev child.
|
|
76
|
+
*
|
|
77
|
+
* The resolved port is exported as `PORT`, and the configured
|
|
78
|
+
* `transport.http.path` (when set) as `FRONTMCP_HTTP_ENTRY_PATH` so the server
|
|
79
|
+
* mounts the MCP endpoint where the generated client URLs point (#446). Both are
|
|
80
|
+
* applied AFTER the inherited env so the dev-resolved values win for this run —
|
|
81
|
+
* the same precedence as `PORT`. A hard-coded `@FrontMcp({ http: { entryPath } })`
|
|
82
|
+
* in metadata still wins over the env (the SDK only reads it as a default).
|
|
83
|
+
*/
|
|
84
|
+
function buildDevChildEnv(params) {
|
|
85
|
+
const { effectiveEnv, baseEnv, port, configHttpPath } = params;
|
|
86
|
+
return {
|
|
87
|
+
...effectiveEnv,
|
|
88
|
+
...baseEnv,
|
|
89
|
+
PORT: String(port),
|
|
90
|
+
...(configHttpPath !== undefined ? { FRONTMCP_HTTP_ENTRY_PATH: configHttpPath } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
73
93
|
async function runDev(opts) {
|
|
74
94
|
// Issue #399 — `--stdio` runs the first-party watch-aware stdio bridge
|
|
75
95
|
// instead of the legacy `tsx --watch + tsc --noEmit --watch` pair. The
|
|
@@ -120,11 +140,20 @@ async function runDev(opts) {
|
|
|
120
140
|
showConflict: !!opts.showConflict,
|
|
121
141
|
envPort: process.env['PORT'],
|
|
122
142
|
});
|
|
143
|
+
// Issue #446 — honor the configured MCP mount path in dev. `transport.http.path`
|
|
144
|
+
// already drives the generated client URLs (eject); propagate it to the spawned
|
|
145
|
+
// server via FRONTMCP_HTTP_ENTRY_PATH so the endpoint is actually mounted there
|
|
146
|
+
// (the SDK's httpOptionsSchema.entryPath default reads this env). Same precedence
|
|
147
|
+
// caveat as PORT: a hard-coded `@FrontMcp({ http: { entryPath } })` still wins.
|
|
148
|
+
const configHttpPath = typeof cfg?.transport?.http?.path === 'string' ? cfg.transport.http.path : undefined;
|
|
123
149
|
console.log(`${(0, colors_1.c)('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);
|
|
124
150
|
if (resolved.configPath || resolved.configDir) {
|
|
125
151
|
console.log(`${(0, colors_1.c)('gray', '[dev]')} config: ${resolved.configPath ?? resolved.configDir}`);
|
|
126
152
|
}
|
|
127
153
|
console.log(`${(0, colors_1.c)('cyan', '[dev]')} listening on port: ${port}`);
|
|
154
|
+
if (configHttpPath) {
|
|
155
|
+
console.log(`${(0, colors_1.c)('gray', '[dev]')} MCP endpoint path: ${configHttpPath}`);
|
|
156
|
+
}
|
|
128
157
|
console.log(`${(0, colors_1.c)('gray', '[dev]')} starting ${(0, colors_1.c)('bold', 'tsx --watch')} and ${(0, colors_1.c)('bold', 'tsc --noEmit --watch')} (async type-checker)`);
|
|
129
158
|
console.log(`${(0, colors_1.c)('gray', 'hint:')} press Ctrl+C to stop`);
|
|
130
159
|
// Use --conditions node to ensure proper Node.js module resolution.
|
|
@@ -139,7 +168,12 @@ async function runDev(opts) {
|
|
|
139
168
|
// Issue #400 — env overlays from `frontmcp.config.env.{shared,dev}` are
|
|
140
169
|
// included via `resolved.effectiveEnv`. `.env`/`.env.local` already loaded
|
|
141
170
|
// into `process.env` above, so they win (they're closer to deployment).
|
|
142
|
-
const childEnv = {
|
|
171
|
+
const childEnv = buildDevChildEnv({
|
|
172
|
+
effectiveEnv: resolved.effectiveEnv,
|
|
173
|
+
baseEnv: process.env,
|
|
174
|
+
port,
|
|
175
|
+
configHttpPath,
|
|
176
|
+
});
|
|
143
177
|
const app = (0, child_process_1.spawn)(npxCmd, ['-y', 'tsx', '--conditions', 'node', '--watch', entry], {
|
|
144
178
|
stdio: 'inherit',
|
|
145
179
|
env: childEnv,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../../src/commands/dev/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from 'child_process';\nimport * as path from 'path';\n\nimport { resolveConfig } from '../../config';\nimport { type ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { loadDevEnv } from '../../shared/env';\nimport { resolveEntry } from '../../shared/fs';\nimport { findNextFreePort, isPortFree, lookupPortOwner } from './port';\n\nconst DEFAULT_DEV_PORT = 3000;\n\nfunction killQuiet(proc?: ChildProcess, signal: NodeJS.Signals = 'SIGINT') {\n try {\n if (proc && proc.exitCode === null && proc.signalCode === null) {\n proc.kill(signal);\n }\n } catch {\n // ignore\n }\n}\n\n/**\n * Resolve the port the dev child should bind to and report any conflict\n * clearly. Returns the chosen port — or never returns and exits the process\n * with a clear error when the port is busy and `--auto-port` was not set.\n *\n * Issue #398: previously the child crashed with a raw `EADDRINUSE` stack\n * trace; this helper turns that into a one-line message with a suggested\n * remediation and (optionally) the owning process.\n */\nexport async function resolveDevPort(opts: {\n port?: number;\n autoPort?: boolean;\n showConflict?: boolean;\n envPort?: string | undefined;\n exit?: (code: number) => never;\n log?: (msg: string) => void;\n}): Promise<number> {\n const exit = opts.exit ?? ((code: number) => process.exit(code) as never);\n const log = opts.log ?? ((msg: string) => console.error(msg));\n const explicit = opts.port ?? (opts.envPort !== undefined && opts.envPort !== '' ? Number(opts.envPort) : undefined);\n const port =\n explicit !== undefined && Number.isFinite(explicit) && (explicit as number) > 0\n ? (explicit as number)\n : DEFAULT_DEV_PORT;\n\n if (await isPortFree(port)) return port;\n\n if (opts.autoPort) {\n const alt = await findNextFreePort(port + 1);\n log(`${c('yellow', '[dev]')} port ${port} is in use; auto-picked ${alt}`);\n return alt;\n }\n\n // Build a clear, actionable error message.\n const lines = [\n `${c('red', '[dev]')} Port ${port} is already in use — refusing to start.`,\n `${c('gray', ' ')} Retry with one of:`,\n `${c('gray', ' ')} • ${c('bold', `frontmcp dev --port <other-port>`)}`,\n `${c('gray', ' ')} • ${c('bold', `frontmcp dev --auto-port`)} ${c('gray', '(pick the next free port automatically)')}`,\n `${c('gray', ' ')} • ${c('bold', `PORT=<other-port> frontmcp dev`)}`,\n ];\n if (opts.showConflict) {\n const owner = await lookupPortOwner(port);\n if (owner) {\n lines.push(`${c('gray', ' ')} Holder of ${port}:`);\n for (const row of owner.split('\\n')) lines.push(`${c('gray', ' ')} ${row}`);\n } else {\n lines.push(`${c('gray', ' ')} (could not identify the holder of port ${port})`);\n }\n } else {\n lines.push(`${c('gray', ' ')} (pass --show-conflict to print which process is holding the port)`);\n }\n for (const line of lines) log(line);\n return exit(1);\n}\n\nexport async function runDev(opts: ParsedArgs): Promise<void> {\n // Issue #399 — `--stdio` runs the first-party watch-aware stdio bridge\n // instead of the legacy `tsx --watch + tsc --noEmit --watch` pair. The\n // bridge owns process stdin/stdout (JSON-RPC frames only), holds the\n // upstream MCP session across child restarts, and replaces the\n // third-party `mcp-remote` recipe for the dev loop.\n if (opts.stdio) {\n const { runDevBridge } = await import('./bridge/index.js');\n return runDevBridge(opts);\n }\n\n const cwd = process.cwd();\n\n // Issue #400 — resolve frontmcp.config so `entry`, `transport.http.port`,\n // and `env.shared`/`env.dev` overlays apply. Precedence:\n // CLI flag > FRONTMCP_<NAME> env > frontmcp.config field > built-in default.\n const resolved = await resolveConfig({\n cwd,\n mode: 'dev',\n configPath: typeof opts.config === 'string' ? opts.config : undefined,\n });\n const cfg = resolved.config;\n\n const cliEntry = typeof opts.entry === 'string' ? opts.entry : undefined;\n const configEntry = typeof cfg?.entry === 'string' ? cfg.entry : undefined;\n const entry = await resolveEntry(cwd, cliEntry ?? configEntry);\n\n // Load .env and .env.local files (these win over config env overlays for\n // parity with existing behavior — file-based env is the deployment escape\n // hatch and shouldn't be silently overridden by committed config).\n loadDevEnv(cwd);\n\n // Resolve the port BEFORE spawning tsx so EADDRINUSE produces a clean\n // one-line error instead of a raw node:net stack trace (issue #398).\n //\n // Two caveats worth knowing about this pre-flight check:\n // 1. TOCTOU — between this probe returning and the child actually binding,\n // another process can grab the port. We accept that race: this is a\n // dev-time tool, the worst case reverts to the prior behaviour (the\n // child surfaces a raw EADDRINUSE), and the common case (port already\n // busy at startup) is the one we wanted to fix.\n // 2. The resolved port is exported as `PORT` to the child. It only takes\n // effect when the user's `@FrontMcp({ http: { port } })` reads\n // `process.env.PORT` (the SDK's `httpOptionsSchema` default does).\n // If the user's metadata HARD-CODES `http.port`, the child binds to\n // that hard-coded value and ignores PORT — the probe is then advisory\n // only. Documented in docs/frontmcp/deployment/local-dev-server.mdx.\n const cliPort = typeof opts.port === 'number' ? opts.port : opts.port ? Number(opts.port) : undefined;\n const configPort = cfg?.transport?.http?.port;\n const port = await resolveDevPort({\n port: cliPort ?? configPort,\n autoPort: !!opts.autoPort,\n showConflict: !!opts.showConflict,\n envPort: process.env['PORT'],\n });\n\n console.log(`${c('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);\n if (resolved.configPath || resolved.configDir) {\n console.log(`${c('gray', '[dev]')} config: ${resolved.configPath ?? resolved.configDir}`);\n }\n console.log(`${c('cyan', '[dev]')} listening on port: ${port}`);\n console.log(\n `${c('gray', '[dev]')} starting ${c('bold', 'tsx --watch')} and ${c(\n 'bold',\n 'tsc --noEmit --watch',\n )} (async type-checker)`,\n );\n console.log(`${c('gray', 'hint:')} press Ctrl+C to stop`);\n\n // Use --conditions node to ensure proper Node.js module resolution.\n // This helps with dynamic require() calls in packages like ioredis.\n // On Windows resolve npx.cmd directly — previously we passed shell:true\n // for the .cmd suffix, but that triggers Node DEP0190 (#381) every run.\n // spawn() resolves .cmd via CreateProcessW since Node 16, so no shell is\n // needed; on Unix spawn() works on 'npx' directly. SIGINT still\n // propagates cleanly because no intermediate shell sits between us and\n // the child process.\n const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';\n // Issue #400 — env overlays from `frontmcp.config.env.{shared,dev}` are\n // included via `resolved.effectiveEnv`. `.env`/`.env.local` already loaded\n // into `process.env` above, so they win (they're closer to deployment).\n const childEnv = { ...resolved.effectiveEnv, ...process.env, PORT: String(port) };\n const app = spawn(npxCmd, ['-y', 'tsx', '--conditions', 'node', '--watch', entry], {\n stdio: 'inherit',\n env: childEnv,\n });\n const checker = spawn(npxCmd, ['-y', 'tsc', '--noEmit', '--pretty', '--watch'], {\n stdio: 'inherit',\n env: childEnv,\n });\n\n const cleanup = (clearTimer = true) => {\n if (clearTimer) {\n clearForceKillTimer();\n }\n killQuiet(checker);\n killQuiet(app);\n };\n\n let forceKillTimer: NodeJS.Timeout | undefined;\n let appClosed = false;\n let checkerClosed = false;\n\n const clearForceKillTimer = () => {\n if (forceKillTimer) {\n clearTimeout(forceKillTimer);\n forceKillTimer = undefined;\n }\n };\n\n const markClosed = (child: 'app' | 'checker') => {\n if (child === 'app') {\n appClosed = true;\n } else {\n checkerClosed = true;\n }\n if (appClosed && checkerClosed) {\n clearForceKillTimer();\n }\n };\n\n process.once('SIGINT', () => {\n cleanup(false);\n // Force-kill after 2s if children haven't exited\n clearForceKillTimer();\n forceKillTimer = setTimeout(() => {\n killQuiet(checker, 'SIGKILL');\n killQuiet(app, 'SIGKILL');\n process.exit(0);\n }, 2000);\n forceKillTimer.unref();\n // Exit cleanly once both children have closed\n const tryExit = () => {\n if (appClosed && checkerClosed) {\n clearForceKillTimer();\n process.exit(0);\n }\n };\n app.once('close', () => {\n markClosed('app');\n tryExit();\n });\n checker.once('close', () => {\n markClosed('checker');\n tryExit();\n });\n });\n\n process.once('SIGTERM', () => {\n cleanup();\n process.exit(0);\n });\n\n let appExitCode: number | null = 0;\n await new Promise<void>((resolve, reject) => {\n app.on('close', (code) => {\n // Capture the child's exit code so it can propagate to the parent\n // shell. SIGINT/SIGTERM yield code=null with a signalCode — treat\n // those as 0 so Ctrl+C doesn't appear as a failure.\n appExitCode = typeof code === 'number' ? code : 0;\n markClosed('app');\n cleanup(false);\n resolve();\n });\n app.on('error', (err) => {\n clearForceKillTimer();\n cleanup();\n reject(err);\n });\n checker.on('close', () => {\n markClosed('checker');\n });\n checker.on('error', (err) => {\n clearForceKillTimer();\n cleanup();\n reject(err);\n });\n });\n\n // Propagate the child's exit code so CI / shells see real failures\n // instead of always-success.\n if (appExitCode && appExitCode !== 0) {\n process.exit(appExitCode);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../../src/commands/dev/dev.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn, type ChildProcess } from 'child_process';\nimport * as path from 'path';\n\nimport { resolveConfig } from '../../config';\nimport { type ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { loadDevEnv } from '../../shared/env';\nimport { resolveEntry } from '../../shared/fs';\nimport { findNextFreePort, isPortFree, lookupPortOwner } from './port';\n\nconst DEFAULT_DEV_PORT = 3000;\n\nfunction killQuiet(proc?: ChildProcess, signal: NodeJS.Signals = 'SIGINT') {\n try {\n if (proc && proc.exitCode === null && proc.signalCode === null) {\n proc.kill(signal);\n }\n } catch {\n // ignore\n }\n}\n\n/**\n * Resolve the port the dev child should bind to and report any conflict\n * clearly. Returns the chosen port — or never returns and exits the process\n * with a clear error when the port is busy and `--auto-port` was not set.\n *\n * Issue #398: previously the child crashed with a raw `EADDRINUSE` stack\n * trace; this helper turns that into a one-line message with a suggested\n * remediation and (optionally) the owning process.\n */\nexport async function resolveDevPort(opts: {\n port?: number;\n autoPort?: boolean;\n showConflict?: boolean;\n envPort?: string | undefined;\n exit?: (code: number) => never;\n log?: (msg: string) => void;\n}): Promise<number> {\n const exit = opts.exit ?? ((code: number) => process.exit(code) as never);\n const log = opts.log ?? ((msg: string) => console.error(msg));\n const explicit = opts.port ?? (opts.envPort !== undefined && opts.envPort !== '' ? Number(opts.envPort) : undefined);\n const port =\n explicit !== undefined && Number.isFinite(explicit) && (explicit as number) > 0\n ? (explicit as number)\n : DEFAULT_DEV_PORT;\n\n if (await isPortFree(port)) return port;\n\n if (opts.autoPort) {\n const alt = await findNextFreePort(port + 1);\n log(`${c('yellow', '[dev]')} port ${port} is in use; auto-picked ${alt}`);\n return alt;\n }\n\n // Build a clear, actionable error message.\n const lines = [\n `${c('red', '[dev]')} Port ${port} is already in use — refusing to start.`,\n `${c('gray', ' ')} Retry with one of:`,\n `${c('gray', ' ')} • ${c('bold', `frontmcp dev --port <other-port>`)}`,\n `${c('gray', ' ')} • ${c('bold', `frontmcp dev --auto-port`)} ${c('gray', '(pick the next free port automatically)')}`,\n `${c('gray', ' ')} • ${c('bold', `PORT=<other-port> frontmcp dev`)}`,\n ];\n if (opts.showConflict) {\n const owner = await lookupPortOwner(port);\n if (owner) {\n lines.push(`${c('gray', ' ')} Holder of ${port}:`);\n for (const row of owner.split('\\n')) lines.push(`${c('gray', ' ')} ${row}`);\n } else {\n lines.push(`${c('gray', ' ')} (could not identify the holder of port ${port})`);\n }\n } else {\n lines.push(`${c('gray', ' ')} (pass --show-conflict to print which process is holding the port)`);\n }\n for (const line of lines) log(line);\n return exit(1);\n}\n\n/**\n * Build the environment handed to the spawned dev child.\n *\n * The resolved port is exported as `PORT`, and the configured\n * `transport.http.path` (when set) as `FRONTMCP_HTTP_ENTRY_PATH` so the server\n * mounts the MCP endpoint where the generated client URLs point (#446). Both are\n * applied AFTER the inherited env so the dev-resolved values win for this run —\n * the same precedence as `PORT`. A hard-coded `@FrontMcp({ http: { entryPath } })`\n * in metadata still wins over the env (the SDK only reads it as a default).\n */\nexport function buildDevChildEnv(params: {\n effectiveEnv: NodeJS.ProcessEnv;\n baseEnv: NodeJS.ProcessEnv;\n port: number;\n configHttpPath?: string;\n}): NodeJS.ProcessEnv {\n const { effectiveEnv, baseEnv, port, configHttpPath } = params;\n return {\n ...effectiveEnv,\n ...baseEnv,\n PORT: String(port),\n ...(configHttpPath !== undefined ? { FRONTMCP_HTTP_ENTRY_PATH: configHttpPath } : {}),\n };\n}\n\nexport async function runDev(opts: ParsedArgs): Promise<void> {\n // Issue #399 — `--stdio` runs the first-party watch-aware stdio bridge\n // instead of the legacy `tsx --watch + tsc --noEmit --watch` pair. The\n // bridge owns process stdin/stdout (JSON-RPC frames only), holds the\n // upstream MCP session across child restarts, and replaces the\n // third-party `mcp-remote` recipe for the dev loop.\n if (opts.stdio) {\n const { runDevBridge } = await import('./bridge/index.js');\n return runDevBridge(opts);\n }\n\n const cwd = process.cwd();\n\n // Issue #400 — resolve frontmcp.config so `entry`, `transport.http.port`,\n // and `env.shared`/`env.dev` overlays apply. Precedence:\n // CLI flag > FRONTMCP_<NAME> env > frontmcp.config field > built-in default.\n const resolved = await resolveConfig({\n cwd,\n mode: 'dev',\n configPath: typeof opts.config === 'string' ? opts.config : undefined,\n });\n const cfg = resolved.config;\n\n const cliEntry = typeof opts.entry === 'string' ? opts.entry : undefined;\n const configEntry = typeof cfg?.entry === 'string' ? cfg.entry : undefined;\n const entry = await resolveEntry(cwd, cliEntry ?? configEntry);\n\n // Load .env and .env.local files (these win over config env overlays for\n // parity with existing behavior — file-based env is the deployment escape\n // hatch and shouldn't be silently overridden by committed config).\n loadDevEnv(cwd);\n\n // Resolve the port BEFORE spawning tsx so EADDRINUSE produces a clean\n // one-line error instead of a raw node:net stack trace (issue #398).\n //\n // Two caveats worth knowing about this pre-flight check:\n // 1. TOCTOU — between this probe returning and the child actually binding,\n // another process can grab the port. We accept that race: this is a\n // dev-time tool, the worst case reverts to the prior behaviour (the\n // child surfaces a raw EADDRINUSE), and the common case (port already\n // busy at startup) is the one we wanted to fix.\n // 2. The resolved port is exported as `PORT` to the child. It only takes\n // effect when the user's `@FrontMcp({ http: { port } })` reads\n // `process.env.PORT` (the SDK's `httpOptionsSchema` default does).\n // If the user's metadata HARD-CODES `http.port`, the child binds to\n // that hard-coded value and ignores PORT — the probe is then advisory\n // only. Documented in docs/frontmcp/deployment/local-dev-server.mdx.\n const cliPort = typeof opts.port === 'number' ? opts.port : opts.port ? Number(opts.port) : undefined;\n const configPort = cfg?.transport?.http?.port;\n const port = await resolveDevPort({\n port: cliPort ?? configPort,\n autoPort: !!opts.autoPort,\n showConflict: !!opts.showConflict,\n envPort: process.env['PORT'],\n });\n\n // Issue #446 — honor the configured MCP mount path in dev. `transport.http.path`\n // already drives the generated client URLs (eject); propagate it to the spawned\n // server via FRONTMCP_HTTP_ENTRY_PATH so the endpoint is actually mounted there\n // (the SDK's httpOptionsSchema.entryPath default reads this env). Same precedence\n // caveat as PORT: a hard-coded `@FrontMcp({ http: { entryPath } })` still wins.\n const configHttpPath = typeof cfg?.transport?.http?.path === 'string' ? cfg.transport.http.path : undefined;\n\n console.log(`${c('cyan', '[dev]')} using entry: ${path.relative(cwd, entry)}`);\n if (resolved.configPath || resolved.configDir) {\n console.log(`${c('gray', '[dev]')} config: ${resolved.configPath ?? resolved.configDir}`);\n }\n console.log(`${c('cyan', '[dev]')} listening on port: ${port}`);\n if (configHttpPath) {\n console.log(`${c('gray', '[dev]')} MCP endpoint path: ${configHttpPath}`);\n }\n console.log(\n `${c('gray', '[dev]')} starting ${c('bold', 'tsx --watch')} and ${c(\n 'bold',\n 'tsc --noEmit --watch',\n )} (async type-checker)`,\n );\n console.log(`${c('gray', 'hint:')} press Ctrl+C to stop`);\n\n // Use --conditions node to ensure proper Node.js module resolution.\n // This helps with dynamic require() calls in packages like ioredis.\n // On Windows resolve npx.cmd directly — previously we passed shell:true\n // for the .cmd suffix, but that triggers Node DEP0190 (#381) every run.\n // spawn() resolves .cmd via CreateProcessW since Node 16, so no shell is\n // needed; on Unix spawn() works on 'npx' directly. SIGINT still\n // propagates cleanly because no intermediate shell sits between us and\n // the child process.\n const npxCmd = process.platform === 'win32' ? 'npx.cmd' : 'npx';\n // Issue #400 — env overlays from `frontmcp.config.env.{shared,dev}` are\n // included via `resolved.effectiveEnv`. `.env`/`.env.local` already loaded\n // into `process.env` above, so they win (they're closer to deployment).\n const childEnv = buildDevChildEnv({\n effectiveEnv: resolved.effectiveEnv,\n baseEnv: process.env,\n port,\n configHttpPath,\n });\n const app = spawn(npxCmd, ['-y', 'tsx', '--conditions', 'node', '--watch', entry], {\n stdio: 'inherit',\n env: childEnv,\n });\n const checker = spawn(npxCmd, ['-y', 'tsc', '--noEmit', '--pretty', '--watch'], {\n stdio: 'inherit',\n env: childEnv,\n });\n\n const cleanup = (clearTimer = true) => {\n if (clearTimer) {\n clearForceKillTimer();\n }\n killQuiet(checker);\n killQuiet(app);\n };\n\n let forceKillTimer: NodeJS.Timeout | undefined;\n let appClosed = false;\n let checkerClosed = false;\n\n const clearForceKillTimer = () => {\n if (forceKillTimer) {\n clearTimeout(forceKillTimer);\n forceKillTimer = undefined;\n }\n };\n\n const markClosed = (child: 'app' | 'checker') => {\n if (child === 'app') {\n appClosed = true;\n } else {\n checkerClosed = true;\n }\n if (appClosed && checkerClosed) {\n clearForceKillTimer();\n }\n };\n\n process.once('SIGINT', () => {\n cleanup(false);\n // Force-kill after 2s if children haven't exited\n clearForceKillTimer();\n forceKillTimer = setTimeout(() => {\n killQuiet(checker, 'SIGKILL');\n killQuiet(app, 'SIGKILL');\n process.exit(0);\n }, 2000);\n forceKillTimer.unref();\n // Exit cleanly once both children have closed\n const tryExit = () => {\n if (appClosed && checkerClosed) {\n clearForceKillTimer();\n process.exit(0);\n }\n };\n app.once('close', () => {\n markClosed('app');\n tryExit();\n });\n checker.once('close', () => {\n markClosed('checker');\n tryExit();\n });\n });\n\n process.once('SIGTERM', () => {\n cleanup();\n process.exit(0);\n });\n\n let appExitCode: number | null = 0;\n await new Promise<void>((resolve, reject) => {\n app.on('close', (code) => {\n // Capture the child's exit code so it can propagate to the parent\n // shell. SIGINT/SIGTERM yield code=null with a signalCode — treat\n // those as 0 so Ctrl+C doesn't appear as a failure.\n appExitCode = typeof code === 'number' ? code : 0;\n markClosed('app');\n cleanup(false);\n resolve();\n });\n app.on('error', (err) => {\n clearForceKillTimer();\n cleanup();\n reject(err);\n });\n checker.on('close', () => {\n markClosed('checker');\n });\n checker.on('error', (err) => {\n clearForceKillTimer();\n cleanup();\n reject(err);\n });\n });\n\n // Propagate the child's exit code so CI / shells see real failures\n // instead of always-success.\n if (appExitCode && appExitCode !== 0) {\n process.exit(appExitCode);\n }\n}\n"]}
|
|
@@ -565,7 +565,7 @@ function generatePmSetupSteps(pm) {
|
|
|
565
565
|
uses: pnpm/action-setup@v4
|
|
566
566
|
|
|
567
567
|
- name: Setup Node.js
|
|
568
|
-
uses: actions/setup-node@
|
|
568
|
+
uses: actions/setup-node@v6
|
|
569
569
|
with:
|
|
570
570
|
node-version: '24'
|
|
571
571
|
cache: '${cfg.ghCache}'
|
|
@@ -575,7 +575,7 @@ function generatePmSetupSteps(pm) {
|
|
|
575
575
|
}
|
|
576
576
|
return `
|
|
577
577
|
- name: Setup Node.js
|
|
578
|
-
uses: actions/setup-node@
|
|
578
|
+
uses: actions/setup-node@v6
|
|
579
579
|
with:
|
|
580
580
|
node-version: '24'
|
|
581
581
|
cache: '${cfg.ghCache}'
|
|
@@ -599,7 +599,7 @@ jobs:
|
|
|
599
599
|
runs-on: ubuntu-latest
|
|
600
600
|
|
|
601
601
|
steps:
|
|
602
|
-
- uses: actions/checkout@
|
|
602
|
+
- uses: actions/checkout@v6
|
|
603
603
|
${generatePmSetupSteps(pm)}
|
|
604
604
|
|
|
605
605
|
- name: Type check
|
|
@@ -625,7 +625,7 @@ jobs:
|
|
|
625
625
|
runs-on: ubuntu-latest
|
|
626
626
|
|
|
627
627
|
steps:
|
|
628
|
-
- uses: actions/checkout@
|
|
628
|
+
- uses: actions/checkout@v6
|
|
629
629
|
${generatePmSetupSteps(pm)}
|
|
630
630
|
|
|
631
631
|
- name: Build
|
|
@@ -655,7 +655,7 @@ jobs:
|
|
|
655
655
|
packages: write
|
|
656
656
|
|
|
657
657
|
steps:
|
|
658
|
-
- uses: actions/checkout@
|
|
658
|
+
- uses: actions/checkout@v6
|
|
659
659
|
|
|
660
660
|
- name: Log in to Container Registry
|
|
661
661
|
uses: docker/login-action@v3
|
|
@@ -693,7 +693,7 @@ jobs:
|
|
|
693
693
|
runs-on: ubuntu-latest
|
|
694
694
|
|
|
695
695
|
steps:
|
|
696
|
-
- uses: actions/checkout@
|
|
696
|
+
- uses: actions/checkout@v6
|
|
697
697
|
${generatePmSetupSteps(pm)}
|
|
698
698
|
|
|
699
699
|
- name: Build
|
|
@@ -722,7 +722,7 @@ jobs:
|
|
|
722
722
|
runs-on: ubuntu-latest
|
|
723
723
|
|
|
724
724
|
steps:
|
|
725
|
-
- uses: actions/checkout@
|
|
725
|
+
- uses: actions/checkout@v6
|
|
726
726
|
${generatePmSetupSteps(pm)}
|
|
727
727
|
|
|
728
728
|
- name: Build
|
|
@@ -759,7 +759,7 @@ jobs:
|
|
|
759
759
|
runs-on: ubuntu-latest
|
|
760
760
|
|
|
761
761
|
steps:
|
|
762
|
-
- uses: actions/checkout@
|
|
762
|
+
- uses: actions/checkout@v6
|
|
763
763
|
${generatePmSetupSteps(pm)}
|
|
764
764
|
|
|
765
765
|
- name: Build
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../../src/commands/scaffold/create.ts"],"names":[],"mappings":"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","sourcesContent":["import { createRequire } from 'module';\nimport * as path from 'path';\n\nimport {\n copyFile,\n cp,\n ensureDir,\n fileExists,\n isDirEmpty,\n readFile,\n readJSON,\n runCmd,\n stat,\n writeFile,\n writeJSON,\n} from '@frontmcp/utils';\n\nimport { c } from '../../core/colors';\nimport { runInit } from '../../core/tsconfig';\nimport { getSelfVersion } from '../../core/version';\nimport { clack } from '../../shared/prompts';\nimport { buildSkillsSection } from '../skills/install';\n\n// Inline skill manifest types to avoid build dependency on @frontmcp/skills source\ninterface SkillCatalogEntry {\n name: string;\n category: string;\n description: string;\n path: string;\n targets: string[];\n hasResources: boolean;\n tags: string[];\n bundle?: string[];\n install: { destinations: string[]; mergeStrategy: string; dependencies?: string[] };\n}\ninterface SkillManifest {\n version: number;\n skills: SkillCatalogEntry[];\n}\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';\nexport type SkillsBundle = 'recommended' | 'minimal' | 'full' | 'none';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n packageManager: PackageManager;\n nxScaffolded?: boolean;\n skillsBundle?: SkillsBundle;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n pm?: PackageManager;\n nx?: boolean;\n skills?: SkillsBundle;\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: '>=24', 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: '>=24' },\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: '>=24' },\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\n/**\n * Render a starter `frontmcp.config.ts` for the chosen deployment target\n * (issue #400). The emitted file is consumed by `dev`, `test`, `inspector`,\n * `pm start/socket`, and `skills install/export` — see the matching\n * `deployment/frontmcp-config` docs page for the full surface.\n */\nfunction renderFrontmcpConfigTemplate(projectName: string, deploymentTarget: DeploymentTarget): string {\n const safeName = sanitizeForFolder(projectName);\n // Every value of `DeploymentTarget` ('node' | 'vercel' | 'lambda' |\n // 'cloudflare') ships HTTP, so the scaffold only ever emits the HTTP\n // client + transport blocks. The stdio variant lived here briefly but\n // was unreachable — reintroduce it (and add a 'desktop'/'cli' target to\n // `DeploymentTarget`) if scaffold should support stdio in the future.\n const port = 3000;\n const clientBlock = ` clients: {\n 'claude-code': {\n name: '${safeName}',\n transport: 'http',\n url: 'http://127.0.0.1:${port}/mcp',\n },\n },`;\n const transportBlock = ` transport: { default: 'http', http: { port: ${port}, path: '/mcp' } },`;\n return `import { defineConfig } from 'frontmcp';\n\n// Single source of truth for every \\`frontmcp\\` CLI command (dev / test /\n// inspector / pm start / socket / skills install / export). Override any\n// field with an explicit CLI flag or the matching \\`FRONTMCP_<NAME>\\` env\n// var — precedence: CLI > env > config > built-in default.\nexport default defineConfig({\n name: '${safeName}',\n entry: './src/main.ts',\n deployments: [{ target: '${deploymentTarget}' }],\n${transportBlock}\n env: {\n shared: {},\n dev: { NODE_ENV: 'development' },\n },\n${clientBlock}\n});\n`;\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, z } from '@frontmcp/sdk';\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 { expect, test } from '@frontmcp/testing';\n\n/**\n * E2E tests for the MCP server.\n *\n * Run with: frontmcp test\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\n// jest.e2e.config.ts and tsconfig.e2e.json removed — `frontmcp test` auto-generates the correct config\n\nfunction generateClaudeMd(\n projectName: string,\n pm: PackageManager,\n skillEntries: { name: string; description: string }[],\n): string {\n const cfg = PM_CONFIG[pm];\n const version = getSelfVersion();\n const skillsBlock = buildSkillsSection(version, skillEntries);\n return `# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n${skillsBlock}\n## Project Overview\n\nTypeScript MCP (Model Context Protocol) server built with the **FrontMCP** framework. Uses decorator-based architecture with \\`@FrontMcp\\`, \\`@App\\`, and \\`@Tool\\` decorators from \\`@frontmcp/sdk\\`. Requires Node >= 22.\n\n## Commands\n\n- \\`${cfg.run} dev\\` — start dev server with hot reload (uses \\`frontmcp dev\\`)\n- \\`${cfg.run} build\\` — production build (uses \\`frontmcp build\\`)\n- \\`${cfg.run} test\\` — run E2E tests (uses \\`frontmcp test\\`)\n- \\`${cfg.run} inspect\\` — launch MCP Inspector (interactive debugging)\n- \\`${cfg.run} doctor\\` — check project configuration\n\n**Important:** Always use the package.json scripts above. Never run \\`npx tsx src/main.ts\\` directly — use \\`${cfg.run} dev\\` instead.\n\n## Architecture\n\n**Entry point:** \\`src/main.ts\\` — defines the \\`Server\\` class with \\`@FrontMcp\\` decorator, registering apps.\n\n**App/Tool hierarchy:** Server → Apps → Tools. Each app groups related tools:\n- \\`src/calc.app.ts\\` — \\`CalcApp\\` registered with \\`@App\\`, contains tools\n- \\`src/tools/add.tool.ts\\` — \\`AddTool\\` extends \\`ToolContext\\`, uses Zod schemas for input/output validation\n\n**Key patterns:**\n- \\`reflect-metadata\\` must be imported at the entry point\n- Tools extend \\`ToolContext\\` and implement \\`async execute(input)\\`\n- Input/output schemas defined with Zod in the \\`@Tool\\` decorator\n- E2E tests use \\`@frontmcp/testing\\` with \\`test.use({ server, port })\\` fixture pattern\n\n## Testing\n\nRun tests with \\`${cfg.run} test\\` (which runs \\`frontmcp test\\` under the hood).\n\n- Test files go in \\`e2e/\\` directory with \\`.e2e.spec.ts\\` extension\n- Split tests by app/feature: \\`e2e/calc.e2e.spec.ts\\`, \\`e2e/my-feature.e2e.spec.ts\\`\n- Do NOT create a standalone \\`jest.e2e.config.ts\\` — \\`frontmcp test\\` auto-generates the correct Jest/SWC config\n\n## Docker\n\nDocker Compose config is in \\`ci/docker-compose.yml\\` (includes Redis). Redis-only: \\`docker compose -f ci/docker-compose.yml up redis -d\\`.\n\n## Environment\n\nSee \\`.env.example\\` for required variables (PORT, NODE_ENV, REDIS_HOST, REDIS_PORT, REDIS_PASSWORD).\n`;\n}\n\nfunction generateAgentsMd(projectName: string, pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `# ${projectName} — Agent Guidelines\n\n## Project Type\n\nFrontMCP standalone app — TypeScript-first framework for building MCP (Model Context Protocol) servers.\n\n## Architecture\n\n- **Language**: TypeScript with strict mode enabled\n- **Build system**: FrontMCP CLI (\\`frontmcp dev\\`, \\`frontmcp build\\`, \\`frontmcp test\\`)\n- **Testing**: Jest via \\`frontmcp test\\` with 95%+ coverage requirement\n- **Package manager**: ${pm}\n\n## Commands\n\n- \\`${cfg.run} dev\\` — start dev server with hot reload\n- \\`${cfg.run} build\\` — production build\n- \\`${cfg.run} test\\` — run E2E tests\n- \\`${cfg.run} inspect\\` — launch MCP Inspector\n- \\`${cfg.run} doctor\\` — check project configuration\n\nDo NOT run \\`npx tsx src/main.ts\\` directly — always use \\`${cfg.run} dev\\`.\n\n## Key Decorators & Context Classes\n\n| Decorator | Context Class | Purpose |\n|-----------|---------------|---------|\n| \\`@Tool\\` | \\`ToolContext\\` | MCP tool with Zod input/output |\n| \\`@Resource\\` / \\`@ResourceTemplate\\` | \\`ResourceContext\\` | MCP resource |\n| \\`@Prompt\\` | \\`PromptContext\\` | MCP prompt returning \\`GetPromptResult\\` |\n| \\`@Skill\\` | \\`SkillContext\\` | Instruction-only AI skill |\n| \\`@Provider\\` | — | DI provider with Symbol token |\n| \\`@App\\` | — | Application grouping tools/resources/prompts |\n| \\`@FrontMcp\\` | — | Server entry point |\n\n## Constraints\n\n- No \\`any\\` types — use \\`unknown\\` for generic defaults\n- No raw \\`node:crypto\\` or \\`fs\\` — use \\`@frontmcp/utils\\`\n- No non-null assertions (\\`!\\`) — throw proper errors\n- Zod v4 for all schema validation\n- \\`@frontmcp/testing\\` for test harnesses\n- Test files use \\`.spec.ts\\` extension (not \\`.test.ts\\`); E2E uses \\`.e2e.spec.ts\\`\n- Split E2E tests by app/feature into separate files\n\n## Structure\n\n- \\`src/main.ts\\` — Server entry point with \\`@FrontMcp\\` decorator\n- \\`src/*.app.ts\\` — App definitions with \\`@App\\` decorator\n- \\`src/tools/*.tool.ts\\` — Tool implementations extending \\`ToolContext\\`\n- \\`e2e/*.e2e.spec.ts\\` — E2E tests using \\`@frontmcp/testing\\`\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\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: nodejs24.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\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 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├── 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\\`\\`\\`\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 loadSkillEntriesForClaudeMd(\n options: Pick<CreateOptions, 'deploymentTarget' | 'skillsBundle'>,\n): Promise<{ name: string; description: string }[]> {\n const bundle = options.skillsBundle ?? 'recommended';\n if (bundle === 'none') return [];\n\n try {\n const catalogDir = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog');\n const manifestPath = path.join(catalogDir, 'skills-manifest.json');\n\n let manifestContent: string;\n if (await fileExists(manifestPath)) {\n manifestContent = await readFile(manifestPath);\n } else {\n const require_ = createRequire(__filename);\n const pkgManifest = require_.resolve('@frontmcp/skills/catalog/skills-manifest.json');\n manifestContent = await readFile(pkgManifest);\n }\n const manifest = JSON.parse(manifestContent) as SkillManifest;\n const target = options.deploymentTarget;\n return manifest.skills\n .filter((s) => {\n const targetMatch = s.targets.includes('all') || s.targets.includes(target);\n const bundleMatch = s.bundle?.includes(bundle);\n return targetMatch && bundleMatch;\n })\n .map((s) => ({ name: s.name, description: s.description }));\n } catch {\n return [];\n }\n}\n\nasync function scaffoldSkills(targetDir: string, options: CreateOptions): Promise<void> {\n const bundle = options.skillsBundle ?? 'recommended';\n if (bundle === 'none') return;\n\n let manifest: SkillManifest;\n try {\n const catalogDir = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog');\n const manifestPath = path.join(catalogDir, 'skills-manifest.json');\n\n // Try bundled catalog first, then fallback to @frontmcp/skills package\n let manifestContent: string;\n if (await fileExists(manifestPath)) {\n manifestContent = await readFile(manifestPath);\n } else {\n try {\n const require_ = createRequire(__filename);\n const pkgManifest = require_.resolve('@frontmcp/skills/catalog/skills-manifest.json');\n manifestContent = await readFile(pkgManifest);\n } catch {\n // Skills catalog not available — skip silently\n return;\n }\n }\n manifest = JSON.parse(manifestContent) as SkillManifest;\n } catch {\n return;\n }\n\n const target = options.deploymentTarget;\n\n // Filter skills by target and bundle\n const matchingSkills = manifest.skills.filter((s) => {\n const targetMatch = s.targets.includes('all') || s.targets.includes(target);\n const bundleMatch = s.bundle?.includes(bundle);\n return targetMatch && bundleMatch;\n });\n\n if (matchingSkills.length === 0) return;\n\n const skillsDir = path.join(targetDir, 'skills');\n\n for (const skill of matchingSkills) {\n const skillTargetDir = path.join(skillsDir, skill.name);\n await ensureDir(skillTargetDir);\n\n // Resolve source skill directory\n let sourceDir: string | undefined;\n const bundledSource = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog', skill.path);\n if (await fileExists(path.join(bundledSource, 'SKILL.md'))) {\n sourceDir = bundledSource;\n } else {\n try {\n const require_ = createRequire(__filename);\n const pkgCatalog = path.dirname(require_.resolve('@frontmcp/skills/catalog/skills-manifest.json'));\n const pkgSource = path.join(pkgCatalog, skill.path);\n if (await fileExists(path.join(pkgSource, 'SKILL.md'))) {\n sourceDir = pkgSource;\n }\n } catch {\n // Package not available\n }\n }\n\n if (!sourceDir) continue;\n\n // Copy SKILL.md (binary-safe)\n const skillMdSrc = path.join(sourceDir, 'SKILL.md');\n if (await fileExists(skillMdSrc)) {\n await copyFile(skillMdSrc, path.join(skillTargetDir, 'SKILL.md'));\n }\n\n // Copy resource directories if present (binary-safe recursive copy)\n if (skill.hasResources) {\n for (const resDir of ['scripts', 'references', 'assets']) {\n const srcRes = path.join(sourceDir, resDir);\n if (await fileExists(srcRes)) {\n await cp(srcRes, path.join(skillTargetDir, resDir), { recursive: true });\n }\n }\n }\n\n console.log(c('green', `✓ added skill: ${skill.name}`));\n }\n\n console.log(c('gray', ` ${matchingSkills.length} skills added (bundle: ${bundle})`));\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 // Issue #400 — emit a starter frontmcp.config.ts so subsequent CLI runs\n // pick up entry / port / env / client snippets without re-typing them.\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'frontmcp.config.ts'),\n renderFrontmcpConfigTemplate(projectName, deploymentTarget),\n );\n\n // E2E scaffolding (jest config auto-generated by `frontmcp test`)\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.spec.ts'), TEMPLATE_E2E_TEST_TS);\n\n // Skills scaffolding\n await scaffoldSkills(targetDir, options);\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 // CLAUDE.md and AGENTS.md for AI coding assistants\n const skillEntries = await loadSkillEntriesForClaudeMd(options);\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'CLAUDE.md'),\n generateClaudeMd(pkgName, packageManager, skillEntries),\n );\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'AGENTS.md'), generateAgentsMd(pkgName, packageManager));\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 `, 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 };\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/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/helpers': '^0.5.20',\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 (flags?.skills) options.skillsBundle = flags.skills;\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 { createRequire } from 'module';\nimport * as path from 'path';\n\nimport {\n copyFile,\n cp,\n ensureDir,\n fileExists,\n isDirEmpty,\n readFile,\n readJSON,\n runCmd,\n stat,\n writeFile,\n writeJSON,\n} from '@frontmcp/utils';\n\nimport { c } from '../../core/colors';\nimport { runInit } from '../../core/tsconfig';\nimport { getSelfVersion } from '../../core/version';\nimport { clack } from '../../shared/prompts';\nimport { buildSkillsSection } from '../skills/install';\n\n// Inline skill manifest types to avoid build dependency on @frontmcp/skills source\ninterface SkillCatalogEntry {\n name: string;\n category: string;\n description: string;\n path: string;\n targets: string[];\n hasResources: boolean;\n tags: string[];\n bundle?: string[];\n install: { destinations: string[]; mergeStrategy: string; dependencies?: string[] };\n}\ninterface SkillManifest {\n version: number;\n skills: SkillCatalogEntry[];\n}\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';\nexport type SkillsBundle = 'recommended' | 'minimal' | 'full' | 'none';\n\nexport interface CreateOptions {\n projectName: string;\n deploymentTarget: DeploymentTarget;\n redisSetup: RedisSetup;\n enableGitHubActions: boolean;\n packageManager: PackageManager;\n nxScaffolded?: boolean;\n skillsBundle?: SkillsBundle;\n}\n\nexport interface CreateFlags {\n yes?: boolean;\n target?: DeploymentTarget;\n redis?: RedisSetup;\n cicd?: boolean;\n pm?: PackageManager;\n nx?: boolean;\n skills?: SkillsBundle;\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: '>=24', 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: '>=24' },\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: '>=24' },\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\n/**\n * Render a starter `frontmcp.config.ts` for the chosen deployment target\n * (issue #400). The emitted file is consumed by `dev`, `test`, `inspector`,\n * `pm start/socket`, and `skills install/export` — see the matching\n * `deployment/frontmcp-config` docs page for the full surface.\n */\nfunction renderFrontmcpConfigTemplate(projectName: string, deploymentTarget: DeploymentTarget): string {\n const safeName = sanitizeForFolder(projectName);\n // Every value of `DeploymentTarget` ('node' | 'vercel' | 'lambda' |\n // 'cloudflare') ships HTTP, so the scaffold only ever emits the HTTP\n // client + transport blocks. The stdio variant lived here briefly but\n // was unreachable — reintroduce it (and add a 'desktop'/'cli' target to\n // `DeploymentTarget`) if scaffold should support stdio in the future.\n const port = 3000;\n const clientBlock = ` clients: {\n 'claude-code': {\n name: '${safeName}',\n transport: 'http',\n url: 'http://127.0.0.1:${port}/mcp',\n },\n },`;\n const transportBlock = ` transport: { default: 'http', http: { port: ${port}, path: '/mcp' } },`;\n return `import { defineConfig } from 'frontmcp';\n\n// Single source of truth for every \\`frontmcp\\` CLI command (dev / test /\n// inspector / pm start / socket / skills install / export). Override any\n// field with an explicit CLI flag or the matching \\`FRONTMCP_<NAME>\\` env\n// var — precedence: CLI > env > config > built-in default.\nexport default defineConfig({\n name: '${safeName}',\n entry: './src/main.ts',\n deployments: [{ target: '${deploymentTarget}' }],\n${transportBlock}\n env: {\n shared: {},\n dev: { NODE_ENV: 'development' },\n },\n${clientBlock}\n});\n`;\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, z } from '@frontmcp/sdk';\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 { expect, test } from '@frontmcp/testing';\n\n/**\n * E2E tests for the MCP server.\n *\n * Run with: frontmcp test\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\n// jest.e2e.config.ts and tsconfig.e2e.json removed — `frontmcp test` auto-generates the correct config\n\nfunction generateClaudeMd(\n projectName: string,\n pm: PackageManager,\n skillEntries: { name: string; description: string }[],\n): string {\n const cfg = PM_CONFIG[pm];\n const version = getSelfVersion();\n const skillsBlock = buildSkillsSection(version, skillEntries);\n return `# CLAUDE.md\n\nThis file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.\n\n${skillsBlock}\n## Project Overview\n\nTypeScript MCP (Model Context Protocol) server built with the **FrontMCP** framework. Uses decorator-based architecture with \\`@FrontMcp\\`, \\`@App\\`, and \\`@Tool\\` decorators from \\`@frontmcp/sdk\\`. Requires Node >= 22.\n\n## Commands\n\n- \\`${cfg.run} dev\\` — start dev server with hot reload (uses \\`frontmcp dev\\`)\n- \\`${cfg.run} build\\` — production build (uses \\`frontmcp build\\`)\n- \\`${cfg.run} test\\` — run E2E tests (uses \\`frontmcp test\\`)\n- \\`${cfg.run} inspect\\` — launch MCP Inspector (interactive debugging)\n- \\`${cfg.run} doctor\\` — check project configuration\n\n**Important:** Always use the package.json scripts above. Never run \\`npx tsx src/main.ts\\` directly — use \\`${cfg.run} dev\\` instead.\n\n## Architecture\n\n**Entry point:** \\`src/main.ts\\` — defines the \\`Server\\` class with \\`@FrontMcp\\` decorator, registering apps.\n\n**App/Tool hierarchy:** Server → Apps → Tools. Each app groups related tools:\n- \\`src/calc.app.ts\\` — \\`CalcApp\\` registered with \\`@App\\`, contains tools\n- \\`src/tools/add.tool.ts\\` — \\`AddTool\\` extends \\`ToolContext\\`, uses Zod schemas for input/output validation\n\n**Key patterns:**\n- \\`reflect-metadata\\` must be imported at the entry point\n- Tools extend \\`ToolContext\\` and implement \\`async execute(input)\\`\n- Input/output schemas defined with Zod in the \\`@Tool\\` decorator\n- E2E tests use \\`@frontmcp/testing\\` with \\`test.use({ server, port })\\` fixture pattern\n\n## Testing\n\nRun tests with \\`${cfg.run} test\\` (which runs \\`frontmcp test\\` under the hood).\n\n- Test files go in \\`e2e/\\` directory with \\`.e2e.spec.ts\\` extension\n- Split tests by app/feature: \\`e2e/calc.e2e.spec.ts\\`, \\`e2e/my-feature.e2e.spec.ts\\`\n- Do NOT create a standalone \\`jest.e2e.config.ts\\` — \\`frontmcp test\\` auto-generates the correct Jest/SWC config\n\n## Docker\n\nDocker Compose config is in \\`ci/docker-compose.yml\\` (includes Redis). Redis-only: \\`docker compose -f ci/docker-compose.yml up redis -d\\`.\n\n## Environment\n\nSee \\`.env.example\\` for required variables (PORT, NODE_ENV, REDIS_HOST, REDIS_PORT, REDIS_PASSWORD).\n`;\n}\n\nfunction generateAgentsMd(projectName: string, pm: PackageManager): string {\n const cfg = PM_CONFIG[pm];\n return `# ${projectName} — Agent Guidelines\n\n## Project Type\n\nFrontMCP standalone app — TypeScript-first framework for building MCP (Model Context Protocol) servers.\n\n## Architecture\n\n- **Language**: TypeScript with strict mode enabled\n- **Build system**: FrontMCP CLI (\\`frontmcp dev\\`, \\`frontmcp build\\`, \\`frontmcp test\\`)\n- **Testing**: Jest via \\`frontmcp test\\` with 95%+ coverage requirement\n- **Package manager**: ${pm}\n\n## Commands\n\n- \\`${cfg.run} dev\\` — start dev server with hot reload\n- \\`${cfg.run} build\\` — production build\n- \\`${cfg.run} test\\` — run E2E tests\n- \\`${cfg.run} inspect\\` — launch MCP Inspector\n- \\`${cfg.run} doctor\\` — check project configuration\n\nDo NOT run \\`npx tsx src/main.ts\\` directly — always use \\`${cfg.run} dev\\`.\n\n## Key Decorators & Context Classes\n\n| Decorator | Context Class | Purpose |\n|-----------|---------------|---------|\n| \\`@Tool\\` | \\`ToolContext\\` | MCP tool with Zod input/output |\n| \\`@Resource\\` / \\`@ResourceTemplate\\` | \\`ResourceContext\\` | MCP resource |\n| \\`@Prompt\\` | \\`PromptContext\\` | MCP prompt returning \\`GetPromptResult\\` |\n| \\`@Skill\\` | \\`SkillContext\\` | Instruction-only AI skill |\n| \\`@Provider\\` | — | DI provider with Symbol token |\n| \\`@App\\` | — | Application grouping tools/resources/prompts |\n| \\`@FrontMcp\\` | — | Server entry point |\n\n## Constraints\n\n- No \\`any\\` types — use \\`unknown\\` for generic defaults\n- No raw \\`node:crypto\\` or \\`fs\\` — use \\`@frontmcp/utils\\`\n- No non-null assertions (\\`!\\`) — throw proper errors\n- Zod v4 for all schema validation\n- \\`@frontmcp/testing\\` for test harnesses\n- Test files use \\`.spec.ts\\` extension (not \\`.test.ts\\`); E2E uses \\`.e2e.spec.ts\\`\n- Split E2E tests by app/feature into separate files\n\n## Structure\n\n- \\`src/main.ts\\` — Server entry point with \\`@FrontMcp\\` decorator\n- \\`src/*.app.ts\\` — App definitions with \\`@App\\` decorator\n- \\`src/tools/*.tool.ts\\` — Tool implementations extending \\`ToolContext\\`\n- \\`e2e/*.e2e.spec.ts\\` — E2E tests using \\`@frontmcp/testing\\`\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\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: nodejs24.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@v6\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@v6\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@v6\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@v6\n${generatePmSetupSteps(pm)}\n\n - name: Build\n run: ${cfg.run} build\n\n - name: Run E2E tests\n run: ${cfg.run} test\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@v6\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@v6\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@v6\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@v6\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 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├── 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\\`\\`\\`\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 loadSkillEntriesForClaudeMd(\n options: Pick<CreateOptions, 'deploymentTarget' | 'skillsBundle'>,\n): Promise<{ name: string; description: string }[]> {\n const bundle = options.skillsBundle ?? 'recommended';\n if (bundle === 'none') return [];\n\n try {\n const catalogDir = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog');\n const manifestPath = path.join(catalogDir, 'skills-manifest.json');\n\n let manifestContent: string;\n if (await fileExists(manifestPath)) {\n manifestContent = await readFile(manifestPath);\n } else {\n const require_ = createRequire(__filename);\n const pkgManifest = require_.resolve('@frontmcp/skills/catalog/skills-manifest.json');\n manifestContent = await readFile(pkgManifest);\n }\n const manifest = JSON.parse(manifestContent) as SkillManifest;\n const target = options.deploymentTarget;\n return manifest.skills\n .filter((s) => {\n const targetMatch = s.targets.includes('all') || s.targets.includes(target);\n const bundleMatch = s.bundle?.includes(bundle);\n return targetMatch && bundleMatch;\n })\n .map((s) => ({ name: s.name, description: s.description }));\n } catch {\n return [];\n }\n}\n\nasync function scaffoldSkills(targetDir: string, options: CreateOptions): Promise<void> {\n const bundle = options.skillsBundle ?? 'recommended';\n if (bundle === 'none') return;\n\n let manifest: SkillManifest;\n try {\n const catalogDir = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog');\n const manifestPath = path.join(catalogDir, 'skills-manifest.json');\n\n // Try bundled catalog first, then fallback to @frontmcp/skills package\n let manifestContent: string;\n if (await fileExists(manifestPath)) {\n manifestContent = await readFile(manifestPath);\n } else {\n try {\n const require_ = createRequire(__filename);\n const pkgManifest = require_.resolve('@frontmcp/skills/catalog/skills-manifest.json');\n manifestContent = await readFile(pkgManifest);\n } catch {\n // Skills catalog not available — skip silently\n return;\n }\n }\n manifest = JSON.parse(manifestContent) as SkillManifest;\n } catch {\n return;\n }\n\n const target = options.deploymentTarget;\n\n // Filter skills by target and bundle\n const matchingSkills = manifest.skills.filter((s) => {\n const targetMatch = s.targets.includes('all') || s.targets.includes(target);\n const bundleMatch = s.bundle?.includes(bundle);\n return targetMatch && bundleMatch;\n });\n\n if (matchingSkills.length === 0) return;\n\n const skillsDir = path.join(targetDir, 'skills');\n\n for (const skill of matchingSkills) {\n const skillTargetDir = path.join(skillsDir, skill.name);\n await ensureDir(skillTargetDir);\n\n // Resolve source skill directory\n let sourceDir: string | undefined;\n const bundledSource = path.resolve(__dirname, '..', '..', '..', '..', 'skills', 'catalog', skill.path);\n if (await fileExists(path.join(bundledSource, 'SKILL.md'))) {\n sourceDir = bundledSource;\n } else {\n try {\n const require_ = createRequire(__filename);\n const pkgCatalog = path.dirname(require_.resolve('@frontmcp/skills/catalog/skills-manifest.json'));\n const pkgSource = path.join(pkgCatalog, skill.path);\n if (await fileExists(path.join(pkgSource, 'SKILL.md'))) {\n sourceDir = pkgSource;\n }\n } catch {\n // Package not available\n }\n }\n\n if (!sourceDir) continue;\n\n // Copy SKILL.md (binary-safe)\n const skillMdSrc = path.join(sourceDir, 'SKILL.md');\n if (await fileExists(skillMdSrc)) {\n await copyFile(skillMdSrc, path.join(skillTargetDir, 'SKILL.md'));\n }\n\n // Copy resource directories if present (binary-safe recursive copy)\n if (skill.hasResources) {\n for (const resDir of ['scripts', 'references', 'assets']) {\n const srcRes = path.join(sourceDir, resDir);\n if (await fileExists(srcRes)) {\n await cp(srcRes, path.join(skillTargetDir, resDir), { recursive: true });\n }\n }\n }\n\n console.log(c('green', `✓ added skill: ${skill.name}`));\n }\n\n console.log(c('gray', ` ${matchingSkills.length} skills added (bundle: ${bundle})`));\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 // Issue #400 — emit a starter frontmcp.config.ts so subsequent CLI runs\n // pick up entry / port / env / client snippets without re-typing them.\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'frontmcp.config.ts'),\n renderFrontmcpConfigTemplate(projectName, deploymentTarget),\n );\n\n // E2E scaffolding (jest config auto-generated by `frontmcp test`)\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'e2e', 'server.e2e.spec.ts'), TEMPLATE_E2E_TEST_TS);\n\n // Skills scaffolding\n await scaffoldSkills(targetDir, options);\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 // CLAUDE.md and AGENTS.md for AI coding assistants\n const skillEntries = await loadSkillEntriesForClaudeMd(options);\n await scaffoldFileIfMissing(\n targetDir,\n path.join(targetDir, 'CLAUDE.md'),\n generateClaudeMd(pkgName, packageManager, skillEntries),\n );\n await scaffoldFileIfMissing(targetDir, path.join(targetDir, 'AGENTS.md'), generateAgentsMd(pkgName, packageManager));\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 `, 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 };\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/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/helpers': '^0.5.20',\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 (flags?.skills) options.skillsBundle = flags.skills;\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"]}
|
package/src/core/tsconfig.d.ts
CHANGED
|
@@ -6,6 +6,14 @@ export declare const REQUIRED_DECORATOR_FIELDS: {
|
|
|
6
6
|
readonly strictFunctionTypes: true;
|
|
7
7
|
readonly moduleResolution: "node";
|
|
8
8
|
};
|
|
9
|
+
/**
|
|
10
|
+
* Filename suffixes for tool UI widget source files that ship to the browser.
|
|
11
|
+
* These are bundled separately by `@frontmcp/uipack` (esbuild) at render time,
|
|
12
|
+
* not by the server-side `tsc --noEmit` pass. We exclude them from the server
|
|
13
|
+
* typecheck so widget-only TS settings (`jsx`, React types) aren't required at
|
|
14
|
+
* the project level (issue #445).
|
|
15
|
+
*/
|
|
16
|
+
export declare const WIDGET_FILE_PATTERNS: readonly ["**/*.widget.tsx", "**/*.widget.jsx"];
|
|
9
17
|
export declare const RECOMMENDED_TSCONFIG: {
|
|
10
18
|
readonly compilerOptions: {
|
|
11
19
|
readonly target: "es2021";
|
|
@@ -24,9 +32,21 @@ export declare const RECOMMENDED_TSCONFIG: {
|
|
|
24
32
|
readonly types: readonly ["node", "@types/jest", "@frontmcp/testing"];
|
|
25
33
|
};
|
|
26
34
|
readonly include: readonly ["src/**/*"];
|
|
35
|
+
readonly exclude: readonly ["**/*.widget.tsx", "**/*.widget.jsx"];
|
|
27
36
|
};
|
|
28
37
|
export declare function deepMerge<T extends Record<string, any>, U extends Record<string, any>>(base: T, patch: U): T & U;
|
|
29
38
|
export declare function ensureRequiredTsOptions(obj: Record<string, any>): Record<string, any>;
|
|
39
|
+
/**
|
|
40
|
+
* Ensure `tsconfig.exclude` contains the widget-file glob patterns so server
|
|
41
|
+
* typecheck skips browser-side `.widget.tsx` / `.widget.jsx` files (issue #445).
|
|
42
|
+
*
|
|
43
|
+
* Preserves any existing exclude entries. Returns a new object — does not
|
|
44
|
+
* mutate `obj`.
|
|
45
|
+
*/
|
|
46
|
+
export declare function ensureWidgetExcludes(obj: Record<string, unknown>): {
|
|
47
|
+
result: Record<string, unknown>;
|
|
48
|
+
added: string[];
|
|
49
|
+
};
|
|
30
50
|
export declare function checkRequiredTsOptions(compilerOptions: Record<string, any> | undefined): {
|
|
31
51
|
ok: string[];
|
|
32
52
|
issues: string[];
|
package/src/core/tsconfig.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.RECOMMENDED_TSCONFIG = exports.REQUIRED_DECORATOR_FIELDS = void 0;
|
|
3
|
+
exports.RECOMMENDED_TSCONFIG = exports.WIDGET_FILE_PATTERNS = exports.REQUIRED_DECORATOR_FIELDS = void 0;
|
|
4
4
|
exports.deepMerge = deepMerge;
|
|
5
5
|
exports.ensureRequiredTsOptions = ensureRequiredTsOptions;
|
|
6
|
+
exports.ensureWidgetExcludes = ensureWidgetExcludes;
|
|
6
7
|
exports.checkRequiredTsOptions = checkRequiredTsOptions;
|
|
7
8
|
exports.runInit = runInit;
|
|
8
9
|
const tslib_1 = require("tslib");
|
|
9
10
|
const path = tslib_1.__importStar(require("path"));
|
|
10
|
-
const colors_1 = require("./colors");
|
|
11
11
|
const utils_1 = require("@frontmcp/utils");
|
|
12
|
+
const colors_1 = require("./colors");
|
|
12
13
|
exports.REQUIRED_DECORATOR_FIELDS = {
|
|
13
14
|
target: 'es2021',
|
|
14
15
|
module: 'esnext',
|
|
@@ -17,6 +18,14 @@ exports.REQUIRED_DECORATOR_FIELDS = {
|
|
|
17
18
|
strictFunctionTypes: true,
|
|
18
19
|
moduleResolution: 'node',
|
|
19
20
|
};
|
|
21
|
+
/**
|
|
22
|
+
* Filename suffixes for tool UI widget source files that ship to the browser.
|
|
23
|
+
* These are bundled separately by `@frontmcp/uipack` (esbuild) at render time,
|
|
24
|
+
* not by the server-side `tsc --noEmit` pass. We exclude them from the server
|
|
25
|
+
* typecheck so widget-only TS settings (`jsx`, React types) aren't required at
|
|
26
|
+
* the project level (issue #445).
|
|
27
|
+
*/
|
|
28
|
+
exports.WIDGET_FILE_PATTERNS = ['**/*.widget.tsx', '**/*.widget.jsx'];
|
|
20
29
|
exports.RECOMMENDED_TSCONFIG = {
|
|
21
30
|
compilerOptions: {
|
|
22
31
|
target: exports.REQUIRED_DECORATOR_FIELDS.target,
|
|
@@ -35,6 +44,7 @@ exports.RECOMMENDED_TSCONFIG = {
|
|
|
35
44
|
types: ['node', '@types/jest', '@frontmcp/testing'],
|
|
36
45
|
},
|
|
37
46
|
include: ['src/**/*'],
|
|
47
|
+
exclude: [...exports.WIDGET_FILE_PATTERNS],
|
|
38
48
|
};
|
|
39
49
|
function deepMerge(base, patch) {
|
|
40
50
|
const out = { ...base };
|
|
@@ -57,6 +67,28 @@ function ensureRequiredTsOptions(obj) {
|
|
|
57
67
|
next.compilerOptions.experimentalDecorators = exports.REQUIRED_DECORATOR_FIELDS.experimentalDecorators;
|
|
58
68
|
return next;
|
|
59
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Ensure `tsconfig.exclude` contains the widget-file glob patterns so server
|
|
72
|
+
* typecheck skips browser-side `.widget.tsx` / `.widget.jsx` files (issue #445).
|
|
73
|
+
*
|
|
74
|
+
* Preserves any existing exclude entries. Returns a new object — does not
|
|
75
|
+
* mutate `obj`.
|
|
76
|
+
*/
|
|
77
|
+
function ensureWidgetExcludes(obj) {
|
|
78
|
+
const next = { ...obj };
|
|
79
|
+
const rawExclude = next['exclude'];
|
|
80
|
+
const existing = Array.isArray(rawExclude) ? rawExclude : [];
|
|
81
|
+
const seen = new Set(existing.filter((v) => typeof v === 'string'));
|
|
82
|
+
const added = [];
|
|
83
|
+
for (const pattern of exports.WIDGET_FILE_PATTERNS) {
|
|
84
|
+
if (!seen.has(pattern)) {
|
|
85
|
+
seen.add(pattern);
|
|
86
|
+
added.push(pattern);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
next['exclude'] = [...existing.filter((v) => typeof v === 'string'), ...added];
|
|
90
|
+
return { result: next, added };
|
|
91
|
+
}
|
|
60
92
|
function normalizeStr(x) {
|
|
61
93
|
return typeof x === 'string' ? x.toLowerCase() : undefined;
|
|
62
94
|
}
|
|
@@ -97,7 +129,14 @@ async function runInit(baseDir) {
|
|
|
97
129
|
}
|
|
98
130
|
let merged = deepMerge(exports.RECOMMENDED_TSCONFIG, existing);
|
|
99
131
|
merged = ensureRequiredTsOptions(merged);
|
|
132
|
+
const { result: withWidgetExcludes, added: addedExcludes } = ensureWidgetExcludes(merged);
|
|
133
|
+
merged = withWidgetExcludes;
|
|
100
134
|
await (0, utils_1.writeJSON)(tsconfigPath, merged);
|
|
101
135
|
console.log((0, colors_1.c)('green', '✅ tsconfig.json verified and updated (required decorator settings enforced).'));
|
|
136
|
+
if (addedExcludes.length > 0) {
|
|
137
|
+
console.log((0, colors_1.c)('gray', ` Added widget-file excludes to tsconfig.exclude (${addedExcludes.join(', ')}) — ` +
|
|
138
|
+
`'.widget.tsx' / '.widget.jsx' files are bundled separately by uipack at render time ` +
|
|
139
|
+
`and don't need to satisfy the server typecheck (issue #445).`));
|
|
140
|
+
}
|
|
102
141
|
}
|
|
103
142
|
//# sourceMappingURL=tsconfig.js.map
|
package/src/core/tsconfig.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsconfig.js","sourceRoot":"","sources":["../../../src/core/tsconfig.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { c } from './colors';\nimport { fileExists, readJSON, writeJSON } from '@frontmcp/utils';\n\nexport const REQUIRED_DECORATOR_FIELDS = {\n target: 'es2021',\n module: 'esnext',\n emitDecoratorMetadata: true,\n experimentalDecorators: true,\n strictFunctionTypes: true,\n moduleResolution: 'node',\n} as const;\n\nexport const RECOMMENDED_TSCONFIG = {\n compilerOptions: {\n target: REQUIRED_DECORATOR_FIELDS.target,\n module: REQUIRED_DECORATOR_FIELDS.module,\n emitDecoratorMetadata: REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata,\n experimentalDecorators: REQUIRED_DECORATOR_FIELDS.experimentalDecorators,\n strictFunctionTypes: REQUIRED_DECORATOR_FIELDS.strictFunctionTypes,\n moduleResolution: REQUIRED_DECORATOR_FIELDS.moduleResolution,\n strict: true,\n esModuleInterop: true,\n resolveJsonModule: true,\n skipLibCheck: true,\n sourceMap: true,\n outDir: 'dist',\n rootDir: 'src',\n types: ['node', '@types/jest', '@frontmcp/testing'],\n },\n include: ['src/**/*'],\n} as const;\n\nexport function deepMerge<T extends Record<string, any>, U extends Record<string, any>>(base: T, patch: U): T & U {\n const out: Record<string, any> = { ...base };\n for (const [k, v] of Object.entries(patch)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n out[k] = deepMerge(base[k] ?? {}, v as Record<string, any>);\n } else {\n out[k] = v;\n }\n }\n return out as T & U;\n}\n\nexport function ensureRequiredTsOptions(obj: Record<string, any>): Record<string, any> {\n const next = { ...obj };\n next.compilerOptions = { ...(next.compilerOptions || {}) };\n next.compilerOptions.target = REQUIRED_DECORATOR_FIELDS.target;\n next.compilerOptions.module = REQUIRED_DECORATOR_FIELDS.module;\n next.compilerOptions.emitDecoratorMetadata = REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata;\n next.compilerOptions.experimentalDecorators = REQUIRED_DECORATOR_FIELDS.experimentalDecorators;\n return next;\n}\n\nfunction normalizeStr(x: unknown): string | undefined {\n return typeof x === 'string' ? x.toLowerCase() : undefined;\n}\n\nexport function checkRequiredTsOptions(compilerOptions: Record<string, any> | undefined) {\n const issues: string[] = [];\n const ok: string[] = [];\n\n const target = normalizeStr(compilerOptions?.target);\n const moduleVal = normalizeStr(compilerOptions?.module);\n const edm = compilerOptions?.emitDecoratorMetadata;\n const ed = compilerOptions?.experimentalDecorators;\n\n if (target === REQUIRED_DECORATOR_FIELDS.target)\n ok.push(`compilerOptions.target = \"${REQUIRED_DECORATOR_FIELDS.target}\"`);\n else issues.push(`compilerOptions.target should be \"${REQUIRED_DECORATOR_FIELDS.target}\"`);\n\n if (moduleVal === REQUIRED_DECORATOR_FIELDS.module)\n ok.push(`compilerOptions.module = \"${REQUIRED_DECORATOR_FIELDS.module}\"`);\n else issues.push(`compilerOptions.module should be \"${REQUIRED_DECORATOR_FIELDS.module}\"`);\n\n if (edm === REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata) ok.push(`compilerOptions.emitDecoratorMetadata = true`);\n else issues.push(`compilerOptions.emitDecoratorMetadata should be true`);\n\n if (ed === REQUIRED_DECORATOR_FIELDS.experimentalDecorators) ok.push(`compilerOptions.experimentalDecorators = true`);\n else issues.push(`compilerOptions.experimentalDecorators should be true`);\n\n return { ok, issues };\n}\n\nexport async function runInit(baseDir?: string): Promise<void> {\n const cwd = baseDir ?? process.cwd();\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const existing = await readJSON<Record<string, any>>(tsconfigPath);\n\n if (!existing) {\n console.log(c('yellow', `tsconfig.json not found — creating one in ${path.relative(process.cwd(), cwd) || '.'}.`));\n await writeJSON(tsconfigPath, RECOMMENDED_TSCONFIG);\n console.log(c('green', '✅ Created tsconfig.json with required decorator settings.'));\n return;\n }\n\n let merged = deepMerge(RECOMMENDED_TSCONFIG as any, existing);\n merged = ensureRequiredTsOptions(merged);\n\n await writeJSON(tsconfigPath, merged);\n console.log(c('green', '✅ tsconfig.json verified and updated (required decorator settings enforced).'));\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tsconfig.js","sourceRoot":"","sources":["../../../src/core/tsconfig.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\n\nimport { fileExists, readJSON, writeJSON } from '@frontmcp/utils';\n\nimport { c } from './colors';\n\nexport const REQUIRED_DECORATOR_FIELDS = {\n target: 'es2021',\n module: 'esnext',\n emitDecoratorMetadata: true,\n experimentalDecorators: true,\n strictFunctionTypes: true,\n moduleResolution: 'node',\n} as const;\n\n/**\n * Filename suffixes for tool UI widget source files that ship to the browser.\n * These are bundled separately by `@frontmcp/uipack` (esbuild) at render time,\n * not by the server-side `tsc --noEmit` pass. We exclude them from the server\n * typecheck so widget-only TS settings (`jsx`, React types) aren't required at\n * the project level (issue #445).\n */\nexport const WIDGET_FILE_PATTERNS = ['**/*.widget.tsx', '**/*.widget.jsx'] as const;\n\nexport const RECOMMENDED_TSCONFIG = {\n compilerOptions: {\n target: REQUIRED_DECORATOR_FIELDS.target,\n module: REQUIRED_DECORATOR_FIELDS.module,\n emitDecoratorMetadata: REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata,\n experimentalDecorators: REQUIRED_DECORATOR_FIELDS.experimentalDecorators,\n strictFunctionTypes: REQUIRED_DECORATOR_FIELDS.strictFunctionTypes,\n moduleResolution: REQUIRED_DECORATOR_FIELDS.moduleResolution,\n strict: true,\n esModuleInterop: true,\n resolveJsonModule: true,\n skipLibCheck: true,\n sourceMap: true,\n outDir: 'dist',\n rootDir: 'src',\n types: ['node', '@types/jest', '@frontmcp/testing'],\n },\n include: ['src/**/*'],\n exclude: [...WIDGET_FILE_PATTERNS],\n} as const;\n\nexport function deepMerge<T extends Record<string, any>, U extends Record<string, any>>(base: T, patch: U): T & U {\n const out: Record<string, any> = { ...base };\n for (const [k, v] of Object.entries(patch)) {\n if (v && typeof v === 'object' && !Array.isArray(v)) {\n out[k] = deepMerge(base[k] ?? {}, v as Record<string, any>);\n } else {\n out[k] = v;\n }\n }\n return out as T & U;\n}\n\nexport function ensureRequiredTsOptions(obj: Record<string, any>): Record<string, any> {\n const next = { ...obj };\n next.compilerOptions = { ...(next.compilerOptions || {}) };\n next.compilerOptions.target = REQUIRED_DECORATOR_FIELDS.target;\n next.compilerOptions.module = REQUIRED_DECORATOR_FIELDS.module;\n next.compilerOptions.emitDecoratorMetadata = REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata;\n next.compilerOptions.experimentalDecorators = REQUIRED_DECORATOR_FIELDS.experimentalDecorators;\n return next;\n}\n\n/**\n * Ensure `tsconfig.exclude` contains the widget-file glob patterns so server\n * typecheck skips browser-side `.widget.tsx` / `.widget.jsx` files (issue #445).\n *\n * Preserves any existing exclude entries. Returns a new object — does not\n * mutate `obj`.\n */\nexport function ensureWidgetExcludes(obj: Record<string, unknown>): {\n result: Record<string, unknown>;\n added: string[];\n} {\n const next: Record<string, unknown> = { ...obj };\n const rawExclude = next['exclude'];\n const existing: unknown[] = Array.isArray(rawExclude) ? rawExclude : [];\n const seen = new Set(existing.filter((v): v is string => typeof v === 'string'));\n const added: string[] = [];\n for (const pattern of WIDGET_FILE_PATTERNS) {\n if (!seen.has(pattern)) {\n seen.add(pattern);\n added.push(pattern);\n }\n }\n next['exclude'] = [...existing.filter((v): v is string => typeof v === 'string'), ...added];\n return { result: next, added };\n}\n\nfunction normalizeStr(x: unknown): string | undefined {\n return typeof x === 'string' ? x.toLowerCase() : undefined;\n}\n\nexport function checkRequiredTsOptions(compilerOptions: Record<string, any> | undefined) {\n const issues: string[] = [];\n const ok: string[] = [];\n\n const target = normalizeStr(compilerOptions?.target);\n const moduleVal = normalizeStr(compilerOptions?.module);\n const edm = compilerOptions?.emitDecoratorMetadata;\n const ed = compilerOptions?.experimentalDecorators;\n\n if (target === REQUIRED_DECORATOR_FIELDS.target)\n ok.push(`compilerOptions.target = \"${REQUIRED_DECORATOR_FIELDS.target}\"`);\n else issues.push(`compilerOptions.target should be \"${REQUIRED_DECORATOR_FIELDS.target}\"`);\n\n if (moduleVal === REQUIRED_DECORATOR_FIELDS.module)\n ok.push(`compilerOptions.module = \"${REQUIRED_DECORATOR_FIELDS.module}\"`);\n else issues.push(`compilerOptions.module should be \"${REQUIRED_DECORATOR_FIELDS.module}\"`);\n\n if (edm === REQUIRED_DECORATOR_FIELDS.emitDecoratorMetadata) ok.push(`compilerOptions.emitDecoratorMetadata = true`);\n else issues.push(`compilerOptions.emitDecoratorMetadata should be true`);\n\n if (ed === REQUIRED_DECORATOR_FIELDS.experimentalDecorators) ok.push(`compilerOptions.experimentalDecorators = true`);\n else issues.push(`compilerOptions.experimentalDecorators should be true`);\n\n return { ok, issues };\n}\n\nexport async function runInit(baseDir?: string): Promise<void> {\n const cwd = baseDir ?? process.cwd();\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n const existing = await readJSON<Record<string, any>>(tsconfigPath);\n\n if (!existing) {\n console.log(c('yellow', `tsconfig.json not found — creating one in ${path.relative(process.cwd(), cwd) || '.'}.`));\n await writeJSON(tsconfigPath, RECOMMENDED_TSCONFIG);\n console.log(c('green', '✅ Created tsconfig.json with required decorator settings.'));\n return;\n }\n\n let merged = deepMerge(RECOMMENDED_TSCONFIG as any, existing);\n merged = ensureRequiredTsOptions(merged);\n\n const { result: withWidgetExcludes, added: addedExcludes } = ensureWidgetExcludes(merged);\n merged = withWidgetExcludes;\n\n await writeJSON(tsconfigPath, merged);\n console.log(c('green', '✅ tsconfig.json verified and updated (required decorator settings enforced).'));\n if (addedExcludes.length > 0) {\n console.log(\n c(\n 'gray',\n ` Added widget-file excludes to tsconfig.exclude (${addedExcludes.join(', ')}) — ` +\n `'.widget.tsx' / '.widget.jsx' files are bundled separately by uipack at render time ` +\n `and don't need to satisfy the server typecheck (issue #445).`,\n ),\n );\n }\n}\n"]}
|