frontmcp 1.1.0 → 1.1.2-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/package.json +5 -5
  2. package/src/commands/build/adapters/cloudflare.js +56 -4
  3. package/src/commands/build/adapters/cloudflare.js.map +1 -1
  4. package/src/commands/build/adapters/distributed.js +4 -1
  5. package/src/commands/build/adapters/distributed.js.map +1 -1
  6. package/src/commands/build/adapters/lambda.js +32 -0
  7. package/src/commands/build/adapters/lambda.js.map +1 -1
  8. package/src/commands/build/bundler.js +23 -1
  9. package/src/commands/build/bundler.js.map +1 -1
  10. package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.d.ts +18 -0
  11. package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.js +58 -0
  12. package/src/commands/build/exec/cli-runtime/extract-public-message.snippet.js.map +1 -0
  13. package/src/commands/build/exec/cli-runtime/generate-cli-entry.d.ts +2 -2
  14. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js +195 -47
  15. package/src/commands/build/exec/cli-runtime/generate-cli-entry.js.map +1 -1
  16. package/src/commands/build/exec/cli-runtime/schema-extractor.d.ts +7 -0
  17. package/src/commands/build/exec/cli-runtime/schema-extractor.js +17 -1
  18. package/src/commands/build/exec/cli-runtime/schema-extractor.js.map +1 -1
  19. package/src/commands/build/exec/index.d.ts +11 -0
  20. package/src/commands/build/exec/index.js +68 -20
  21. package/src/commands/build/exec/index.js.map +1 -1
  22. package/src/commands/build/exec/installer-script.d.ts +8 -2
  23. package/src/commands/build/exec/installer-script.js +34 -15
  24. package/src/commands/build/exec/installer-script.js.map +1 -1
  25. package/src/commands/build/exec/manifest.d.ts +16 -3
  26. package/src/commands/build/exec/manifest.js +17 -5
  27. package/src/commands/build/exec/manifest.js.map +1 -1
  28. package/src/commands/build/exec/runner-script.d.ts +9 -1
  29. package/src/commands/build/exec/runner-script.js +60 -2
  30. package/src/commands/build/exec/runner-script.js.map +1 -1
  31. package/src/commands/build/index.js +86 -22
  32. package/src/commands/build/index.js.map +1 -1
  33. package/src/commands/build/load-entry-config.d.ts +33 -0
  34. package/src/commands/build/load-entry-config.js +206 -0
  35. package/src/commands/build/load-entry-config.js.map +1 -0
  36. package/src/commands/build/mcpb/manifest.d.ts +14 -0
  37. package/src/commands/build/mcpb/manifest.js +29 -0
  38. package/src/commands/build/mcpb/manifest.js.map +1 -1
  39. package/src/commands/build/types.d.ts +36 -1
  40. package/src/commands/build/types.js.map +1 -1
  41. package/src/commands/dev/doctor.js +7 -3
  42. package/src/commands/dev/doctor.js.map +1 -1
  43. package/src/commands/package/install.d.ts +1 -1
  44. package/src/commands/package/install.js +10 -8
  45. package/src/commands/package/install.js.map +1 -1
  46. package/src/commands/package/types.d.ts +2 -1
  47. package/src/commands/package/types.js.map +1 -1
  48. package/src/config/frontmcp-config.loader.d.ts +20 -0
  49. package/src/config/frontmcp-config.loader.js +152 -5
  50. package/src/config/frontmcp-config.loader.js.map +1 -1
  51. package/src/config/index.d.ts +1 -1
  52. package/src/config/index.js +2 -1
  53. package/src/config/index.js.map +1 -1
@@ -93,6 +93,17 @@ exports.mcpbManifestSchema = lazy_zod_1.z
93
93
  .array(lazy_zod_1.z.object({ name: lazy_zod_1.z.string(), description: lazy_zod_1.z.string() }).strict())
94
94
  .optional(),
95
95
  tools_generated: lazy_zod_1.z.boolean().optional(),
96
+ resources: lazy_zod_1.z
97
+ .array(lazy_zod_1.z
98
+ .object({
99
+ name: lazy_zod_1.z.string().optional(),
100
+ uri: lazy_zod_1.z.string(),
101
+ description: lazy_zod_1.z.string().optional(),
102
+ mimeType: lazy_zod_1.z.string().optional(),
103
+ })
104
+ .strict())
105
+ .optional(),
106
+ resources_generated: lazy_zod_1.z.boolean().optional(),
96
107
  prompts: lazy_zod_1.z
97
108
  .array(lazy_zod_1.z
98
109
  .object({ name: lazy_zod_1.z.string(), description: lazy_zod_1.z.string().optional() })
@@ -196,6 +207,15 @@ function generateMcpbManifest(input) {
196
207
  const tools = schema.tools
197
208
  .filter((t) => !schema_extractor_1.SYSTEM_TOOL_NAMES.has(t.name))
198
209
  .map((t) => ({ name: t.name, description: t.description || '' }));
210
+ // #376 — emit resources alongside tools/prompts. The server runtime
211
+ // already registers @Resource entries, but the manifest writer was
212
+ // dropping them, so MCPB-aware clients had no way to discover them.
213
+ const resources = schema.resources.map((r) => ({
214
+ ...(r.name ? { name: r.name } : {}),
215
+ uri: r.uri,
216
+ ...(r.description ? { description: r.description } : {}),
217
+ ...(r.mimeType ? { mimeType: r.mimeType } : {}),
218
+ }));
199
219
  const prompts = schema.prompts.map((p) => ({
200
220
  name: p.name,
201
221
  ...(p.description ? { description: p.description } : {}),
@@ -236,6 +256,15 @@ function generateMcpbManifest(input) {
236
256
  },
237
257
  tools,
238
258
  tools_generated: false,
259
+ ...(resources.length > 0
260
+ ? {
261
+ resources,
262
+ // FrontMCP resources resolve dynamically (their bodies come from
263
+ // execute()/read()), so consumers should still query the server at
264
+ // runtime — but the static manifest now exposes name/uri/mimeType.
265
+ resources_generated: true,
266
+ }
267
+ : {}),
239
268
  prompts,
240
269
  // FrontMCP prompts resolve dynamically via execute() — MCPB's static `text`
241
270
  // template cannot represent JS logic. Set generated:true so consumers query
@@ -1 +1 @@
1
- {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/commands/build/mcpb/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCPB manifest generator + Zod schema for the emitted manifest.\n *\n * Source priority when resolving fields:\n * deployment.* (frontmcp.config) > package.json > hard defaults\n *\n * See https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { z } from '@frontmcp/lazy-zod';\nimport { type ExtractedSchema, SYSTEM_TOOL_NAMES } from '../exec/cli-runtime/schema-extractor';\nimport type {\n McpbAuthor,\n McpbCompatibility,\n McpbDeployment,\n McpbRepository,\n McpbUserConfigEntry,\n} from '../../../config/frontmcp-config.types';\nimport {\n DEFAULT_NODE_COMPAT,\n DEFAULT_PLATFORMS,\n MCPB_MANIFEST_VERSION,\n} from './constants';\n\n// ============================================\n// Emitted manifest shape (MCPB v0.3 subset we produce)\n// ============================================\n\nexport interface McpbMcpConfig {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n platform_overrides?: Record<string, McpbMcpConfig>;\n}\n\nexport interface McpbManifest {\n manifest_version: string;\n name: string;\n version: string;\n description: string;\n display_name?: string;\n long_description?: string;\n author: McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: { type: string; url: string };\n documentation?: string;\n support?: string;\n icon?: string;\n keywords?: string[];\n privacy_policies?: string[];\n compatibility?: McpbCompatibility;\n server: {\n type: 'node' | 'python' | 'binary' | 'uv';\n entry_point: string;\n mcp_config: McpbMcpConfig;\n };\n tools?: Array<{ name: string; description: string }>;\n tools_generated?: boolean;\n prompts?: Array<{ name: string; description?: string }>;\n prompts_generated?: boolean;\n user_config?: Record<string, McpbUserConfigEntry>;\n _meta?: Record<string, unknown>;\n}\n\n// ============================================\n// Zod schema (used by validate.ts)\n// ============================================\n\nconst authorSchema = z\n .object({\n name: z.string(),\n email: z.string().optional(),\n url: z.string().optional(),\n })\n .strict();\n\nconst userConfigEntrySchema = z\n .object({\n type: z.enum(['string', 'number', 'boolean', 'directory', 'file']),\n title: z.string(),\n description: z.string().optional(),\n required: z.boolean().optional(),\n default: z.union([z.string(), z.number(), z.boolean()]).optional(),\n multiple: z.boolean().optional(),\n sensitive: z.boolean().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .strict();\n\nconst mcpConfigSchema: z.ZodType<McpbMcpConfig> = z.lazy(() =>\n z\n .object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n platform_overrides: z.record(z.string(), mcpConfigSchema).optional(),\n })\n .strict(),\n);\n\nexport const mcpbManifestSchema = z\n .object({\n manifest_version: z.string(),\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string(),\n display_name: z.string().optional(),\n long_description: z.string().optional(),\n author: authorSchema,\n license: z.string().optional(),\n homepage: z.string().optional(),\n repository: z\n .object({ type: z.string(), url: z.string() })\n .strict()\n .optional(),\n documentation: z.string().optional(),\n support: z.string().optional(),\n icon: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n privacy_policies: z.array(z.string()).optional(),\n compatibility: z\n .object({\n claude_desktop: z.string().optional(),\n platforms: z.array(z.enum(['darwin', 'win32', 'linux'])).optional(),\n runtimes: z\n .object({ node: z.string().optional(), python: z.string().optional() })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n server: z\n .object({\n type: z.enum(['node', 'python', 'binary', 'uv']),\n entry_point: z.string(),\n mcp_config: mcpConfigSchema,\n })\n .strict(),\n tools: z\n .array(z.object({ name: z.string(), description: z.string() }).strict())\n .optional(),\n tools_generated: z.boolean().optional(),\n prompts: z\n .array(\n z\n .object({ name: z.string(), description: z.string().optional() })\n .strict(),\n )\n .optional(),\n prompts_generated: z.boolean().optional(),\n user_config: z.record(z.string(), userConfigEntrySchema).optional(),\n _meta: z.record(z.string(), z.unknown()).optional(),\n })\n .strict();\n\n// ============================================\n// Sources + helpers\n// ============================================\n\nexport interface PackageJsonMeta {\n name?: string;\n version?: string;\n description?: string;\n author?: string | McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: string | { type?: string; url?: string };\n keywords?: string[];\n icon?: string;\n}\n\n/** Read and parse package.json from the given directory. Returns {} if absent. */\nexport function loadPackageJsonMeta(cwd: string): PackageJsonMeta {\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) return {};\n try {\n return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as PackageJsonMeta;\n } catch {\n return {};\n }\n}\n\n/**\n * Parse npm-style \"Name <email> (url)\" into an McpbAuthor.\n * Falls back to `{ name: <raw> }` when parsing fails.\n */\nexport function parseAuthor(author: unknown): McpbAuthor {\n if (!author) return { name: 'unknown' };\n if (typeof author === 'object' && 'name' in author) {\n const a = author as McpbAuthor;\n return {\n name: a.name,\n ...(a.email ? { email: a.email } : {}),\n ...(a.url ? { url: a.url } : {}),\n };\n }\n if (typeof author !== 'string') {\n return { name: String(author) };\n }\n const match = author.match(/^([^<(]+?)(?:\\s*<([^>]+)>)?(?:\\s*\\(([^)]+)\\))?$/);\n if (!match || !match[1]) return { name: author };\n const [, name, email, url] = match;\n return {\n name: name.trim(),\n ...(email ? { email: email.trim() } : {}),\n ...(url ? { url: url.trim() } : {}),\n };\n}\n\n/** Normalize repository field (string → {type, url}). */\nexport function normalizeRepository(\n repo: McpbRepository | PackageJsonMeta['repository'] | undefined,\n): { type: string; url: string } | undefined {\n if (!repo) return undefined;\n if (typeof repo === 'string') {\n return { type: 'git', url: repo };\n }\n if (typeof repo === 'object' && repo.url) {\n return { type: repo.type || 'git', url: repo.url };\n }\n return undefined;\n}\n\n/** Resolve first-existing icon path. */\nexport function resolveIconPath(cwd: string, deploymentIcon?: string, pkgIcon?: string): string | undefined {\n const candidates = [deploymentIcon, pkgIcon, 'icon.png', 'assets/icon.png'].filter(\n (x): x is string => !!x,\n );\n for (const rel of candidates) {\n if (fs.existsSync(path.resolve(cwd, rel))) {\n return rel;\n }\n }\n return undefined;\n}\n\n// ============================================\n// Generator input + output\n// ============================================\n\nexport interface GenerateMcpbManifestInput {\n /** Resolved server name. */\n name: string;\n /** Resolved server version. */\n version: string;\n /** Optional resolved node version range (e.g., \">=22.0.0\"). */\n nodeVersion?: string;\n /** Project root. Used for icon resolution and package.json fallback. */\n cwd: string;\n /** Deployment config from frontmcp.config (may be undefined). */\n deployment?: McpbDeployment;\n /** Schema extracted from the compiled server bundle. */\n schema: ExtractedSchema;\n /** env → user_config reference map built by user-config.ts. */\n userConfigEnv: Record<string, string>;\n /** user_config entries built by user-config.ts. */\n userConfig: Record<string, McpbUserConfigEntry>;\n /** platform_overrides from binary.ts (may be empty). */\n platformOverrides?: Record<string, McpbMcpConfig>;\n /** Whether an icon was copied into the staged archive root. */\n hasIcon?: boolean;\n /** Tool name of the CLI version emitting this manifest (for _meta). */\n cliVersion?: string;\n}\n\n/** Produce the final MCPB manifest object. */\nexport function generateMcpbManifest(input: GenerateMcpbManifestInput): McpbManifest {\n const {\n name,\n version,\n cwd,\n deployment,\n schema,\n userConfig,\n userConfigEnv,\n platformOverrides,\n hasIcon,\n cliVersion,\n } = input;\n\n const pkg = loadPackageJsonMeta(cwd);\n\n const description = deployment?.longDescription?.split('\\n')[0]?.trim()\n || pkg.description\n || '';\n\n const author = deployment?.author || parseAuthor(pkg.author);\n const license = deployment?.license ?? pkg.license;\n const homepage = deployment?.homepage ?? pkg.homepage;\n const repository = normalizeRepository(deployment?.repository ?? pkg.repository);\n const keywords = deployment?.keywords ?? pkg.keywords;\n const icon = hasIcon ? 'icon.png' : undefined;\n\n const nodeVersion = deployment?.compatibility?.runtimes?.node\n ?? input.nodeVersion\n ?? DEFAULT_NODE_COMPAT;\n\n const compatibility: McpbCompatibility = {\n ...(deployment?.compatibility?.claude_desktop\n ? { claude_desktop: deployment.compatibility.claude_desktop }\n : {}),\n platforms: deployment?.compatibility?.platforms ?? [...DEFAULT_PLATFORMS],\n runtimes: {\n ...(deployment?.compatibility?.runtimes?.python\n ? { python: deployment.compatibility.runtimes.python }\n : {}),\n node: nodeVersion,\n },\n };\n\n const tools = schema.tools\n .filter((t) => !SYSTEM_TOOL_NAMES.has(t.name))\n .map((t) => ({ name: t.name, description: t.description || '' }));\n\n const prompts = schema.prompts.map((p) => ({\n name: p.name,\n ...(p.description ? { description: p.description } : {}),\n }));\n\n const mcpConfig: McpbMcpConfig = {\n command: 'node',\n args: ['${__dirname}/server/index.js'],\n ...(Object.keys(userConfigEnv).length > 0 ? { env: userConfigEnv } : {}),\n ...(platformOverrides && Object.keys(platformOverrides).length > 0\n ? { platform_overrides: platformOverrides }\n : {}),\n };\n\n const manifest: McpbManifest = {\n manifest_version: MCPB_MANIFEST_VERSION,\n name,\n version,\n description,\n ...(deployment?.displayName ? { display_name: deployment.displayName } : {}),\n ...(deployment?.longDescription\n ? { long_description: deployment.longDescription }\n : {}),\n author,\n ...(license ? { license } : {}),\n ...(homepage ? { homepage } : {}),\n ...(repository ? { repository } : {}),\n ...(deployment?.documentation ? { documentation: deployment.documentation } : {}),\n ...(deployment?.support ? { support: deployment.support } : {}),\n ...(icon ? { icon } : {}),\n ...(keywords && keywords.length > 0 ? { keywords } : {}),\n ...(deployment?.privacyPolicies && deployment.privacyPolicies.length > 0\n ? { privacy_policies: deployment.privacyPolicies }\n : {}),\n compatibility,\n server: {\n type: 'node',\n entry_point: 'server/index.js',\n mcp_config: mcpConfig,\n },\n tools,\n tools_generated: false,\n prompts,\n // FrontMCP prompts resolve dynamically via execute() — MCPB's static `text`\n // template cannot represent JS logic. Set generated:true so consumers query\n // the server at runtime while still getting name/description hints here.\n prompts_generated: true,\n ...(Object.keys(userConfig).length > 0 ? { user_config: userConfig } : {}),\n _meta: {\n 'dev.frontmcp.generator': cliVersion ? `frontmcp@${cliVersion}` : 'frontmcp',\n 'dev.frontmcp.capabilities': schema.capabilities,\n },\n };\n\n return manifest;\n}\n"]}
1
+ {"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../../../../src/commands/build/mcpb/manifest.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * MCPB manifest generator + Zod schema for the emitted manifest.\n *\n * Source priority when resolving fields:\n * deployment.* (frontmcp.config) > package.json > hard defaults\n *\n * See https://github.com/modelcontextprotocol/mcpb/blob/main/MANIFEST.md\n */\n\nimport * as fs from 'fs';\nimport * as path from 'path';\nimport { z } from '@frontmcp/lazy-zod';\nimport { type ExtractedSchema, SYSTEM_TOOL_NAMES } from '../exec/cli-runtime/schema-extractor';\nimport type {\n McpbAuthor,\n McpbCompatibility,\n McpbDeployment,\n McpbRepository,\n McpbUserConfigEntry,\n} from '../../../config/frontmcp-config.types';\nimport {\n DEFAULT_NODE_COMPAT,\n DEFAULT_PLATFORMS,\n MCPB_MANIFEST_VERSION,\n} from './constants';\n\n// ============================================\n// Emitted manifest shape (MCPB v0.3 subset we produce)\n// ============================================\n\nexport interface McpbMcpConfig {\n command: string;\n args?: string[];\n env?: Record<string, string>;\n platform_overrides?: Record<string, McpbMcpConfig>;\n}\n\nexport interface McpbManifest {\n manifest_version: string;\n name: string;\n version: string;\n description: string;\n display_name?: string;\n long_description?: string;\n author: McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: { type: string; url: string };\n documentation?: string;\n support?: string;\n icon?: string;\n keywords?: string[];\n privacy_policies?: string[];\n compatibility?: McpbCompatibility;\n server: {\n type: 'node' | 'python' | 'binary' | 'uv';\n entry_point: string;\n mcp_config: McpbMcpConfig;\n };\n tools?: Array<{ name: string; description: string }>;\n tools_generated?: boolean;\n resources?: Array<{ name?: string; uri: string; description?: string; mimeType?: string }>;\n resources_generated?: boolean;\n prompts?: Array<{ name: string; description?: string }>;\n prompts_generated?: boolean;\n user_config?: Record<string, McpbUserConfigEntry>;\n _meta?: Record<string, unknown>;\n}\n\n// ============================================\n// Zod schema (used by validate.ts)\n// ============================================\n\nconst authorSchema = z\n .object({\n name: z.string(),\n email: z.string().optional(),\n url: z.string().optional(),\n })\n .strict();\n\nconst userConfigEntrySchema = z\n .object({\n type: z.enum(['string', 'number', 'boolean', 'directory', 'file']),\n title: z.string(),\n description: z.string().optional(),\n required: z.boolean().optional(),\n default: z.union([z.string(), z.number(), z.boolean()]).optional(),\n multiple: z.boolean().optional(),\n sensitive: z.boolean().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .strict();\n\nconst mcpConfigSchema: z.ZodType<McpbMcpConfig> = z.lazy(() =>\n z\n .object({\n command: z.string(),\n args: z.array(z.string()).optional(),\n env: z.record(z.string(), z.string()).optional(),\n platform_overrides: z.record(z.string(), mcpConfigSchema).optional(),\n })\n .strict(),\n);\n\nexport const mcpbManifestSchema = z\n .object({\n manifest_version: z.string(),\n name: z.string().min(1),\n version: z.string().min(1),\n description: z.string(),\n display_name: z.string().optional(),\n long_description: z.string().optional(),\n author: authorSchema,\n license: z.string().optional(),\n homepage: z.string().optional(),\n repository: z\n .object({ type: z.string(), url: z.string() })\n .strict()\n .optional(),\n documentation: z.string().optional(),\n support: z.string().optional(),\n icon: z.string().optional(),\n keywords: z.array(z.string()).optional(),\n privacy_policies: z.array(z.string()).optional(),\n compatibility: z\n .object({\n claude_desktop: z.string().optional(),\n platforms: z.array(z.enum(['darwin', 'win32', 'linux'])).optional(),\n runtimes: z\n .object({ node: z.string().optional(), python: z.string().optional() })\n .strict()\n .optional(),\n })\n .strict()\n .optional(),\n server: z\n .object({\n type: z.enum(['node', 'python', 'binary', 'uv']),\n entry_point: z.string(),\n mcp_config: mcpConfigSchema,\n })\n .strict(),\n tools: z\n .array(z.object({ name: z.string(), description: z.string() }).strict())\n .optional(),\n tools_generated: z.boolean().optional(),\n resources: z\n .array(\n z\n .object({\n name: z.string().optional(),\n uri: z.string(),\n description: z.string().optional(),\n mimeType: z.string().optional(),\n })\n .strict(),\n )\n .optional(),\n resources_generated: z.boolean().optional(),\n prompts: z\n .array(\n z\n .object({ name: z.string(), description: z.string().optional() })\n .strict(),\n )\n .optional(),\n prompts_generated: z.boolean().optional(),\n user_config: z.record(z.string(), userConfigEntrySchema).optional(),\n _meta: z.record(z.string(), z.unknown()).optional(),\n })\n .strict();\n\n// ============================================\n// Sources + helpers\n// ============================================\n\nexport interface PackageJsonMeta {\n name?: string;\n version?: string;\n description?: string;\n author?: string | McpbAuthor;\n license?: string;\n homepage?: string;\n repository?: string | { type?: string; url?: string };\n keywords?: string[];\n icon?: string;\n}\n\n/** Read and parse package.json from the given directory. Returns {} if absent. */\nexport function loadPackageJsonMeta(cwd: string): PackageJsonMeta {\n const pkgPath = path.join(cwd, 'package.json');\n if (!fs.existsSync(pkgPath)) return {};\n try {\n return JSON.parse(fs.readFileSync(pkgPath, 'utf-8')) as PackageJsonMeta;\n } catch {\n return {};\n }\n}\n\n/**\n * Parse npm-style \"Name <email> (url)\" into an McpbAuthor.\n * Falls back to `{ name: <raw> }` when parsing fails.\n */\nexport function parseAuthor(author: unknown): McpbAuthor {\n if (!author) return { name: 'unknown' };\n if (typeof author === 'object' && 'name' in author) {\n const a = author as McpbAuthor;\n return {\n name: a.name,\n ...(a.email ? { email: a.email } : {}),\n ...(a.url ? { url: a.url } : {}),\n };\n }\n if (typeof author !== 'string') {\n return { name: String(author) };\n }\n const match = author.match(/^([^<(]+?)(?:\\s*<([^>]+)>)?(?:\\s*\\(([^)]+)\\))?$/);\n if (!match || !match[1]) return { name: author };\n const [, name, email, url] = match;\n return {\n name: name.trim(),\n ...(email ? { email: email.trim() } : {}),\n ...(url ? { url: url.trim() } : {}),\n };\n}\n\n/** Normalize repository field (string → {type, url}). */\nexport function normalizeRepository(\n repo: McpbRepository | PackageJsonMeta['repository'] | undefined,\n): { type: string; url: string } | undefined {\n if (!repo) return undefined;\n if (typeof repo === 'string') {\n return { type: 'git', url: repo };\n }\n if (typeof repo === 'object' && repo.url) {\n return { type: repo.type || 'git', url: repo.url };\n }\n return undefined;\n}\n\n/** Resolve first-existing icon path. */\nexport function resolveIconPath(cwd: string, deploymentIcon?: string, pkgIcon?: string): string | undefined {\n const candidates = [deploymentIcon, pkgIcon, 'icon.png', 'assets/icon.png'].filter(\n (x): x is string => !!x,\n );\n for (const rel of candidates) {\n if (fs.existsSync(path.resolve(cwd, rel))) {\n return rel;\n }\n }\n return undefined;\n}\n\n// ============================================\n// Generator input + output\n// ============================================\n\nexport interface GenerateMcpbManifestInput {\n /** Resolved server name. */\n name: string;\n /** Resolved server version. */\n version: string;\n /** Optional resolved node version range (e.g., \">=22.0.0\"). */\n nodeVersion?: string;\n /** Project root. Used for icon resolution and package.json fallback. */\n cwd: string;\n /** Deployment config from frontmcp.config (may be undefined). */\n deployment?: McpbDeployment;\n /** Schema extracted from the compiled server bundle. */\n schema: ExtractedSchema;\n /** env → user_config reference map built by user-config.ts. */\n userConfigEnv: Record<string, string>;\n /** user_config entries built by user-config.ts. */\n userConfig: Record<string, McpbUserConfigEntry>;\n /** platform_overrides from binary.ts (may be empty). */\n platformOverrides?: Record<string, McpbMcpConfig>;\n /** Whether an icon was copied into the staged archive root. */\n hasIcon?: boolean;\n /** Tool name of the CLI version emitting this manifest (for _meta). */\n cliVersion?: string;\n}\n\n/** Produce the final MCPB manifest object. */\nexport function generateMcpbManifest(input: GenerateMcpbManifestInput): McpbManifest {\n const {\n name,\n version,\n cwd,\n deployment,\n schema,\n userConfig,\n userConfigEnv,\n platformOverrides,\n hasIcon,\n cliVersion,\n } = input;\n\n const pkg = loadPackageJsonMeta(cwd);\n\n const description = deployment?.longDescription?.split('\\n')[0]?.trim()\n || pkg.description\n || '';\n\n const author = deployment?.author || parseAuthor(pkg.author);\n const license = deployment?.license ?? pkg.license;\n const homepage = deployment?.homepage ?? pkg.homepage;\n const repository = normalizeRepository(deployment?.repository ?? pkg.repository);\n const keywords = deployment?.keywords ?? pkg.keywords;\n const icon = hasIcon ? 'icon.png' : undefined;\n\n const nodeVersion = deployment?.compatibility?.runtimes?.node\n ?? input.nodeVersion\n ?? DEFAULT_NODE_COMPAT;\n\n const compatibility: McpbCompatibility = {\n ...(deployment?.compatibility?.claude_desktop\n ? { claude_desktop: deployment.compatibility.claude_desktop }\n : {}),\n platforms: deployment?.compatibility?.platforms ?? [...DEFAULT_PLATFORMS],\n runtimes: {\n ...(deployment?.compatibility?.runtimes?.python\n ? { python: deployment.compatibility.runtimes.python }\n : {}),\n node: nodeVersion,\n },\n };\n\n const tools = schema.tools\n .filter((t) => !SYSTEM_TOOL_NAMES.has(t.name))\n .map((t) => ({ name: t.name, description: t.description || '' }));\n\n // #376 — emit resources alongside tools/prompts. The server runtime\n // already registers @Resource entries, but the manifest writer was\n // dropping them, so MCPB-aware clients had no way to discover them.\n const resources = schema.resources.map((r) => ({\n ...(r.name ? { name: r.name } : {}),\n uri: r.uri,\n ...(r.description ? { description: r.description } : {}),\n ...(r.mimeType ? { mimeType: r.mimeType } : {}),\n }));\n\n const prompts = schema.prompts.map((p) => ({\n name: p.name,\n ...(p.description ? { description: p.description } : {}),\n }));\n\n const mcpConfig: McpbMcpConfig = {\n command: 'node',\n args: ['${__dirname}/server/index.js'],\n ...(Object.keys(userConfigEnv).length > 0 ? { env: userConfigEnv } : {}),\n ...(platformOverrides && Object.keys(platformOverrides).length > 0\n ? { platform_overrides: platformOverrides }\n : {}),\n };\n\n const manifest: McpbManifest = {\n manifest_version: MCPB_MANIFEST_VERSION,\n name,\n version,\n description,\n ...(deployment?.displayName ? { display_name: deployment.displayName } : {}),\n ...(deployment?.longDescription\n ? { long_description: deployment.longDescription }\n : {}),\n author,\n ...(license ? { license } : {}),\n ...(homepage ? { homepage } : {}),\n ...(repository ? { repository } : {}),\n ...(deployment?.documentation ? { documentation: deployment.documentation } : {}),\n ...(deployment?.support ? { support: deployment.support } : {}),\n ...(icon ? { icon } : {}),\n ...(keywords && keywords.length > 0 ? { keywords } : {}),\n ...(deployment?.privacyPolicies && deployment.privacyPolicies.length > 0\n ? { privacy_policies: deployment.privacyPolicies }\n : {}),\n compatibility,\n server: {\n type: 'node',\n entry_point: 'server/index.js',\n mcp_config: mcpConfig,\n },\n tools,\n tools_generated: false,\n ...(resources.length > 0\n ? {\n resources,\n // FrontMCP resources resolve dynamically (their bodies come from\n // execute()/read()), so consumers should still query the server at\n // runtime — but the static manifest now exposes name/uri/mimeType.\n resources_generated: true,\n }\n : {}),\n prompts,\n // FrontMCP prompts resolve dynamically via execute() — MCPB's static `text`\n // template cannot represent JS logic. Set generated:true so consumers query\n // the server at runtime while still getting name/description hints here.\n prompts_generated: true,\n ...(Object.keys(userConfig).length > 0 ? { user_config: userConfig } : {}),\n _meta: {\n 'dev.frontmcp.generator': cliVersion ? `frontmcp@${cliVersion}` : 'frontmcp',\n 'dev.frontmcp.capabilities': schema.capabilities,\n },\n };\n\n return manifest;\n}\n"]}
@@ -1,3 +1,4 @@
1
+ import type { DeploymentTarget } from '../../config/frontmcp-config.types';
1
2
  /**
2
3
  * Configuration for a deployment adapter.
3
4
  * Each adapter defines how to compile and package the FrontMCP server
@@ -31,9 +32,14 @@ export type AdapterTemplate = {
31
32
  /**
32
33
  * Generate the deployment platform config file content.
33
34
  * @param cwd - Current working directory (for detecting package manager, etc.)
35
+ * @param deployment - Resolved `frontmcp.config.deployments[]` entry for this
36
+ * target, when one was found. Adapters that opt in (e.g., cloudflare)
37
+ * merge platform-specific fields (`wrangler.name`, `compatibilityDate`)
38
+ * into their generated config so values declared in `frontmcp.config.js`
39
+ * actually reach the platform — see #374.
34
40
  * @returns Object (for JSON) or string (for TOML/YAML)
35
41
  */
36
- getConfig?: (cwd: string) => object | string;
42
+ getConfig?: (cwd: string, deployment?: DeploymentTarget) => object | string;
37
43
  /** Name of the config file (e.g., 'vercel.json', 'wrangler.toml') */
38
44
  configFileName?: string;
39
45
  /**
@@ -44,5 +50,34 @@ export type AdapterTemplate = {
44
50
  * @param bundleOutput - Name of the bundled file (e.g., 'handler.cjs')
45
51
  */
46
52
  postBundle?: (outDir: string, cwd: string, bundleOutput: string) => Promise<void>;
53
+ /**
54
+ * Pre-build validation hook. Runs after schema/decorator extraction but
55
+ * before TypeScript compilation. Allows the adapter to fail loudly when
56
+ * the user's config references runtime features that won't work on the
57
+ * target platform (e.g., sqlite on Cloudflare Workers).
58
+ *
59
+ * @param decoratorConfig - Best-effort `__frontmcp:config` metadata
60
+ * extracted from the entry's @FrontMcp() decorator. May be undefined
61
+ * when the entry exports a plain config object or the decorator's
62
+ * value evaluates to undefined at module-load time (e.g., env-gated
63
+ * ternaries that resolve to undefined when the env isn't set).
64
+ * @param info - Round-2 (#375): structural metadata about the entry source.
65
+ * `info.keysSeenInSource` lists the top-level property names that appear
66
+ * in `@FrontMcp({...})` arg expressions even when their values are
67
+ * conditional. Adapters can use this to reject incompatible options
68
+ * (e.g., `sqlite: process.env.X ? {...} : undefined`) that the runtime
69
+ * config alone can't catch.
70
+ * @throws to abort the build with a user-facing message.
71
+ */
72
+ validate?: (decoratorConfig: Record<string, unknown> | undefined, info?: {
73
+ keysSeenInSource: string[];
74
+ }) => void;
75
+ /**
76
+ * Whether `getConfig()` output should overwrite an existing config file
77
+ * (e.g., wrangler.toml) on every build. When false, an existing file is
78
+ * left untouched but its contents are diffed against the build output and
79
+ * the build fails on mismatch (#374). Default: false (preserve existing).
80
+ */
81
+ alwaysWriteConfig?: boolean;
47
82
  };
48
83
  export type AdapterName = 'node' | 'vercel' | 'lambda' | 'cloudflare' | 'distributed';
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/commands/build/types.ts"],"names":[],"mappings":"","sourcesContent":["/**\n * Configuration for a deployment adapter.\n * Each adapter defines how to compile and package the FrontMCP server\n * for a specific deployment target.\n */\nexport type AdapterTemplate = {\n /** Module format for TypeScript compilation */\n moduleFormat: 'commonjs' | 'esnext';\n\n /**\n * Generate the entry point file content.\n * @param mainModulePath - Relative path to the compiled main module (e.g., './main.js')\n * @returns The content for index.js, or empty string if no wrapper needed\n */\n getEntryTemplate: (mainModulePath: string) => string;\n\n /**\n * Generate the serverless setup file content.\n * This file is imported first to set environment variables before decorators run.\n * @returns The content for serverless-setup.js, or undefined if not needed\n */\n getSetupTemplate?: () => string;\n\n /**\n * Whether to bundle the output with rspack.\n * Recommended for serverless deployments to avoid ESM/CJS issues.\n */\n shouldBundle?: boolean;\n\n /**\n * Output filename for the bundled file (e.g., 'handler.cjs').\n * Only used when shouldBundle is true.\n */\n bundleOutput?: string;\n\n /**\n * Generate the deployment platform config file content.\n * @param cwd - Current working directory (for detecting package manager, etc.)\n * @returns Object (for JSON) or string (for TOML/YAML)\n */\n getConfig?: (cwd: string) => object | string;\n\n /** Name of the config file (e.g., 'vercel.json', 'wrangler.toml') */\n configFileName?: string;\n\n /**\n * Post-bundle hook for creating deployment-specific output structure.\n * Called after bundling is complete.\n * @param outDir - The output directory (e.g., 'dist')\n * @param cwd - Current working directory\n * @param bundleOutput - Name of the bundled file (e.g., 'handler.cjs')\n */\n postBundle?: (outDir: string, cwd: string, bundleOutput: string) => Promise<void>;\n};\n\nexport type AdapterName = 'node' | 'vercel' | 'lambda' | 'cloudflare' | 'distributed';\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/commands/build/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { DeploymentTarget } from '../../config/frontmcp-config.types';\n\n/**\n * Configuration for a deployment adapter.\n * Each adapter defines how to compile and package the FrontMCP server\n * for a specific deployment target.\n */\nexport type AdapterTemplate = {\n /** Module format for TypeScript compilation */\n moduleFormat: 'commonjs' | 'esnext';\n\n /**\n * Generate the entry point file content.\n * @param mainModulePath - Relative path to the compiled main module (e.g., './main.js')\n * @returns The content for index.js, or empty string if no wrapper needed\n */\n getEntryTemplate: (mainModulePath: string) => string;\n\n /**\n * Generate the serverless setup file content.\n * This file is imported first to set environment variables before decorators run.\n * @returns The content for serverless-setup.js, or undefined if not needed\n */\n getSetupTemplate?: () => string;\n\n /**\n * Whether to bundle the output with rspack.\n * Recommended for serverless deployments to avoid ESM/CJS issues.\n */\n shouldBundle?: boolean;\n\n /**\n * Output filename for the bundled file (e.g., 'handler.cjs').\n * Only used when shouldBundle is true.\n */\n bundleOutput?: string;\n\n /**\n * Generate the deployment platform config file content.\n * @param cwd - Current working directory (for detecting package manager, etc.)\n * @param deployment - Resolved `frontmcp.config.deployments[]` entry for this\n * target, when one was found. Adapters that opt in (e.g., cloudflare)\n * merge platform-specific fields (`wrangler.name`, `compatibilityDate`)\n * into their generated config so values declared in `frontmcp.config.js`\n * actually reach the platform — see #374.\n * @returns Object (for JSON) or string (for TOML/YAML)\n */\n getConfig?: (cwd: string, deployment?: DeploymentTarget) => object | string;\n\n /** Name of the config file (e.g., 'vercel.json', 'wrangler.toml') */\n configFileName?: string;\n\n /**\n * Post-bundle hook for creating deployment-specific output structure.\n * Called after bundling is complete.\n * @param outDir - The output directory (e.g., 'dist')\n * @param cwd - Current working directory\n * @param bundleOutput - Name of the bundled file (e.g., 'handler.cjs')\n */\n postBundle?: (outDir: string, cwd: string, bundleOutput: string) => Promise<void>;\n\n /**\n * Pre-build validation hook. Runs after schema/decorator extraction but\n * before TypeScript compilation. Allows the adapter to fail loudly when\n * the user's config references runtime features that won't work on the\n * target platform (e.g., sqlite on Cloudflare Workers).\n *\n * @param decoratorConfig - Best-effort `__frontmcp:config` metadata\n * extracted from the entry's @FrontMcp() decorator. May be undefined\n * when the entry exports a plain config object or the decorator's\n * value evaluates to undefined at module-load time (e.g., env-gated\n * ternaries that resolve to undefined when the env isn't set).\n * @param info - Round-2 (#375): structural metadata about the entry source.\n * `info.keysSeenInSource` lists the top-level property names that appear\n * in `@FrontMcp({...})` arg expressions even when their values are\n * conditional. Adapters can use this to reject incompatible options\n * (e.g., `sqlite: process.env.X ? {...} : undefined`) that the runtime\n * config alone can't catch.\n * @throws to abort the build with a user-facing message.\n */\n validate?: (\n decoratorConfig: Record<string, unknown> | undefined,\n info?: { keysSeenInSource: string[] },\n ) => void;\n\n /**\n * Whether `getConfig()` output should overwrite an existing config file\n * (e.g., wrangler.toml) on every build. When false, an existing file is\n * left untouched but its contents are diffed against the build output and\n * the build fails on mismatch (#374). Default: false (preserve existing).\n */\n alwaysWriteConfig?: boolean;\n};\n\nexport type AdapterName = 'node' | 'vercel' | 'lambda' | 'cloudflare' | 'distributed';\n"]}
@@ -2,10 +2,10 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runDoctor = runDoctor;
4
4
  const tslib_1 = require("tslib");
5
- const path = tslib_1.__importStar(require("path"));
6
5
  const child_process_1 = require("child_process");
7
- const colors_1 = require("../../core/colors");
6
+ const path = tslib_1.__importStar(require("path"));
8
7
  const utils_1 = require("@frontmcp/utils");
8
+ const colors_1 = require("../../core/colors");
9
9
  const tsconfig_1 = require("../../core/tsconfig");
10
10
  const fs_1 = require("../../shared/fs");
11
11
  function cmpSemver(a, b) {
@@ -35,7 +35,11 @@ async function runDoctor() {
35
35
  let npmVer = 'unknown';
36
36
  try {
37
37
  npmVer = await new Promise((resolve, reject) => {
38
- const child = (0, child_process_1.spawn)('npm', ['-v'], { shell: true });
38
+ // shell:true triggers Node DEP0190 (deprecated unescaped-arg passing).
39
+ // Use explicit binary names: npm.cmd on win32, npm elsewhere — args
40
+ // already in array form, no shell needed.
41
+ const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';
42
+ const child = (0, child_process_1.spawn)(npmCmd, ['-v']);
39
43
  let out = '';
40
44
  child.stdout?.on('data', (d) => (out += String(d)));
41
45
  child.on('close', () => resolve(out.trim()));
@@ -1 +1 @@
1
- {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../../src/commands/dev/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from 'path';\nimport { spawn } from 'child_process';\nimport { c } from '../../core/colors';\nimport { fileExists, readJSON } from '@frontmcp/utils';\nimport { checkRequiredTsOptions } from '../../core/tsconfig';\nimport { resolveEntry } from '../../shared/fs';\n\nfunction cmpSemver(a: string, b: string): number {\n const pa = a.split('.').map((n) => parseInt(n, 10) || 0);\n const pb = b.split('.').map((n) => parseInt(n, 10) || 0);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] || 0) > (pb[i] || 0)) return 1;\n if ((pa[i] || 0) < (pb[i] || 0)) return -1;\n }\n return 0;\n}\n\nexport async function runDoctor(): Promise<void> {\n const MIN_NODE = '22.0.0';\n const MIN_NPM = '10.0.0';\n const cwd = process.cwd();\n\n let ok = true;\n\n const nodeVer = process.versions.node;\n if (cmpSemver(nodeVer, MIN_NODE) >= 0) {\n console.log(`✅ Node ${nodeVer} (min ${MIN_NODE})`);\n } else {\n ok = false;\n console.log(`❌ Node ${nodeVer} — please upgrade to >= ${MIN_NODE}`);\n }\n\n let npmVer = 'unknown';\n try {\n npmVer = await new Promise<string>((resolve, reject) => {\n const child = spawn('npm', ['-v'], { shell: true });\n let out = '';\n child.stdout?.on('data', (d) => (out += String(d)));\n child.on('close', () => resolve(out.trim()));\n child.on('error', reject);\n });\n if (cmpSemver(npmVer, MIN_NPM) >= 0) {\n console.log(`✅ npm ${npmVer} (min ${MIN_NPM})`);\n } else {\n ok = false;\n console.log(`❌ npm ${npmVer} — please upgrade to >= ${MIN_NPM}`);\n }\n } catch {\n ok = false;\n console.log('❌ npm not found in PATH');\n }\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n if (await fileExists(tsconfigPath)) {\n console.log(`✅ tsconfig.json found`);\n const tsconfig = await readJSON<Record<string, any>>(tsconfigPath);\n const { ok: oks, issues } = checkRequiredTsOptions(tsconfig?.compilerOptions);\n for (const line of oks) console.log(c('green', ` ✓ ${line}`));\n if (issues.length) {\n ok = false;\n for (const line of issues) console.log(c('yellow', ` • ${line}`));\n console.log(c('cyan', ` -> Run \"frontmcp init\" to apply the required settings.`));\n }\n } else {\n ok = false;\n console.log(`❌ tsconfig.json not found — run ${c('cyan', 'frontmcp init')}`);\n }\n\n try {\n const entry = await resolveEntry(cwd);\n console.log(`✅ entry detected: ${path.relative(cwd, entry)}`);\n } catch (e: unknown) {\n ok = false;\n const firstLine = e instanceof Error ? (e.message.split('\\n')[0] ?? 'entry not found') : 'entry not found';\n console.log(`❌ entry not detected — ${firstLine}`);\n }\n\n if (ok) console.log(c('green', '\\nAll checks passed. You are ready to go!'));\n else console.log(c('yellow', '\\nSome checks failed. See above for fixes.'));\n}\n"]}
1
+ {"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../../../src/commands/dev/doctor.ts"],"names":[],"mappings":"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","sourcesContent":["import { spawn } from 'child_process';\nimport * as path from 'path';\n\nimport { fileExists, readJSON } from '@frontmcp/utils';\n\nimport { c } from '../../core/colors';\nimport { checkRequiredTsOptions } from '../../core/tsconfig';\nimport { resolveEntry } from '../../shared/fs';\n\nfunction cmpSemver(a: string, b: string): number {\n const pa = a.split('.').map((n) => parseInt(n, 10) || 0);\n const pb = b.split('.').map((n) => parseInt(n, 10) || 0);\n for (let i = 0; i < 3; i++) {\n if ((pa[i] || 0) > (pb[i] || 0)) return 1;\n if ((pa[i] || 0) < (pb[i] || 0)) return -1;\n }\n return 0;\n}\n\nexport async function runDoctor(): Promise<void> {\n const MIN_NODE = '22.0.0';\n const MIN_NPM = '10.0.0';\n const cwd = process.cwd();\n\n let ok = true;\n\n const nodeVer = process.versions.node;\n if (cmpSemver(nodeVer, MIN_NODE) >= 0) {\n console.log(`✅ Node ${nodeVer} (min ${MIN_NODE})`);\n } else {\n ok = false;\n console.log(`❌ Node ${nodeVer} — please upgrade to >= ${MIN_NODE}`);\n }\n\n let npmVer = 'unknown';\n try {\n npmVer = await new Promise<string>((resolve, reject) => {\n // shell:true triggers Node DEP0190 (deprecated unescaped-arg passing).\n // Use explicit binary names: npm.cmd on win32, npm elsewhere — args\n // already in array form, no shell needed.\n const npmCmd = process.platform === 'win32' ? 'npm.cmd' : 'npm';\n const child = spawn(npmCmd, ['-v']);\n let out = '';\n child.stdout?.on('data', (d) => (out += String(d)));\n child.on('close', () => resolve(out.trim()));\n child.on('error', reject);\n });\n if (cmpSemver(npmVer, MIN_NPM) >= 0) {\n console.log(`✅ npm ${npmVer} (min ${MIN_NPM})`);\n } else {\n ok = false;\n console.log(`❌ npm ${npmVer} — please upgrade to >= ${MIN_NPM}`);\n }\n } catch {\n ok = false;\n console.log('❌ npm not found in PATH');\n }\n\n const tsconfigPath = path.join(cwd, 'tsconfig.json');\n if (await fileExists(tsconfigPath)) {\n console.log(`✅ tsconfig.json found`);\n const tsconfig = await readJSON<Record<string, any>>(tsconfigPath);\n const { ok: oks, issues } = checkRequiredTsOptions(tsconfig?.compilerOptions);\n for (const line of oks) console.log(c('green', ` ✓ ${line}`));\n if (issues.length) {\n ok = false;\n for (const line of issues) console.log(c('yellow', ` • ${line}`));\n console.log(c('cyan', ` -> Run \"frontmcp init\" to apply the required settings.`));\n }\n } else {\n ok = false;\n console.log(`❌ tsconfig.json not found — run ${c('cyan', 'frontmcp init')}`);\n }\n\n try {\n const entry = await resolveEntry(cwd);\n console.log(`✅ entry detected: ${path.relative(cwd, entry)}`);\n } catch (e: unknown) {\n ok = false;\n const firstLine = e instanceof Error ? (e.message.split('\\n')[0] ?? 'entry not found') : 'entry not found';\n console.log(`❌ entry not detected — ${firstLine}`);\n }\n\n if (ok) console.log(c('green', '\\nAll checks passed. You are ready to go!'));\n else console.log(c('yellow', '\\nSome checks failed. See above for fixes.'));\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  /**
2
2
  * runInstall() orchestrator — installs an MCP app from npm, local, or git source.
3
3
  */
4
- import { ParsedArgs } from '../../core/args';
4
+ import { type ParsedArgs } from '../../core/args';
5
5
  export declare function runInstall(opts: ParsedArgs): Promise<void>;
@@ -5,18 +5,18 @@
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.runInstall = runInstall;
7
7
  const tslib_1 = require("tslib");
8
- const path = tslib_1.__importStar(require("path"));
9
8
  const fs = tslib_1.__importStar(require("fs"));
10
9
  const os = tslib_1.__importStar(require("os"));
10
+ const path = tslib_1.__importStar(require("path"));
11
+ const utils_1 = require("@frontmcp/utils");
11
12
  const colors_1 = require("../../core/colors");
12
13
  const paths_1 = require("../pm/paths");
13
- const types_1 = require("./types");
14
- const registry_1 = require("./registry");
15
14
  const questionnaire_1 = require("./questionnaire");
16
- const npm_1 = require("./sources/npm");
17
- const local_1 = require("./sources/local");
15
+ const registry_1 = require("./registry");
18
16
  const git_1 = require("./sources/git");
19
- const utils_1 = require("@frontmcp/utils");
17
+ const local_1 = require("./sources/local");
18
+ const npm_1 = require("./sources/npm");
19
+ const types_1 = require("./types");
20
20
  async function runInstall(opts) {
21
21
  const sourceStr = opts._[1];
22
22
  if (!sourceStr) {
@@ -99,8 +99,10 @@ async function runInstall(opts) {
99
99
  (0, questionnaire_1.writeEnvFile)(installDir, result.envContent);
100
100
  console.log(`${(0, colors_1.c)('green', '[install]')} configuration saved to .env`);
101
101
  }
102
- // 8. Register in registry
103
- const port = opts.port || manifestData.network.defaultPort;
102
+ // 8. Register in registry. CLI builds omit the network section (they don't
103
+ // bind a port), so fall back to undefined when --port wasn't passed.
104
+ // Use `??` (not `||`) so an explicit `--port 0` overrides the manifest.
105
+ const port = opts.port ?? manifestData.network?.defaultPort;
104
106
  (0, registry_1.registerApp)(manifestData.name, {
105
107
  version: manifestData.version,
106
108
  installDir,
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../../src/commands/package/install.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * runInstall() orchestrator — installs an MCP app from npm, local, or git source.\n */\n\nimport * as path from 'path';\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport { ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { appDir, ensurePmDirs } from '../pm/paths';\nimport { parseInstallSource } from './types';\nimport { registerApp } from './registry';\nimport { runQuestionnaire, writeEnvFile } from './questionnaire';\nimport { fetchFromNpm } from './sources/npm';\nimport { fetchFromLocal } from './sources/local';\nimport { fetchFromGit } from './sources/git';\nimport { ExecManifest } from '../build/exec/manifest';\nimport { runCmd } from '@frontmcp/utils';\n\nexport async function runInstall(opts: ParsedArgs): Promise<void> {\n const sourceStr = opts._[1];\n if (!sourceStr) {\n throw new Error('Missing install source. Usage: frontmcp install <npm-package|./local-path|github:user/repo>');\n }\n\n const source = parseInstallSource(sourceStr);\n console.log(`${c('cyan', '[install]')} source: ${source.type} → ${source.ref}`);\n\n // Create temp directory\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'frontmcp-install-'));\n\n try {\n // 1. Fetch to temp directory\n console.log(`${c('cyan', '[install]')} fetching...`);\n let packageDir: string;\n\n switch (source.type) {\n case 'npm':\n packageDir = await fetchFromNpm(source.ref, tmpDir, opts.registry);\n break;\n case 'local':\n packageDir = await fetchFromLocal(source.ref, tmpDir);\n break;\n case 'git':\n packageDir = await fetchFromGit(source.ref, tmpDir);\n break;\n case 'esm':\n throw new Error(\n 'ESM sources cannot be installed via \"frontmcp install\". ' +\n 'Use loadFrom() in your FrontMcp config to load ESM packages at runtime.',\n );\n }\n\n // 2. Look for manifest\n let manifest = findManifest(packageDir);\n\n // 3. If no manifest, check for frontmcp.config.js and build\n if (!manifest) {\n const configPath = path.join(packageDir, 'frontmcp.config.js');\n const configJsonPath = path.join(packageDir, 'frontmcp.config.json');\n\n if (fs.existsSync(configPath) || fs.existsSync(configJsonPath)) {\n console.log(`${c('cyan', '[install]')} no manifest found, building from config...`);\n await runCmd('npx', ['frontmcp', 'build', '--target', 'node'], {\n cwd: packageDir,\n });\n manifest = findManifest(path.join(packageDir, 'dist')) || findManifest(packageDir);\n }\n }\n\n if (!manifest) {\n throw new Error(\n 'Could not find or generate a manifest. Ensure the package has a ' +\n 'frontmcp.config.js (or frontmcp.config.json) or was built with \"frontmcp build --target node\".',\n );\n }\n\n const { data: manifestData, dir: manifestDir } = manifest;\n\n // 4. Install to ~/.frontmcp/apps/{name}/\n const installDir = appDir(manifestData.name);\n ensurePmDirs();\n fs.mkdirSync(installDir, { recursive: true });\n\n console.log(`${c('cyan', '[install]')} installing \"${manifestData.name}\" to ${installDir}`);\n\n // Copy bundle + manifest + runner\n copyIfExists(manifestDir, installDir, manifestData.bundle);\n copyIfExists(manifestDir, installDir, `${manifestData.name}.manifest.json`);\n copyIfExists(manifestDir, installDir, manifestData.name);\n\n // Make runner executable\n const runnerPath = path.join(installDir, manifestData.name);\n if (fs.existsSync(runnerPath)) {\n fs.chmodSync(runnerPath, 0o755);\n }\n\n // 5. Install native addons\n if (manifestData.dependencies.nativeAddons.length > 0) {\n console.log(`${c('cyan', '[install]')} installing native dependencies...`);\n await runCmd('npm', ['init', '-y', '--silent'], { cwd: installDir });\n await runCmd('npm', ['install', ...manifestData.dependencies.nativeAddons, '--save', '--silent'], {\n cwd: installDir,\n });\n }\n\n // 6. Set up SQLite data dir if needed\n if (manifestData.storage.type === 'sqlite') {\n const dataDir = path.join(os.homedir(), '.frontmcp', 'data', manifestData.name);\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n // 7. Run setup questionnaire\n if (manifestData.setup?.steps && manifestData.setup.steps.length > 0) {\n console.log(`\\n${c('bold', 'Setup Configuration')}`);\n const result = await runQuestionnaire(manifestData.setup.steps, {\n silent: opts.yes,\n });\n writeEnvFile(installDir, result.envContent);\n console.log(`${c('green', '[install]')} configuration saved to .env`);\n }\n\n // 8. Register in registry\n const port = opts.port || manifestData.network.defaultPort;\n registerApp(manifestData.name, {\n version: manifestData.version,\n installDir,\n installedAt: new Date().toISOString(),\n runner: path.join(installDir, manifestData.name),\n bundle: path.join(installDir, manifestData.bundle),\n storage: manifestData.storage.type,\n port,\n source: { type: source.type, ref: source.ref },\n });\n\n console.log(`\\n${c('green', `Installed \"${manifestData.name}\" successfully.`)}`);\n console.log(`\\n${c('bold', 'Start with:')}`);\n console.log(` frontmcp start ${manifestData.name}`);\n console.log(`\\n${c('bold', 'Reconfigure:')}`);\n console.log(` frontmcp configure ${manifestData.name}`);\n } finally {\n // Clean up temp directory\n try {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // ignore cleanup errors\n }\n }\n}\n\nfunction findManifest(dir: string): { data: ExecManifest; dir: string } | null {\n if (!fs.existsSync(dir)) return null;\n\n const files = fs.readdirSync(dir);\n const manifestFile = files.find((f: string) => f.endsWith('.manifest.json'));\n\n if (manifestFile) {\n const manifestPath = path.join(dir, manifestFile);\n const data = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as ExecManifest;\n return { data, dir };\n }\n\n // Check dist/ subdirectory\n const distDir = path.join(dir, 'dist');\n if (fs.existsSync(distDir)) {\n return findManifest(distDir);\n }\n\n return null;\n}\n\nfunction copyIfExists(fromDir: string, toDir: string, filename: string): void {\n const src = path.join(fromDir, filename);\n if (fs.existsSync(src)) {\n fs.copyFileSync(src, path.join(toDir, filename));\n }\n}\n"]}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../../../src/commands/package/install.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * runInstall() orchestrator — installs an MCP app from npm, local, or git source.\n */\n\nimport * as fs from 'fs';\nimport * as os from 'os';\nimport * as path from 'path';\n\nimport { runCmd } from '@frontmcp/utils';\n\nimport { type ParsedArgs } from '../../core/args';\nimport { c } from '../../core/colors';\nimport { type ExecManifest } from '../build/exec/manifest';\nimport { appDir, ensurePmDirs } from '../pm/paths';\nimport { runQuestionnaire, writeEnvFile } from './questionnaire';\nimport { registerApp } from './registry';\nimport { fetchFromGit } from './sources/git';\nimport { fetchFromLocal } from './sources/local';\nimport { fetchFromNpm } from './sources/npm';\nimport { parseInstallSource } from './types';\n\nexport async function runInstall(opts: ParsedArgs): Promise<void> {\n const sourceStr = opts._[1];\n if (!sourceStr) {\n throw new Error('Missing install source. Usage: frontmcp install <npm-package|./local-path|github:user/repo>');\n }\n\n const source = parseInstallSource(sourceStr);\n console.log(`${c('cyan', '[install]')} source: ${source.type} → ${source.ref}`);\n\n // Create temp directory\n const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'frontmcp-install-'));\n\n try {\n // 1. Fetch to temp directory\n console.log(`${c('cyan', '[install]')} fetching...`);\n let packageDir: string;\n\n switch (source.type) {\n case 'npm':\n packageDir = await fetchFromNpm(source.ref, tmpDir, opts.registry);\n break;\n case 'local':\n packageDir = await fetchFromLocal(source.ref, tmpDir);\n break;\n case 'git':\n packageDir = await fetchFromGit(source.ref, tmpDir);\n break;\n case 'esm':\n throw new Error(\n 'ESM sources cannot be installed via \"frontmcp install\". ' +\n 'Use loadFrom() in your FrontMcp config to load ESM packages at runtime.',\n );\n }\n\n // 2. Look for manifest\n let manifest = findManifest(packageDir);\n\n // 3. If no manifest, check for frontmcp.config.js and build\n if (!manifest) {\n const configPath = path.join(packageDir, 'frontmcp.config.js');\n const configJsonPath = path.join(packageDir, 'frontmcp.config.json');\n\n if (fs.existsSync(configPath) || fs.existsSync(configJsonPath)) {\n console.log(`${c('cyan', '[install]')} no manifest found, building from config...`);\n await runCmd('npx', ['frontmcp', 'build', '--target', 'node'], {\n cwd: packageDir,\n });\n manifest = findManifest(path.join(packageDir, 'dist')) || findManifest(packageDir);\n }\n }\n\n if (!manifest) {\n throw new Error(\n 'Could not find or generate a manifest. Ensure the package has a ' +\n 'frontmcp.config.js (or frontmcp.config.json) or was built with \"frontmcp build --target node\".',\n );\n }\n\n const { data: manifestData, dir: manifestDir } = manifest;\n\n // 4. Install to ~/.frontmcp/apps/{name}/\n const installDir = appDir(manifestData.name);\n ensurePmDirs();\n fs.mkdirSync(installDir, { recursive: true });\n\n console.log(`${c('cyan', '[install]')} installing \"${manifestData.name}\" to ${installDir}`);\n\n // Copy bundle + manifest + runner\n copyIfExists(manifestDir, installDir, manifestData.bundle);\n copyIfExists(manifestDir, installDir, `${manifestData.name}.manifest.json`);\n copyIfExists(manifestDir, installDir, manifestData.name);\n\n // Make runner executable\n const runnerPath = path.join(installDir, manifestData.name);\n if (fs.existsSync(runnerPath)) {\n fs.chmodSync(runnerPath, 0o755);\n }\n\n // 5. Install native addons\n if (manifestData.dependencies.nativeAddons.length > 0) {\n console.log(`${c('cyan', '[install]')} installing native dependencies...`);\n await runCmd('npm', ['init', '-y', '--silent'], { cwd: installDir });\n await runCmd('npm', ['install', ...manifestData.dependencies.nativeAddons, '--save', '--silent'], {\n cwd: installDir,\n });\n }\n\n // 6. Set up SQLite data dir if needed\n if (manifestData.storage.type === 'sqlite') {\n const dataDir = path.join(os.homedir(), '.frontmcp', 'data', manifestData.name);\n fs.mkdirSync(dataDir, { recursive: true });\n }\n\n // 7. Run setup questionnaire\n if (manifestData.setup?.steps && manifestData.setup.steps.length > 0) {\n console.log(`\\n${c('bold', 'Setup Configuration')}`);\n const result = await runQuestionnaire(manifestData.setup.steps, {\n silent: opts.yes,\n });\n writeEnvFile(installDir, result.envContent);\n console.log(`${c('green', '[install]')} configuration saved to .env`);\n }\n\n // 8. Register in registry. CLI builds omit the network section (they don't\n // bind a port), so fall back to undefined when --port wasn't passed.\n // Use `??` (not `||`) so an explicit `--port 0` overrides the manifest.\n const port = opts.port ?? manifestData.network?.defaultPort;\n registerApp(manifestData.name, {\n version: manifestData.version,\n installDir,\n installedAt: new Date().toISOString(),\n runner: path.join(installDir, manifestData.name),\n bundle: path.join(installDir, manifestData.bundle),\n storage: manifestData.storage.type,\n port,\n source: { type: source.type, ref: source.ref },\n });\n\n console.log(`\\n${c('green', `Installed \"${manifestData.name}\" successfully.`)}`);\n console.log(`\\n${c('bold', 'Start with:')}`);\n console.log(` frontmcp start ${manifestData.name}`);\n console.log(`\\n${c('bold', 'Reconfigure:')}`);\n console.log(` frontmcp configure ${manifestData.name}`);\n } finally {\n // Clean up temp directory\n try {\n fs.rmSync(tmpDir, { recursive: true, force: true });\n } catch {\n // ignore cleanup errors\n }\n }\n}\n\nfunction findManifest(dir: string): { data: ExecManifest; dir: string } | null {\n if (!fs.existsSync(dir)) return null;\n\n const files = fs.readdirSync(dir);\n const manifestFile = files.find((f: string) => f.endsWith('.manifest.json'));\n\n if (manifestFile) {\n const manifestPath = path.join(dir, manifestFile);\n const data = JSON.parse(fs.readFileSync(manifestPath, 'utf-8')) as ExecManifest;\n return { data, dir };\n }\n\n // Check dist/ subdirectory\n const distDir = path.join(dir, 'dist');\n if (fs.existsSync(distDir)) {\n return findManifest(distDir);\n }\n\n return null;\n}\n\nfunction copyIfExists(fromDir: string, toDir: string, filename: string): void {\n const src = path.join(fromDir, filename);\n if (fs.existsSync(src)) {\n fs.copyFileSync(src, path.join(toDir, filename));\n }\n}\n"]}
@@ -15,7 +15,8 @@ export interface FrontmcpRegistry {
15
15
  runner: string;
16
16
  bundle: string;
17
17
  storage: 'sqlite' | 'redis' | 'none';
18
- port: number;
18
+ /** Server port. Optional because CLI builds (no network) don't bind a port. */
19
+ port?: number;
19
20
  source?: {
20
21
  type: InstallSourceType;
21
22
  ref: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/commands/package/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAuCH,gDAeC;AAtBD;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAAC,MAAc;IAC/C,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAED,iHAAiH;IACjH,IAAI,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC","sourcesContent":["/**\n * Install source parsing and types.\n */\n\nexport type InstallSourceType = 'npm' | 'local' | 'git' | 'esm';\n\nexport interface InstallSource {\n type: InstallSourceType;\n ref: string;\n}\n\nexport interface FrontmcpRegistry {\n version: 1;\n apps: Record<\n string,\n {\n version: string;\n installDir: string;\n installedAt: string;\n runner: string;\n bundle: string;\n storage: 'sqlite' | 'redis' | 'none';\n port: number;\n source?: { type: InstallSourceType; ref: string };\n /** Resolved ESM version (for ESM-loaded apps) */\n esmVersion?: string;\n /** Path to cached ESM bundle */\n esmCachePath?: string;\n /** ISO timestamp of last update check */\n lastUpdateCheck?: string;\n }\n >;\n}\n\n/**\n * Parse an install source string into a typed source object.\n *\n * - Starts with `./ | ../ | /` → local\n * - Starts with `github:` or `git+` or ends with `.git` → git\n * - Everything else → npm\n */\nexport function parseInstallSource(source: string): InstallSource {\n if (source.startsWith('./') || source.startsWith('../') || source.startsWith('/')) {\n return { type: 'local', ref: source };\n }\n\n // ESM sources: explicit esm.sh URL or esm: prefix (checked before git to avoid esm:...pkg.git misclassification)\n if (source.startsWith('https://esm.sh/') || source.startsWith('esm:')) {\n return { type: 'esm', ref: source.replace(/^esm:/, '') };\n }\n\n if (source.startsWith('github:') || source.startsWith('git+') || source.endsWith('.git')) {\n return { type: 'git', ref: source };\n }\n\n return { type: 'npm', ref: source };\n}\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/commands/package/types.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAwCH,gDAeC;AAtBD;;;;;;GAMG;AACH,SAAgB,kBAAkB,CAAC,MAAc;IAC/C,IAAI,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QAClF,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACxC,CAAC;IAED,iHAAiH;IACjH,IAAI,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,EAAE,CAAC;IAC3D,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QACzF,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;IACtC,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACtC,CAAC","sourcesContent":["/**\n * Install source parsing and types.\n */\n\nexport type InstallSourceType = 'npm' | 'local' | 'git' | 'esm';\n\nexport interface InstallSource {\n type: InstallSourceType;\n ref: string;\n}\n\nexport interface FrontmcpRegistry {\n version: 1;\n apps: Record<\n string,\n {\n version: string;\n installDir: string;\n installedAt: string;\n runner: string;\n bundle: string;\n storage: 'sqlite' | 'redis' | 'none';\n /** Server port. Optional because CLI builds (no network) don't bind a port. */\n port?: number;\n source?: { type: InstallSourceType; ref: string };\n /** Resolved ESM version (for ESM-loaded apps) */\n esmVersion?: string;\n /** Path to cached ESM bundle */\n esmCachePath?: string;\n /** ISO timestamp of last update check */\n lastUpdateCheck?: string;\n }\n >;\n}\n\n/**\n * Parse an install source string into a typed source object.\n *\n * - Starts with `./ | ../ | /` → local\n * - Starts with `github:` or `git+` or ends with `.git` → git\n * - Everything else → npm\n */\nexport function parseInstallSource(source: string): InstallSource {\n if (source.startsWith('./') || source.startsWith('../') || source.startsWith('/')) {\n return { type: 'local', ref: source };\n }\n\n // ESM sources: explicit esm.sh URL or esm: prefix (checked before git to avoid esm:...pkg.git misclassification)\n if (source.startsWith('https://esm.sh/') || source.startsWith('esm:')) {\n return { type: 'esm', ref: source.replace(/^esm:/, '') };\n }\n\n if (source.startsWith('github:') || source.startsWith('git+') || source.endsWith('.git')) {\n return { type: 'git', ref: source };\n }\n\n return { type: 'npm', ref: source };\n}\n"]}
@@ -18,6 +18,26 @@ import type { DeploymentTarget } from './frontmcp-config.types';
18
18
  * 6. Derive from package.json (minimal config with 'node' target)
19
19
  */
20
20
  export declare function loadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed>;
21
+ /**
22
+ * Variant that load-errors propagate (parse failures in `frontmcp.config.ts`,
23
+ * missing dependencies, etc.) but schema-validation errors return `undefined`.
24
+ *
25
+ * Used by `runBuild` to support both shapes: the new top-level
26
+ * `frontmcpConfigSchema` (with `deployments`) and the older exec-only shape
27
+ * (top-level `cli`, `sea`, `esbuild`) that `loadExecConfig` consumes
28
+ * directly. A user with the old shape should still get a successful build
29
+ * — the exec-loader picks the file up from disk by itself.
30
+ *
31
+ * Returns `undefined` when:
32
+ * - no config file is present (caller falls back to CLI flags), or
33
+ * - the file loads but doesn't match the new schema (legacy shape).
34
+ *
35
+ * Throws when:
36
+ * - the file exists but can't be parsed (TS syntax error, ESM/CJS mismatch
37
+ * that even esbuild can't recover from, etc.) — i.e., #365 silent-default
38
+ * regressions.
39
+ */
40
+ export declare function tryLoadFrontMcpConfig(cwd: string): Promise<FrontMcpConfigParsed | undefined>;
21
41
  /**
22
42
  * Validate raw config against the Zod schema.
23
43
  */