frontmcp 1.2.0 → 1.3.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/package.json +4 -4
- package/src/commands/build/exec/bin-meta.d.ts +49 -0
- package/src/commands/build/exec/bin-meta.js +68 -0
- package/src/commands/build/exec/bin-meta.js.map +1 -0
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +195 -3
- package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/plugin-emitter.d.ts +160 -0
- package/src/commands/build/exec/cli-runtime/plugin-emitter.js +512 -0
- package/src/commands/build/exec/cli-runtime/plugin-emitter.js.map +1 -0
- package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +13 -1
- package/src/commands/build/exec/cli-runtime/schema-extractor.js +29 -3
- package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -1
- package/src/commands/build/exec/cli-runtime/skill-md-compose.d.ts +25 -0
- package/src/commands/build/exec/cli-runtime/skill-md-compose.js +63 -0
- package/src/commands/build/exec/cli-runtime/skill-md-compose.js.map +1 -0
- package/src/commands/build/exec/index.js +26 -0
- package/src/commands/build/exec/index.js.map +1 -1
- package/src/commands/dev/bridge/child-supervisor.d.ts +48 -0
- package/src/commands/dev/bridge/child-supervisor.js +228 -0
- package/src/commands/dev/bridge/child-supervisor.js.map +1 -0
- package/src/commands/dev/bridge/errors.d.ts +23 -0
- package/src/commands/dev/bridge/errors.js +34 -0
- package/src/commands/dev/bridge/errors.js.map +1 -0
- package/src/commands/dev/bridge/index.d.ts +30 -0
- package/src/commands/dev/bridge/index.js +220 -0
- package/src/commands/dev/bridge/index.js.map +1 -0
- package/src/commands/dev/bridge/log.d.ts +29 -0
- package/src/commands/dev/bridge/log.js +82 -0
- package/src/commands/dev/bridge/log.js.map +1 -0
- package/src/commands/dev/bridge/state-machine.d.ts +56 -0
- package/src/commands/dev/bridge/state-machine.js +245 -0
- package/src/commands/dev/bridge/state-machine.js.map +1 -0
- package/src/commands/dev/bridge/stdio-framer.d.ts +47 -0
- package/src/commands/dev/bridge/stdio-framer.js +128 -0
- package/src/commands/dev/bridge/stdio-framer.js.map +1 -0
- package/src/commands/dev/bridge/upstream-client.d.ts +49 -0
- package/src/commands/dev/bridge/upstream-client.js +159 -0
- package/src/commands/dev/bridge/upstream-client.js.map +1 -0
- package/src/commands/dev/bridge/watcher.d.ts +30 -0
- package/src/commands/dev/bridge/watcher.js +87 -0
- package/src/commands/dev/bridge/watcher.js.map +1 -0
- package/src/commands/dev/dev.d.ts +18 -1
- package/src/commands/dev/dev.js +134 -14
- package/src/commands/dev/dev.js.map +1 -1
- package/src/commands/dev/inspector.d.ts +13 -1
- package/src/commands/dev/inspector.js +77 -3
- package/src/commands/dev/inspector.js.map +1 -1
- package/src/commands/dev/port.d.ts +23 -0
- package/src/commands/dev/port.js +87 -0
- package/src/commands/dev/port.js.map +1 -0
- package/src/commands/dev/register.d.ts +1 -1
- package/src/commands/dev/register.js +28 -4
- package/src/commands/dev/register.js.map +1 -1
- package/src/commands/dev/test.d.ts +26 -1
- package/src/commands/dev/test.js +181 -64
- package/src/commands/dev/test.js.map +1 -1
- package/src/commands/eject/mcp-client.d.ts +25 -0
- package/src/commands/eject/mcp-client.js +74 -0
- package/src/commands/eject/mcp-client.js.map +1 -0
- package/src/commands/eject/register.d.ts +9 -0
- package/src/commands/eject/register.js +56 -0
- package/src/commands/eject/register.js.map +1 -0
- package/src/commands/install/install-claude-plugin.d.ts +13 -0
- package/src/commands/install/install-claude-plugin.js +327 -0
- package/src/commands/install/install-claude-plugin.js.map +1 -0
- package/src/commands/install/register.d.ts +16 -0
- package/src/commands/install/register.js +70 -0
- package/src/commands/install/register.js.map +1 -0
- package/src/commands/scaffold/create.js +44 -0
- package/src/commands/scaffold/create.js.map +1 -1
- package/src/commands/skills/from-entry.d.ts +31 -0
- package/src/commands/skills/from-entry.js +68 -0
- package/src/commands/skills/from-entry.js.map +1 -0
- package/src/commands/skills/install.d.ts +12 -0
- package/src/commands/skills/install.js +173 -8
- package/src/commands/skills/install.js.map +1 -1
- package/src/commands/skills/register.js +7 -3
- package/src/commands/skills/register.js.map +1 -1
- package/src/config/frontmcp-config.loader.d.ts +28 -0
- package/src/config/frontmcp-config.loader.js +146 -67
- package/src/config/frontmcp-config.loader.js.map +1 -1
- package/src/config/frontmcp-config.resolve.d.ts +67 -0
- package/src/config/frontmcp-config.resolve.js +118 -0
- package/src/config/frontmcp-config.resolve.js.map +1 -0
- package/src/config/frontmcp-config.schema.d.ts +207 -0
- package/src/config/frontmcp-config.schema.js +217 -1
- package/src/config/frontmcp-config.schema.js.map +1 -1
- package/src/config/frontmcp-config.types.d.ts +133 -0
- package/src/config/frontmcp-config.types.js.map +1 -1
- package/src/config/index.d.ts +2 -1
- package/src/config/index.js +3 -1
- package/src/config/index.js.map +1 -1
- package/src/core/args.d.ts +13 -0
- package/src/core/args.js.map +1 -1
- package/src/core/bridge.js +39 -0
- package/src/core/bridge.js.map +1 -1
- package/src/core/cli.d.ts +0 -6
- package/src/core/cli.js +23 -3
- package/src/core/cli.js.map +1 -1
- package/src/core/help.d.ts +1 -1
- package/src/core/help.js +27 -6
- package/src/core/help.js.map +1 -1
- package/src/core/program.d.ts +1 -1
- package/src/core/program.js +56 -12
- package/src/core/program.js.map +1 -1
- package/src/core/project-commands.d.ts +44 -0
- package/src/core/project-commands.js +216 -0
- package/src/core/project-commands.js.map +1 -0
|
@@ -268,6 +268,127 @@ export interface McpbDeployment extends DeploymentBase {
|
|
|
268
268
|
deterministic?: boolean;
|
|
269
269
|
}
|
|
270
270
|
export type DeploymentTarget = NodeDeployment | DistributedDeployment | CliDeployment | VercelDeployment | LambdaDeployment | CloudflareDeployment | BrowserDeployment | SdkDeployment | McpbDeployment;
|
|
271
|
+
/** Positional argument for a project-defined command. */
|
|
272
|
+
export interface ProjectCommandArgument {
|
|
273
|
+
/** Argument name (kebab-case). Shown in --help. */
|
|
274
|
+
name: string;
|
|
275
|
+
/** Required (`<name>`) vs optional (`[name]`). @default false */
|
|
276
|
+
required?: boolean;
|
|
277
|
+
/** One-line description. */
|
|
278
|
+
description?: string;
|
|
279
|
+
/** Variadic (`<name...>`/`[name...]`). @default false */
|
|
280
|
+
variadic?: boolean;
|
|
281
|
+
}
|
|
282
|
+
/** Named option for a project-defined command. */
|
|
283
|
+
export interface ProjectCommandOption {
|
|
284
|
+
/** Commander flag spec, e.g. `-f, --force` or `-p, --port <num>`. */
|
|
285
|
+
flags: string;
|
|
286
|
+
/** One-line description. */
|
|
287
|
+
description?: string;
|
|
288
|
+
/** Default value forwarded to Commander. */
|
|
289
|
+
default?: string | number | boolean;
|
|
290
|
+
}
|
|
291
|
+
/** A single project-defined CLI command. */
|
|
292
|
+
export interface ProjectCommandEntry {
|
|
293
|
+
/** Path to the runner module (TS or JS), relative to project root. */
|
|
294
|
+
entry: string;
|
|
295
|
+
/** One-line description shown under "Project commands" in --help. */
|
|
296
|
+
description?: string;
|
|
297
|
+
/** Positional arguments. */
|
|
298
|
+
arguments?: ProjectCommandArgument[];
|
|
299
|
+
/** Named options. */
|
|
300
|
+
options?: ProjectCommandOption[];
|
|
301
|
+
/** Hide from --help. Verb is still invokable. @default false */
|
|
302
|
+
hidden?: boolean;
|
|
303
|
+
}
|
|
304
|
+
/** CLI extension block — see `cli.commands` in frontmcp.config. */
|
|
305
|
+
export interface CliExtensionConfig {
|
|
306
|
+
/**
|
|
307
|
+
* Map of verb name → command definition. Verb names may include `:`,
|
|
308
|
+
* `_`, and `-` (e.g. `project:init`, `db-migrate`). Reserved verbs (the
|
|
309
|
+
* built-in ones) are rejected at config-load time.
|
|
310
|
+
*/
|
|
311
|
+
commands?: Record<string, ProjectCommandEntry>;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Per-protocol defaults consumed by `dev` / `inspector` / `pm start` /
|
|
315
|
+
* `pm socket` so server-startup flags don't have to be re-typed on every
|
|
316
|
+
* CLI invocation.
|
|
317
|
+
*/
|
|
318
|
+
export interface TransportConfig {
|
|
319
|
+
/** Default protocol when no flag is set. */
|
|
320
|
+
default?: 'http' | 'sse' | 'stdio';
|
|
321
|
+
/** HTTP transport defaults — overridden by `--port` / per-deployment `server.http.port`. */
|
|
322
|
+
http?: {
|
|
323
|
+
/** Default HTTP port. */
|
|
324
|
+
port?: number;
|
|
325
|
+
/** Mount path (e.g., '/mcp'). */
|
|
326
|
+
path?: string;
|
|
327
|
+
/** Bind address. */
|
|
328
|
+
host?: string;
|
|
329
|
+
};
|
|
330
|
+
/** Stdio transport defaults — used by `inspector` to spawn the server. */
|
|
331
|
+
stdio?: {
|
|
332
|
+
command?: string;
|
|
333
|
+
args?: string[];
|
|
334
|
+
};
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Top-level env overlays. `shared` applies everywhere; mode-specific
|
|
338
|
+
* overlays (`dev`, `test`, `ship`) are merged on top of `shared`.
|
|
339
|
+
*
|
|
340
|
+
* Effective env = `shared` ⊕ `<mode>` (later wins). `.env` / `.env.local`
|
|
341
|
+
* files still load and take precedence over config overlays (parity with
|
|
342
|
+
* existing `dev` behavior).
|
|
343
|
+
*/
|
|
344
|
+
export interface EnvOverlays {
|
|
345
|
+
shared?: Record<string, string>;
|
|
346
|
+
dev?: Record<string, string>;
|
|
347
|
+
test?: Record<string, string>;
|
|
348
|
+
ship?: Record<string, string>;
|
|
349
|
+
}
|
|
350
|
+
export type McpClientName = 'claude-code' | 'claude-desktop' | 'cursor' | 'windsurf' | 'vscode';
|
|
351
|
+
export interface ClientConnection {
|
|
352
|
+
/** Display name. Defaults to the top-level `name` field. */
|
|
353
|
+
name?: string;
|
|
354
|
+
/** Transport protocol. */
|
|
355
|
+
transport: 'http' | 'sse' | 'stdio';
|
|
356
|
+
/** Spawn command (for `stdio` transport). */
|
|
357
|
+
command?: string;
|
|
358
|
+
/** Spawn args (for `stdio` transport). */
|
|
359
|
+
args?: string[];
|
|
360
|
+
/** Env vars to set on the spawned client. */
|
|
361
|
+
env?: Record<string, string>;
|
|
362
|
+
/** Server URL (for `http` / `sse` transport). */
|
|
363
|
+
url?: string;
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Per-client connection descriptors consumed by `frontmcp eject-mcp-config
|
|
367
|
+
* <client>` to emit ready-to-paste `.mcp.json` /
|
|
368
|
+
* `claude_desktop_config.json` / Cursor / Windsurf / VS Code snippets.
|
|
369
|
+
*/
|
|
370
|
+
export type ClientsConfig = Partial<Record<McpClientName, ClientConnection>>;
|
|
371
|
+
/**
|
|
372
|
+
* `frontmcp test` defaults. CLI flags (`--timeout`, `--runInBand`,
|
|
373
|
+
* `--coverage`, positional test patterns) override these.
|
|
374
|
+
*/
|
|
375
|
+
export interface TestConfig {
|
|
376
|
+
timeoutMs?: number;
|
|
377
|
+
runInBand?: boolean;
|
|
378
|
+
testMatch?: string[];
|
|
379
|
+
coverage?: boolean;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* `frontmcp skills install` / `export` defaults. `install` is the list of
|
|
383
|
+
* catalog skill names a project depends on so `frontmcp skills install`
|
|
384
|
+
* with no arguments installs the curated set.
|
|
385
|
+
*/
|
|
386
|
+
export interface SkillsCliConfig {
|
|
387
|
+
provider?: 'claude' | 'codex';
|
|
388
|
+
bundle?: 'recommended' | 'minimal' | 'full' | 'none';
|
|
389
|
+
install?: string[];
|
|
390
|
+
exportTarget?: 'cursor' | 'windsurf' | 'copilot';
|
|
391
|
+
}
|
|
271
392
|
export interface FrontMcpConfig {
|
|
272
393
|
/** JSON Schema pointer for IDE autocomplete. */
|
|
273
394
|
$schema?: string;
|
|
@@ -283,5 +404,17 @@ export interface FrontMcpConfig {
|
|
|
283
404
|
deployments: DeploymentTarget[];
|
|
284
405
|
/** Build/bundler options. */
|
|
285
406
|
build?: BuildOptions;
|
|
407
|
+
/** Project-defined CLI extensions (issue #409). */
|
|
408
|
+
cli?: CliExtensionConfig;
|
|
409
|
+
/** Transport defaults consumed by `dev` / `inspector` / `pm start` / `pm socket`. */
|
|
410
|
+
transport?: TransportConfig;
|
|
411
|
+
/** Env overlays merged in addition to `.env` / `.env.local`. */
|
|
412
|
+
env?: EnvOverlays;
|
|
413
|
+
/** Per-client snippets emitted by `frontmcp eject-mcp-config <client>`. */
|
|
414
|
+
clients?: ClientsConfig;
|
|
415
|
+
/** `frontmcp test` defaults overridden by CLI flags. */
|
|
416
|
+
test?: TestConfig;
|
|
417
|
+
/** `frontmcp skills install` / `export` defaults. */
|
|
418
|
+
skills?: SkillsCliConfig;
|
|
286
419
|
}
|
|
287
420
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmcp-config.types.js","sourceRoot":"","sources":["../../../src/config/frontmcp-config.types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG","sourcesContent":["/**\n * FrontMCP Configuration Types\n *\n * Defines the unified deployment configuration schema.\n * Used by `frontmcp.config.(json|yml|js|ts)` files.\n *\n * Separation of concerns:\n * - frontmcp.config = deployment (targets, server defaults, cookies, CSP)\n * - @FrontMcp() = runtime (auth, tools, resources, transport)\n * - Environment variables = secrets/overrides (Redis password, API keys)\n */\n\n// ============================================\n// Server Defaults\n// ============================================\n\nexport interface CorsConfig {\n /** Allowed origins. Empty array = permissive. */\n origins?: string[];\n /** Allow credentials (cookies, authorization headers). @default false */\n credentials?: boolean;\n /** Preflight cache max age in seconds. */\n maxAge?: number;\n}\n\nexport interface CspConfig {\n /** Enable CSP headers. @default false */\n enabled?: boolean;\n /** CSP directives (e.g., 'default-src': \"'self'\"). */\n directives?: Record<string, string | string[]>;\n /** Report URI for CSP violations. */\n reportUri?: string;\n /** Use Content-Security-Policy-Report-Only instead. @default false */\n reportOnly?: boolean;\n}\n\nexport interface CookiesConfig {\n /** LB affinity cookie name. @default '__frontmcp_node' */\n affinity?: string;\n /** Cookie domain. */\n domain?: string;\n /** SameSite policy. @default 'Strict' */\n sameSite?: 'Strict' | 'Lax' | 'None';\n}\n\nexport interface SecurityHeadersConfig {\n /** Strict-Transport-Security. Set to false to disable. */\n hsts?: string | false;\n /** X-Content-Type-Options. Set to false to disable. @default 'nosniff' */\n contentTypeOptions?: string | false;\n /** X-Frame-Options. Set to false to disable. @default 'DENY' */\n frameOptions?: string | false;\n /** Custom response headers. */\n custom?: Record<string, string>;\n}\n\n/**\n * HTTP options — aligns with `@FrontMcp({ http })`.\n *\n * Available on targets that serve HTTP:\n * - node, distributed: full (port + cors)\n * - vercel, lambda, cloudflare: no port (platform-managed), but cors applies\n * - browser, sdk, cli: not available\n */\nexport interface HttpConfig {\n /** HTTP port. Only for node/distributed. @default 3000 */\n port?: number;\n /** Unix socket path (alternative to port). Only for node/distributed. */\n socketPath?: string;\n /** MCP entry path ('' or '/mcp'). @default '' */\n entryPath?: string;\n /** CORS configuration. */\n cors?: CorsConfig;\n}\n\n/**\n * Server-level options for targets that handle HTTP responses.\n * Separated from HttpConfig because these apply even to serverless\n * targets that don't control the port (Cloudflare, Vercel, Lambda).\n */\nexport interface ServerDefaults {\n /** HTTP configuration (port, cors). */\n http?: HttpConfig;\n /** Content Security Policy. */\n csp?: CspConfig;\n /** Cookie configuration. */\n cookies?: CookiesConfig;\n /** Security headers. */\n headers?: SecurityHeadersConfig;\n}\n\n// ============================================\n// Build Options\n// ============================================\n\nexport interface EsbuildOptions {\n /** Dependencies to exclude from bundle. */\n external?: string[];\n /** Global defines. */\n define?: Record<string, string>;\n /** Build target (e.g., 'node22'). */\n target?: string;\n /** Minify output. */\n minify?: boolean;\n}\n\nexport interface BuildOptions {\n /** esbuild/bundler options. */\n esbuild?: EsbuildOptions;\n /** System/native dependencies for CLI packaging. */\n dependencies?: {\n system?: string[];\n nativeAddons?: string[];\n };\n /** Storage type for CLI setup. */\n storage?: {\n type: 'sqlite' | 'redis' | 'none';\n required?: boolean;\n };\n /** Network defaults. */\n network?: {\n defaultPort?: number;\n supportsSocket?: boolean;\n };\n}\n\n// ============================================\n// HA Configuration (distributed target only)\n// ============================================\n\nexport interface HaDeploymentConfig {\n /** Heartbeat interval in ms. @default 10000 */\n heartbeatIntervalMs?: number;\n /** Heartbeat TTL in ms (should be 2-3x interval). @default 30000 */\n heartbeatTtlMs?: number;\n /** Grace period before claiming orphaned sessions. @default 5000 */\n takeoverGracePeriodMs?: number;\n /** Redis key prefix for HA keys. @default 'mcp:ha:' */\n redisKeyPrefix?: string;\n}\n\n// ============================================\n// CLI Configuration (cli target only)\n// ============================================\n\nexport interface CliTargetConfig {\n /** CLI description. */\n description?: string;\n /** Default output format. @default 'text' */\n outputDefault?: 'text' | 'json';\n /** Require authentication for CLI. */\n authRequired?: boolean;\n /** Tools to exclude from CLI. */\n excludeTools?: string[];\n /** OAuth configuration for CLI authentication. */\n oauth?: {\n serverUrl?: string;\n clientId?: string;\n defaultScope?: string;\n portRange?: [number, number];\n };\n}\n\n// ============================================\n// Wrangler Configuration (cloudflare target only)\n// ============================================\n\nexport interface WranglerConfig {\n /** Worker name. */\n name?: string;\n /** Compatibility date. */\n compatibilityDate?: string;\n}\n\n// ============================================\n// Deployment Targets\n// ============================================\n\nexport type DeploymentTargetType =\n | 'node'\n | 'distributed'\n | 'cli'\n | 'vercel'\n | 'lambda'\n | 'cloudflare'\n | 'browser'\n | 'sdk'\n | 'mcpb';\n\ninterface DeploymentBase {\n /** Deployment target type. */\n target: DeploymentTargetType;\n /** Output directory override. @default 'dist/{target}' */\n outDir?: string;\n /** Environment variables injected at build time. */\n env?: Record<string, string>;\n}\n\nexport interface NodeDeployment extends DeploymentBase {\n target: 'node';\n /** Server config (http with port, csp, cookies, headers). */\n server?: ServerDefaults;\n}\n\nexport interface DistributedDeployment extends DeploymentBase {\n target: 'distributed';\n /** Server config (http with port, csp, cookies, headers). */\n server?: ServerDefaults;\n /** HA configuration. */\n ha?: HaDeploymentConfig;\n}\n\nexport interface CliDeployment extends DeploymentBase {\n target: 'cli';\n /** Output JS bundle instead of native binary. */\n js?: boolean;\n /** CLI-specific configuration. */\n cli?: CliTargetConfig;\n /** Single Executable Application settings. */\n sea?: { enabled?: boolean };\n}\n\nexport interface VercelDeployment extends DeploymentBase {\n target: 'vercel';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n}\n\nexport interface LambdaDeployment extends DeploymentBase {\n target: 'lambda';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n}\n\nexport interface CloudflareDeployment extends DeploymentBase {\n target: 'cloudflare';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n /** Wrangler configuration. */\n wrangler?: WranglerConfig;\n}\n\nexport interface BrowserDeployment extends DeploymentBase {\n target: 'browser';\n /** No server — browser bundles are client-side. */\n}\n\nexport interface SdkDeployment extends DeploymentBase {\n target: 'sdk';\n /** No server — SDK is a library. */\n}\n\n// ============================================\n// MCPB Deployment (MCP Bundle)\n// ============================================\n\nexport interface McpbAuthor {\n name: string;\n email?: string;\n url?: string;\n}\n\nexport type McpbUserConfigType = 'string' | 'number' | 'boolean' | 'directory' | 'file';\n\nexport interface McpbUserConfigEntry {\n type: McpbUserConfigType;\n title: string;\n description?: string;\n required?: boolean;\n default?: string | number | boolean;\n multiple?: boolean;\n sensitive?: boolean;\n min?: number;\n max?: number;\n}\n\nexport interface McpbCompatibility {\n /** Semver range for Claude Desktop (e.g., \">=1.0.0\"). */\n claude_desktop?: string;\n /** Supported platforms. */\n platforms?: Array<'darwin' | 'win32' | 'linux'>;\n /** Runtime version constraints. */\n runtimes?: {\n node?: string;\n python?: string;\n };\n}\n\nexport type McpbRepository = string | { type: string; url: string };\n\nexport interface McpbDeployment extends DeploymentBase {\n target: 'mcpb';\n /** Human-friendly display name. */\n displayName?: string;\n /** Long markdown description. */\n longDescription?: string;\n /** Author object — overrides parsed package.json.author. */\n author?: McpbAuthor;\n /** SPDX license identifier — overrides package.json.license. */\n license?: string;\n /** Project homepage URL. */\n homepage?: string;\n /** Source repository. */\n repository?: McpbRepository;\n /** Documentation URL. */\n documentation?: string;\n /** Support URL (issues/contact). */\n support?: string;\n /** Path to icon (PNG) relative to project root. */\n icon?: string;\n /** Keywords for search. */\n keywords?: string[];\n /** Privacy policy URLs. */\n privacyPolicies?: string[];\n /** Runtime/platform compatibility constraints. */\n compatibility?: McpbCompatibility;\n /** User-configurable inputs (injected as env vars). */\n userConfig?: Record<string, McpbUserConfigEntry>;\n /** Single-executable binary integration. */\n sea?: {\n /** Build SEA binary for host platform. */\n enabled?: boolean;\n /** Directory of pre-built cross-platform SEA binaries to merge. */\n mergeFrom?: string;\n };\n /** Include node_modules/ in archive (opt-in). */\n includeNodeModules?: boolean;\n /** Deterministic archive output. @default true */\n deterministic?: boolean;\n}\n\nexport type DeploymentTarget =\n | NodeDeployment\n | DistributedDeployment\n | CliDeployment\n | VercelDeployment\n | LambdaDeployment\n | CloudflareDeployment\n | BrowserDeployment\n | SdkDeployment\n | McpbDeployment;\n\n// ============================================\n// Top-Level Config\n// ============================================\n\nexport interface FrontMcpConfig {\n /** JSON Schema pointer for IDE autocomplete. */\n $schema?: string;\n /** Server name (alphanumeric, .-_ allowed). */\n name: string;\n /** Server version (semver). @default '1.0.0' */\n version?: string;\n /** Entry point file path. */\n entry?: string;\n /** Node.js version requirement. @default '>=22.0.0' */\n nodeVersion?: string;\n /** Build targets — server config lives inside each target that needs it. */\n deployments: DeploymentTarget[];\n /** Build/bundler options. */\n build?: BuildOptions;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"frontmcp-config.types.js","sourceRoot":"","sources":["../../../src/config/frontmcp-config.types.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;GAUG","sourcesContent":["/**\n * FrontMCP Configuration Types\n *\n * Defines the unified deployment configuration schema.\n * Used by `frontmcp.config.(json|yml|js|ts)` files.\n *\n * Separation of concerns:\n * - frontmcp.config = deployment (targets, server defaults, cookies, CSP)\n * - @FrontMcp() = runtime (auth, tools, resources, transport)\n * - Environment variables = secrets/overrides (Redis password, API keys)\n */\n\n// ============================================\n// Server Defaults\n// ============================================\n\nexport interface CorsConfig {\n /** Allowed origins. Empty array = permissive. */\n origins?: string[];\n /** Allow credentials (cookies, authorization headers). @default false */\n credentials?: boolean;\n /** Preflight cache max age in seconds. */\n maxAge?: number;\n}\n\nexport interface CspConfig {\n /** Enable CSP headers. @default false */\n enabled?: boolean;\n /** CSP directives (e.g., 'default-src': \"'self'\"). */\n directives?: Record<string, string | string[]>;\n /** Report URI for CSP violations. */\n reportUri?: string;\n /** Use Content-Security-Policy-Report-Only instead. @default false */\n reportOnly?: boolean;\n}\n\nexport interface CookiesConfig {\n /** LB affinity cookie name. @default '__frontmcp_node' */\n affinity?: string;\n /** Cookie domain. */\n domain?: string;\n /** SameSite policy. @default 'Strict' */\n sameSite?: 'Strict' | 'Lax' | 'None';\n}\n\nexport interface SecurityHeadersConfig {\n /** Strict-Transport-Security. Set to false to disable. */\n hsts?: string | false;\n /** X-Content-Type-Options. Set to false to disable. @default 'nosniff' */\n contentTypeOptions?: string | false;\n /** X-Frame-Options. Set to false to disable. @default 'DENY' */\n frameOptions?: string | false;\n /** Custom response headers. */\n custom?: Record<string, string>;\n}\n\n/**\n * HTTP options — aligns with `@FrontMcp({ http })`.\n *\n * Available on targets that serve HTTP:\n * - node, distributed: full (port + cors)\n * - vercel, lambda, cloudflare: no port (platform-managed), but cors applies\n * - browser, sdk, cli: not available\n */\nexport interface HttpConfig {\n /** HTTP port. Only for node/distributed. @default 3000 */\n port?: number;\n /** Unix socket path (alternative to port). Only for node/distributed. */\n socketPath?: string;\n /** MCP entry path ('' or '/mcp'). @default '' */\n entryPath?: string;\n /** CORS configuration. */\n cors?: CorsConfig;\n}\n\n/**\n * Server-level options for targets that handle HTTP responses.\n * Separated from HttpConfig because these apply even to serverless\n * targets that don't control the port (Cloudflare, Vercel, Lambda).\n */\nexport interface ServerDefaults {\n /** HTTP configuration (port, cors). */\n http?: HttpConfig;\n /** Content Security Policy. */\n csp?: CspConfig;\n /** Cookie configuration. */\n cookies?: CookiesConfig;\n /** Security headers. */\n headers?: SecurityHeadersConfig;\n}\n\n// ============================================\n// Build Options\n// ============================================\n\nexport interface EsbuildOptions {\n /** Dependencies to exclude from bundle. */\n external?: string[];\n /** Global defines. */\n define?: Record<string, string>;\n /** Build target (e.g., 'node22'). */\n target?: string;\n /** Minify output. */\n minify?: boolean;\n}\n\nexport interface BuildOptions {\n /** esbuild/bundler options. */\n esbuild?: EsbuildOptions;\n /** System/native dependencies for CLI packaging. */\n dependencies?: {\n system?: string[];\n nativeAddons?: string[];\n };\n /** Storage type for CLI setup. */\n storage?: {\n type: 'sqlite' | 'redis' | 'none';\n required?: boolean;\n };\n /** Network defaults. */\n network?: {\n defaultPort?: number;\n supportsSocket?: boolean;\n };\n}\n\n// ============================================\n// HA Configuration (distributed target only)\n// ============================================\n\nexport interface HaDeploymentConfig {\n /** Heartbeat interval in ms. @default 10000 */\n heartbeatIntervalMs?: number;\n /** Heartbeat TTL in ms (should be 2-3x interval). @default 30000 */\n heartbeatTtlMs?: number;\n /** Grace period before claiming orphaned sessions. @default 5000 */\n takeoverGracePeriodMs?: number;\n /** Redis key prefix for HA keys. @default 'mcp:ha:' */\n redisKeyPrefix?: string;\n}\n\n// ============================================\n// CLI Configuration (cli target only)\n// ============================================\n\nexport interface CliTargetConfig {\n /** CLI description. */\n description?: string;\n /** Default output format. @default 'text' */\n outputDefault?: 'text' | 'json';\n /** Require authentication for CLI. */\n authRequired?: boolean;\n /** Tools to exclude from CLI. */\n excludeTools?: string[];\n /** OAuth configuration for CLI authentication. */\n oauth?: {\n serverUrl?: string;\n clientId?: string;\n defaultScope?: string;\n portRange?: [number, number];\n };\n}\n\n// ============================================\n// Wrangler Configuration (cloudflare target only)\n// ============================================\n\nexport interface WranglerConfig {\n /** Worker name. */\n name?: string;\n /** Compatibility date. */\n compatibilityDate?: string;\n}\n\n// ============================================\n// Deployment Targets\n// ============================================\n\nexport type DeploymentTargetType =\n | 'node'\n | 'distributed'\n | 'cli'\n | 'vercel'\n | 'lambda'\n | 'cloudflare'\n | 'browser'\n | 'sdk'\n | 'mcpb';\n\ninterface DeploymentBase {\n /** Deployment target type. */\n target: DeploymentTargetType;\n /** Output directory override. @default 'dist/{target}' */\n outDir?: string;\n /** Environment variables injected at build time. */\n env?: Record<string, string>;\n}\n\nexport interface NodeDeployment extends DeploymentBase {\n target: 'node';\n /** Server config (http with port, csp, cookies, headers). */\n server?: ServerDefaults;\n}\n\nexport interface DistributedDeployment extends DeploymentBase {\n target: 'distributed';\n /** Server config (http with port, csp, cookies, headers). */\n server?: ServerDefaults;\n /** HA configuration. */\n ha?: HaDeploymentConfig;\n}\n\nexport interface CliDeployment extends DeploymentBase {\n target: 'cli';\n /** Output JS bundle instead of native binary. */\n js?: boolean;\n /** CLI-specific configuration. */\n cli?: CliTargetConfig;\n /** Single Executable Application settings. */\n sea?: { enabled?: boolean };\n}\n\nexport interface VercelDeployment extends DeploymentBase {\n target: 'vercel';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n}\n\nexport interface LambdaDeployment extends DeploymentBase {\n target: 'lambda';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n}\n\nexport interface CloudflareDeployment extends DeploymentBase {\n target: 'cloudflare';\n /** Server config (no port — platform-managed, but cors/csp/cookies apply). */\n server?: ServerDefaults;\n /** Wrangler configuration. */\n wrangler?: WranglerConfig;\n}\n\nexport interface BrowserDeployment extends DeploymentBase {\n target: 'browser';\n /** No server — browser bundles are client-side. */\n}\n\nexport interface SdkDeployment extends DeploymentBase {\n target: 'sdk';\n /** No server — SDK is a library. */\n}\n\n// ============================================\n// MCPB Deployment (MCP Bundle)\n// ============================================\n\nexport interface McpbAuthor {\n name: string;\n email?: string;\n url?: string;\n}\n\nexport type McpbUserConfigType = 'string' | 'number' | 'boolean' | 'directory' | 'file';\n\nexport interface McpbUserConfigEntry {\n type: McpbUserConfigType;\n title: string;\n description?: string;\n required?: boolean;\n default?: string | number | boolean;\n multiple?: boolean;\n sensitive?: boolean;\n min?: number;\n max?: number;\n}\n\nexport interface McpbCompatibility {\n /** Semver range for Claude Desktop (e.g., \">=1.0.0\"). */\n claude_desktop?: string;\n /** Supported platforms. */\n platforms?: Array<'darwin' | 'win32' | 'linux'>;\n /** Runtime version constraints. */\n runtimes?: {\n node?: string;\n python?: string;\n };\n}\n\nexport type McpbRepository = string | { type: string; url: string };\n\nexport interface McpbDeployment extends DeploymentBase {\n target: 'mcpb';\n /** Human-friendly display name. */\n displayName?: string;\n /** Long markdown description. */\n longDescription?: string;\n /** Author object — overrides parsed package.json.author. */\n author?: McpbAuthor;\n /** SPDX license identifier — overrides package.json.license. */\n license?: string;\n /** Project homepage URL. */\n homepage?: string;\n /** Source repository. */\n repository?: McpbRepository;\n /** Documentation URL. */\n documentation?: string;\n /** Support URL (issues/contact). */\n support?: string;\n /** Path to icon (PNG) relative to project root. */\n icon?: string;\n /** Keywords for search. */\n keywords?: string[];\n /** Privacy policy URLs. */\n privacyPolicies?: string[];\n /** Runtime/platform compatibility constraints. */\n compatibility?: McpbCompatibility;\n /** User-configurable inputs (injected as env vars). */\n userConfig?: Record<string, McpbUserConfigEntry>;\n /** Single-executable binary integration. */\n sea?: {\n /** Build SEA binary for host platform. */\n enabled?: boolean;\n /** Directory of pre-built cross-platform SEA binaries to merge. */\n mergeFrom?: string;\n };\n /** Include node_modules/ in archive (opt-in). */\n includeNodeModules?: boolean;\n /** Deterministic archive output. @default true */\n deterministic?: boolean;\n}\n\nexport type DeploymentTarget =\n | NodeDeployment\n | DistributedDeployment\n | CliDeployment\n | VercelDeployment\n | LambdaDeployment\n | CloudflareDeployment\n | BrowserDeployment\n | SdkDeployment\n | McpbDeployment;\n\n// ============================================\n// CLI extension (issue #409)\n// ============================================\n\n/** Positional argument for a project-defined command. */\nexport interface ProjectCommandArgument {\n /** Argument name (kebab-case). Shown in --help. */\n name: string;\n /** Required (`<name>`) vs optional (`[name]`). @default false */\n required?: boolean;\n /** One-line description. */\n description?: string;\n /** Variadic (`<name...>`/`[name...]`). @default false */\n variadic?: boolean;\n}\n\n/** Named option for a project-defined command. */\nexport interface ProjectCommandOption {\n /** Commander flag spec, e.g. `-f, --force` or `-p, --port <num>`. */\n flags: string;\n /** One-line description. */\n description?: string;\n /** Default value forwarded to Commander. */\n default?: string | number | boolean;\n}\n\n/** A single project-defined CLI command. */\nexport interface ProjectCommandEntry {\n /** Path to the runner module (TS or JS), relative to project root. */\n entry: string;\n /** One-line description shown under \"Project commands\" in --help. */\n description?: string;\n /** Positional arguments. */\n arguments?: ProjectCommandArgument[];\n /** Named options. */\n options?: ProjectCommandOption[];\n /** Hide from --help. Verb is still invokable. @default false */\n hidden?: boolean;\n}\n\n/** CLI extension block — see `cli.commands` in frontmcp.config. */\nexport interface CliExtensionConfig {\n /**\n * Map of verb name → command definition. Verb names may include `:`,\n * `_`, and `-` (e.g. `project:init`, `db-migrate`). Reserved verbs (the\n * built-in ones) are rejected at config-load time.\n */\n commands?: Record<string, ProjectCommandEntry>;\n}\n\n// ============================================\n// Top-Level Config\n// ============================================\n\n// ============================================\n// Transport defaults (issue #400)\n// ============================================\n\n/**\n * Per-protocol defaults consumed by `dev` / `inspector` / `pm start` /\n * `pm socket` so server-startup flags don't have to be re-typed on every\n * CLI invocation.\n */\nexport interface TransportConfig {\n /** Default protocol when no flag is set. */\n default?: 'http' | 'sse' | 'stdio';\n /** HTTP transport defaults — overridden by `--port` / per-deployment `server.http.port`. */\n http?: {\n /** Default HTTP port. */\n port?: number;\n /** Mount path (e.g., '/mcp'). */\n path?: string;\n /** Bind address. */\n host?: string;\n };\n /** Stdio transport defaults — used by `inspector` to spawn the server. */\n stdio?: {\n command?: string;\n args?: string[];\n };\n}\n\n// ============================================\n// Env overlays (issue #400)\n// ============================================\n\n/**\n * Top-level env overlays. `shared` applies everywhere; mode-specific\n * overlays (`dev`, `test`, `ship`) are merged on top of `shared`.\n *\n * Effective env = `shared` ⊕ `<mode>` (later wins). `.env` / `.env.local`\n * files still load and take precedence over config overlays (parity with\n * existing `dev` behavior).\n */\nexport interface EnvOverlays {\n shared?: Record<string, string>;\n dev?: Record<string, string>;\n test?: Record<string, string>;\n ship?: Record<string, string>;\n}\n\n// ============================================\n// MCP client connection snippets (issue #400)\n// ============================================\n\nexport type McpClientName = 'claude-code' | 'claude-desktop' | 'cursor' | 'windsurf' | 'vscode';\n\nexport interface ClientConnection {\n /** Display name. Defaults to the top-level `name` field. */\n name?: string;\n /** Transport protocol. */\n transport: 'http' | 'sse' | 'stdio';\n /** Spawn command (for `stdio` transport). */\n command?: string;\n /** Spawn args (for `stdio` transport). */\n args?: string[];\n /** Env vars to set on the spawned client. */\n env?: Record<string, string>;\n /** Server URL (for `http` / `sse` transport). */\n url?: string;\n}\n\n/**\n * Per-client connection descriptors consumed by `frontmcp eject-mcp-config\n * <client>` to emit ready-to-paste `.mcp.json` /\n * `claude_desktop_config.json` / Cursor / Windsurf / VS Code snippets.\n */\nexport type ClientsConfig = Partial<Record<McpClientName, ClientConnection>>;\n\n// ============================================\n// Test runner defaults (issue #400)\n// ============================================\n\n/**\n * `frontmcp test` defaults. CLI flags (`--timeout`, `--runInBand`,\n * `--coverage`, positional test patterns) override these.\n */\nexport interface TestConfig {\n timeoutMs?: number;\n runInBand?: boolean;\n testMatch?: string[];\n coverage?: boolean;\n}\n\n// ============================================\n// Skills install / export defaults (issue #400)\n// ============================================\n\n/**\n * `frontmcp skills install` / `export` defaults. `install` is the list of\n * catalog skill names a project depends on so `frontmcp skills install`\n * with no arguments installs the curated set.\n */\nexport interface SkillsCliConfig {\n provider?: 'claude' | 'codex';\n bundle?: 'recommended' | 'minimal' | 'full' | 'none';\n install?: string[];\n exportTarget?: 'cursor' | 'windsurf' | 'copilot';\n}\n\n// ============================================\n// Top-level config\n// ============================================\n\nexport interface FrontMcpConfig {\n /** JSON Schema pointer for IDE autocomplete. */\n $schema?: string;\n /** Server name (alphanumeric, .-_ allowed). */\n name: string;\n /** Server version (semver). @default '1.0.0' */\n version?: string;\n /** Entry point file path. */\n entry?: string;\n /** Node.js version requirement. @default '>=22.0.0' */\n nodeVersion?: string;\n /** Build targets — server config lives inside each target that needs it. */\n deployments: DeploymentTarget[];\n /** Build/bundler options. */\n build?: BuildOptions;\n /** Project-defined CLI extensions (issue #409). */\n cli?: CliExtensionConfig;\n\n // Issue #400 — config drives every command, not just `build`\n /** Transport defaults consumed by `dev` / `inspector` / `pm start` / `pm socket`. */\n transport?: TransportConfig;\n /** Env overlays merged in addition to `.env` / `.env.local`. */\n env?: EnvOverlays;\n /** Per-client snippets emitted by `frontmcp eject-mcp-config <client>`. */\n clients?: ClientsConfig;\n /** `frontmcp test` defaults overridden by CLI flags. */\n test?: TestConfig;\n /** `frontmcp skills install` / `export` defaults. */\n skills?: SkillsCliConfig;\n}\n"]}
|
package/src/config/index.d.ts
CHANGED
|
@@ -2,4 +2,5 @@ export { defineConfig } from './define-config';
|
|
|
2
2
|
export { loadFrontMcpConfig, tryLoadFrontMcpConfig, validateConfig, findDeployment, getDeploymentTargets, } from './frontmcp-config.loader';
|
|
3
3
|
export { frontmcpConfigSchema } from './frontmcp-config.schema';
|
|
4
4
|
export type { FrontMcpConfigParsed } from './frontmcp-config.schema';
|
|
5
|
-
export type {
|
|
5
|
+
export type { ClientConnection, ClientsConfig, EnvOverlays, DeploymentTarget, DeploymentTargetType, FrontMcpConfig, McpClientName, ServerDefaults, SkillsCliConfig, TestConfig, TransportConfig, CliExtensionConfig, ProjectCommandEntry, ProjectCommandArgument, ProjectCommandOption, } from './frontmcp-config.types';
|
|
6
|
+
export { resolveConfig, type ResolvedFrontMcpConfig, type ResolveConfigOptions, type ResolveMode, } from './frontmcp-config.resolve';
|
package/src/config/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.frontmcpConfigSchema = exports.getDeploymentTargets = exports.findDeployment = exports.validateConfig = exports.tryLoadFrontMcpConfig = exports.loadFrontMcpConfig = exports.defineConfig = void 0;
|
|
3
|
+
exports.resolveConfig = exports.frontmcpConfigSchema = exports.getDeploymentTargets = exports.findDeployment = exports.validateConfig = exports.tryLoadFrontMcpConfig = exports.loadFrontMcpConfig = exports.defineConfig = void 0;
|
|
4
4
|
var define_config_1 = require("./define-config");
|
|
5
5
|
Object.defineProperty(exports, "defineConfig", { enumerable: true, get: function () { return define_config_1.defineConfig; } });
|
|
6
6
|
var frontmcp_config_loader_1 = require("./frontmcp-config.loader");
|
|
@@ -11,4 +11,6 @@ Object.defineProperty(exports, "findDeployment", { enumerable: true, get: functi
|
|
|
11
11
|
Object.defineProperty(exports, "getDeploymentTargets", { enumerable: true, get: function () { return frontmcp_config_loader_1.getDeploymentTargets; } });
|
|
12
12
|
var frontmcp_config_schema_1 = require("./frontmcp-config.schema");
|
|
13
13
|
Object.defineProperty(exports, "frontmcpConfigSchema", { enumerable: true, get: function () { return frontmcp_config_schema_1.frontmcpConfigSchema; } });
|
|
14
|
+
var frontmcp_config_resolve_1 = require("./frontmcp-config.resolve");
|
|
15
|
+
Object.defineProperty(exports, "resolveConfig", { enumerable: true, get: function () { return frontmcp_config_resolve_1.resolveConfig; } });
|
|
14
16
|
//# sourceMappingURL=index.js.map
|
package/src/config/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,mEAMkC;AALhC,4HAAA,kBAAkB,OAAA;AAClB,+HAAA,qBAAqB,OAAA;AACrB,wHAAA,cAAc,OAAA;AACd,wHAAA,cAAc,OAAA;AACd,8HAAA,oBAAoB,OAAA;AAEtB,mEAAgE;AAAvD,8HAAA,oBAAoB,OAAA","sourcesContent":["export { defineConfig } from './define-config';\nexport {\n loadFrontMcpConfig,\n tryLoadFrontMcpConfig,\n validateConfig,\n findDeployment,\n getDeploymentTargets,\n} from './frontmcp-config.loader';\nexport { frontmcpConfigSchema } from './frontmcp-config.schema';\nexport type { FrontMcpConfigParsed } from './frontmcp-config.schema';\nexport type {
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/config/index.ts"],"names":[],"mappings":";;;AAAA,iDAA+C;AAAtC,6GAAA,YAAY,OAAA;AACrB,mEAMkC;AALhC,4HAAA,kBAAkB,OAAA;AAClB,+HAAA,qBAAqB,OAAA;AACrB,wHAAA,cAAc,OAAA;AACd,wHAAA,cAAc,OAAA;AACd,8HAAA,oBAAoB,OAAA;AAEtB,mEAAgE;AAAvD,8HAAA,oBAAoB,OAAA;AAmB7B,qEAKmC;AAJjC,wHAAA,aAAa,OAAA","sourcesContent":["export { defineConfig } from './define-config';\nexport {\n loadFrontMcpConfig,\n tryLoadFrontMcpConfig,\n validateConfig,\n findDeployment,\n getDeploymentTargets,\n} from './frontmcp-config.loader';\nexport { frontmcpConfigSchema } from './frontmcp-config.schema';\nexport type { FrontMcpConfigParsed } from './frontmcp-config.schema';\nexport type {\n ClientConnection,\n ClientsConfig,\n EnvOverlays,\n DeploymentTarget,\n DeploymentTargetType,\n FrontMcpConfig,\n McpClientName,\n ServerDefaults,\n SkillsCliConfig,\n TestConfig,\n TransportConfig,\n CliExtensionConfig,\n ProjectCommandEntry,\n ProjectCommandArgument,\n ProjectCommandOption,\n} from './frontmcp-config.types';\nexport {\n resolveConfig,\n type ResolvedFrontMcpConfig,\n type ResolveConfigOptions,\n type ResolveMode,\n} from './frontmcp-config.resolve';\n"]}
|
package/src/core/args.d.ts
CHANGED
|
@@ -35,8 +35,21 @@ export interface ParsedArgs {
|
|
|
35
35
|
maxRestarts?: number;
|
|
36
36
|
follow?: boolean;
|
|
37
37
|
lines?: number;
|
|
38
|
+
autoPort?: boolean;
|
|
39
|
+
showConflict?: boolean;
|
|
38
40
|
registry?: string;
|
|
39
41
|
nx?: boolean;
|
|
42
|
+
stdio?: boolean;
|
|
43
|
+
serve?: boolean;
|
|
44
|
+
logFile?: string;
|
|
45
|
+
bufferSize?: number;
|
|
46
|
+
reloadDeadlineMs?: number;
|
|
47
|
+
config?: string;
|
|
48
|
+
out?: string;
|
|
49
|
+
dryRun?: boolean;
|
|
50
|
+
provider?: 'claude' | 'codex';
|
|
51
|
+
bundle?: 'recommended' | 'minimal' | 'full' | 'none';
|
|
52
|
+
exportTarget?: 'cursor' | 'windsurf' | 'copilot';
|
|
40
53
|
}
|
|
41
54
|
/**
|
|
42
55
|
* @deprecated Use commander-based parsing via {@link createProgram} instead.
|
package/src/core/args.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/core/args.ts"],"names":[],"mappings":";;AAiDA,kDAEC;AAED,sCAEC;
|
|
1
|
+
{"version":3,"file":"args.js","sourceRoot":"","sources":["../../../src/core/args.ts"],"names":[],"mappings":"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","sourcesContent":["export type Command =\n | 'dev'\n | 'build'\n | 'init'\n | 'doctor'\n | 'inspector'\n | 'create'\n | 'help'\n | 'version'\n | 'test'\n | 'socket'\n // Process Manager commands\n | 'start'\n | 'stop'\n | 'restart'\n | 'status'\n | 'list'\n | 'logs'\n | 'service'\n // Package Manager commands\n | 'install'\n | 'uninstall'\n | 'configure';\n\nexport type DeploymentAdapter = 'node' | 'vercel' | 'lambda' | 'cloudflare' | 'distributed';\nexport type BuildTarget =\n | 'cli'\n | 'node'\n | 'sdk'\n | 'browser'\n | 'cloudflare'\n | 'vercel'\n | 'lambda'\n | 'distributed'\n | 'mcpb';\n\nconst DEPLOYMENT_ADAPTERS: readonly DeploymentAdapter[] = ['node', 'vercel', 'lambda', 'cloudflare', 'distributed'];\nconst BUILD_TARGETS: readonly BuildTarget[] = [\n 'cli',\n 'node',\n 'sdk',\n 'browser',\n 'cloudflare',\n 'vercel',\n 'lambda',\n 'distributed',\n 'mcpb',\n];\n\nexport function isDeploymentAdapter(val: string): val is DeploymentAdapter {\n return (DEPLOYMENT_ADAPTERS as readonly string[]).includes(val);\n}\n\nexport function isBuildTarget(val: string): val is BuildTarget {\n return (BUILD_TARGETS as readonly string[]).includes(val);\n}\n\nexport type RedisSetupOption = 'docker' | 'existing' | 'none';\nexport type PackageManagerOption = 'npm' | 'yarn' | 'pnpm';\n\nexport interface ParsedArgs {\n _: string[];\n outDir?: string;\n entry?: string;\n help?: boolean;\n runInBand?: boolean;\n watch?: boolean;\n verbose?: boolean;\n timeout?: number;\n coverage?: boolean;\n // Build --target flag (unified build target)\n buildTarget?: BuildTarget;\n // Build --js flag (cli target: produce JS bundle instead of SEA binary)\n js?: boolean;\n // MCPB flags\n sea?: boolean;\n mergeFrom?: string;\n icon?: string;\n noDeterministic?: boolean;\n stageOnly?: boolean;\n // Create command flags\n yes?: boolean;\n target?: DeploymentAdapter;\n redis?: RedisSetupOption;\n cicd?: boolean;\n pm?: PackageManagerOption;\n // Socket command flags\n socket?: string;\n db?: string;\n background?: boolean;\n // Process Manager flags\n port?: number;\n force?: boolean;\n maxRestarts?: number;\n follow?: boolean;\n lines?: number;\n // `frontmcp dev` flags (issue #398)\n autoPort?: boolean;\n showConflict?: boolean;\n // Install flags\n registry?: string;\n // Create --nx flag\n nx?: boolean;\n // Issue #399 — `frontmcp dev` watch-aware stdio bridge\n stdio?: boolean;\n serve?: boolean;\n logFile?: string;\n bufferSize?: number;\n reloadDeadlineMs?: number;\n // Issue #400 — top-level config flag (forwarded from program.opts().config)\n config?: string;\n // Issue #400 — eject-mcp-config flags\n out?: string;\n dryRun?: boolean;\n // Issue #400 — skills install / export defaults via config\n provider?: 'claude' | 'codex';\n bundle?: 'recommended' | 'minimal' | 'full' | 'none';\n exportTarget?: 'cursor' | 'windsurf' | 'copilot';\n}\n\n/**\n * @deprecated Use commander-based parsing via {@link createProgram} instead.\n * Kept for backward compatibility and existing test coverage.\n */\nexport function parseArgs(argv: string[]): ParsedArgs {\n const out: ParsedArgs = { _: [] };\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i];\n if (a === '--out-dir' || a === '-o') out.outDir = argv[++i];\n else if (a === '--entry' || a === '-e') out.entry = argv[++i];\n else if (a === '--help' || a === '-h') out.help = true;\n else if (a === '--runInBand' || a === '-i') out.runInBand = true;\n else if (a === '--watch' || a === '-w') out.watch = true;\n else if (a === '--verbose' || a === '-v') out.verbose = true;\n else if (a === '--timeout' || a === '-t') {\n const parsed = parseInt(argv[++i], 10);\n out.timeout = Number.isNaN(parsed) ? undefined : parsed;\n } else if (a === '--coverage' || a === '-c') out.coverage = true;\n // Create command flags\n else if (a === '--yes' || a === '-y') out.yes = true;\n else if (a === '--target') {\n const val = argv[++i];\n if (isDeploymentAdapter(val)) out.target = val;\n if (isBuildTarget(val)) out.buildTarget = val;\n } else if (a === '--redis') out.redis = argv[++i] as RedisSetupOption;\n else if (a === '--cicd') out.cicd = true;\n else if (a === '--no-cicd') out.cicd = false;\n else if (a === '--pm') out.pm = argv[++i] as PackageManagerOption;\n // Socket command flags\n else if (a === '--socket' || a === '-s') out.socket = argv[++i];\n else if (a === '--db') out.db = argv[++i];\n else if (a === '--background' || a === '-b') out.background = true;\n else if (a === '--js') out.js = true;\n // Process Manager flags\n else if (a === '--port' || a === '-p') {\n const parsed = parseInt(argv[++i], 10);\n out.port = Number.isNaN(parsed) ? undefined : parsed;\n } else if (a === '--force' || a === '-f') out.force = true;\n else if (a === '--max-restarts') {\n const parsed = parseInt(argv[++i], 10);\n out.maxRestarts = Number.isNaN(parsed) ? undefined : parsed;\n } else if (a === '--follow' || a === '-F') out.follow = true;\n else if (a === '--lines' || a === '-n') {\n const parsed = parseInt(argv[++i], 10);\n out.lines = Number.isNaN(parsed) ? undefined : parsed;\n }\n // Create --nx flag\n else if (a === '--nx') out.nx = true;\n // Install flags\n else if (a === '--registry') out.registry = argv[++i];\n else out._.push(a);\n }\n return out;\n}\n"]}
|
package/src/core/bridge.js
CHANGED
|
@@ -75,6 +75,45 @@ function toParsedArgs(commandName, positionalArgs, options) {
|
|
|
75
75
|
// Package manager
|
|
76
76
|
if (options['registry'] !== undefined)
|
|
77
77
|
out.registry = options['registry'];
|
|
78
|
+
// Dev (issue #398): port conflict handling
|
|
79
|
+
if (options['autoPort'] !== undefined)
|
|
80
|
+
out.autoPort = options['autoPort'];
|
|
81
|
+
if (options['showConflict'] !== undefined)
|
|
82
|
+
out.showConflict = options['showConflict'];
|
|
83
|
+
// Dev (issue #399): watch-aware stdio bridge
|
|
84
|
+
if (options['stdio'] !== undefined)
|
|
85
|
+
out.stdio = options['stdio'];
|
|
86
|
+
if (options['serve'] !== undefined)
|
|
87
|
+
out.serve = options['serve'];
|
|
88
|
+
if (options['logFile'] !== undefined)
|
|
89
|
+
out.logFile = options['logFile'];
|
|
90
|
+
if (options['bufferSize'] !== undefined) {
|
|
91
|
+
out.bufferSize =
|
|
92
|
+
typeof options['bufferSize'] === 'number' ? options['bufferSize'] : parseInt(String(options['bufferSize']), 10);
|
|
93
|
+
}
|
|
94
|
+
if (options['reloadDeadlineMs'] !== undefined) {
|
|
95
|
+
out.reloadDeadlineMs =
|
|
96
|
+
typeof options['reloadDeadlineMs'] === 'number'
|
|
97
|
+
? options['reloadDeadlineMs']
|
|
98
|
+
: parseInt(String(options['reloadDeadlineMs']), 10);
|
|
99
|
+
}
|
|
100
|
+
// Issue #400 — top-level --config flag forwarded from program.opts()
|
|
101
|
+
if (options['config'] !== undefined)
|
|
102
|
+
out.config = options['config'];
|
|
103
|
+
// Issue #400 — eject-mcp-config
|
|
104
|
+
if (options['out'] !== undefined)
|
|
105
|
+
out.out = options['out'];
|
|
106
|
+
if (options['dryRun'] !== undefined)
|
|
107
|
+
out.dryRun = options['dryRun'];
|
|
108
|
+
// Issue #400 — skills install/export defaults via config (still allow CLI override)
|
|
109
|
+
if (options['provider'] !== undefined)
|
|
110
|
+
out.provider = options['provider'];
|
|
111
|
+
if (options['bundle'] !== undefined) {
|
|
112
|
+
out.bundle = options['bundle'];
|
|
113
|
+
}
|
|
114
|
+
if (options['exportTarget'] !== undefined) {
|
|
115
|
+
out.exportTarget = options['exportTarget'];
|
|
116
|
+
}
|
|
78
117
|
return out;
|
|
79
118
|
}
|
|
80
119
|
//# sourceMappingURL=bridge.js.map
|
package/src/core/bridge.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../src/core/bridge.ts"],"names":[],"mappings":";;AAYA,
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../../../src/core/bridge.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n type BuildTarget,\n type DeploymentAdapter,\n type PackageManagerOption,\n type ParsedArgs,\n type RedisSetupOption,\n} from './args';\n\n/**\n * Convert commander's parsed command name, positional arguments, and options\n * into the {@link ParsedArgs} shape expected by existing handlers.\n */\nexport function toParsedArgs(\n commandName: string,\n positionalArgs: string[],\n options: Record<string, unknown>,\n): ParsedArgs {\n const out: ParsedArgs = { _: [commandName, ...positionalArgs] };\n\n // General\n if (options['outDir'] !== undefined) out.outDir = options['outDir'] as string;\n if (options['entry'] !== undefined) out.entry = options['entry'] as string;\n\n // Build --target resolution\n if (commandName === 'build') {\n if (options['target'] !== undefined) out.buildTarget = options['target'] as BuildTarget;\n if (options['js'] !== undefined) out.js = options['js'] as boolean;\n if (options['sea'] !== undefined) out.sea = options['sea'] as boolean;\n if (options['mergeFrom'] !== undefined) out.mergeFrom = options['mergeFrom'] as string;\n if (options['icon'] !== undefined) out.icon = options['icon'] as string;\n if (options['deterministic'] === false) out.noDeterministic = true;\n if (options['stageOnly'] !== undefined) out.stageOnly = options['stageOnly'] as boolean;\n }\n\n // Create\n if (options['yes'] !== undefined) out.yes = options['yes'] as boolean;\n if (commandName === 'create' && options['target'] !== undefined) out.target = options['target'] as DeploymentAdapter;\n if (options['redis'] !== undefined) out.redis = options['redis'] as RedisSetupOption;\n if (options['cicd'] !== undefined) out.cicd = options['cicd'] as boolean;\n if (options['pm'] !== undefined) out.pm = options['pm'] as PackageManagerOption;\n if (options['nx'] !== undefined) out.nx = options['nx'] as boolean;\n\n // Test\n if (options['runInBand'] !== undefined) out.runInBand = options['runInBand'] as boolean;\n if (options['watch'] !== undefined) out.watch = options['watch'] as boolean;\n if (options['verbose'] !== undefined) out.verbose = options['verbose'] as boolean;\n if (options['timeout'] !== undefined) out.timeout = options['timeout'] as number;\n if (options['coverage'] !== undefined) out.coverage = options['coverage'] as boolean;\n\n // PM - start / socket\n if (options['port'] !== undefined) out.port = options['port'] as number;\n if (options['socket'] !== undefined) out.socket = options['socket'] as string;\n if (options['db'] !== undefined) out.db = options['db'] as string;\n if (options['background'] !== undefined) out.background = options['background'] as boolean;\n if (options['maxRestarts'] !== undefined) out.maxRestarts = options['maxRestarts'] as number;\n\n // PM - stop\n if (options['force'] !== undefined) out.force = options['force'] as boolean;\n\n // PM - logs\n if (options['follow'] !== undefined) out.follow = options['follow'] as boolean;\n if (options['lines'] !== undefined) out.lines = options['lines'] as number;\n\n // Package manager\n if (options['registry'] !== undefined) out.registry = options['registry'] as string;\n\n // Dev (issue #398): port conflict handling\n if (options['autoPort'] !== undefined) out.autoPort = options['autoPort'] as boolean;\n if (options['showConflict'] !== undefined) out.showConflict = options['showConflict'] as boolean;\n\n // Dev (issue #399): watch-aware stdio bridge\n if (options['stdio'] !== undefined) out.stdio = options['stdio'] as boolean;\n if (options['serve'] !== undefined) out.serve = options['serve'] as boolean;\n if (options['logFile'] !== undefined) out.logFile = options['logFile'] as string;\n if (options['bufferSize'] !== undefined) {\n out.bufferSize =\n typeof options['bufferSize'] === 'number' ? options['bufferSize'] : parseInt(String(options['bufferSize']), 10);\n }\n if (options['reloadDeadlineMs'] !== undefined) {\n out.reloadDeadlineMs =\n typeof options['reloadDeadlineMs'] === 'number'\n ? options['reloadDeadlineMs']\n : parseInt(String(options['reloadDeadlineMs']), 10);\n }\n\n // Issue #400 — top-level --config flag forwarded from program.opts()\n if (options['config'] !== undefined) out.config = options['config'] as string;\n // Issue #400 — eject-mcp-config\n if (options['out'] !== undefined) out.out = options['out'] as string;\n if (options['dryRun'] !== undefined) out.dryRun = options['dryRun'] as boolean;\n // Issue #400 — skills install/export defaults via config (still allow CLI override)\n if (options['provider'] !== undefined) out.provider = options['provider'] as 'claude' | 'codex';\n if (options['bundle'] !== undefined) {\n out.bundle = options['bundle'] as 'recommended' | 'minimal' | 'full' | 'none';\n }\n if (options['exportTarget'] !== undefined) {\n out.exportTarget = options['exportTarget'] as 'cursor' | 'windsurf' | 'copilot';\n }\n\n return out;\n}\n"]}
|
package/src/core/cli.d.ts
CHANGED
package/src/core/cli.js
CHANGED
|
@@ -1,23 +1,43 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
/**
|
|
4
5
|
* frontmcp - FrontMCP command line interface
|
|
5
6
|
*
|
|
6
7
|
* Uses commander.js for argument parsing, command management, and
|
|
7
8
|
* auto-generated help. Interactive TUI is handled by @clack/prompts.
|
|
8
9
|
*/
|
|
9
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
-
const program_1 = require("./program");
|
|
11
10
|
const colors_1 = require("./colors");
|
|
11
|
+
const program_1 = require("./program");
|
|
12
|
+
const project_commands_1 = require("./project-commands");
|
|
12
13
|
async function main() {
|
|
13
14
|
try {
|
|
14
|
-
const program = (0, program_1.createProgram)();
|
|
15
|
+
const program = await (0, program_1.createProgram)();
|
|
16
|
+
// `--list-commands` is a top-level metadata flag. Only honor it when it
|
|
17
|
+
// appears BEFORE any verb token — otherwise `frontmcp my-tool --list-commands`
|
|
18
|
+
// would bypass the user's `my-tool` action.
|
|
19
|
+
const argv = process.argv.slice(2);
|
|
20
|
+
const firstVerbIdx = argv.findIndex((a) => !a.startsWith('-'));
|
|
21
|
+
const preVerb = firstVerbIdx === -1 ? argv : argv.slice(0, firstVerbIdx);
|
|
22
|
+
if (preVerb.includes('--list-commands')) {
|
|
23
|
+
for (const sub of program.commands) {
|
|
24
|
+
const tag = (0, project_commands_1.isProjectCommand)(sub) ? '[project]' : '[built-in]';
|
|
25
|
+
process.stdout.write(`${sub.name()}\t${tag}\t${sub.description() ?? ''}\n`);
|
|
26
|
+
}
|
|
27
|
+
setImmediate(() => process.exit(0));
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
15
30
|
await program.parseAsync(process.argv);
|
|
16
31
|
// Defer process.exit() by one event-loop tick so native addon destructors
|
|
17
32
|
// (ONNX runtime, etc.) can release mutexes before V8 tears down.
|
|
18
33
|
setImmediate(() => process.exit(0));
|
|
19
34
|
}
|
|
20
35
|
catch (err) {
|
|
36
|
+
if (err instanceof project_commands_1.ProjectCommandFailedError) {
|
|
37
|
+
// The child already printed its own output via stdio:'inherit'; just
|
|
38
|
+
// exit with its code. Don't re-print a stack trace.
|
|
39
|
+
process.exit(err.exitCode);
|
|
40
|
+
}
|
|
21
41
|
console.error('\n' + (0, colors_1.c)('red', err instanceof Error ? err.stack || err.message : String(err)));
|
|
22
42
|
process.exit(1);
|
|
23
43
|
}
|
package/src/core/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/core/cli.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/core/cli.ts"],"names":[],"mappings":";;;AACA;;;;;GAKG;AACH,qCAA6B;AAC7B,uCAA0C;AAC1C,yDAAiF;AAEjF,KAAK,UAAU,IAAI;IACjB,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,IAAA,uBAAa,GAAE,CAAC;QAEtC,wEAAwE;QACxE,+EAA+E;QAC/E,4CAA4C;QAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QACnC,MAAM,YAAY,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,OAAO,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;QACzE,IAAI,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,EAAE,CAAC;YACxC,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;gBACnC,MAAM,GAAG,GAAG,IAAA,mCAAgB,EAAC,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,YAAY,CAAC;gBAC/D,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,KAAK,GAAG,KAAK,GAAG,CAAC,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;YAC9E,CAAC;YACD,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;QAED,MAAM,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACvC,0EAA0E;QAC1E,iEAAiE;QACjE,YAAY,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,4CAAyB,EAAE,CAAC;YAC7C,qEAAqE;YACrE,oDAAoD;YACpD,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAC7B,CAAC;QACD,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,IAAA,UAAC,EAAC,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC9F,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC;AAED,IAAI,EAAE,CAAC","sourcesContent":["#!/usr/bin/env node\n/**\n * frontmcp - FrontMCP command line interface\n *\n * Uses commander.js for argument parsing, command management, and\n * auto-generated help. Interactive TUI is handled by @clack/prompts.\n */\nimport { c } from './colors';\nimport { createProgram } from './program';\nimport { isProjectCommand, ProjectCommandFailedError } from './project-commands';\n\nasync function main(): Promise<void> {\n try {\n const program = await createProgram();\n\n // `--list-commands` is a top-level metadata flag. Only honor it when it\n // appears BEFORE any verb token — otherwise `frontmcp my-tool --list-commands`\n // would bypass the user's `my-tool` action.\n const argv = process.argv.slice(2);\n const firstVerbIdx = argv.findIndex((a) => !a.startsWith('-'));\n const preVerb = firstVerbIdx === -1 ? argv : argv.slice(0, firstVerbIdx);\n if (preVerb.includes('--list-commands')) {\n for (const sub of program.commands) {\n const tag = isProjectCommand(sub) ? '[project]' : '[built-in]';\n process.stdout.write(`${sub.name()}\\t${tag}\\t${sub.description() ?? ''}\\n`);\n }\n setImmediate(() => process.exit(0));\n return;\n }\n\n await program.parseAsync(process.argv);\n // Defer process.exit() by one event-loop tick so native addon destructors\n // (ONNX runtime, etc.) can release mutexes before V8 tears down.\n setImmediate(() => process.exit(0));\n } catch (err: unknown) {\n if (err instanceof ProjectCommandFailedError) {\n // The child already printed its own output via stdio:'inherit'; just\n // exit with its code. Don't re-print a stack trace.\n process.exit(err.exitCode);\n }\n console.error('\\n' + c('red', err instanceof Error ? err.stack || err.message : String(err)));\n process.exit(1);\n }\n}\n\nmain();\n"]}
|
package/src/core/help.d.ts
CHANGED
package/src/core/help.js
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.customizeHelp = customizeHelp;
|
|
4
4
|
const colors_1 = require("./colors");
|
|
5
|
+
const project_commands_1 = require("./project-commands");
|
|
6
|
+
// commander v13 exposes registered arguments on the private `_args` property.
|
|
7
|
+
// Newer (v14+) versions expose `registeredArguments`; prefer that when present.
|
|
8
|
+
function getArgs(cmd) {
|
|
9
|
+
const fromNewApi = cmd.registeredArguments;
|
|
10
|
+
if (fromNewApi)
|
|
11
|
+
return fromNewApi;
|
|
12
|
+
return (cmd._args ?? []);
|
|
13
|
+
}
|
|
5
14
|
/**
|
|
6
15
|
* Command groups in display order, mapped to the command names they contain.
|
|
7
16
|
* The `skills` group is handled separately to show subcommands inline.
|
|
@@ -22,22 +31,24 @@ const EXAMPLES = [
|
|
|
22
31
|
];
|
|
23
32
|
/** Format a top-level command line with cyan name and dim arg placeholders. */
|
|
24
33
|
function formatCommandLine(sub, padWidth) {
|
|
34
|
+
const argsList = getArgs(sub);
|
|
25
35
|
const rawName = sub.name();
|
|
26
|
-
const rawArgs =
|
|
36
|
+
const rawArgs = argsList.map((a) => (a.required ? `<${a.name()}>` : `[${a.name()}]`)).join(' ');
|
|
27
37
|
const rawTerm = rawArgs ? `${rawName} ${rawArgs}` : rawName;
|
|
28
38
|
const name = (0, colors_1.c)('cyan', rawName);
|
|
29
|
-
const args =
|
|
39
|
+
const args = argsList.map((a) => (0, colors_1.c)('dim', a.required ? `<${a.name()}>` : `[${a.name()}]`)).join(' ');
|
|
30
40
|
const term = args ? `${name} ${args}` : name;
|
|
31
41
|
const padding = ' '.repeat(Math.max(2, padWidth - rawTerm.length + 2));
|
|
32
42
|
return ` ${term}${padding}${sub.description()}`;
|
|
33
43
|
}
|
|
34
44
|
/** Format a skills subcommand as "skills <subname> <args>". */
|
|
35
45
|
function formatSkillsLine(sub, padWidth) {
|
|
46
|
+
const argsList = getArgs(sub);
|
|
36
47
|
const rawPrefix = `skills ${sub.name()}`;
|
|
37
|
-
const rawArgs =
|
|
48
|
+
const rawArgs = argsList.map((a) => (a.required ? `<${a.name()}>` : `[${a.name()}]`)).join(' ');
|
|
38
49
|
const rawTerm = rawArgs ? `${rawPrefix} ${rawArgs}` : rawPrefix;
|
|
39
50
|
const prefix = (0, colors_1.c)('cyan', rawPrefix);
|
|
40
|
-
const args =
|
|
51
|
+
const args = argsList.map((a) => (0, colors_1.c)('dim', a.required ? `<${a.name()}>` : `[${a.name()}]`)).join(' ');
|
|
41
52
|
const term = args ? `${prefix} ${args}` : prefix;
|
|
42
53
|
const padding = ' '.repeat(Math.max(2, padWidth - rawTerm.length + 2));
|
|
43
54
|
return ` ${term}${padding}${sub.description()}`;
|
|
@@ -58,7 +69,7 @@ function customizeHelp(program) {
|
|
|
58
69
|
const skillsSubs = skillsCmd ? helper.visibleCommands(skillsCmd) : [];
|
|
59
70
|
if (skillsCmd) {
|
|
60
71
|
for (const sub of skillsSubs) {
|
|
61
|
-
const rawArgs = sub
|
|
72
|
+
const rawArgs = getArgs(sub)
|
|
62
73
|
.map((a) => (a.required ? `<${a.name()}>` : `[${a.name()}]`))
|
|
63
74
|
.join(' ');
|
|
64
75
|
const rawTerm = rawArgs ? `skills ${sub.name()} ${rawArgs}` : `skills ${sub.name()}`;
|
|
@@ -91,9 +102,19 @@ function customizeHelp(program) {
|
|
|
91
102
|
}
|
|
92
103
|
lines.push('');
|
|
93
104
|
}
|
|
105
|
+
// Project commands (registered via cli.commands in frontmcp.config).
|
|
106
|
+
// Hide commands marked with `hidden: true`.
|
|
107
|
+
const projectCommands = allCommands.filter((sc) => (0, project_commands_1.isProjectCommand)(sc) && !(0, project_commands_1.isCommandHidden)(sc));
|
|
108
|
+
if (projectCommands.length > 0) {
|
|
109
|
+
lines.push((0, colors_1.c)('bold', 'Project Commands'));
|
|
110
|
+
for (const sub of projectCommands) {
|
|
111
|
+
lines.push(formatCommandLine(sub, termWidth));
|
|
112
|
+
}
|
|
113
|
+
lines.push('');
|
|
114
|
+
}
|
|
94
115
|
// Other commands not in any group
|
|
95
116
|
const renderedNames = new Set([...GROUPS.flatMap(([, names]) => names), 'skills']);
|
|
96
|
-
const other = allCommands.filter((sc) => !renderedNames.has(sc.name()));
|
|
117
|
+
const other = allCommands.filter((sc) => !renderedNames.has(sc.name()) && !(0, project_commands_1.isProjectCommand)(sc));
|
|
97
118
|
if (other.length > 0) {
|
|
98
119
|
lines.push((0, colors_1.c)('bold', 'Other'));
|
|
99
120
|
for (const sub of other) {
|