mcp-use 2.0.0-beta.11 → 2.0.0-beta.13

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 (51) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/bin/main.d.ts.map +1 -1
  3. package/dist/bin.js +5 -2
  4. package/dist/bin.js.map +1 -1
  5. package/dist/branding.d.ts +7 -10
  6. package/dist/branding.d.ts.map +1 -1
  7. package/dist/{chunk-GTOOHAI2.js → chunk-JEVBOMCE.js} +4 -3
  8. package/dist/chunk-JEVBOMCE.js.map +1 -0
  9. package/dist/{chunk-5M5NVF36.js → chunk-RHITI5QM.js} +67 -8
  10. package/dist/chunk-RHITI5QM.js.map +1 -0
  11. package/dist/{chunk-DQ7LE4ZA.js → chunk-XKJP5S7C.js} +17 -14
  12. package/dist/chunk-XKJP5S7C.js.map +1 -0
  13. package/dist/cli/build.d.ts +1 -1
  14. package/dist/cli/dev.d.ts.map +1 -1
  15. package/dist/cli/mcp-env-declaration.d.ts +20 -0
  16. package/dist/cli/mcp-env-declaration.d.ts.map +1 -0
  17. package/dist/cli/tunnel.d.ts.map +1 -1
  18. package/dist/cli/views.d.ts +7 -5
  19. package/dist/cli/views.d.ts.map +1 -1
  20. package/dist/commands/build.js +6 -6
  21. package/dist/commands/build.js.map +1 -1
  22. package/dist/commands/client.d.ts.map +1 -1
  23. package/dist/commands/client.js +1 -1
  24. package/dist/commands/dev.js +79 -12
  25. package/dist/commands/dev.js.map +1 -1
  26. package/dist/commands/load-client.d.ts +2 -0
  27. package/dist/commands/load-client.d.ts.map +1 -1
  28. package/dist/commands/screenshot.js +1 -1
  29. package/dist/config.d.ts +8 -8
  30. package/dist/index.js +32 -51
  31. package/dist/index.js.map +1 -1
  32. package/dist/inspector-shell.d.ts +3 -0
  33. package/dist/inspector-shell.d.ts.map +1 -1
  34. package/dist/{landing-handler-3VN4BMR2.js → landing-handler-Z7WDR4S2.js} +6 -3
  35. package/dist/landing-handler-Z7WDR4S2.js.map +1 -0
  36. package/dist/landing-handler.d.ts +1 -1
  37. package/dist/landing-handler.d.ts.map +1 -1
  38. package/dist/landing.d.ts +2 -0
  39. package/dist/landing.d.ts.map +1 -1
  40. package/dist/landing.js +1 -1
  41. package/dist/react/types/register.d.ts +1 -1
  42. package/dist/react/types/register.d.ts.map +1 -1
  43. package/dist/server.d.ts +2 -3
  44. package/dist/server.d.ts.map +1 -1
  45. package/package.json +8 -8
  46. package/dist/chunk-5M5NVF36.js.map +0 -1
  47. package/dist/chunk-DQ7LE4ZA.js.map +0 -1
  48. package/dist/chunk-GTOOHAI2.js.map +0 -1
  49. package/dist/cli/tools-declaration.d.ts +0 -22
  50. package/dist/cli/tools-declaration.d.ts.map +0 -1
  51. package/dist/landing-handler-3VN4BMR2.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/cli/entry.ts","../src/cli/vite-config.ts","../src/cli/mcp-env-declaration.ts","../src/cli/workspace.ts","../src/cli/views.ts","../src/cli/views-plugin.ts"],"sourcesContent":["/**\n * Server-entry discovery for `mcp-use build` and `mcp-use dev`.\n *\n * The entry contract (CLI_SPEC.md): the user's entry module default-exports\n * the `MCPServer` instance and never calls `listen()` itself — the CLI owns\n * the socket.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { isAbsolute, join, resolve } from \"node:path\";\n\n/**\n * Conventional entry locations, checked in order relative to the project\n * root; the first existing file wins.\n *\n * @internal\n */\nexport const ENTRY_CANDIDATES = [\n \"src/index.ts\",\n \"src/server.ts\",\n \"index.ts\",\n \"server.ts\",\n] as const;\n\n/**\n * Locate the server entry for a project.\n *\n * With `override` set (the `--entry` flag), the path is resolved against\n * `cwd` and must exist. Otherwise the {@link ENTRY_CANDIDATES} are probed in\n * order and the first hit wins.\n *\n * @param cwd - Absolute path to the project root.\n * @param override - Explicit entry path (`--entry`), absolute or relative to `cwd`.\n * @returns Absolute path to the entry file.\n * @throws If the override does not exist, or no conventional candidate is\n * found — the error lists every location that was checked.\n *\n * @internal\n */\nexport function discoverEntry(cwd: string, override?: string): string {\n if (override !== undefined) {\n const entry = isAbsolute(override) ? override : resolve(cwd, override);\n if (!existsSync(entry)) {\n throw new Error(`Entry not found: ${entry} (from --entry \"${override}\")`);\n }\n return entry;\n }\n for (const candidate of ENTRY_CANDIDATES) {\n const entry = join(cwd, candidate);\n if (existsSync(entry)) {\n return entry;\n }\n }\n throw new Error(\n `No server entry found in ${cwd}. Looked for: ` +\n `${ENTRY_CANDIDATES.join(\", \")}. ` +\n `Create one of these (default-exporting your MCPServer instance) ` +\n `or pass --entry <path>.`\n );\n}\n","/**\n * Resolve the project-level Vite config used only by the views client build.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst VITE_CONFIG_CANDIDATES = [\n \"vite.config.ts\",\n \"vite.config.js\",\n \"vite.config.mts\",\n \"vite.config.cjs\",\n] as const;\n\n/**\n * Locate a project Vite config, or disable config loading when absent.\n *\n * @param cwd - Absolute project root.\n * @returns Absolute config path or `false`.\n *\n * @internal\n */\nexport function resolveUserViteConfig(cwd: string): string | false {\n for (const name of VITE_CONFIG_CANDIDATES) {\n const path = join(cwd, name);\n if (existsSync(path)) return path;\n }\n return false;\n}\n\n/**\n * Resolve the framework-owned Tailwind stylesheet for project CSS imports.\n *\n * @returns Absolute path exported by the installed `tailwindcss` dependency.\n *\n * @internal\n */\nexport function resolveTailwindCss(): string {\n return fileURLToPath(import.meta.resolve(\"tailwindcss/index.css\"));\n}\n","/**\n * Root-level MCP env declaration shared by `mcp-use dev` and `mcp-use build`.\n *\n * Combines CSS module typing and a live type-only edge to the server entry so\n * exported `ToolRef`s update in TypeScript without rerunning the CLI.\n */\n\nimport { writeFile } from \"node:fs/promises\";\nimport { extname, join, relative, sep } from \"node:path\";\n\n/** Filename of the project-owned MCP env declaration. */\nexport const MCP_ENV_DECLARATION_NAME = \"mcp-env.d.ts\";\n\nfunction declarationImportPath(cwd: string, entry: string): string {\n let importPath = relative(cwd, entry).split(sep).join(\"/\");\n const extension = extname(importPath);\n const runtimeExtension =\n extension === \".mts\"\n ? \".mjs\"\n : extension === \".cts\"\n ? \".cjs\"\n : extension === \".ts\" || extension === \".tsx\"\n ? \".js\"\n : extension;\n\n if (extension !== runtimeExtension) {\n importPath = `${importPath.slice(0, -extension.length)}${runtimeExtension}`;\n }\n return importPath.startsWith(\".\") ? importPath : `./${importPath}`;\n}\n\n/** Build the stable declaration contents for a discovered server entry. */\nexport function renderMcpEnvDeclaration(cwd: string, entry: string): string {\n const importPath = declarationImportPath(cwd, entry);\n return [\n \"// mcp-use generated env declaration\",\n 'declare module \"*.css\";',\n \"\",\n 'declare module \"mcp-use/react\" {',\n \" interface Register {\",\n ` tools: typeof import(${JSON.stringify(importPath)});`,\n \" }\",\n \"}\",\n \"\",\n \"export {};\",\n \"\",\n ].join(\"\\n\");\n}\n\n/**\n * Create the root `mcp-env.d.ts` if absent.\n *\n * Exclusive-create mode makes this safe when dev and build start together and\n * guarantees that a user-authored declaration is never truncated or replaced.\n *\n * @returns `true` when this invocation created the file.\n */\nexport async function ensureMcpEnvDeclaration(\n cwd: string,\n entry: string\n): Promise<boolean> {\n const declarationPath = join(cwd, MCP_ENV_DECLARATION_NAME);\n try {\n await writeFile(declarationPath, renderMcpEnvDeclaration(cwd, entry), {\n encoding: \"utf8\",\n flag: \"wx\",\n });\n return true;\n } catch (error) {\n if (\n error !== null &&\n typeof error === \"object\" &&\n \"code\" in error &&\n error.code === \"EEXIST\"\n ) {\n return false;\n }\n throw error;\n }\n}\n","/**\n * The per-project `.mcp-use/` workspace convention — the Next.js `.next`\n * analog. Everything tooling writes for a project lives under this single,\n * gitignored directory so a checkout stays clean and `rm -rf .mcp-use` is\n * always safe.\n *\n * The layout is a fixed convention, not configuration: there is deliberately\n * no config file and no `outDir` knob (runtime/project configuration lives on\n * the `MCPServer` constructor).\n *\n * This module is PURE: it only derives path strings (no filesystem access).\n *\n * Layout (relative to the project root):\n *\n * ```text\n * .mcp-use/\n * ├─ build/ ← compiled server + manifest.json (this package)\n * ├─ generated/ ← output of the typegen escape-hatch command — reserved (VIEWS_SPEC.md)\n * ├─ cache/ ← disposable dev/build scratch\n * ├─ state/ ← mutable runtime state (e.g. tunnel.json)\n * └─ cloud/ ← cloud linkage (link.json)\n * ```\n *\n * `build/` must contain NO mutable runtime state (that is `state/`'s job) so\n * build output stays reproducible and disposable. This is the per-project\n * workspace, distinct from the global `~/.mcp-use/` store (CLI auth,\n * credentials, per-user caches).\n */\n\nimport { join } from \"node:path\";\n\n/**\n * Fixed name of the per-project workspace directory.\n *\n * @internal\n */\nexport const WORKSPACE_DIR_NAME = \".mcp-use\";\n\n/**\n * Basename of the build manifest written inside the build output directory.\n *\n * @internal\n */\nexport const BUILD_MANIFEST_NAME = \"manifest.json\";\n\n/**\n * Manifest written to `.mcp-use/build/manifest.json` by {@link runBuild} and\n * read back by `mcp-use start`.\n *\n * @internal\n */\nexport interface BuildManifest {\n /** Unique identifier for this build (random hex, regenerated per build). */\n buildId: string;\n /**\n * Filename of the emitted server entry, relative to the build directory\n * (e.g. `\"index.js\"`). `mcp-use start` imports `<build>/<entryPoint>` and\n * serves its default export.\n */\n entryPoint: string;\n /** ISO-8601 timestamp of when the build finished. */\n createdAt: string;\n /**\n * Whether the build was created with `mcp-use build --with-inspector`.\n * Consumed by `mcp-use start` to decide whether to mount the inspector shell.\n */\n inspector: boolean;\n}\n\n/**\n * Every resolved path for a project's `.mcp-use/` workspace.\n *\n * @internal\n */\nexport interface WorkspacePaths {\n /** The project root (the directory containing `.mcp-use/`). */\n projectRoot: string;\n /** The `.mcp-use/` workspace directory. */\n workspace: string;\n /** Build output directory: `.mcp-use/build`. */\n build: string;\n /**\n * Generated `.d.ts` artifacts directory — reserved for the typegen\n * escape-hatch command (VIEWS_SPEC.md § Typegen, demoted).\n */\n generated: string;\n /** Disposable dev/build scratch directory. */\n cache: string;\n /** Mutable runtime state directory. */\n state: string;\n /** Cloud linkage directory — reserved. */\n cloud: string;\n /** Build manifest: `<build>/manifest.json`. */\n buildManifest: string;\n /** Tunnel subdomain persistence: `<state>/tunnel.json`. */\n tunnel: string;\n}\n\n/**\n * Derive every workspace path for a project from its root. Pure — no\n * filesystem access.\n *\n * @param projectRoot - Absolute path to the project root.\n *\n * @example\n * ```ts\n * const paths = resolveWorkspacePaths(process.cwd());\n * console.log(paths.build); // <cwd>/.mcp-use/build\n * ```\n *\n * @internal\n */\nexport function resolveWorkspacePaths(projectRoot: string): WorkspacePaths {\n const workspace = join(projectRoot, WORKSPACE_DIR_NAME);\n const build = join(workspace, \"build\");\n return {\n projectRoot,\n workspace,\n build,\n generated: join(workspace, \"generated\"),\n cache: join(workspace, \"cache\"),\n state: join(workspace, \"state\"),\n cloud: join(workspace, \"cloud\"),\n buildManifest: join(build, BUILD_MANIFEST_NAME),\n tunnel: join(workspace, \"state\", \"tunnel.json\"),\n };\n}\n","/**\n * View discovery for `mcp-use build` / `mcp-use dev`.\n *\n * Views live under `views/<name>/view.tsx` (VIEWS_SPEC.md § File-based views).\n */\n\nimport { existsSync, readdirSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { ViteDevServer } from \"vite\";\n\nimport type { ViewsManifest } from \"../views/types.js\";\n\n/** Author-facing view source directory at the project root. */\nexport const VIEWS_SOURCE_DIR = \"views\" as const;\n\n/** Prefix for per-view virtual entry modules (`virtual:mcp-use/views/<name>`). */\nexport const VIRTUAL_VIEW_PREFIX = \"virtual:mcp-use/views/\";\n\n/** Resolved virtual id prefix (Rollup null-prefixed module id). */\nexport const VIRTUAL_VIEW_RESOLVED_PREFIX = `\\0${VIRTUAL_VIEW_PREFIX}`;\n\n/**\n * One discovered view directory.\n *\n * @internal\n */\nexport interface DiscoveredView {\n /** View directory name (the `views/<name>` segment). */\n name: string;\n /** Absolute path to `views/<name>/view.tsx`. */\n entryPath: string;\n}\n\n/**\n * Scan `views/<name>/view.tsx` under the project root.\n *\n * A missing or empty `views/` directory yields an empty list — tool-only\n * projects keep byte-identical CLI behavior.\n *\n * @param cwd - Absolute project root.\n * @returns Discovered views sorted by name.\n *\n * @internal\n */\nexport function discoverViews(cwd: string): DiscoveredView[] {\n const viewsDir = join(cwd, VIEWS_SOURCE_DIR);\n if (!existsSync(viewsDir)) {\n return [];\n }\n\n const views: DiscoveredView[] = [];\n for (const entry of readdirSync(viewsDir, { withFileTypes: true })) {\n if (!entry.isDirectory()) {\n continue;\n }\n const entryPath = join(viewsDir, entry.name, \"view.tsx\");\n if (existsSync(entryPath)) {\n views.push({ name: entry.name, entryPath });\n }\n }\n views.sort((a, b) => a.name.localeCompare(b.name));\n return views;\n}\n\n/**\n * Virtual module id for a view entry (`virtual:mcp-use/views/<name>`).\n *\n * @param name - View directory name.\n *\n * @internal\n */\nexport function virtualViewId(name: string): string {\n return `${VIRTUAL_VIEW_PREFIX}${name}`;\n}\n\n/**\n * Dev URL path Vite serves a resolved virtual module at (browser-loadable).\n *\n * @param name - View directory name.\n *\n * @internal\n */\nexport function devVirtualEntryPath(name: string): string {\n return `/@id/__x00__${VIRTUAL_VIEW_PREFIX}${name}`;\n}\n\n/**\n * Whether a filesystem path is a view component file or lives under a view dir.\n *\n * @internal\n */\nexport function isViewPath(file: string, cwd: string): boolean {\n const rel = file.startsWith(cwd) ? file.slice(cwd.length + 1) : file;\n return /^views\\/[^/]+\\//.test(rel) || /^views\\/[^/]+\\/view\\.tsx$/.test(rel);\n}\n\n/**\n * Whether a path is a view's `view.tsx` entry.\n *\n * @internal\n */\nexport function isViewEntryPath(file: string, cwd: string): boolean {\n const rel = file.startsWith(cwd) ? file.slice(cwd.length + 1) : file;\n return /^views\\/[^/]+\\/view\\.tsx$/.test(rel);\n}\n\n/**\n * Build a dev-shaped views manifest (Vite URLs, `/@vite/client` script hook).\n *\n * @internal\n */\nexport function buildDevViewsManifest(views: DiscoveredView[]): ViewsManifest {\n const manifest: ViewsManifest = {};\n for (const view of views) {\n manifest[view.name] = {\n kind: \"external\",\n entry: devVirtualEntryPath(view.name),\n css: [],\n scripts: [\"/@vite/client\"],\n };\n }\n return manifest;\n}\n\n/**\n * Create a temporary Vite dev server for build-time binding validation.\n *\n * @internal\n */\nexport async function createBindingValidationServer(\n cwd: string,\n cacheDir: string,\n configFile: string | false\n): Promise<ViteDevServer> {\n const { createServer } = await import(\"vite\");\n return createServer({\n root: cwd,\n configFile,\n envFile: false,\n logLevel: \"warn\",\n cacheDir,\n server: { middlewareMode: true, hmr: false },\n ssr: { external: true },\n });\n}\n","/**\n * Vite plugin: virtual view entry modules and optional SSR wrapper entry.\n */\n\nimport type { Plugin } from \"vite\";\n\nimport type { DiscoveredView } from \"./views.js\";\nimport {\n VIRTUAL_VIEW_PREFIX,\n VIRTUAL_VIEW_RESOLVED_PREFIX,\n virtualViewId,\n} from \"./views.js\";\n\nconst VIRTUAL_TAILWIND_ID = \"virtual:mcp-use/tailwind.css\";\nconst VIRTUAL_TAILWIND_RESOLVED_ID = `\\0${VIRTUAL_TAILWIND_ID}`;\n\n/**\n * Options for {@link mcpUseViewsPlugin}.\n *\n * @internal\n */\nexport interface McpUseViewsPluginOptions {\n /** Static list or live getter (dev rediscovery). */\n getViews: () => DiscoveredView[];\n /**\n * Dev-mode entry shape. When present, every virtual entry self-accepts HMR\n * updates (`import.meta.hot.accept()`) so an update that propagates past the\n * view module re-runs the bootstrap instead of full-reloading the iframe\n * document (which would wipe bridge state). Absent for builds — entries stay\n * byte-identical to the production contract.\n */\n dev?: {\n /**\n * Whether React Fast Refresh is active (`@vitejs/plugin-react` resolved).\n * When `true`, entries import the plugin's virtual refresh preamble\n * (`@vitejs/plugin-react/preamble`) before any component module so the\n * refresh runtime hooks the document — the role `transformIndexHtml`\n * plays for Vite-served HTML, which synthesized srcdoc documents never\n * pass through.\n */\n reactRefresh: boolean;\n };\n}\n\n/**\n * Vite plugin that resolves `virtual:mcp-use/views/<name>` to bootstrap code.\n *\n * Applies only to the **client** environment.\n *\n * @internal\n */\nexport function mcpUseViewsPlugin(options: McpUseViewsPluginOptions): Plugin {\n return {\n name: \"mcp-use-views\",\n applyToEnvironment(environment) {\n return environment.name === \"client\";\n },\n resolveId(id) {\n if (id === VIRTUAL_TAILWIND_ID) {\n return VIRTUAL_TAILWIND_RESOLVED_ID;\n }\n if (!id.startsWith(VIRTUAL_VIEW_PREFIX)) {\n return undefined;\n }\n return `\\0${id}`;\n },\n load(id) {\n if (id === VIRTUAL_TAILWIND_RESOLVED_ID) {\n return `@import \"tailwindcss\";`;\n }\n if (!id.startsWith(VIRTUAL_VIEW_RESOLVED_PREFIX)) {\n return undefined;\n }\n const name = id.slice(VIRTUAL_VIEW_RESOLVED_PREFIX.length);\n const view = options.getViews().find((v) => v.name === name);\n if (view === undefined) {\n return undefined;\n }\n const lines: string[] = [];\n if (options.dev?.reactRefresh === true) {\n // Must be the first import: the preamble hooks the refresh runtime\n // into the window before react-dom (via the bootstrap import below)\n // or any refresh-wrapped view module evaluates.\n lines.push(`import \"@vitejs/plugin-react/preamble\";`);\n }\n lines.push(`import ${JSON.stringify(VIRTUAL_TAILWIND_ID)};`);\n lines.push(\n `import { bootstrapView } from \"mcp-use/react\";`,\n `import * as viewModule from ${JSON.stringify(view.entryPath)};`,\n `bootstrapView(viewModule);`\n );\n if (options.dev !== undefined) {\n lines.push(\n `if (import.meta.hot) {`,\n ` import.meta.hot.accept();`,\n `}`\n );\n }\n lines.push(\"\");\n return lines.join(\"\\n\");\n },\n };\n}\n\n/**\n * Rollup input map for a client views build (one entry per view).\n *\n * @internal\n */\nexport function clientBuildInputs(\n views: DiscoveredView[]\n): Record<string, string> {\n const input: Record<string, string> = {};\n for (const view of views) {\n input[view.name] = virtualViewId(view.name);\n }\n return input;\n}\n"],"mappings":"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","names":["existsSync","join","join","join","existsSync","join"]}
@@ -2,7 +2,7 @@
2
2
  * `mcp-use build` — Vite SSR/node build of the user's server entry into the
3
3
  * `.mcp-use/build/` workspace directory (CLI_SPEC.md § Commands → build).
4
4
  *
5
- * When views exist (under `resources/<name>/view.tsx`), also runs a client-environment
5
+ * When views exist (under `views/<name>/view.tsx`), also runs a client-environment
6
6
  * build per view (hashed assets on disk), validates bindings, and emits a
7
7
  * wrapper entry that primes views before re-exporting the server (VIEWS_SPEC.md §
8
8
  * Build system).
@@ -1 +1 @@
1
- {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAyDH;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAwID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAgc/D"}
1
+ {"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/cli/dev.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAyDH;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACzB,yCAAyC;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;OAKG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;OAYG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAwID;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAsB,MAAM,CAAC,OAAO,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAwb/D"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Root-level MCP env declaration shared by `mcp-use dev` and `mcp-use build`.
3
+ *
4
+ * Combines CSS module typing and a live type-only edge to the server entry so
5
+ * exported `ToolRef`s update in TypeScript without rerunning the CLI.
6
+ */
7
+ /** Filename of the project-owned MCP env declaration. */
8
+ export declare const MCP_ENV_DECLARATION_NAME = "mcp-env.d.ts";
9
+ /** Build the stable declaration contents for a discovered server entry. */
10
+ export declare function renderMcpEnvDeclaration(cwd: string, entry: string): string;
11
+ /**
12
+ * Create the root `mcp-env.d.ts` if absent.
13
+ *
14
+ * Exclusive-create mode makes this safe when dev and build start together and
15
+ * guarantees that a user-authored declaration is never truncated or replaced.
16
+ *
17
+ * @returns `true` when this invocation created the file.
18
+ */
19
+ export declare function ensureMcpEnvDeclaration(cwd: string, entry: string): Promise<boolean>;
20
+ //# sourceMappingURL=mcp-env-declaration.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-env-declaration.d.ts","sourceRoot":"","sources":["../../src/cli/mcp-env-declaration.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAKH,yDAAyD;AACzD,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AAoBvD,2EAA2E;AAC3E,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAe1E;AAED;;;;;;;GAOG;AACH,wBAAsB,uBAAuB,CAC3C,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GACZ,OAAO,CAAC,OAAO,CAAC,CAmBlB"}
@@ -1 +1 @@
1
- {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/cli/tunnel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAQD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,+DAA+D;IAC/D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,4EAA4E;IAC5E,MAAM,IAAI;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAClC;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CA6NxE"}
1
+ {"version":3,"file":"tunnel.d.ts","sourceRoot":"","sources":["../../src/cli/tunnel.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AASH;;;GAGG;AACH,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAQD;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC5B;;;OAGG;IACH,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,+DAA+D;IAC/D,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACtB,4EAA4E;IAC5E,MAAM,IAAI;QAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;CAClC;AAKD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,aAAa,EAAE,MAAM,GAAG,aAAa,CAiTxE"}
@@ -1,10 +1,12 @@
1
1
  /**
2
2
  * View discovery for `mcp-use build` / `mcp-use dev`.
3
3
  *
4
- * Views live under `resources/<name>/view.tsx` (VIEWS_SPEC.md § File-based views).
4
+ * Views live under `views/<name>/view.tsx` (VIEWS_SPEC.md § File-based views).
5
5
  */
6
6
  import type { ViteDevServer } from "vite";
7
7
  import type { ViewsManifest } from "../views/types.js";
8
+ /** Author-facing view source directory at the project root. */
9
+ export declare const VIEWS_SOURCE_DIR: "views";
8
10
  /** Prefix for per-view virtual entry modules (`virtual:mcp-use/views/<name>`). */
9
11
  export declare const VIRTUAL_VIEW_PREFIX = "virtual:mcp-use/views/";
10
12
  /** Resolved virtual id prefix (Rollup null-prefixed module id). */
@@ -15,15 +17,15 @@ export declare const VIRTUAL_VIEW_RESOLVED_PREFIX = "\0virtual:mcp-use/views/";
15
17
  * @internal
16
18
  */
17
19
  export interface DiscoveredView {
18
- /** View directory name (the `resources/<name>` segment). */
20
+ /** View directory name (the `views/<name>` segment). */
19
21
  name: string;
20
- /** Absolute path to `resources/<name>/view.tsx`. */
22
+ /** Absolute path to `views/<name>/view.tsx`. */
21
23
  entryPath: string;
22
24
  }
23
25
  /**
24
- * Scan `resources/<name>/view.tsx` under the project root.
26
+ * Scan `views/<name>/view.tsx` under the project root.
25
27
  *
26
- * A missing or empty `resources/` directory yields an empty list — tool-only
28
+ * A missing or empty `views/` directory yields an empty list — tool-only
27
29
  * projects keep byte-identical CLI behavior.
28
30
  *
29
31
  * @param cwd - Absolute project root.
@@ -1 +1 @@
1
- {"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/cli/views.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAE5D,mEAAmE;AACnE,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AAEvE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,4DAA4D;IAC5D,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAkB3D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAK7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,aAAa,CAW5E;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GAAG,KAAK,GACzB,OAAO,CAAC,aAAa,CAAC,CAWxB"}
1
+ {"version":3,"file":"views.d.ts","sourceRoot":"","sources":["../../src/cli/views.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,MAAM,CAAC;AAE1C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,+DAA+D;AAC/D,eAAO,MAAM,gBAAgB,EAAG,OAAgB,CAAC;AAEjD,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,2BAA2B,CAAC;AAE5D,mEAAmE;AACnE,eAAO,MAAM,4BAA4B,6BAA6B,CAAC;AAEvE;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,IAAI,EAAE,MAAM,CAAC;IACb,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,EAAE,CAkB3D;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAElD;AAED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAG7D;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAGlE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,cAAc,EAAE,GAAG,aAAa,CAW5E;AAED;;;;GAIG;AACH,wBAAsB,6BAA6B,CACjD,GAAG,EAAE,MAAM,EACX,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,GAAG,KAAK,GACzB,OAAO,CAAC,aAAa,CAAC,CAWxB"}
@@ -2,13 +2,13 @@ import {
2
2
  createBindingValidationServer,
3
3
  discoverEntry,
4
4
  discoverViews,
5
- ensureToolsDeclaration,
5
+ ensureMcpEnvDeclaration,
6
6
  mcpUseViewsPlugin,
7
7
  resolveTailwindCss,
8
8
  resolveUserViteConfig,
9
9
  resolveWorkspacePaths,
10
10
  virtualViewId
11
- } from "../chunk-DQ7LE4ZA.js";
11
+ } from "../chunk-XKJP5S7C.js";
12
12
  import {
13
13
  viewAssetsBasePath
14
14
  } from "../chunk-STCR3P5O.js";
@@ -211,8 +211,8 @@ async function buildExternalView(view, options) {
211
211
  async function runBuild(options) {
212
212
  const startedAt = performance.now();
213
213
  const entry = discoverEntry(options.cwd, options.entry);
214
- if (await ensureToolsDeclaration(options.cwd, entry)) {
215
- console.log("[mcp-use] created tools.d.ts");
214
+ if (await ensureMcpEnvDeclaration(options.cwd, entry)) {
215
+ console.log("[mcp-use] created mcp-env.d.ts");
216
216
  }
217
217
  const paths = resolveWorkspacePaths(options.cwd);
218
218
  const views = discoverViews(options.cwd);
@@ -229,7 +229,7 @@ async function runBuild(options) {
229
229
  ssr: entry,
230
230
  outDir: paths.build,
231
231
  emptyOutDir: true,
232
- target: "node24",
232
+ target: "node22",
233
233
  sourcemap: true,
234
234
  minify: false,
235
235
  rollupOptions: {
@@ -335,7 +335,7 @@ async function runBuild(options) {
335
335
  ssr: wrapperEntry,
336
336
  outDir: paths.build,
337
337
  emptyOutDir: false,
338
- target: "node24",
338
+ target: "node22",
339
339
  sourcemap: true,
340
340
  minify: false,
341
341
  rollupOptions: {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/cli/build.ts","../../src/cli/views-bindings.ts"],"sourcesContent":["/**\n * `mcp-use build` — Vite SSR/node build of the user's server entry into the\n * `.mcp-use/build/` workspace directory (CLI_SPEC.md § Commands → build).\n *\n * When views exist (under `resources/<name>/view.tsx`), also runs a client-environment\n * build per view (hashed assets on disk), validates bindings, and emits a\n * wrapper entry that primes views before re-exporting the server (VIEWS_SPEC.md §\n * Build system).\n *\n * `vite` is an optional peer dependency of `mcp-use` (never a regular\n * dependency): this module is only ever reached through the bin's dynamic\n * `import(\"./cli/index.js\")`, so a missing install surfaces as a rejected\n * promise there (classified by `bin/main.ts`'s `isViteMissing`), not at\n * package load time.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { cp, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport tailwindcss from \"@tailwindcss/vite\";\nimport react from \"@vitejs/plugin-react\";\nimport { build } from \"vite\";\n\nimport { discoverEntry } from \"./entry.js\";\nimport { mcpUseViewsPlugin } from \"./views-plugin.js\";\nimport { ensureToolsDeclaration } from \"./tools-declaration.js\";\nimport {\n resolveBuildBasePath,\n validateViewBindingsAtBuild,\n} from \"./views-bindings.js\";\nimport {\n createBindingValidationServer,\n discoverViews,\n virtualViewId,\n type DiscoveredView,\n} from \"./views.js\";\nimport { resolveTailwindCss, resolveUserViteConfig } from \"./vite-config.js\";\nimport { resolveWorkspacePaths, type BuildManifest } from \"./workspace.js\";\nimport { normalizeAssetsBaseUrl } from \"../views/origin.js\";\nimport { viewAssetsBasePath } from \"../views/document.js\";\nimport type { ViewsManifest } from \"../views/types.js\";\n\n/** Fixed filename of the emitted server entry inside `.mcp-use/build/`. */\nconst BUILD_ENTRY_NAME = \"index.js\";\n\nconst WRAPPER_BASENAME = \"entry-wrapper.ts\";\n\n/** Inline imported assets as data URLs up to this byte size (effectively all). */\nconst ASSETS_INLINE_LIMIT = 100 * 1024 * 1024;\n\nasync function copyPublicAssets(cwd: string, outputDir: string): Promise<void> {\n const publicSrc = join(cwd, \"public\");\n if (existsSync(publicSrc)) {\n await cp(publicSrc, outputDir, { recursive: true });\n }\n}\n\n/**\n * Options for {@link runBuild}.\n *\n * @internal\n */\nexport interface BuildOptions {\n /** Absolute path to the project root (the directory containing the entry). */\n cwd: string;\n /**\n * Explicit entry path (the `--entry` flag), absolute or relative to `cwd`.\n *\n * @defaultValue Conventional discovery: `src/index.ts`, `src/server.ts`,\n * `index.ts`, `server.ts` — first hit wins.\n */\n entry?: string;\n /**\n * When true (`mcp-use build --with-inspector`), record `inspector: true`\n * in the build manifest.\n */\n withInspector?: boolean;\n}\n\n/**\n * Emit a short-lived wrapper module under `.mcp-use/cache/` that primes views\n * before re-exporting the user's entry (VIEWS_SPEC.md § Registration mechanism).\n */\nasync function writeWrapperEntry(\n cacheDir: string,\n userEntry: string,\n viewsManifest: ViewsManifest\n): Promise<string> {\n const wrapperPath = join(cacheDir, WRAPPER_BASENAME);\n await mkdir(cacheDir, { recursive: true });\n const manifestJson = JSON.stringify(viewsManifest);\n await writeFile(\n wrapperPath,\n [\n `import server from ${JSON.stringify(userEntry)};`,\n `import { registerViews } from \"mcp-use\";`,\n `server[registerViews](${manifestJson});`,\n `export default server;`,\n \"\",\n ].join(\"\\n\")\n );\n return wrapperPath;\n}\n\nfunction readBuildAssetsBase(): string | undefined {\n const raw = process.env[\"MCP_ASSETS_URL\"];\n if (raw === undefined || raw.trim() === \"\") {\n return undefined;\n }\n try {\n return normalizeAssetsBaseUrl(new URL(raw).href.replace(/\\/$/, \"\"));\n } catch {\n return undefined;\n }\n}\n\n/** Rewrite a view-relative manifest path to a full CDN URL at build time. */\nfunction toCdnAssetUrl(\n relativePath: string,\n viewName: string,\n assetsBase: string,\n basePath: string\n): string {\n const clean = relativePath.replace(/^\\/+/, \"\");\n return `${assetsBase}${viewAssetsBasePath(basePath, viewName)}${clean}`;\n}\n\nfunction applyBuildAssetsPrefix(\n entry: ViewsManifest[string],\n viewName: string,\n assetsBase: string,\n basePath: string\n): ViewsManifest[string] {\n if (entry.kind !== \"external\") {\n return entry;\n }\n return {\n ...entry,\n entry: toCdnAssetUrl(entry.entry, viewName, assetsBase, basePath),\n css: entry.css.map((path) =>\n toCdnAssetUrl(path, viewName, assetsBase, basePath)\n ),\n ...(entry.scripts !== undefined && {\n scripts: entry.scripts.map((path) =>\n toCdnAssetUrl(path, viewName, assetsBase, basePath)\n ),\n }),\n };\n}\n\n/**\n * Build one view into hashed assets on disk, then record view-relative paths\n * in the manifest (served over HTTP at runtime).\n */\nasync function buildExternalView(\n view: DiscoveredView,\n options: {\n cwd: string;\n cacheDir: string;\n viewsOutDir: string;\n userViteConfig: string | false;\n }\n): Promise<ViewsManifest[string]> {\n const viewOutDir = join(options.viewsOutDir, view.name);\n const clientResult = await build({\n root: options.cwd,\n configFile: options.userViteConfig,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: options.cacheDir,\n resolve: { alias: { tailwindcss: resolveTailwindCss() } },\n plugins: [\n tailwindcss(),\n react(),\n mcpUseViewsPlugin({ getViews: () => [view] }),\n ],\n build: {\n outDir: viewOutDir,\n emptyOutDir: true,\n target: \"es2022\",\n sourcemap: false,\n minify: true,\n cssCodeSplit: false,\n assetsInlineLimit: ASSETS_INLINE_LIMIT,\n rollupOptions: {\n input: { [view.name]: virtualViewId(view.name) },\n output: {\n format: \"es\",\n codeSplitting: false,\n entryFileNames: \"assets/[name]-[hash].js\",\n assetFileNames: \"assets/[name]-[hash][extname]\",\n },\n },\n },\n base: \"./\",\n });\n\n const clientOutput = Array.isArray(clientResult)\n ? clientResult[0]\n : clientResult;\n if (clientOutput === undefined || !(\"output\" in clientOutput)) {\n throw new Error(`Client build for view \"${view.name}\" produced no output.`);\n }\n\n const rawOutput = clientOutput.output;\n const items = Array.isArray(rawOutput) ? rawOutput : Object.values(rawOutput);\n\n let jsFileName: string | undefined;\n let cssFileName: string | undefined;\n\n for (const item of items) {\n if (typeof item !== \"object\" || item === null || !(\"fileName\" in item)) {\n continue;\n }\n const fileName = (item as { fileName: unknown }).fileName;\n if (typeof fileName !== \"string\") {\n continue;\n }\n const typed = item as {\n type?: string;\n isEntry?: boolean;\n fileName: string;\n };\n if (typed.type === \"chunk\" && typed.isEntry === true) {\n jsFileName = typed.fileName;\n } else if (typed.type === \"asset\" && typed.fileName.endsWith(\".css\")) {\n cssFileName = typed.fileName;\n }\n }\n\n if (jsFileName === undefined) {\n throw new Error(\n `Client build produced no entry chunk for view \"${view.name}\".`\n );\n }\n\n return {\n kind: \"external\",\n entry: jsFileName.replace(/^\\/+/, \"\"),\n css: cssFileName !== undefined ? [cssFileName.replace(/^\\/+/, \"\")] : [],\n };\n}\n\n/**\n * Build the project's server for production: a Vite build of the SSR/node\n * environment only (the client environment for views arrives with\n * VIEWS_SPEC.md), emitted as ESM to `.mcp-use/build/` with a `manifest.json`\n * alongside it.\n *\n * Dependencies stay external (`ssr: { external: true }`): only the\n * user's own source is bundled; every bare import resolves from\n * `node_modules` at runtime. The built entry preserves the default export\n * (the `MCPServer` instance) so `mcp-use start` can import and serve it.\n *\n * There is deliberately no typecheck step — the build is transpile-only;\n * users run `tsc --noEmit` via their own script.\n *\n * @param options - Project root and optional entry override.\n * @throws If no entry is found (see {@link discoverEntry}), or if `vite` is\n * not installed (`mcp-use build` requires it as a devDependency) — the\n * `import(\"vite\")` rejection propagates to the bin's dispatch boundary,\n * which classifies it and prints the install hint.\n *\n * @internal Reached only via the bin's `import(\"./cli/index.js\")`\n * dispatch (`bin/main.ts`) — not re-exported from the package's \".\" entry.\n */\nexport async function runBuild(options: BuildOptions): Promise<void> {\n const startedAt = performance.now();\n const entry = discoverEntry(options.cwd, options.entry);\n if (await ensureToolsDeclaration(options.cwd, entry)) {\n console.log(\"[mcp-use] created tools.d.ts\");\n }\n const paths = resolveWorkspacePaths(options.cwd);\n const views = discoverViews(options.cwd);\n const userViteConfig = resolveUserViteConfig(options.cwd);\n const inspector = options.withInspector === true;\n\n if (views.length === 0) {\n await build({\n root: options.cwd,\n configFile: false,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: paths.cache,\n build: {\n ssr: entry,\n outDir: paths.build,\n emptyOutDir: true,\n target: \"node24\",\n sourcemap: true,\n minify: false,\n rollupOptions: {\n output: {\n format: \"es\",\n entryFileNames: BUILD_ENTRY_NAME,\n },\n },\n },\n ssr: {\n external: true,\n target: \"node\",\n },\n });\n\n // Branding may reference project-public icon files even when the server\n // has no views. Keep the runtime public-asset location identical in both\n // shapes so `mcp-use start` and serverless built entries behave alike.\n await copyPublicAssets(options.cwd, join(paths.build, \"views/public\"));\n\n const manifest: BuildManifest = {\n buildId: randomBytes(8).toString(\"hex\"),\n entryPoint: BUILD_ENTRY_NAME,\n createdAt: new Date().toISOString(),\n inspector,\n };\n await mkdir(paths.build, { recursive: true });\n await writeFile(\n paths.buildManifest,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n\n const duration = Math.round(performance.now() - startedAt);\n console.log(\n `[mcp-use] built ${relative(options.cwd, entry)} → ` +\n `${relative(options.cwd, paths.build)}/${BUILD_ENTRY_NAME} (${duration}ms)`\n );\n return;\n }\n\n await rm(paths.build, { recursive: true, force: true });\n\n const viewsOutDir = join(paths.build, \"views\");\n await mkdir(viewsOutDir, { recursive: true });\n\n const bindingServer = await createBindingValidationServer(\n options.cwd,\n paths.cache,\n false\n );\n let buildBasePath: string;\n try {\n buildBasePath = await resolveBuildBasePath(\n bindingServer.environments.ssr,\n entry\n );\n } catch (error) {\n await bindingServer.close();\n throw error;\n }\n\n const viewsManifest: ViewsManifest = {};\n const buildAssetsBase = readBuildAssetsBase();\n for (const view of views) {\n let manifestEntry = await buildExternalView(view, {\n cwd: options.cwd,\n cacheDir: paths.cache,\n viewsOutDir,\n userViteConfig,\n });\n if (buildAssetsBase !== undefined) {\n manifestEntry = applyBuildAssetsPrefix(\n manifestEntry,\n view.name,\n buildAssetsBase,\n buildBasePath\n );\n }\n viewsManifest[view.name] = manifestEntry;\n }\n\n if (buildAssetsBase !== undefined) {\n console.log(\n `[mcp-use] MCP_ASSETS_URL set — manifest uses CDN URLs; upload ` +\n `${relative(options.cwd, viewsOutDir)}/ to your asset host.`\n );\n if (buildBasePath !== \"/mcp\") {\n console.log(\n `[mcp-use] CDN manifest uses basePath ${buildBasePath} from server entry`\n );\n }\n }\n\n await copyPublicAssets(options.cwd, join(viewsOutDir, \"public\"));\n\n try {\n await validateViewBindingsAtBuild(\n bindingServer.environments.ssr,\n entry,\n viewsManifest\n );\n } finally {\n await bindingServer.close();\n }\n\n const wrapperEntry = await writeWrapperEntry(\n paths.cache,\n entry,\n viewsManifest\n );\n\n await build({\n root: options.cwd,\n configFile: false,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: paths.cache,\n build: {\n ssr: wrapperEntry,\n outDir: paths.build,\n emptyOutDir: false,\n target: \"node24\",\n sourcemap: true,\n minify: false,\n rollupOptions: {\n output: {\n format: \"es\",\n entryFileNames: BUILD_ENTRY_NAME,\n },\n },\n },\n ssr: {\n external: true,\n target: \"node\",\n },\n });\n\n const manifest: BuildManifest = {\n buildId: randomBytes(8).toString(\"hex\"),\n entryPoint: BUILD_ENTRY_NAME,\n createdAt: new Date().toISOString(),\n inspector,\n };\n await mkdir(paths.build, { recursive: true });\n await writeFile(\n paths.buildManifest,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n\n const duration = Math.round(performance.now() - startedAt);\n const viewNames = views.map((v) => v.name).join(\", \");\n console.log(\n `[mcp-use] built ${relative(options.cwd, entry)} + views (${viewNames}) → ` +\n `${relative(options.cwd, paths.build)}/${BUILD_ENTRY_NAME} (${duration}ms)`\n );\n}\n","/**\n * Build-time view binding validation via mount-time checks.\n */\n\nimport { createServerModuleRunner, type DevEnvironment } from \"vite\";\n\nimport type { ViewsManifest } from \"../views/types.js\";\n\nconst DEFAULT_BASE_PATH = \"/mcp\";\n\n/** Synthetic origin for entry evaluation when OAuth needs MCP_URL at import. */\nconst BUILD_ENTRY_MCP_URL = \"http://localhost:3000\";\n\n/**\n * Duck-typed server shape needed for binding validation.\n *\n * @internal\n */\ninterface ServerLike {\n getHandler(): unknown;\n __primeViews(views: ViewsManifest, options?: { dev?: boolean }): void;\n basePath?: string;\n}\n\n/**\n * Import the server entry and read `basePath` from the default export.\n *\n * Does not prime views or call `getHandler()`. Sets a synthetic `MCP_URL` only\n * when unset so OAuth entries can construct during build introspection.\n *\n * @internal\n */\nexport async function resolveBuildBasePath(\n environment: DevEnvironment,\n entry: string\n): Promise<string> {\n const runner = createServerModuleRunner(environment, {\n hmr: false,\n sourcemapInterceptor: \"node\",\n });\n\n const previousMcpUrl = process.env[\"MCP_URL\"];\n try {\n if (previousMcpUrl === undefined) {\n process.env[\"MCP_URL\"] = BUILD_ENTRY_MCP_URL;\n }\n\n const serverModule = (await runner.import(entry)) as {\n default?: ServerLike;\n };\n const server = serverModule.default;\n if (server === null || typeof server !== \"object\") {\n throw new Error(\n \"The server entry must default-export the MCPServer instance.\"\n );\n }\n\n return server.basePath ?? DEFAULT_BASE_PATH;\n } finally {\n if (previousMcpUrl === undefined) {\n delete process.env[\"MCP_URL\"];\n } else {\n process.env[\"MCP_URL\"] = previousMcpUrl;\n }\n await runner.close();\n }\n}\n\n/**\n * Prime the server with the manifest and run mount-time binding validation\n * by calling `getHandler()`.\n *\n * Surfaces the same errors as runtime mount: missing primed view, missing\n * `outputSchema`, double binding. Unbound views emit a warning to stderr.\n *\n * @param environment - Vite SSR environment for module evaluation.\n * @param entry - Absolute path to the user's server entry.\n * @param viewsManifest - Built or dev-shaped manifest to prime.\n * @throws On binding hard errors (naming the view/tool).\n *\n * @internal\n */\nexport async function validateViewBindingsAtBuild(\n environment: DevEnvironment,\n entry: string,\n viewsManifest: ViewsManifest\n): Promise<void> {\n const runner = createServerModuleRunner(environment, {\n hmr: false,\n sourcemapInterceptor: \"node\",\n });\n\n try {\n const serverModule = (await runner.import(entry)) as {\n default?: ServerLike;\n };\n const server = serverModule.default;\n if (server === null || typeof server !== \"object\") {\n throw new Error(\n \"The server entry must default-export the MCPServer instance.\"\n );\n }\n\n if (typeof server.__primeViews !== \"function\") {\n throw new Error(\n \"The entry's default export does not support __primeViews.\"\n );\n }\n server.__primeViews(viewsManifest);\n server.getHandler();\n } finally {\n await runner.close();\n }\n}\n"],"mappings":"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","names":["manifest","duration"]}
1
+ {"version":3,"sources":["../../src/cli/build.ts","../../src/cli/views-bindings.ts"],"sourcesContent":["/**\n * `mcp-use build` — Vite SSR/node build of the user's server entry into the\n * `.mcp-use/build/` workspace directory (CLI_SPEC.md § Commands → build).\n *\n * When views exist (under `views/<name>/view.tsx`), also runs a client-environment\n * build per view (hashed assets on disk), validates bindings, and emits a\n * wrapper entry that primes views before re-exporting the server (VIEWS_SPEC.md §\n * Build system).\n *\n * `vite` is an optional peer dependency of `mcp-use` (never a regular\n * dependency): this module is only ever reached through the bin's dynamic\n * `import(\"./cli/index.js\")`, so a missing install surfaces as a rejected\n * promise there (classified by `bin/main.ts`'s `isViteMissing`), not at\n * package load time.\n */\n\nimport { randomBytes } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport { cp, mkdir, rm, writeFile } from \"node:fs/promises\";\nimport { join, relative } from \"node:path\";\nimport tailwindcss from \"@tailwindcss/vite\";\nimport react from \"@vitejs/plugin-react\";\nimport { build } from \"vite\";\n\nimport { discoverEntry } from \"./entry.js\";\nimport { mcpUseViewsPlugin } from \"./views-plugin.js\";\nimport { ensureMcpEnvDeclaration } from \"./mcp-env-declaration.js\";\nimport {\n resolveBuildBasePath,\n validateViewBindingsAtBuild,\n} from \"./views-bindings.js\";\nimport {\n createBindingValidationServer,\n discoverViews,\n virtualViewId,\n type DiscoveredView,\n} from \"./views.js\";\nimport { resolveTailwindCss, resolveUserViteConfig } from \"./vite-config.js\";\nimport { resolveWorkspacePaths, type BuildManifest } from \"./workspace.js\";\nimport { normalizeAssetsBaseUrl } from \"../views/origin.js\";\nimport { viewAssetsBasePath } from \"../views/document.js\";\nimport type { ViewsManifest } from \"../views/types.js\";\n\n/** Fixed filename of the emitted server entry inside `.mcp-use/build/`. */\nconst BUILD_ENTRY_NAME = \"index.js\";\n\nconst WRAPPER_BASENAME = \"entry-wrapper.ts\";\n\n/** Inline imported assets as data URLs up to this byte size (effectively all). */\nconst ASSETS_INLINE_LIMIT = 100 * 1024 * 1024;\n\nasync function copyPublicAssets(cwd: string, outputDir: string): Promise<void> {\n const publicSrc = join(cwd, \"public\");\n if (existsSync(publicSrc)) {\n await cp(publicSrc, outputDir, { recursive: true });\n }\n}\n\n/**\n * Options for {@link runBuild}.\n *\n * @internal\n */\nexport interface BuildOptions {\n /** Absolute path to the project root (the directory containing the entry). */\n cwd: string;\n /**\n * Explicit entry path (the `--entry` flag), absolute or relative to `cwd`.\n *\n * @defaultValue Conventional discovery: `src/index.ts`, `src/server.ts`,\n * `index.ts`, `server.ts` — first hit wins.\n */\n entry?: string;\n /**\n * When true (`mcp-use build --with-inspector`), record `inspector: true`\n * in the build manifest.\n */\n withInspector?: boolean;\n}\n\n/**\n * Emit a short-lived wrapper module under `.mcp-use/cache/` that primes views\n * before re-exporting the user's entry (VIEWS_SPEC.md § Registration mechanism).\n */\nasync function writeWrapperEntry(\n cacheDir: string,\n userEntry: string,\n viewsManifest: ViewsManifest\n): Promise<string> {\n const wrapperPath = join(cacheDir, WRAPPER_BASENAME);\n await mkdir(cacheDir, { recursive: true });\n const manifestJson = JSON.stringify(viewsManifest);\n await writeFile(\n wrapperPath,\n [\n `import server from ${JSON.stringify(userEntry)};`,\n `import { registerViews } from \"mcp-use\";`,\n `server[registerViews](${manifestJson});`,\n `export default server;`,\n \"\",\n ].join(\"\\n\")\n );\n return wrapperPath;\n}\n\nfunction readBuildAssetsBase(): string | undefined {\n const raw = process.env[\"MCP_ASSETS_URL\"];\n if (raw === undefined || raw.trim() === \"\") {\n return undefined;\n }\n try {\n return normalizeAssetsBaseUrl(new URL(raw).href.replace(/\\/$/, \"\"));\n } catch {\n return undefined;\n }\n}\n\n/** Rewrite a view-relative manifest path to a full CDN URL at build time. */\nfunction toCdnAssetUrl(\n relativePath: string,\n viewName: string,\n assetsBase: string,\n basePath: string\n): string {\n const clean = relativePath.replace(/^\\/+/, \"\");\n return `${assetsBase}${viewAssetsBasePath(basePath, viewName)}${clean}`;\n}\n\nfunction applyBuildAssetsPrefix(\n entry: ViewsManifest[string],\n viewName: string,\n assetsBase: string,\n basePath: string\n): ViewsManifest[string] {\n if (entry.kind !== \"external\") {\n return entry;\n }\n return {\n ...entry,\n entry: toCdnAssetUrl(entry.entry, viewName, assetsBase, basePath),\n css: entry.css.map((path) =>\n toCdnAssetUrl(path, viewName, assetsBase, basePath)\n ),\n ...(entry.scripts !== undefined && {\n scripts: entry.scripts.map((path) =>\n toCdnAssetUrl(path, viewName, assetsBase, basePath)\n ),\n }),\n };\n}\n\n/**\n * Build one view into hashed assets on disk, then record view-relative paths\n * in the manifest (served over HTTP at runtime).\n */\nasync function buildExternalView(\n view: DiscoveredView,\n options: {\n cwd: string;\n cacheDir: string;\n viewsOutDir: string;\n userViteConfig: string | false;\n }\n): Promise<ViewsManifest[string]> {\n const viewOutDir = join(options.viewsOutDir, view.name);\n const clientResult = await build({\n root: options.cwd,\n configFile: options.userViteConfig,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: options.cacheDir,\n resolve: { alias: { tailwindcss: resolveTailwindCss() } },\n plugins: [\n tailwindcss(),\n react(),\n mcpUseViewsPlugin({ getViews: () => [view] }),\n ],\n build: {\n outDir: viewOutDir,\n emptyOutDir: true,\n target: \"es2022\",\n sourcemap: false,\n minify: true,\n cssCodeSplit: false,\n assetsInlineLimit: ASSETS_INLINE_LIMIT,\n rollupOptions: {\n input: { [view.name]: virtualViewId(view.name) },\n output: {\n format: \"es\",\n codeSplitting: false,\n entryFileNames: \"assets/[name]-[hash].js\",\n assetFileNames: \"assets/[name]-[hash][extname]\",\n },\n },\n },\n base: \"./\",\n });\n\n const clientOutput = Array.isArray(clientResult)\n ? clientResult[0]\n : clientResult;\n if (clientOutput === undefined || !(\"output\" in clientOutput)) {\n throw new Error(`Client build for view \"${view.name}\" produced no output.`);\n }\n\n const rawOutput = clientOutput.output;\n const items = Array.isArray(rawOutput) ? rawOutput : Object.values(rawOutput);\n\n let jsFileName: string | undefined;\n let cssFileName: string | undefined;\n\n for (const item of items) {\n if (typeof item !== \"object\" || item === null || !(\"fileName\" in item)) {\n continue;\n }\n const fileName = (item as { fileName: unknown }).fileName;\n if (typeof fileName !== \"string\") {\n continue;\n }\n const typed = item as {\n type?: string;\n isEntry?: boolean;\n fileName: string;\n };\n if (typed.type === \"chunk\" && typed.isEntry === true) {\n jsFileName = typed.fileName;\n } else if (typed.type === \"asset\" && typed.fileName.endsWith(\".css\")) {\n cssFileName = typed.fileName;\n }\n }\n\n if (jsFileName === undefined) {\n throw new Error(\n `Client build produced no entry chunk for view \"${view.name}\".`\n );\n }\n\n return {\n kind: \"external\",\n entry: jsFileName.replace(/^\\/+/, \"\"),\n css: cssFileName !== undefined ? [cssFileName.replace(/^\\/+/, \"\")] : [],\n };\n}\n\n/**\n * Build the project's server for production: a Vite build of the SSR/node\n * environment only (the client environment for views arrives with\n * VIEWS_SPEC.md), emitted as ESM to `.mcp-use/build/` with a `manifest.json`\n * alongside it.\n *\n * Dependencies stay external (`ssr: { external: true }`): only the\n * user's own source is bundled; every bare import resolves from\n * `node_modules` at runtime. The built entry preserves the default export\n * (the `MCPServer` instance) so `mcp-use start` can import and serve it.\n *\n * There is deliberately no typecheck step — the build is transpile-only;\n * users run `tsc --noEmit` via their own script.\n *\n * @param options - Project root and optional entry override.\n * @throws If no entry is found (see {@link discoverEntry}), or if `vite` is\n * not installed (`mcp-use build` requires it as a devDependency) — the\n * `import(\"vite\")` rejection propagates to the bin's dispatch boundary,\n * which classifies it and prints the install hint.\n *\n * @internal Reached only via the bin's `import(\"./cli/index.js\")`\n * dispatch (`bin/main.ts`) — not re-exported from the package's \".\" entry.\n */\nexport async function runBuild(options: BuildOptions): Promise<void> {\n const startedAt = performance.now();\n const entry = discoverEntry(options.cwd, options.entry);\n if (await ensureMcpEnvDeclaration(options.cwd, entry)) {\n console.log(\"[mcp-use] created mcp-env.d.ts\");\n }\n const paths = resolveWorkspacePaths(options.cwd);\n const views = discoverViews(options.cwd);\n const userViteConfig = resolveUserViteConfig(options.cwd);\n const inspector = options.withInspector === true;\n\n if (views.length === 0) {\n await build({\n root: options.cwd,\n configFile: false,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: paths.cache,\n build: {\n ssr: entry,\n outDir: paths.build,\n emptyOutDir: true,\n target: \"node22\",\n sourcemap: true,\n minify: false,\n rollupOptions: {\n output: {\n format: \"es\",\n entryFileNames: BUILD_ENTRY_NAME,\n },\n },\n },\n ssr: {\n external: true,\n target: \"node\",\n },\n });\n\n // Branding may reference project-public icon files even when the server\n // has no views. Keep the runtime public-asset location identical in both\n // shapes so `mcp-use start` and serverless built entries behave alike.\n await copyPublicAssets(options.cwd, join(paths.build, \"views/public\"));\n\n const manifest: BuildManifest = {\n buildId: randomBytes(8).toString(\"hex\"),\n entryPoint: BUILD_ENTRY_NAME,\n createdAt: new Date().toISOString(),\n inspector,\n };\n await mkdir(paths.build, { recursive: true });\n await writeFile(\n paths.buildManifest,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n\n const duration = Math.round(performance.now() - startedAt);\n console.log(\n `[mcp-use] built ${relative(options.cwd, entry)} → ` +\n `${relative(options.cwd, paths.build)}/${BUILD_ENTRY_NAME} (${duration}ms)`\n );\n return;\n }\n\n await rm(paths.build, { recursive: true, force: true });\n\n const viewsOutDir = join(paths.build, \"views\");\n await mkdir(viewsOutDir, { recursive: true });\n\n const bindingServer = await createBindingValidationServer(\n options.cwd,\n paths.cache,\n false\n );\n let buildBasePath: string;\n try {\n buildBasePath = await resolveBuildBasePath(\n bindingServer.environments.ssr,\n entry\n );\n } catch (error) {\n await bindingServer.close();\n throw error;\n }\n\n const viewsManifest: ViewsManifest = {};\n const buildAssetsBase = readBuildAssetsBase();\n for (const view of views) {\n let manifestEntry = await buildExternalView(view, {\n cwd: options.cwd,\n cacheDir: paths.cache,\n viewsOutDir,\n userViteConfig,\n });\n if (buildAssetsBase !== undefined) {\n manifestEntry = applyBuildAssetsPrefix(\n manifestEntry,\n view.name,\n buildAssetsBase,\n buildBasePath\n );\n }\n viewsManifest[view.name] = manifestEntry;\n }\n\n if (buildAssetsBase !== undefined) {\n console.log(\n `[mcp-use] MCP_ASSETS_URL set — manifest uses CDN URLs; upload ` +\n `${relative(options.cwd, viewsOutDir)}/ to your asset host.`\n );\n if (buildBasePath !== \"/mcp\") {\n console.log(\n `[mcp-use] CDN manifest uses basePath ${buildBasePath} from server entry`\n );\n }\n }\n\n await copyPublicAssets(options.cwd, join(viewsOutDir, \"public\"));\n\n try {\n await validateViewBindingsAtBuild(\n bindingServer.environments.ssr,\n entry,\n viewsManifest\n );\n } finally {\n await bindingServer.close();\n }\n\n const wrapperEntry = await writeWrapperEntry(\n paths.cache,\n entry,\n viewsManifest\n );\n\n await build({\n root: options.cwd,\n configFile: false,\n envFile: false,\n logLevel: \"warn\",\n cacheDir: paths.cache,\n build: {\n ssr: wrapperEntry,\n outDir: paths.build,\n emptyOutDir: false,\n target: \"node22\",\n sourcemap: true,\n minify: false,\n rollupOptions: {\n output: {\n format: \"es\",\n entryFileNames: BUILD_ENTRY_NAME,\n },\n },\n },\n ssr: {\n external: true,\n target: \"node\",\n },\n });\n\n const manifest: BuildManifest = {\n buildId: randomBytes(8).toString(\"hex\"),\n entryPoint: BUILD_ENTRY_NAME,\n createdAt: new Date().toISOString(),\n inspector,\n };\n await mkdir(paths.build, { recursive: true });\n await writeFile(\n paths.buildManifest,\n `${JSON.stringify(manifest, null, 2)}\\n`\n );\n\n const duration = Math.round(performance.now() - startedAt);\n const viewNames = views.map((v) => v.name).join(\", \");\n console.log(\n `[mcp-use] built ${relative(options.cwd, entry)} + views (${viewNames}) → ` +\n `${relative(options.cwd, paths.build)}/${BUILD_ENTRY_NAME} (${duration}ms)`\n );\n}\n","/**\n * Build-time view binding validation via mount-time checks.\n */\n\nimport { createServerModuleRunner, type DevEnvironment } from \"vite\";\n\nimport type { ViewsManifest } from \"../views/types.js\";\n\nconst DEFAULT_BASE_PATH = \"/mcp\";\n\n/** Synthetic origin for entry evaluation when OAuth needs MCP_URL at import. */\nconst BUILD_ENTRY_MCP_URL = \"http://localhost:3000\";\n\n/**\n * Duck-typed server shape needed for binding validation.\n *\n * @internal\n */\ninterface ServerLike {\n getHandler(): unknown;\n __primeViews(views: ViewsManifest, options?: { dev?: boolean }): void;\n basePath?: string;\n}\n\n/**\n * Import the server entry and read `basePath` from the default export.\n *\n * Does not prime views or call `getHandler()`. Sets a synthetic `MCP_URL` only\n * when unset so OAuth entries can construct during build introspection.\n *\n * @internal\n */\nexport async function resolveBuildBasePath(\n environment: DevEnvironment,\n entry: string\n): Promise<string> {\n const runner = createServerModuleRunner(environment, {\n hmr: false,\n sourcemapInterceptor: \"node\",\n });\n\n const previousMcpUrl = process.env[\"MCP_URL\"];\n try {\n if (previousMcpUrl === undefined) {\n process.env[\"MCP_URL\"] = BUILD_ENTRY_MCP_URL;\n }\n\n const serverModule = (await runner.import(entry)) as {\n default?: ServerLike;\n };\n const server = serverModule.default;\n if (server === null || typeof server !== \"object\") {\n throw new Error(\n \"The server entry must default-export the MCPServer instance.\"\n );\n }\n\n return server.basePath ?? DEFAULT_BASE_PATH;\n } finally {\n if (previousMcpUrl === undefined) {\n delete process.env[\"MCP_URL\"];\n } else {\n process.env[\"MCP_URL\"] = previousMcpUrl;\n }\n await runner.close();\n }\n}\n\n/**\n * Prime the server with the manifest and run mount-time binding validation\n * by calling `getHandler()`.\n *\n * Surfaces the same errors as runtime mount: missing primed view, missing\n * `outputSchema`, double binding. Unbound views emit a warning to stderr.\n *\n * @param environment - Vite SSR environment for module evaluation.\n * @param entry - Absolute path to the user's server entry.\n * @param viewsManifest - Built or dev-shaped manifest to prime.\n * @throws On binding hard errors (naming the view/tool).\n *\n * @internal\n */\nexport async function validateViewBindingsAtBuild(\n environment: DevEnvironment,\n entry: string,\n viewsManifest: ViewsManifest\n): Promise<void> {\n const runner = createServerModuleRunner(environment, {\n hmr: false,\n sourcemapInterceptor: \"node\",\n });\n\n try {\n const serverModule = (await runner.import(entry)) as {\n default?: ServerLike;\n };\n const server = serverModule.default;\n if (server === null || typeof server !== \"object\") {\n throw new Error(\n \"The server entry must default-export the MCPServer instance.\"\n );\n }\n\n if (typeof server.__primeViews !== \"function\") {\n throw new Error(\n \"The entry's default export does not support __primeViews.\"\n );\n }\n server.__primeViews(viewsManifest);\n server.getHandler();\n } finally {\n await runner.close();\n }\n}\n"],"mappings":"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","names":["manifest","duration"]}
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAiCrD,+CAA+C;AAC/C,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBxE;AAoTD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,aAAa,SAAU,GACtB,OAAO,CAAC,aAAa,CAAC,CAWxB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC,CAOxB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBzB"}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/commands/client.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AA+DrD,+CAA+C;AAC/C,wBAAsB,SAAS,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAqBxE;AAuUD;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,aAAa,SAAU,GACtB,OAAO,CAAC,aAAa,CAAC,CAWxB;AAED;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,OAAO,CAAC,aAAa,CAAC,CAOxB;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,SAAS,MAAM,EAAE,GACtB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAyBzB"}
@@ -3,7 +3,7 @@ import {
3
3
  openSavedConnection,
4
4
  parseMcpArguments,
5
5
  runClient
6
- } from "../chunk-5M5NVF36.js";
6
+ } from "../chunk-RHITI5QM.js";
7
7
  import "../chunk-XUD22N3Y.js";
8
8
  export {
9
9
  openDirectConnection,
@@ -5,13 +5,13 @@ import {
5
5
  buildDevViewsManifest,
6
6
  discoverEntry,
7
7
  discoverViews,
8
- ensureToolsDeclaration,
8
+ ensureMcpEnvDeclaration,
9
9
  isViewPath,
10
10
  mcpUseViewsPlugin,
11
11
  resolveTailwindCss,
12
12
  resolveUserViteConfig,
13
13
  resolveWorkspacePaths
14
- } from "../chunk-DQ7LE4ZA.js";
14
+ } from "../chunk-XKJP5S7C.js";
15
15
 
16
16
  // src/cli/dev.ts
17
17
  import { spawn as spawn2 } from "child_process";
@@ -100,10 +100,19 @@ var DEFAULT_TUNNEL_API = "https://local.mcp-use.run";
100
100
  function tunnelApiBase() {
101
101
  return process.env["MCP_USE_TUNNEL_API"] ?? DEFAULT_TUNNEL_API;
102
102
  }
103
+ var RESPAWN_BACKOFF_INITIAL_MS = 1e3;
104
+ var RESPAWN_BACKOFF_MAX_MS = 3e4;
103
105
  function createTunnelManager(stateFilePath) {
104
106
  let proc;
105
107
  let currentUrl = null;
106
108
  let currentSubdomain;
109
+ let activePort;
110
+ let intentionalStop = false;
111
+ let respawnInFlight;
112
+ let respawnBackoffMs = RESPAWN_BACKOFF_INITIAL_MS;
113
+ const sleep = (ms) => new Promise((resolve) => {
114
+ setTimeout(resolve, ms);
115
+ });
107
116
  const markShutdown = () => {
108
117
  if (proc !== void 0 && "markShutdown" in proc && typeof proc.markShutdown === "function") {
109
118
  proc.markShutdown();
@@ -141,6 +150,8 @@ function createTunnelManager(stateFilePath) {
141
150
  );
142
151
  }
143
152
  };
153
+ let scheduleRespawn = () => {
154
+ };
144
155
  const spawnTunnel = (port, subdomain) => new Promise((resolve, reject) => {
145
156
  console.log(`[mcp-use] starting tunnel for port ${port}\u2026`);
146
157
  const userAgent = process.env["npm_config_user_agent"] ?? "";
@@ -208,7 +219,11 @@ function createTunnelManager(stateFilePath) {
208
219
  if (proc === child) {
209
220
  proc = void 0;
210
221
  currentUrl = null;
211
- currentSubdomain = void 0;
222
+ if (intentionalStop) {
223
+ currentSubdomain = void 0;
224
+ } else {
225
+ scheduleRespawn();
226
+ }
212
227
  }
213
228
  });
214
229
  const setupTimeout = setTimeout(() => {
@@ -218,11 +233,62 @@ function createTunnelManager(stateFilePath) {
218
233
  }
219
234
  }, 3e4);
220
235
  });
236
+ scheduleRespawn = () => {
237
+ if (intentionalStop || activePort === void 0 || currentUrl !== null) {
238
+ return;
239
+ }
240
+ if (respawnInFlight !== void 0) {
241
+ return;
242
+ }
243
+ respawnInFlight = (async () => {
244
+ while (!intentionalStop && activePort !== void 0 && currentUrl === null) {
245
+ console.log("[mcp-use] tunnel disconnected, restarting\u2026");
246
+ const subdomain = currentSubdomain ?? await loadSavedSubdomain();
247
+ try {
248
+ if (subdomain !== void 0) {
249
+ await releaseSubdomain(subdomain);
250
+ }
251
+ let tunnelInfo;
252
+ try {
253
+ tunnelInfo = await spawnTunnel(activePort, subdomain);
254
+ } catch (error) {
255
+ if (subdomain !== void 0) {
256
+ console.log(
257
+ `[mcp-use] subdomain "${subdomain}" unavailable, requesting a new one\u2026`
258
+ );
259
+ tunnelInfo = await spawnTunnel(activePort, void 0);
260
+ } else {
261
+ throw error;
262
+ }
263
+ }
264
+ proc = tunnelInfo.process;
265
+ currentUrl = tunnelInfo.url;
266
+ currentSubdomain = tunnelInfo.subdomain;
267
+ await persistSubdomain(tunnelInfo.subdomain);
268
+ respawnBackoffMs = RESPAWN_BACKOFF_INITIAL_MS;
269
+ return;
270
+ } catch (error) {
271
+ console.warn(
272
+ `[mcp-use] tunnel restart failed: ${error instanceof Error ? error.message : String(error)}`
273
+ );
274
+ await sleep(respawnBackoffMs);
275
+ respawnBackoffMs = Math.min(
276
+ respawnBackoffMs * 2,
277
+ RESPAWN_BACKOFF_MAX_MS
278
+ );
279
+ }
280
+ }
281
+ })().finally(() => {
282
+ respawnInFlight = void 0;
283
+ });
284
+ };
221
285
  return {
222
286
  status() {
223
287
  return { url: currentUrl };
224
288
  },
225
289
  async start(port) {
290
+ intentionalStop = false;
291
+ activePort = port;
226
292
  if (currentUrl !== null) {
227
293
  return {
228
294
  url: currentUrl,
@@ -254,7 +320,11 @@ function createTunnelManager(stateFilePath) {
254
320
  return { url: tunnelInfo.url, subdomain: tunnelInfo.subdomain };
255
321
  },
256
322
  async stop() {
323
+ intentionalStop = true;
257
324
  markShutdown();
325
+ if (respawnInFlight !== void 0) {
326
+ await respawnInFlight;
327
+ }
258
328
  if (currentSubdomain !== void 0) {
259
329
  await releaseSubdomain(currentSubdomain);
260
330
  }
@@ -262,8 +332,10 @@ function createTunnelManager(stateFilePath) {
262
332
  proc.kill("SIGINT");
263
333
  proc = void 0;
264
334
  }
335
+ activePort = void 0;
265
336
  currentUrl = null;
266
337
  currentSubdomain = void 0;
338
+ respawnBackoffMs = RESPAWN_BACKOFF_INITIAL_MS;
267
339
  }
268
340
  };
269
341
  }
@@ -359,8 +431,8 @@ async function runDev(options) {
359
431
  process.env["PORT"] = String(port);
360
432
  const localFallbackMcpUrl = process.env["MCP_URL"] === void 0 && (host === "127.0.0.1" || host === "localhost" || host === "::1") ? `http://localhost:${port}` : void 0;
361
433
  const entry = discoverEntry(options.cwd, options.entry);
362
- if (await ensureToolsDeclaration(options.cwd, entry)) {
363
- console.log("[mcp-use] created tools.d.ts");
434
+ if (await ensureMcpEnvDeclaration(options.cwd, entry)) {
435
+ console.log("[mcp-use] created mcp-env.d.ts");
364
436
  }
365
437
  let currentViews = discoverViews(options.cwd);
366
438
  const viewsAtStartup = currentViews.length > 0;
@@ -530,15 +602,10 @@ async function runDev(options) {
530
602
  const tunnelUrl = tunnelManager.status().url;
531
603
  const tunnelHost = tunnelUrl !== null ? new URL(tunnelUrl).hostname : null;
532
604
  const extra = tunnelHost !== null ? [tunnelHost] : [];
533
- const readOnly = req.method === "GET" || req.method === "HEAD";
534
- const hostResult = validateHostHeader(req.headers.host, [
605
+ const result = validateHostHeader(req.headers.host, [
535
606
  ...localhostAllowedHostnames(),
536
607
  ...extra
537
608
  ]);
538
- const result = hostResult.ok && !readOnly ? validateOriginHeader(req.headers.origin, [
539
- ...localhostAllowedOrigins(),
540
- ...extra
541
- ]) : hostResult;
542
609
  if (result.ok) {
543
610
  return false;
544
611
  }
@@ -578,7 +645,7 @@ async function runDev(options) {
578
645
  const url = req.url ?? "/";
579
646
  const pathname = new URL(url, "http://127.0.0.1").pathname;
580
647
  const viewsEnabled = viewsAtStartup && currentViews.length > 0;
581
- const isViteRequest = req.method === "GET" && (pathname.startsWith("/@") || pathname.startsWith("/node_modules/") || pathname.startsWith("/.mcp-use/") || viewsEnabled && pathname.startsWith("/resources/"));
648
+ const isViteRequest = req.method === "GET" && (pathname.startsWith("/@") || pathname.startsWith("/node_modules/") || pathname.startsWith("/.mcp-use/") || viewsEnabled && pathname.startsWith("/views/"));
582
649
  if (viewsEnabled && isViteRequest) {
583
650
  applyViteModuleCors(req, res, {
584
651
  tunnelActive: tunnelManager.status().url !== null,