@mistflow-ai/mcp 0.7.4 → 0.7.5

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 (3) hide show
  1. package/dist/cli.js +20 -20
  2. package/dist/index.js +12 -12
  3. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -1,27 +1,27 @@
1
1
  #!/usr/bin/env node
2
- var Xe=Object.defineProperty;var u=(e,t)=>()=>(e&&(t=e(e=0)),t);var oe=(e,t)=>{for(var n in t)Xe(e,n,{get:t[n],enumerable:!0})};function ce(){let e=[];return e.push("Mistflow is a full-stack app builder that creates and deploys web apps from natural language descriptions. When a user asks to build, create, or make a web app, website, landing page, dashboard, internal tool, marketplace, content site, or browser game, use Mistflow tools. Mistflow creates NEW apps from scratch. It does NOT modify existing non-Mistflow codebases."),e.push(""),e.push("Call `mist_help` at any point for the full CLI command reference. The 4 MCP tools handle short, structured, AI-native flows (auth, project state, browser automation, CLI discovery). Everything else is the `mist` CLI \u2014 invoke via your shell/bash tool."),e.push(""),e.push(Ze),e.push(""),e.push(et),e.push(""),e.push(tt),e.push(""),e.push(nt),e.push(""),e.push(ot),e.push(""),e.push(rt),e.push(""),e.push("New app workflow (entirely CLI-driven):"),e.push("1. Choose destination: if the user did not already specify a path, ask whether to scaffold in the current folder or a new subfolder here. Resolve the absolute path before `mist init`."),e.push('2. Plan: run `mist plan --describe "<user\'s description>" --json` via your shell/bash tool. Pass the user\'s description EXACTLY as written \u2014 do NOT expand, rephrase, or add features. Relay any returned questions to the user, then submit answers via `echo \'<answers-json>\' | mist plan --token <id> --answers-stdin --json`. When status becomes "design_clarify_pending", poll with `mist plan-directions --cid <id> --wait --json`. When directions are ready, the CLI writes `<cwd>/.mistflow/design-directions.html` with each direction rendered in its own fonts + palette + hero treatment \u2014 run `open "<path>"` for the user so they can see visual options, THEN ask them to pick one by name. The sentinel payload (stderr) includes the `previewPath`. Finalize with `echo \'<pick-json>\' | mist plan --cid <id> --pick-stdin --json`. If the CLI returns status "confirm_new_project" (safety gate when inside an existing codebase), ask the user whether to scaffold a new Mistflow app or edit the existing code.'),e.push("3. Mockup (optional): run `mist mockup --plan-id <id>` via your shell/bash tool \u2014 generates a visual HTML wireframe for user preview. Iterative: pass --feedback to refine, --approved to lock in the design."),e.push("4. Scaffold: run `mist init --plan-id <id> --path <absolute-path>` via your shell/bash tool. `mist init` is transactional: it registers the cloud project first, scaffolds in a temp directory, and only moves the completed app into place after both steps succeed. If it fails before that move, stop and fix the error instead of continuing to cloud commands. Returns fast; does NOT run npm install."),e.push("5. Install dependencies: run `mist install <projectPath>` via your shell/bash tool (streams output)."),e.push("6. Implement: run `mist implement <absolute-path>` via your shell/bash tool \u2014 executes plan steps one at a time. Call repeatedly until all steps are done; it auto-marks the previous step as completed on each call."),e.push("7. Deploy: run `mist deploy [path]` via your shell/bash tool \u2014 tars, uploads, polls status with live streaming. Subcommands: `mist deploy promote` (staging\u2192prod), `mist deploy preview` (local tunnel), `mist deploy rollback <id>`, `mist deploy verify <url>`, `mist deploy redeploy`."),e.push("8. QA: run `mist qa <live-url>` via your shell/bash tool, or just `mist qa` from inside the project if mistflow.json already has deploy.url. Call AFTER deploy. Do NOT show the URL to the user until QA passes."),e.push("9. Seed sample data (optional but recommended before QA when acceptance criteria depend on populated tables/lists): run `mist seed <absolute-path>` via your shell/bash tool. This defaults to local-only seeding against PGlite; use `--allow-remote` only when you intentionally want to seed a remote environment. Use `--reset` to clear the matched tables first."),e.push(""),e.push("Companion CLI (`@mistflow-ai/cli`, invoke as `mist` or via `npx -y @mistflow-ai/cli`) is the primary path for EVERYTHING except the 4 MCP tools below:"),e.push("- `mist plan` / `mist plan-directions` \u2014 plan an app."),e.push("- `mist init` \u2014 scaffold a new project from a plan (fast, ~10s)."),e.push("- `mist install` / `mist build` / `mist mockup` / `mist implement` / `mist debug` / `mist seed` / `mist qa` \u2014 local project lifecycle."),e.push("- `mist deploy` (+ promote/preview/rollback/verify/redeploy subcommands) \u2014 deploy orchestration."),e.push("- `mist status` / `mist fix` \u2014 feature manifest viewer + iteration loop."),e.push("- `mist contracts` \u2014 integration-contract layer management."),e.push("- `mist doctor` \u2014 project health diagnostics."),e.push("- `mist login` / `mist projects` / `mist logs` / `mist env` / `mist domains` / `mist rollback` \u2014 cloud-coordination commands."),e.push("- Call mist_help for the full reference."),e.push(""),e.push(it),e.push(""),e.push(st),e.push(""),e.push("Design presets (optional, between steps 2 and 3): run `mist projects designs`, `mist projects app-styles`, `mist projects integrations` via your shell/bash tool to browse catalogs. After `mist plan` generates a plan, it may recommend designs and styles \u2014 present these to the user before calling `mist init`."),e.push(""),e.push("Updating an existing Mistflow app:"),e.push("- Cosmetic or single-file changes: edit files directly, then `mist deploy` to publish."),e.push("- New page or feature (no new data model): mist_project action=get for context, build it, then `mist deploy`."),e.push('- Feature needing new data model: ask product questions, call `mist_project action=get` for context, then run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist deploy`.'),e.push('- Integration addition: ask product questions, call `mist_project action=get`, optionally browse `mist projects integrations`, run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist env` to set required keys before deploy, then `mist deploy`, then `mist qa`.'),e.push("- Bug fix: run `mist debug <absolute-path>` to analyze, fix the code, then `mist deploy`."),e.push(""),e.push("Template forking: use the Mistflow dashboard UI (app.mistflow.ai) to fork templates for now. CLI-side template-fork plumbing is in place but the API-client bridge lands in a follow-up release."),e.push(""),e.push("The 4 MCP tools:"),e.push("- mist_setup: authentication. Only call when user has never signed in or a tool returned 'auth_missing'/'auth_revoked'. Do NOT call for 500s, 404s, or network errors. Also accepts an apiKey parameter for headless auth."),e.push("- mist_project: read/write project state (actions: 'get' / 'update'). Other project queries (errors, logs, deployments, share, version, catalog browsing) moved to `mist projects <subcommand>` in the CLI."),e.push("- mist_browser: navigate, interact with, and screenshot the app during preview or after deploy. Returns screenshots inline in tool results \u2014 the one tool that genuinely needs the MCP transport."),e.push("- mist_help: returns the full CLI command reference. Call once per session to learn the available `mist` commands."),e.join(`
3
- `)}var Ze,et,tt,nt,rt,ot,st,it,se,ie,ae,le,R=u(()=>{"use strict";Ze="When invoking `mist plan` through your shell/bash tool, give it at least a 2 minute budget before assuming it stalled. `mist plan` commonly takes 30-150s. Heavier commands like install/build/qa/deploy can need a longer budget (up to about 5 minutes).",et='Treat the CLI\'s returned JSON as authoritative. If `mist plan --describe ...` returns `status: "clarify"`, the planning call completed and is waiting on user answers. Do NOT rerun the same command or describe it as "still generating". Only poll again when status is `"design_clarify_pending"`, and then use `mist plan-directions --cid <id> --wait --json`.',tt='When submitting discovery answers back to `mist plan --token ... --answers-stdin`, prefer an array payload like `{"answers":[{"question":"...","decisionKey":"...","answer":"..."}]}`. Do NOT collapse answers into a `{decisionKey: answer}` map because multiple discovery questions can share the same decision key.',nt="Before scaffolding a NEW app, resolve the destination path explicitly. If the user asked to create/build a new app and the current directory is not already that Mistflow project, ask whether to scaffold in the current folder or a new subfolder here (unless the user already gave a path). Do NOT inspect sibling directories and silently adopt one as the base just because it looks similar. Reuse an existing Mistflow project only when the user explicitly asks to continue/edit that project.",rt="If `mist plan` fails with a message like `Request to /api/plan timed out after 60s`, the host AI should suspect a stale CLI binary before blaming the backend. Check `mist --version`. If the installed CLI is behind the backend's advertised latest version, run `mist upgrade` (for the self-installed CLI in `~/.mistflow/bin/mist`) or retry with `npx -y @mistflow-ai/cli@latest ...`.",ot="`mist init` is all-or-nothing for normal users: it registers the cloud project first, scaffolds in a temp directory, then moves the finished app into place only after both steps succeed. If auth, quota, or network registration fails, stop before any app appears locally. Do NOT suggest reusing another app unless the user explicitly asks.",st="If `mist init` fails, stop before any cloud command and explain why. Do NOT default to reusing some other existing app as recovery unless the user explicitly asked to continue that app.",it='IMPORTANT \u2014 chaining discipline: once the user approves the plan, the init \u2192 install \u2192 implement (repeat) \u2192 build \u2192 deploy \u2192 seed (when needed) \u2192 qa chain is expected. Do NOT pause between these calls to ask the user "should I continue?" or offer options like "full build vs step-by-step." The tool itself will return a status requiring user input when it actually needs one (e.g. confirm_new_project, confirm_dark_theme, awaiting promotion). Otherwise, chain calls continuously. Brief one-line status updates are fine and encouraged; permission requests are not.',se="Connect the user's Mistflow account. Call this ONLY when: (a) the user has literally never signed in, or (b) a previous tool call returned error code 'auth_missing' or 'auth_revoked'. DO NOT call this tool in response to 500 errors, 404 errors, network errors, or any generic failure \u2014 those are backend issues, not auth issues. Running mist_setup when not needed wastes the user's time and creates login fatigue. Once signed in, the MCP persists a long-lived API key and never asks again. Two-phase device code flow: (1) Call without deviceCode \u2014 opens browser, returns status 'pending' with deviceCode and userCode. Tell the user the verification code and that they need to approve in the browser. (2) Call again with deviceCode after ~15 seconds \u2014 polls for approval. Also accepts an apiKey for headless auth (skips device code entirely).",ie="Read or update Mistflow project state. 'get' loads plan progress, env vars, and deploy info \u2014 call this at the start of an incremental change so you understand the current app before editing. 'update' marks plan steps complete or adds env vars (note: `mist implement` in the CLI auto-marks the previous step, so manual updates are rarely needed).",ae="Unified browser tool for navigating, interacting with, and capturing the app. Use 'navigate' to open a URL, interaction actions (click/type/fill/etc.) to test flows, 'snapshot' to inspect the accessibility tree, and 'screenshot' for a visual capture. Use after mist_preview to verify UI, test flows, and iterate on design.",le="Returns the Mistflow CLI command reference. Call this ONCE at session start (or whenever you're unsure which tool to use) to learn every `mist` CLI command, when to prefer it over an MCP tool, and how to chain calls. Results are static \u2014 no backend round-trip, safe to call frequently."});import{existsSync as z,readFileSync as me,writeFileSync as at,mkdirSync as lt}from"fs";import{join as H,dirname as K}from"path";import{homedir as ct}from"os";import{fileURLToPath as pt}from"url";function C(){if(O)return O;try{let e=pt(import.meta.url),t=K(e);for(let n=0;n<6;n++){let o=H(t,"package.json");if(z(o)){let s=JSON.parse(me(o,"utf-8"));if(s.name==="@mistflow-ai/mcp"&&typeof s.version=="string")return O=s.version,s.version}let r=K(t);if(r===t)break;t=r}}catch{}return O="0.0.0","0.0.0"}function M(e){let t=/^(\d+)\.(\d+)\.(\d+)/.exec(e.trim());return t?[parseInt(t[1],10),parseInt(t[2],10),parseInt(t[3],10)]:null}function pe(e,t){let n=M(e),o=M(t);if(!n||!o)return 0;for(let r=0;r<3;r++){if(n[r]<o[r])return-1;if(n[r]>o[r])return 1}return 0}function dt(e,t,n){if(n&&pe(e,n)<0)return"unsupported";if(!t||pe(e,t)>=0)return"none";let r=M(e),s=M(t);return!r||!s?"none":r[0]<s[0]?"major":r[1]<s[1]?"minor":"patch"}function I(e){let t=e.get("x-mistflow-mcp-latest")??"",n=e.get("x-mistflow-mcp-min-supported")??"",o=e.get("x-mistflow-mcp-changelog-url")??"";!t&&!n||(g={latest:t,minSupported:n,changelogUrl:o})}function fe(){let e=process.env.MISTFLOW_STATE_DIR||H(ct(),".mistflow");return H(e,"upgrade-state.json")}function ut(){try{let e=fe();return z(e)?JSON.parse(me(e,"utf-8")):{}}catch{return{}}}function mt(e){try{let t=fe(),n=K(t);z(n)||lt(n,{recursive:!0}),at(t,JSON.stringify(e,null,2)+`
4
- `,{mode:384})}catch{}}function ft(e){return e==="patch"?7*864e5:e==="minor"?1*864e5:0}function ge(){if(process.env.MISTFLOW_NO_UPGRADE_CHECK==="1"||!g)return null;let e=C();if(e==="0.0.0")return null;let t=dt(e,g.latest,g.minSupported);if(t==="none")return null;if(t==="unsupported")return ue(t,e,g);if(de)return null;let n=ut(),o=Date.now(),r=ft(t);return n.dismissedForVersion===g.latest&&t!=="major"||n.lastLatestSeen===g.latest&&n.lastShownMs&&o-n.lastShownMs<r?null:(de=!0,mt({...n,lastShownMs:o,lastLatestSeen:g.latest}),ue(t,e,g))}function ue(e,t,n){let o="npx -y mistflow-ai install",r=n.changelogUrl?`
2
+ var Xe=Object.defineProperty;var u=(e,t)=>()=>(e&&(t=e(e=0)),t);var re=(e,t)=>{for(var n in t)Xe(e,n,{get:t[n],enumerable:!0})};function ce(){let e=[];return e.push("Mistflow is a full-stack app builder that creates and deploys web apps from natural language descriptions. When a user asks to build, create, or make a web app, website, landing page, dashboard, internal tool, marketplace, content site, or browser game, use Mistflow tools. Mistflow creates NEW apps from scratch. It does NOT modify existing non-Mistflow codebases."),e.push(""),e.push("Call `mist_help` at any point for the full CLI command reference. The 4 MCP tools handle short, structured, AI-native flows (auth, project state, browser automation, CLI discovery). Everything else is the `mist` CLI \u2014 invoke via your shell/bash tool."),e.push(""),e.push(Ze),e.push(""),e.push(et),e.push(""),e.push(tt),e.push(""),e.push(nt),e.push(""),e.push(it),e.push(""),e.push(rt),e.push(""),e.push(ot),e.push(""),e.push("New app workflow (entirely CLI-driven):"),e.push("1. Choose destination: if the user did not already specify a path, ask whether to scaffold in the current folder or a new subfolder here. Resolve the absolute path before `mist init`."),e.push('2. Plan: run `mist plan --describe "<user\'s description>" --json` via your shell/bash tool. Pass the user\'s description EXACTLY as written \u2014 do NOT expand, rephrase, or add features. Relay any returned questions to the user, then submit answers via `echo \'<answers-json>\' | mist plan --token <id> --answers-stdin --json`. When status becomes "design_clarify_pending", poll with `mist plan-directions --cid <id> --wait --json`. When directions are ready, the CLI writes `<cwd>/.mistflow/design-directions.html` with each direction rendered in its own fonts + palette + hero treatment \u2014 run `open "<path>"` for the user so they can see visual options, THEN ask them to pick one by name. The sentinel payload (stderr) includes the `previewPath`. Finalize with `echo \'<pick-json>\' | mist plan --cid <id> --pick-stdin --json`. If the CLI returns status "confirm_new_project" (safety gate when inside an existing codebase), ask the user whether to scaffold a new Mistflow app or edit the existing code.'),e.push("3. Mockup (optional): run `mist mockup --plan-id <id>` via your shell/bash tool \u2014 generates a visual HTML wireframe for user preview. Iterative: pass --feedback to refine, --approved to lock in the design."),e.push("4. Scaffold: run `mist init --plan-id <id> --path <absolute-path>` via your shell/bash tool. `mist init` is transactional: it registers the cloud project first, scaffolds in a temp directory, and only moves the completed app into place after both steps succeed. If it fails before that move, stop and fix the error instead of continuing to cloud commands. Returns fast; does NOT run npm install."),e.push("5. Install dependencies: run `mist install <projectPath>` via your shell/bash tool (streams output)."),e.push("6. Implement: run `mist implement <absolute-path>` via your shell/bash tool \u2014 executes plan steps one at a time. Call repeatedly until all steps are done; it auto-marks the previous step as completed on each call."),e.push("7. Deploy: run `mist deploy [path]` via your shell/bash tool \u2014 tars, uploads, polls status with live streaming. Subcommands: `mist deploy promote` (staging\u2192prod), `mist deploy preview` (local tunnel), `mist deploy rollback <id>`, `mist deploy verify <url>`, `mist deploy redeploy`."),e.push("8. QA: run `mist qa <live-url>` via your shell/bash tool, or just `mist qa` from inside the project if mistflow.json already has deploy.url. Call AFTER deploy. Do NOT show the URL to the user until QA passes."),e.push("9. Seed sample data (optional but recommended before QA when acceptance criteria depend on populated tables/lists): run `mist seed <absolute-path>` via your shell/bash tool. This defaults to local-only seeding against PGlite; use `--allow-remote` only when you intentionally want to seed a remote environment. Use `--reset` to clear the matched tables first."),e.push(""),e.push("Companion CLI (`@mistflow-ai/cli`, invoke as `mist` or via `npx -y @mistflow-ai/cli`) is the primary path for EVERYTHING except the 4 MCP tools below:"),e.push("- `mist plan` / `mist plan-directions` \u2014 plan an app."),e.push("- `mist init` \u2014 scaffold a new project from a plan (fast, ~10s)."),e.push("- `mist install` / `mist build` / `mist mockup` / `mist implement` / `mist debug` / `mist seed` / `mist qa` \u2014 local project lifecycle."),e.push("- `mist deploy` (+ promote/preview/rollback/verify/redeploy subcommands) \u2014 deploy orchestration."),e.push("- `mist status` / `mist fix` \u2014 feature manifest viewer + iteration loop."),e.push("- `mist contracts` \u2014 integration-contract layer management."),e.push("- `mist doctor` \u2014 project health diagnostics."),e.push("- `mist login` / `mist projects` / `mist logs` / `mist env` / `mist domains` / `mist rollback` \u2014 cloud-coordination commands."),e.push("- Call mist_help for the full reference."),e.push(""),e.push(at),e.push(""),e.push(st),e.push(""),e.push("Design presets (optional, between steps 2 and 3): run `mist projects designs`, `mist projects app-styles`, `mist projects integrations` via your shell/bash tool to browse catalogs. After `mist plan` generates a plan, it may recommend designs and styles \u2014 present these to the user before calling `mist init`."),e.push(""),e.push("Updating an existing Mistflow app:"),e.push("- Cosmetic or single-file changes: edit files directly, then `mist deploy` to publish."),e.push("- New page or feature (no new data model): mist_project action=get for context, build it, then `mist deploy`."),e.push('- Feature needing new data model: ask product questions, call `mist_project action=get` for context, then run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist deploy`.'),e.push('- Integration addition: ask product questions, call `mist_project action=get`, optionally browse `mist projects integrations`, run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist env` to set required keys before deploy, then `mist deploy`, then `mist qa`.'),e.push("- Bug fix: run `mist debug <absolute-path>` to analyze, fix the code, then `mist deploy`."),e.push(""),e.push("Template forking: use the Mistflow dashboard UI (app.mistflow.ai) to fork templates for now. CLI-side template-fork plumbing is in place but the API-client bridge lands in a follow-up release."),e.push(""),e.push("The 4 MCP tools:"),e.push("- mist_setup: authentication. Only call when user has never signed in or a tool returned 'auth_missing'/'auth_revoked'. Do NOT call for 500s, 404s, or network errors. Also accepts an apiKey parameter for headless auth."),e.push("- mist_project: read/write project state (actions: 'get' / 'update'). Other project queries (errors, logs, deployments, share, version, catalog browsing) moved to `mist projects <subcommand>` in the CLI."),e.push("- mist_browser: navigate, interact with, and screenshot the app during preview or after deploy. Returns screenshots inline in tool results \u2014 the one tool that genuinely needs the MCP transport."),e.push("- mist_help: returns the full CLI command reference. Call once per session to learn the available `mist` commands."),e.join(`
3
+ `)}var Ze,et,tt,nt,ot,rt,st,it,at,se,ie,ae,le,C=u(()=>{"use strict";Ze="When invoking `mist plan` through your shell/bash tool, give it at least a 2 minute budget before assuming it stalled. `mist plan` commonly takes 30-150s. Heavier commands like install/build/qa/deploy can need a longer budget (up to about 5 minutes).",et='Treat the CLI\'s returned JSON as authoritative. If `mist plan --describe ...` returns `status: "clarify"`, the planning call completed and is waiting on user answers. Do NOT rerun the same command or describe it as "still generating". Only poll again when status is `"design_clarify_pending"`, and then use `mist plan-directions --cid <id> --wait --json`.',tt='When submitting discovery answers back to `mist plan --token ... --answers-stdin`, prefer an array payload like `{"answers":[{"question":"...","decisionKey":"...","answer":"..."}]}`. Do NOT collapse answers into a `{decisionKey: answer}` map because multiple discovery questions can share the same decision key.',nt="Before scaffolding a NEW app, resolve the destination path explicitly. If the user asked to create/build a new app and the current directory is not already that Mistflow project, ask whether to scaffold in the current folder or a new subfolder here (unless the user already gave a path). Do NOT inspect sibling directories and silently adopt one as the base just because it looks similar. Reuse an existing Mistflow project only when the user explicitly asks to continue/edit that project.",ot="If `mist plan` fails with a message like `Request to /api/plan timed out after 60s`, the host AI should suspect a stale CLI binary before blaming the backend. Check `mist --version`. If the installed CLI is behind the backend's advertised latest version, run `mist upgrade` (for the self-installed CLI in `~/.mistflow/bin/mist`) or retry with `npx -y @mistflow-ai/cli@latest ...`.",rt="`mist init` is all-or-nothing for normal users: it registers the cloud project first, scaffolds in a temp directory, then moves the finished app into place only after both steps succeed. If auth, quota, or network registration fails, stop before any app appears locally. Do NOT suggest reusing another app unless the user explicitly asks.",st="If `mist init` fails, stop before any cloud command and explain why. Do NOT default to reusing some other existing app as recovery unless the user explicitly asked to continue that app.",it="When a `mist` CLI command emits a line on stderr starting with `::mistflow-discovery-prompt::`, `::mistflow-design-picker::`, or `::mistflow-upgrade-prompt::`, parse the JSON payload AFTER the marker and surface it via your native structured-question UI \u2014 `AskUserQuestion` in Claude Code, quick pick in Cursor, equivalents in other hosts. Do NOT just print the stdout questions as plain numbered text; the sentinel exists specifically so you can render proper radio-button-style choices. Payload shapes: discovery has `questions[]` each with `id`/`decisionKey`/`question`/`options[]` (each option: `label`, `description`) plus a `recommended` hint and a `followUpCmd` to run with the user's answers; design-picker has `directions[]` with `id`/`name`/`description` + a `previewPath` to open and a `followUpCmd` for submitting the pick; upgrade-prompt has `actions[]` with `id`/`label`/`cmd`. Collect the answers, then run the `followUpCmd` \u2014 don't ask the user to run it themselves.",at='IMPORTANT \u2014 chaining discipline: once the user approves the plan, the init \u2192 install \u2192 implement (repeat) \u2192 build \u2192 deploy \u2192 seed (when needed) \u2192 qa chain is expected. Do NOT pause between these calls to ask the user "should I continue?" or offer options like "full build vs step-by-step." The tool itself will return a status requiring user input when it actually needs one (e.g. confirm_new_project, confirm_dark_theme, awaiting promotion). Otherwise, chain calls continuously. Brief one-line status updates are fine and encouraged; permission requests are not.',se="Connect the user's Mistflow account. Call this ONLY when: (a) the user has literally never signed in, or (b) a previous tool call returned error code 'auth_missing' or 'auth_revoked'. DO NOT call this tool in response to 500 errors, 404 errors, network errors, or any generic failure \u2014 those are backend issues, not auth issues. Running mist_setup when not needed wastes the user's time and creates login fatigue. Once signed in, the MCP persists a long-lived API key and never asks again. Two-phase device code flow: (1) Call without deviceCode \u2014 opens browser, returns status 'pending' with deviceCode and userCode. Tell the user the verification code and that they need to approve in the browser. (2) Call again with deviceCode after ~15 seconds \u2014 polls for approval. Also accepts an apiKey for headless auth (skips device code entirely).",ie="Read or update Mistflow project state. 'get' loads plan progress, env vars, and deploy info \u2014 call this at the start of an incremental change so you understand the current app before editing. 'update' marks plan steps complete or adds env vars (note: `mist implement` in the CLI auto-marks the previous step, so manual updates are rarely needed).",ae="Unified browser tool for navigating, interacting with, and capturing the app. Use 'navigate' to open a URL, interaction actions (click/type/fill/etc.) to test flows, 'snapshot' to inspect the accessibility tree, and 'screenshot' for a visual capture. Use after mist_preview to verify UI, test flows, and iterate on design.",le="Returns the Mistflow CLI command reference. Call this ONCE at session start (or whenever you're unsure which tool to use) to learn every `mist` CLI command, when to prefer it over an MCP tool, and how to chain calls. Results are static \u2014 no backend round-trip, safe to call frequently."});import{existsSync as z,readFileSync as me,writeFileSync as lt,mkdirSync as ct}from"fs";import{join as H,dirname as K}from"path";import{homedir as pt}from"os";import{fileURLToPath as dt}from"url";function R(){if(O)return O;try{let e=dt(import.meta.url),t=K(e);for(let n=0;n<6;n++){let r=H(t,"package.json");if(z(r)){let s=JSON.parse(me(r,"utf-8"));if(s.name==="@mistflow-ai/mcp"&&typeof s.version=="string")return O=s.version,s.version}let o=K(t);if(o===t)break;t=o}}catch{}return O="0.0.0","0.0.0"}function M(e){let t=/^(\d+)\.(\d+)\.(\d+)/.exec(e.trim());return t?[parseInt(t[1],10),parseInt(t[2],10),parseInt(t[3],10)]:null}function pe(e,t){let n=M(e),r=M(t);if(!n||!r)return 0;for(let o=0;o<3;o++){if(n[o]<r[o])return-1;if(n[o]>r[o])return 1}return 0}function ut(e,t,n){if(n&&pe(e,n)<0)return"unsupported";if(!t||pe(e,t)>=0)return"none";let o=M(e),s=M(t);return!o||!s?"none":o[0]<s[0]?"major":o[1]<s[1]?"minor":"patch"}function I(e){let t=e.get("x-mistflow-mcp-latest")??"",n=e.get("x-mistflow-mcp-min-supported")??"",r=e.get("x-mistflow-mcp-changelog-url")??"";!t&&!n||(g={latest:t,minSupported:n,changelogUrl:r})}function fe(){let e=process.env.MISTFLOW_STATE_DIR||H(pt(),".mistflow");return H(e,"upgrade-state.json")}function mt(){try{let e=fe();return z(e)?JSON.parse(me(e,"utf-8")):{}}catch{return{}}}function ft(e){try{let t=fe(),n=K(t);z(n)||ct(n,{recursive:!0}),lt(t,JSON.stringify(e,null,2)+`
4
+ `,{mode:384})}catch{}}function gt(e){return e==="patch"?7*864e5:e==="minor"?1*864e5:0}function ge(){if(process.env.MISTFLOW_NO_UPGRADE_CHECK==="1"||!g)return null;let e=R();if(e==="0.0.0")return null;let t=ut(e,g.latest,g.minSupported);if(t==="none")return null;if(t==="unsupported")return ue(t,e,g);if(de)return null;let n=mt(),r=Date.now(),o=gt(t);return n.dismissedForVersion===g.latest&&t!=="major"||n.lastLatestSeen===g.latest&&n.lastShownMs&&r-n.lastShownMs<o?null:(de=!0,ft({...n,lastShownMs:r,lastLatestSeen:g.latest}),ue(t,e,g))}function ue(e,t,n){let r="npx -y mistflow-ai install",o=n.changelogUrl?`
5
5
  What's new: ${n.changelogUrl}`:"";return e==="unsupported"?`
6
6
 
7
7
  ---
8
8
  Mistflow ${t} is no longer supported.
9
9
  You must upgrade to ${n.latest} or newer to continue:
10
10
 
11
- ${o}
11
+ ${r}
12
12
 
13
- After upgrading, restart your AI editor.${r}
13
+ After upgrading, restart your AI editor.${o}
14
14
  ---`:e==="major"?`
15
15
 
16
16
  ---
17
17
  Mistflow ${n.latest} is available (you have ${t}).
18
- This is a major update. Run \`${o}\` and restart your editor.${r}
18
+ This is a major update. Run \`${r}\` and restart your editor.${o}
19
19
  ---`:e==="minor"?`
20
20
 
21
21
  --- Mistflow update available: ${t} -> ${n.latest} ---
22
- Run \`${o}\` to upgrade, then restart your editor.${r}`:`
22
+ Run \`${r}\` to upgrade, then restart your editor.${o}`:`
23
23
 
24
- (Mistflow ${n.latest} is out, you have ${t}. Run \`${o}\` when convenient.)`}var O,g,de,L=u(()=>{"use strict";O=null;g=null;de=!1});function c(e,t=!1){let n=e;try{let o=ge();o&&(n=e+o)}catch{}return{content:[{type:"text",text:n}],isError:t}}function he(e){return c(`This is not a Mistflow project (no mistflow.json found at ${e}).
24
+ (Mistflow ${n.latest} is out, you have ${t}. Run \`${r}\` when convenient.)`}var O,g,de,L=u(()=>{"use strict";O=null;g=null;de=!1});function c(e,t=!1){let n=e;try{let r=ge();r&&(n=e+r)}catch{}return{content:[{type:"text",text:n}],isError:t}}function he(e){return c(`This is not a Mistflow project (no mistflow.json found at ${e}).
25
25
 
26
26
  Mistflow creates new projects from scratch \u2014 it doesn't work inside existing codebases.
27
27
 
@@ -30,15 +30,15 @@ To get started:
30
30
  2. Run mist init --plan-id <planId> --path <absolute-path>
31
31
  3. Run mist install <absolute-path>, then mist implement <absolute-path>
32
32
 
33
- If you want to deploy an existing project, use your framework's deploy tools directly.`,!0)}var P=u(()=>{"use strict";L()});import{readFileSync as gt,existsSync as ye,writeFileSync as ht,mkdirSync as yt,renameSync as wt,unlinkSync as bt}from"fs";import{join as we,dirname as vt}from"path";import{homedir as _t}from"os";import{randomBytes as kt}from"crypto";function be(){return we(_t(),".mistflow","credentials.json")}function A(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function ve(){let e=be();if(!ye(e))return null;try{let t=JSON.parse(gt(e,"utf-8"));return typeof t.apiKey=="string"?{[St]:t}:t}catch{return null}}function G(){let e=process.env.MISTFLOW_API_KEY;if(e)return{ok:!0,creds:{apiKey:e,orgId:"",orgSlug:"env"}};let t=ve();if(!t)return{ok:!1,reason:"missing"};let n=A(),o=t[n];return o&&typeof o.apiKey=="string"&&o.apiKey&&typeof o.orgId=="string"?{ok:!0,creds:o}:{ok:!1,reason:"missing"}}function Q(e){let t=be(),n=vt(t);ye(n)||yt(n,{recursive:!0});let o=ve()??{},r=A();o[r]=e;let s=we(n,`.credentials.tmp.${kt(8).toString("hex")}`);try{ht(s,JSON.stringify(o,null,2)+`
34
- `,{mode:384}),wt(s,t)}catch(i){try{bt(s)}catch{}throw i}}function Y(){return G().ok}var St,X=u(()=>{"use strict";St="https://api.mistflow.ai"});function f(){return A()}function j(){let e=G();if(!e.ok)throw new m("auth_missing","No Mistflow credentials found.",401);return xt(e.creds)}function xt(e){return{Authorization:`ApiKey ${e.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()}}function Rt(e){try{I(e.headers)}catch{}}async function Ct(e,t,n,o){for(let r=0;r<2;r++)try{return await fetch(e,{...t,signal:AbortSignal.timeout(n)})}catch(s){let i=s instanceof Error&&s.name==="TimeoutError",a=s instanceof TypeError;if(o&&r===0&&(i||a)){console.error(`[api] Retrying ${e} after ${i?"timeout":"network error"}`);continue}throw s}throw new Error("fetchWithRetry: exhausted retries")}async function Pt(e){let t=null;try{t=await e.json()}catch{t=null}let n=t&&typeof t.code=="string"?t.code:void 0,o=t&&typeof t.message=="string"?t.message:t&&typeof t.detail=="string"?t.detail:e.statusText||"Request failed";if(n)return new m(n,o,e.status,t?.details);let r=e.status;return r===401?new m("auth_invalid",o,r):r===403?new m("permission_denied",o,r):r===404?new m("not_found",o,r):r===409?new m("conflict",o,r):r===422?new m("validation_error",o,r):r===429?new m("rate_limited",o,r):r>=500?new m("server_error",e.statusText||"Internal server error",r):new m("client_error",o,r)}async function jt(e,t={}){let n=j(),{timeoutMs:o,idempotent:r,...s}=t,i=o??3e4,a=(s.method??"GET").toUpperCase(),p=r??(a==="GET"||a==="HEAD"),l;try{l=await Ct(`${f()}${e}`,{...s,headers:{...n,...s.headers}},i,p)}catch(_){throw _ instanceof Error&&_.name==="TimeoutError"?new m("network_error","Request timed out. Try again in a moment."):new m("network_error","Cannot reach Mistflow servers. Check your network.")}if(Rt(l),!l.ok)throw await Pt(l);return l.json()}async function _e(e,t,n="neon",o){return jt("/api/projects",{method:"POST",body:JSON.stringify({name:e,template:t,db_provider:n,requested_subdomain:o})})}var m,On,$=u(()=>{"use strict";X();L();m=class extends Error{constructor(n,o,r,s){super(o);this.code=n;this.statusCode=r;this.details=s;this.name="MistflowApiError"}get isAuth(){return this.code.startsWith("auth_")}get isTransient(){return this.code==="server_error"||this.code==="upstream_error"||this.code==="network_error"||this.code==="rate_limited"}};On=300*1e3});import{z as Z}from"zod";import{platform as It}from"os";import{execFile as ke}from"child_process";function Ut(e){return"error"in e}function xe(e){return new Promise(t=>setTimeout(t,e))}function Et(e){return new Promise(t=>{let n=It();n==="win32"?ke("cmd.exe",["/c","start","",e],o=>{o&&console.error("Could not open browser:",o.message),t(!o)}):ke(n==="darwin"?"open":"xdg-open",[e],r=>{r&&console.error("Could not open browser:",r.message),t(!r)}),setTimeout(()=>t(!1),5e3)})}async function Se(e,t,n,o){let r=n,s=o.sleep??xe;for(let i=0;i<t;i++){await s(r);let a;try{let l=await o.fetch(`${f()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e})});if(!l.ok)continue;a=await l.json()}catch{continue}if(Ut(a))switch(a.error){case"authorization_pending":continue;case"slow_down":r+=5e3;continue;case"expired_token":return c("The sign-in link expired. Run mist_setup again to get a new code.",!0);case"access_denied":return c("Sign-in was cancelled. Run mist_setup again to try again.",!0);case"already_exchanged":return c("This sign-in link was already used. Run mist_setup again to get a new code.",!0)}let p=a.email||a.org_name||a.org_slug;return Q({apiKey:a.api_key,apiKeyId:a.api_key_id,apiKeyName:a.api_key_name,orgId:a.org_id,orgSlug:a.org_slug,email:a.email}),c(`Connected to Mistflow as ${p}. You are ready to build and deploy.`)}return null}async function Ot(e,t=Dt){let n=e;if(n?.apiKey)try{let i=await t.fetch(`${f()}/api/org`,{headers:{Authorization:`ApiKey ${n.apiKey}`}});if(!i.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await i.json();return Q({apiKey:n.apiKey,orgId:a.id,orgSlug:a.slug}),c(`Connected to Mistflow as ${a.slug} via API key. You are ready to build and deploy.`)}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}if(n?.deviceCode){let i=await Se(n.deviceCode,6,5e3,t);return i||c(JSON.stringify({status:"pending",deviceCode:n.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let o;try{let i=await t.fetch(`${f()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!i.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);o=await i.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let r=`${o.verification_uri}?code=${o.user_code}`;console.error(`
35
- Sign in at: ${r}
36
- Your code: ${o.user_code}
37
- `);try{await t.openBrowser(r)}catch{}let s=await Se(o.device_code,6,5e3,t);return s||c(JSON.stringify({status:"pending",deviceCode:o.device_code,signInUrl:r,userCode:o.user_code,instruction:"The user hasn't approved yet. Wait ~15 seconds, then call mist_setup again with deviceCode='"+o.device_code+"' to check if they approved."}))}var Tt,Dt,Re,Ce=u(()=>{"use strict";R();P();$();X();Tt=Z.object({apiKey:Z.string().optional().describe("API key (mist_...) for headless auth. Skips the device code flow entirely. Generate one at app.mistflow.ai/mcp-keys."),deviceCode:Z.string().optional().describe("Resume polling for a pending device code. Returned by a previous mist_setup call with status 'pending'. Call mist_setup again with this value after ~15 seconds to check if the user approved.")});Dt={fetch:globalThis.fetch,openBrowser:Et,sleep:xe};Re={name:"mist_setup",description:se,inputSchema:Tt,handler:e=>Ot(e)}});import{existsSync as Mt,readFileSync as Lt}from"fs";function Pe(e){let t=new Set;if(!Mt(e))return t;let n=Lt(e,"utf-8");for(let o of n.split(`
38
- `)){let r=o.trim();if(!r||r.startsWith("#"))continue;let s=r.indexOf("=");if(s>0){let i=r.slice(0,s).trim(),a=r.slice(s+1).trim();a&&a!=='""'&&a!=="''"&&t.add(i)}}return t}var je=u(()=>{"use strict"});var re={};oe(re,{emptyState:()=>ne,fetchRemoteState:()=>Ft,fuzzyMatch:()=>Bt,getLocalStatePath:()=>ee,readLocalState:()=>qt,syncRemoteState:()=>Vt,writeLocalState:()=>te});import{existsSync as Ie,readFileSync as At,writeFileSync as $t,mkdirSync as Nt}from"fs";import{join as Te}from"path";function ee(e){return Te(e,".mistflow","state.json")}function qt(e){let t=ee(e);if(!Ie(t))return null;try{return JSON.parse(At(t,"utf-8"))}catch{return null}}function te(e,t){let n=Te(e,".mistflow");Ie(n)||Nt(n,{recursive:!0}),$t(ee(e),JSON.stringify(t,null,2)+`
39
- `)}function ne(e,t){return{projectId:e,name:t,template:"",features:[],dbSchema:[],deployCount:0,decisions:[],provenance:[]}}async function Ft(e){let t;try{t=j()}catch{return null}try{let n=await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{headers:{...t,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()}});try{I(n.headers)}catch{}return n.ok?await n.json():null}catch{return null}}async function Vt(e,t){let n;try{n=j()}catch{return!1}try{let o=await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...n,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()},body:JSON.stringify(t)});try{I(o.headers)}catch{}return o.ok}catch{return!1}}function Bt(e,t){let n=e.toLowerCase(),o=t.toLowerCase();return o.includes(n)||n.includes(o)?!0:n.split(/\s+/).some(s=>s.length>=3&&o.includes(s))}var N=u(()=>{"use strict";$();L()});var De={};oe(De,{ensureBackendRegistered:()=>Qt,ensureShadcnComponents:()=>Yt});import{existsSync as Ee,readFileSync as Jt,writeFileSync as Wt}from"fs";import{join as q}from"path";import{spawn as Ht}from"child_process";function Kt(e,t,n,o,r){return new Promise(s=>{let i=Ht(e,t,{cwd:n,stdio:["pipe","pipe","pipe"],timeout:o,...r?{env:{...process.env,...r}}:{}}),a="",p="";i.stdout?.on("data",l=>{a+=l.toString()}),i.stderr?.on("data",l=>{p+=l.toString()}),i.on("close",l=>s({success:l===0,stdout:a,stderr:p})),i.on("error",l=>s({success:!1,stdout:a,stderr:p+l.message}))})}function zt(e){let t=q(e,"mistflow.json");if(!Ee(t))return null;try{return JSON.parse(Jt(t,"utf-8"))}catch{return null}}function Gt(e,t){Wt(q(e,"mistflow.json"),JSON.stringify(t,null,2))}async function Ue(e,t){try{let n=t.features,o=t.steps,r={plan:t};Array.isArray(n)&&n.length>0&&(r.features=n.map(s=>s.name)),Array.isArray(o)&&o.length>0&&(r.provenance=o.map(s=>({feature:s.name??s.title??`Step ${s.number??"?"}`,user_intent:(s.description??"").slice(0,500),decisions:"Seeded from plan",tradeoffs:"",files_affected:[]}))),await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...j(),"Content-Type":"application/json"},body:JSON.stringify(r)})}catch(n){console.error("[self-heal] state sync failed:",n instanceof Error?n.message:String(n))}}async function Qt(e,t={}){let n=zt(e);if(n){if(!Y())return n.projectId;if(!n.projectId)try{let r=n.plan?.requestedSubdomain,s=await _e(n.name,void 0,n.dbProvider??"neon",r);return n.projectId=s.id,Gt(e,n),te(e,ne(s.id,n.name)),n.plan&&await Ue(s.id,n.plan),console.error(`[self-heal] registered project ${s.id.slice(0,8)} with backend`),s.id}catch(o){console.error("[self-heal] createProject failed:",o instanceof Error?o.message:String(o));return}return t.forceSync&&n.plan&&n.projectId&&await Ue(n.projectId,n.plan),n.projectId}}async function Yt(e,t){let n=["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"],o=t&&t.length>0?t:n,r=q(e,"components","ui"),s=[],i=[];for(let l of o)Ee(q(r,`${l}.tsx`))?s.push(l):i.push(l);if(i.length===0)return{installed:[],alreadyPresent:s};let a={NPM_CONFIG_LEGACY_PEER_DEPS:"true"},p=await Kt("npx",["--yes","shadcn@latest","add","-y","-o",...i],e,18e4,a);return p.success?{installed:i,alreadyPresent:s}:{installed:[],alreadyPresent:s,failed:`shadcn add failed for: ${i.join(", ")}. ${p.stderr.slice(-300)}`.trim()}}var Oe=u(()=>{"use strict";$();N()});import{z as y}from"zod";import{resolve as Xt,join as Me}from"path";import{existsSync as Zt,readFileSync as Le,writeFileSync as en}from"fs";var tn,Ae,$e=u(()=>{"use strict";P();je();tn=y.object({action:y.enum(["get","update"]).default("get").describe("'get' reads current project state. 'update' modifies it."),projectPath:y.string().optional().describe("Path to the project directory (default: current working directory)"),completedStep:y.number().optional().describe("(update only) Mark a plan step as completed by step number"),addEnvVar:y.object({key:y.string(),description:y.string().optional(),setupUrl:y.string().optional()}).optional().describe("(update only) Add a required env var to the project manifest")}),Ae={name:"mist_state",description:"Read or update project state in mistflow.json. Use action='get' to load plan progress, env var status, and deploy info. Use action='update' to mark plan steps complete or add required env vars. Use when the user says 'mist status', 'mist state', or 'mist update state'.",inputSchema:tn,handler:async e=>{let t=e,n=Xt(t.projectPath??process.cwd()),o=Me(n,"mistflow.json");if(!Zt(o))return he(n);let r;try{r=JSON.parse(Le(o,"utf-8"))}catch{return c("Failed to parse mistflow.json.",!0)}if(t.action==="get"){if(!r.projectId)try{let{ensureBackendRegistered:d}=await Promise.resolve().then(()=>(Oe(),De));await d(n)&&(r=JSON.parse(Le(o,"utf-8")))}catch{}let a=r.plan,p=a?.steps?.filter(d=>d.status==="completed").length??0,l=a?.steps?.length??0,_=Pe(Me(n,".env.local")),T=r.env?.required?Object.entries(r.env.required).map(([d,D])=>({name:d,description:D?.description,configured:_.has(d)})):[];r.projectId&&Promise.resolve().then(()=>(N(),re)).then(({fetchRemoteState:d})=>d(r.projectId)).catch(()=>{});let x=[`Project: ${r.name}`];if(a){x.push(`Plan: ${a.summary??a.name??"unnamed"} \u2014 ${p}/${l} steps complete`);for(let d of a.steps){let D=d.status==="completed"?"\u2713":d.status==="in_progress"?"\u2192":" ";x.push(` [${D}] ${d.number}. ${d.name}`)}}let U=T.filter(d=>!d.configured);U.length>0&&x.push(`Missing env vars: ${U.map(d=>d.name).join(", ")}`),r.deploy?.url?x.push(`Deployed: ${r.deploy.url} (${r.deploy.count??0} deploys)`):x.push("Not deployed yet");let E=[],W=a?.steps?.find(d=>d.status!=="completed");return W?E.push(`NEXT: Run mist implement <absolute-path> to work on step ${W.number} (${W.name}).`):a&&p===l&&(r.deploy?.url||E.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT ask the user \u2014 just deploy.")),U.length>0&&E.push(`Missing env vars in .env.local: ${U.map(d=>d.name).join(", ")}`),c(JSON.stringify({name:r.name,projectId:r.projectId,planProgress:a?{name:a.name,summary:a.summary,totalSteps:l,completedSteps:p,steps:a.steps}:null,envStatus:T,deploy:r.deploy??null,contextMessage:x.join(`
40
- `),nextSteps:E}))}let s=[];if(t.completedStep!==void 0){let a=r.plan;if(a?.steps){let p=a.steps.findIndex(l=>l.number===t.completedStep);if(p===-1)return c(`Step ${t.completedStep} not found in the plan.`,!0);a.steps[p].status="completed",s.push(`Step ${t.completedStep} marked as completed`)}}t.addEnvVar&&(r.env||(r.env={required:{}}),r.env.required||(r.env.required={}),r.env.required[t.addEnvVar.key]={description:t.addEnvVar.description,setupUrl:t.addEnvVar.setupUrl},s.push(`Added required env var: ${t.addEnvVar.key}`)),en(o,JSON.stringify(r,null,2)+`
41
- `),r.projectId&&Promise.resolve().then(()=>(N(),re)).then(async({readLocalState:a,syncRemoteState:p})=>{let l=a(n);l&&await p(r.projectId,l)}).catch(()=>{});let i=[];if(t.completedStep!==void 0){let p=r.plan?.steps?.find(l=>l.status!=="completed");p?i.push(`NEXT: Run mist implement <absolute-path> to work on step ${p.number} (${p.name}). Do this now.`):i.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT suggest localhost.")}return t.addEnvVar&&(i.push(`Add ${t.addEnvVar.key} to your .env.local file`),t.addEnvVar.setupUrl&&i.push(`Get the value from: ${t.addEnvVar.setupUrl}`)),c(JSON.stringify({updated:!0,changes:s,message:s.length>0?`Project state saved. ${s.join(". ")}.`:"No changes made.",nextSteps:i.length>0?i:void 0}))}}});import{z as w}from"zod";var nn,Ne,qe=u(()=>{"use strict";R();$e();nn=w.object({action:w.enum(["get","update"]).default("get").describe("'get' reads current project state (context oracle \u2014 call before making decisions in an existing project). 'update' marks steps complete or adds env vars. All other project queries moved to the CLI in MCP 0.6.0: `mist projects share`, `mist projects errors`, `mist projects logs`, `mist projects deployments`, `mist projects version`, `mist projects designs`, `mist projects app-styles`, `mist projects integrations`."),projectPath:w.string().optional().describe("Path to the project directory (default: cwd)"),completedStep:w.number().optional().describe("(update) Mark a plan step as completed by step number"),addEnvVar:w.object({key:w.string(),description:w.string().optional(),setupUrl:w.string().optional()}).optional().describe("(update) Add a required env var to the project manifest")}),Ne={name:"mist_project",description:ie,inputSchema:nn,handler:async e=>{let t=e;return Ae.handler({action:t.action,projectPath:t.projectPath,completedStep:t.completedStep,addEnvVar:t.addEnvVar})}}});async function rn(){try{return await import("playwright")}catch{throw new Error("Playwright is not installed. Run: cd packages/mcp-server && pnpm add playwright && npx playwright install chromium")}}async function on(){let e=await rn();return(!k||!k.isConnected())&&(k=await e.chromium.launch({headless:!0})),b&&(await b.close().catch(()=>{}),b=null),b=await k.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),h=await b.newPage(),h}async function Fe(){return h&&!h.isClosed()?h:(F||(F=on().finally(()=>{F=null})),F)}async function Ve(){h&&!h.isClosed()&&await h.close().catch(()=>{}),b&&await b.close().catch(()=>{}),k?.isConnected()&&await k.close().catch(()=>{}),h=null,b=null,k=null}async function V(e){return await e.locator("body").ariaSnapshot()}async function B(e,t=!1){return await e.screenshot({fullPage:t,type:"png"})}var k,b,h,F,Be=u(()=>{"use strict";k=null,b=null,h=null,F=null;process.once("SIGTERM",()=>{Ve().finally(()=>process.exit(0))});process.once("SIGINT",()=>{Ve().finally(()=>process.exit(0))})});import{z as S}from"zod";var sn,Je,We=u(()=>{"use strict";R();P();Be();sn=S.object({action:S.enum(["navigate","go_back","go_forward","click","type","fill","select_option","press_key","hover","screenshot","snapshot"]).describe("Action to perform. Navigation: navigate|go_back|go_forward. Interaction: click|type|fill|select_option|press_key|hover. Visual: screenshot (returns image) | snapshot (returns accessibility tree)."),url:S.string().optional().describe("URL to navigate to. Required for 'navigate'; optional for 'screenshot' (navigates before capturing)."),selector:S.string().optional().describe("CSS selector of the target element. Required for: click, type, fill, select_option, hover. Optional for screenshot (captures just that element)."),value:S.string().optional().describe("Text to type/fill, option to select, or key to press (e.g. 'Enter', 'Tab'). Required for: type, fill, select_option, press_key."),fullPage:S.boolean().default(!1).describe("For 'screenshot': capture the full scrollable page instead of just the viewport."),includeScreenshot:S.boolean().default(!1).describe("For navigate/interact actions: also return a screenshot alongside the accessibility snapshot.")}),Je={name:"mist_browser",description:ae,inputSchema:sn,handler:async e=>{let t=e,n=await Fe();if(t.action==="navigate"){if(!t.url)return c("URL is required for 'navigate'.",!0);let s=[],i=l=>{l.type()==="error"&&s.push(l.text())};n.on("console",i),await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{});let a=[],p=l=>a.push(l.message);if(n.on("pageerror",p),await n.waitForTimeout(500),n.removeListener("console",i),n.removeListener("pageerror",p),s.length>0||a.length>0){let l=await V(n),_=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:l,consoleErrors:s,pageErrors:a,hasErrors:!0})}];if(t.includeScreenshot){let T=await B(n);_.push({type:"image",data:T.toString("base64"),mimeType:"image/png"})}return{content:_}}}else if(t.action==="go_back")await n.goBack({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="go_forward")await n.goForward({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="click"){if(!t.selector)return c("Selector is required for 'click'.",!0);await n.click(t.selector,{timeout:1e4}),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="type"){if(!t.selector)return c("Selector is required for 'type'.",!0);if(!t.value)return c("Value is required for 'type'.",!0);await n.type(t.selector,t.value,{delay:50})}else if(t.action==="fill"){if(!t.selector)return c("Selector is required for 'fill'.",!0);if(!t.value)return c("Value is required for 'fill'.",!0);await n.fill(t.selector,t.value)}else if(t.action==="select_option"){if(!t.selector)return c("Selector is required for 'select_option'.",!0);if(!t.value)return c("Value is required for 'select_option'.",!0);await n.selectOption(t.selector,t.value)}else if(t.action==="hover"){if(!t.selector)return c("Selector is required for 'hover'.",!0);await n.hover(t.selector,{timeout:1e4})}else if(t.action==="press_key"){if(!t.value)return c("Value is required for 'press_key' (e.g. 'Enter').",!0);await n.keyboard.press(t.value),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="screenshot"){t.url&&(await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{}));let s;if(t.selector){let i=await n.$(t.selector);if(!i)return c(`Element not found: ${t.selector}`,!0);s=await i.screenshot({type:"png"})}else s=await B(n,t.fullPage);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),message:`Screenshot captured (${t.fullPage?"full page":"viewport"})`})},{type:"image",data:s.toString("base64"),mimeType:"image/png"}]}}else if(t.action==="snapshot"){let s=await V(n);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:s})}]}}let o=await V(n),r=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:o})}];if(t.includeScreenshot){let s=await B(n);r.push({type:"image",data:s.toString("base64"),mimeType:"image/png"})}return{content:r}}}});import{z as He}from"zod";var Ke,ze,Ge=u(()=>{"use strict";R();P();Ke=`# Mistflow CLI reference
33
+ If you want to deploy an existing project, use your framework's deploy tools directly.`,!0)}var P=u(()=>{"use strict";L()});import{readFileSync as ht,existsSync as ye,writeFileSync as yt,mkdirSync as wt,renameSync as bt,unlinkSync as vt}from"fs";import{join as we,dirname as _t}from"path";import{homedir as kt}from"os";import{randomBytes as St}from"crypto";function be(){return we(kt(),".mistflow","credentials.json")}function A(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function ve(){let e=be();if(!ye(e))return null;try{let t=JSON.parse(ht(e,"utf-8"));return typeof t.apiKey=="string"?{[xt]:t}:t}catch{return null}}function G(){let e=process.env.MISTFLOW_API_KEY;if(e)return{ok:!0,creds:{apiKey:e,orgId:"",orgSlug:"env"}};let t=ve();if(!t)return{ok:!1,reason:"missing"};let n=A(),r=t[n];return r&&typeof r.apiKey=="string"&&r.apiKey&&typeof r.orgId=="string"?{ok:!0,creds:r}:{ok:!1,reason:"missing"}}function Q(e){let t=be(),n=_t(t);ye(n)||wt(n,{recursive:!0});let r=ve()??{},o=A();r[o]=e;let s=we(n,`.credentials.tmp.${St(8).toString("hex")}`);try{yt(s,JSON.stringify(r,null,2)+`
34
+ `,{mode:384}),bt(s,t)}catch(i){try{vt(s)}catch{}throw i}}function Y(){return G().ok}var xt,X=u(()=>{"use strict";xt="https://api.mistflow.ai"});function f(){return A()}function j(){let e=G();if(!e.ok)throw new m("auth_missing","No Mistflow credentials found.",401);return Ct(e.creds)}function Ct(e){return{Authorization:`ApiKey ${e.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()}}function Rt(e){try{I(e.headers)}catch{}}async function Pt(e,t,n,r){for(let o=0;o<2;o++)try{return await fetch(e,{...t,signal:AbortSignal.timeout(n)})}catch(s){let i=s instanceof Error&&s.name==="TimeoutError",a=s instanceof TypeError;if(r&&o===0&&(i||a)){console.error(`[api] Retrying ${e} after ${i?"timeout":"network error"}`);continue}throw s}throw new Error("fetchWithRetry: exhausted retries")}async function jt(e){let t=null;try{t=await e.json()}catch{t=null}let n=t&&typeof t.code=="string"?t.code:void 0,r=t&&typeof t.message=="string"?t.message:t&&typeof t.detail=="string"?t.detail:e.statusText||"Request failed";if(n)return new m(n,r,e.status,t?.details);let o=e.status;return o===401?new m("auth_invalid",r,o):o===403?new m("permission_denied",r,o):o===404?new m("not_found",r,o):o===409?new m("conflict",r,o):o===422?new m("validation_error",r,o):o===429?new m("rate_limited",r,o):o>=500?new m("server_error",e.statusText||"Internal server error",o):new m("client_error",r,o)}async function It(e,t={}){let n=j(),{timeoutMs:r,idempotent:o,...s}=t,i=r??3e4,a=(s.method??"GET").toUpperCase(),p=o??(a==="GET"||a==="HEAD"),l;try{l=await Pt(`${f()}${e}`,{...s,headers:{...n,...s.headers}},i,p)}catch(_){throw _ instanceof Error&&_.name==="TimeoutError"?new m("network_error","Request timed out. Try again in a moment."):new m("network_error","Cannot reach Mistflow servers. Check your network.")}if(Rt(l),!l.ok)throw await jt(l);return l.json()}async function _e(e,t,n="neon",r){return It("/api/projects",{method:"POST",body:JSON.stringify({name:e,template:t,db_provider:n,requested_subdomain:r})})}var m,Mn,$=u(()=>{"use strict";X();L();m=class extends Error{constructor(n,r,o,s){super(r);this.code=n;this.statusCode=o;this.details=s;this.name="MistflowApiError"}get isAuth(){return this.code.startsWith("auth_")}get isTransient(){return this.code==="server_error"||this.code==="upstream_error"||this.code==="network_error"||this.code==="rate_limited"}};Mn=300*1e3});import{z as Z}from"zod";import{platform as Tt}from"os";import{execFile as ke}from"child_process";function Et(e){return"error"in e}function xe(e){return new Promise(t=>setTimeout(t,e))}function Dt(e){return new Promise(t=>{let n=Tt();n==="win32"?ke("cmd.exe",["/c","start","",e],r=>{r&&console.error("Could not open browser:",r.message),t(!r)}):ke(n==="darwin"?"open":"xdg-open",[e],o=>{o&&console.error("Could not open browser:",o.message),t(!o)}),setTimeout(()=>t(!1),5e3)})}async function Se(e,t,n,r){let o=n,s=r.sleep??xe;for(let i=0;i<t;i++){await s(o);let a;try{let l=await r.fetch(`${f()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e})});if(!l.ok)continue;a=await l.json()}catch{continue}if(Et(a))switch(a.error){case"authorization_pending":continue;case"slow_down":o+=5e3;continue;case"expired_token":return c("The sign-in link expired. Run mist_setup again to get a new code.",!0);case"access_denied":return c("Sign-in was cancelled. Run mist_setup again to try again.",!0);case"already_exchanged":return c("This sign-in link was already used. Run mist_setup again to get a new code.",!0)}let p=a.email||a.org_name||a.org_slug;return Q({apiKey:a.api_key,apiKeyId:a.api_key_id,apiKeyName:a.api_key_name,orgId:a.org_id,orgSlug:a.org_slug,email:a.email}),c(`Connected to Mistflow as ${p}. You are ready to build and deploy.`)}return null}async function Mt(e,t=Ot){let n=e;if(n?.apiKey)try{let i=await t.fetch(`${f()}/api/org`,{headers:{Authorization:`ApiKey ${n.apiKey}`}});if(!i.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await i.json();return Q({apiKey:n.apiKey,orgId:a.id,orgSlug:a.slug}),c(`Connected to Mistflow as ${a.slug} via API key. You are ready to build and deploy.`)}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}if(n?.deviceCode){let i=await Se(n.deviceCode,6,5e3,t);return i||c(JSON.stringify({status:"pending",deviceCode:n.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let r;try{let i=await t.fetch(`${f()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!i.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);r=await i.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let o=`${r.verification_uri}?code=${r.user_code}`;console.error(`
35
+ Sign in at: ${o}
36
+ Your code: ${r.user_code}
37
+ `);try{await t.openBrowser(o)}catch{}let s=await Se(r.device_code,6,5e3,t);return s||c(JSON.stringify({status:"pending",deviceCode:r.device_code,signInUrl:o,userCode:r.user_code,instruction:"The user hasn't approved yet. Wait ~15 seconds, then call mist_setup again with deviceCode='"+r.device_code+"' to check if they approved."}))}var Ut,Ot,Ce,Re=u(()=>{"use strict";C();P();$();X();Ut=Z.object({apiKey:Z.string().optional().describe("API key (mist_...) for headless auth. Skips the device code flow entirely. Generate one at app.mistflow.ai/mcp-keys."),deviceCode:Z.string().optional().describe("Resume polling for a pending device code. Returned by a previous mist_setup call with status 'pending'. Call mist_setup again with this value after ~15 seconds to check if the user approved.")});Ot={fetch:globalThis.fetch,openBrowser:Dt,sleep:xe};Ce={name:"mist_setup",description:se,inputSchema:Ut,handler:e=>Mt(e)}});import{existsSync as Lt,readFileSync as At}from"fs";function Pe(e){let t=new Set;if(!Lt(e))return t;let n=At(e,"utf-8");for(let r of n.split(`
38
+ `)){let o=r.trim();if(!o||o.startsWith("#"))continue;let s=o.indexOf("=");if(s>0){let i=o.slice(0,s).trim(),a=o.slice(s+1).trim();a&&a!=='""'&&a!=="''"&&t.add(i)}}return t}var je=u(()=>{"use strict"});var oe={};re(oe,{emptyState:()=>ne,fetchRemoteState:()=>Vt,fuzzyMatch:()=>Jt,getLocalStatePath:()=>ee,readLocalState:()=>Ft,syncRemoteState:()=>Bt,writeLocalState:()=>te});import{existsSync as Ie,readFileSync as $t,writeFileSync as Nt,mkdirSync as qt}from"fs";import{join as Te}from"path";function ee(e){return Te(e,".mistflow","state.json")}function Ft(e){let t=ee(e);if(!Ie(t))return null;try{return JSON.parse($t(t,"utf-8"))}catch{return null}}function te(e,t){let n=Te(e,".mistflow");Ie(n)||qt(n,{recursive:!0}),Nt(ee(e),JSON.stringify(t,null,2)+`
39
+ `)}function ne(e,t){return{projectId:e,name:t,template:"",features:[],dbSchema:[],deployCount:0,decisions:[],provenance:[]}}async function Vt(e){let t;try{t=j()}catch{return null}try{let n=await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{headers:{...t,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()}});try{I(n.headers)}catch{}return n.ok?await n.json():null}catch{return null}}async function Bt(e,t){let n;try{n=j()}catch{return!1}try{let r=await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...n,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()},body:JSON.stringify(t)});try{I(r.headers)}catch{}return r.ok}catch{return!1}}function Jt(e,t){let n=e.toLowerCase(),r=t.toLowerCase();return r.includes(n)||n.includes(r)?!0:n.split(/\s+/).some(s=>s.length>=3&&r.includes(s))}var N=u(()=>{"use strict";$();L()});var De={};re(De,{ensureBackendRegistered:()=>Yt,ensureShadcnComponents:()=>Xt});import{existsSync as Ee,readFileSync as Wt,writeFileSync as Ht}from"fs";import{join as q}from"path";import{spawn as Kt}from"child_process";function zt(e,t,n,r,o){return new Promise(s=>{let i=Kt(e,t,{cwd:n,stdio:["pipe","pipe","pipe"],timeout:r,...o?{env:{...process.env,...o}}:{}}),a="",p="";i.stdout?.on("data",l=>{a+=l.toString()}),i.stderr?.on("data",l=>{p+=l.toString()}),i.on("close",l=>s({success:l===0,stdout:a,stderr:p})),i.on("error",l=>s({success:!1,stdout:a,stderr:p+l.message}))})}function Gt(e){let t=q(e,"mistflow.json");if(!Ee(t))return null;try{return JSON.parse(Wt(t,"utf-8"))}catch{return null}}function Qt(e,t){Ht(q(e,"mistflow.json"),JSON.stringify(t,null,2))}async function Ue(e,t){try{let n=t.features,r=t.steps,o={plan:t};Array.isArray(n)&&n.length>0&&(o.features=n.map(s=>s.name)),Array.isArray(r)&&r.length>0&&(o.provenance=r.map(s=>({feature:s.name??s.title??`Step ${s.number??"?"}`,user_intent:(s.description??"").slice(0,500),decisions:"Seeded from plan",tradeoffs:"",files_affected:[]}))),await fetch(`${f()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...j(),"Content-Type":"application/json"},body:JSON.stringify(o)})}catch(n){console.error("[self-heal] state sync failed:",n instanceof Error?n.message:String(n))}}async function Yt(e,t={}){let n=Gt(e);if(n){if(!Y())return n.projectId;if(!n.projectId)try{let o=n.plan?.requestedSubdomain,s=await _e(n.name,void 0,n.dbProvider??"neon",o);return n.projectId=s.id,Qt(e,n),te(e,ne(s.id,n.name)),n.plan&&await Ue(s.id,n.plan),console.error(`[self-heal] registered project ${s.id.slice(0,8)} with backend`),s.id}catch(r){console.error("[self-heal] createProject failed:",r instanceof Error?r.message:String(r));return}return t.forceSync&&n.plan&&n.projectId&&await Ue(n.projectId,n.plan),n.projectId}}async function Xt(e,t){let n=["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"],r=t&&t.length>0?t:n,o=q(e,"components","ui"),s=[],i=[];for(let l of r)Ee(q(o,`${l}.tsx`))?s.push(l):i.push(l);if(i.length===0)return{installed:[],alreadyPresent:s};let a={NPM_CONFIG_LEGACY_PEER_DEPS:"true"},p=await zt("npx",["--yes","shadcn@latest","add","-y","-o",...i],e,18e4,a);return p.success?{installed:i,alreadyPresent:s}:{installed:[],alreadyPresent:s,failed:`shadcn add failed for: ${i.join(", ")}. ${p.stderr.slice(-300)}`.trim()}}var Oe=u(()=>{"use strict";$();N()});import{z as y}from"zod";import{resolve as Zt,join as Me}from"path";import{existsSync as en,readFileSync as Le,writeFileSync as tn}from"fs";var nn,Ae,$e=u(()=>{"use strict";P();je();nn=y.object({action:y.enum(["get","update"]).default("get").describe("'get' reads current project state. 'update' modifies it."),projectPath:y.string().optional().describe("Path to the project directory (default: current working directory)"),completedStep:y.number().optional().describe("(update only) Mark a plan step as completed by step number"),addEnvVar:y.object({key:y.string(),description:y.string().optional(),setupUrl:y.string().optional()}).optional().describe("(update only) Add a required env var to the project manifest")}),Ae={name:"mist_state",description:"Read or update project state in mistflow.json. Use action='get' to load plan progress, env var status, and deploy info. Use action='update' to mark plan steps complete or add required env vars. Use when the user says 'mist status', 'mist state', or 'mist update state'.",inputSchema:nn,handler:async e=>{let t=e,n=Zt(t.projectPath??process.cwd()),r=Me(n,"mistflow.json");if(!en(r))return he(n);let o;try{o=JSON.parse(Le(r,"utf-8"))}catch{return c("Failed to parse mistflow.json.",!0)}if(t.action==="get"){if(!o.projectId)try{let{ensureBackendRegistered:d}=await Promise.resolve().then(()=>(Oe(),De));await d(n)&&(o=JSON.parse(Le(r,"utf-8")))}catch{}let a=o.plan,p=a?.steps?.filter(d=>d.status==="completed").length??0,l=a?.steps?.length??0,_=Pe(Me(n,".env.local")),T=o.env?.required?Object.entries(o.env.required).map(([d,D])=>({name:d,description:D?.description,configured:_.has(d)})):[];o.projectId&&Promise.resolve().then(()=>(N(),oe)).then(({fetchRemoteState:d})=>d(o.projectId)).catch(()=>{});let x=[`Project: ${o.name}`];if(a){x.push(`Plan: ${a.summary??a.name??"unnamed"} \u2014 ${p}/${l} steps complete`);for(let d of a.steps){let D=d.status==="completed"?"\u2713":d.status==="in_progress"?"\u2192":" ";x.push(` [${D}] ${d.number}. ${d.name}`)}}let U=T.filter(d=>!d.configured);U.length>0&&x.push(`Missing env vars: ${U.map(d=>d.name).join(", ")}`),o.deploy?.url?x.push(`Deployed: ${o.deploy.url} (${o.deploy.count??0} deploys)`):x.push("Not deployed yet");let E=[],W=a?.steps?.find(d=>d.status!=="completed");return W?E.push(`NEXT: Run mist implement <absolute-path> to work on step ${W.number} (${W.name}).`):a&&p===l&&(o.deploy?.url||E.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT ask the user \u2014 just deploy.")),U.length>0&&E.push(`Missing env vars in .env.local: ${U.map(d=>d.name).join(", ")}`),c(JSON.stringify({name:o.name,projectId:o.projectId,planProgress:a?{name:a.name,summary:a.summary,totalSteps:l,completedSteps:p,steps:a.steps}:null,envStatus:T,deploy:o.deploy??null,contextMessage:x.join(`
40
+ `),nextSteps:E}))}let s=[];if(t.completedStep!==void 0){let a=o.plan;if(a?.steps){let p=a.steps.findIndex(l=>l.number===t.completedStep);if(p===-1)return c(`Step ${t.completedStep} not found in the plan.`,!0);a.steps[p].status="completed",s.push(`Step ${t.completedStep} marked as completed`)}}t.addEnvVar&&(o.env||(o.env={required:{}}),o.env.required||(o.env.required={}),o.env.required[t.addEnvVar.key]={description:t.addEnvVar.description,setupUrl:t.addEnvVar.setupUrl},s.push(`Added required env var: ${t.addEnvVar.key}`)),tn(r,JSON.stringify(o,null,2)+`
41
+ `),o.projectId&&Promise.resolve().then(()=>(N(),oe)).then(async({readLocalState:a,syncRemoteState:p})=>{let l=a(n);l&&await p(o.projectId,l)}).catch(()=>{});let i=[];if(t.completedStep!==void 0){let p=o.plan?.steps?.find(l=>l.status!=="completed");p?i.push(`NEXT: Run mist implement <absolute-path> to work on step ${p.number} (${p.name}). Do this now.`):i.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT suggest localhost.")}return t.addEnvVar&&(i.push(`Add ${t.addEnvVar.key} to your .env.local file`),t.addEnvVar.setupUrl&&i.push(`Get the value from: ${t.addEnvVar.setupUrl}`)),c(JSON.stringify({updated:!0,changes:s,message:s.length>0?`Project state saved. ${s.join(". ")}.`:"No changes made.",nextSteps:i.length>0?i:void 0}))}}});import{z as w}from"zod";var on,Ne,qe=u(()=>{"use strict";C();$e();on=w.object({action:w.enum(["get","update"]).default("get").describe("'get' reads current project state (context oracle \u2014 call before making decisions in an existing project). 'update' marks steps complete or adds env vars. All other project queries moved to the CLI in MCP 0.6.0: `mist projects share`, `mist projects errors`, `mist projects logs`, `mist projects deployments`, `mist projects version`, `mist projects designs`, `mist projects app-styles`, `mist projects integrations`."),projectPath:w.string().optional().describe("Path to the project directory (default: cwd)"),completedStep:w.number().optional().describe("(update) Mark a plan step as completed by step number"),addEnvVar:w.object({key:w.string(),description:w.string().optional(),setupUrl:w.string().optional()}).optional().describe("(update) Add a required env var to the project manifest")}),Ne={name:"mist_project",description:ie,inputSchema:on,handler:async e=>{let t=e;return Ae.handler({action:t.action,projectPath:t.projectPath,completedStep:t.completedStep,addEnvVar:t.addEnvVar})}}});async function rn(){try{return await import("playwright")}catch{throw new Error("Playwright is not installed. Run: cd packages/mcp-server && pnpm add playwright && npx playwright install chromium")}}async function sn(){let e=await rn();return(!k||!k.isConnected())&&(k=await e.chromium.launch({headless:!0})),b&&(await b.close().catch(()=>{}),b=null),b=await k.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),h=await b.newPage(),h}async function Fe(){return h&&!h.isClosed()?h:(F||(F=sn().finally(()=>{F=null})),F)}async function Ve(){h&&!h.isClosed()&&await h.close().catch(()=>{}),b&&await b.close().catch(()=>{}),k?.isConnected()&&await k.close().catch(()=>{}),h=null,b=null,k=null}async function V(e){return await e.locator("body").ariaSnapshot()}async function B(e,t=!1){return await e.screenshot({fullPage:t,type:"png"})}var k,b,h,F,Be=u(()=>{"use strict";k=null,b=null,h=null,F=null;process.once("SIGTERM",()=>{Ve().finally(()=>process.exit(0))});process.once("SIGINT",()=>{Ve().finally(()=>process.exit(0))})});import{z as S}from"zod";var an,Je,We=u(()=>{"use strict";C();P();Be();an=S.object({action:S.enum(["navigate","go_back","go_forward","click","type","fill","select_option","press_key","hover","screenshot","snapshot"]).describe("Action to perform. Navigation: navigate|go_back|go_forward. Interaction: click|type|fill|select_option|press_key|hover. Visual: screenshot (returns image) | snapshot (returns accessibility tree)."),url:S.string().optional().describe("URL to navigate to. Required for 'navigate'; optional for 'screenshot' (navigates before capturing)."),selector:S.string().optional().describe("CSS selector of the target element. Required for: click, type, fill, select_option, hover. Optional for screenshot (captures just that element)."),value:S.string().optional().describe("Text to type/fill, option to select, or key to press (e.g. 'Enter', 'Tab'). Required for: type, fill, select_option, press_key."),fullPage:S.boolean().default(!1).describe("For 'screenshot': capture the full scrollable page instead of just the viewport."),includeScreenshot:S.boolean().default(!1).describe("For navigate/interact actions: also return a screenshot alongside the accessibility snapshot.")}),Je={name:"mist_browser",description:ae,inputSchema:an,handler:async e=>{let t=e,n=await Fe();if(t.action==="navigate"){if(!t.url)return c("URL is required for 'navigate'.",!0);let s=[],i=l=>{l.type()==="error"&&s.push(l.text())};n.on("console",i),await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{});let a=[],p=l=>a.push(l.message);if(n.on("pageerror",p),await n.waitForTimeout(500),n.removeListener("console",i),n.removeListener("pageerror",p),s.length>0||a.length>0){let l=await V(n),_=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:l,consoleErrors:s,pageErrors:a,hasErrors:!0})}];if(t.includeScreenshot){let T=await B(n);_.push({type:"image",data:T.toString("base64"),mimeType:"image/png"})}return{content:_}}}else if(t.action==="go_back")await n.goBack({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="go_forward")await n.goForward({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="click"){if(!t.selector)return c("Selector is required for 'click'.",!0);await n.click(t.selector,{timeout:1e4}),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="type"){if(!t.selector)return c("Selector is required for 'type'.",!0);if(!t.value)return c("Value is required for 'type'.",!0);await n.type(t.selector,t.value,{delay:50})}else if(t.action==="fill"){if(!t.selector)return c("Selector is required for 'fill'.",!0);if(!t.value)return c("Value is required for 'fill'.",!0);await n.fill(t.selector,t.value)}else if(t.action==="select_option"){if(!t.selector)return c("Selector is required for 'select_option'.",!0);if(!t.value)return c("Value is required for 'select_option'.",!0);await n.selectOption(t.selector,t.value)}else if(t.action==="hover"){if(!t.selector)return c("Selector is required for 'hover'.",!0);await n.hover(t.selector,{timeout:1e4})}else if(t.action==="press_key"){if(!t.value)return c("Value is required for 'press_key' (e.g. 'Enter').",!0);await n.keyboard.press(t.value),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="screenshot"){t.url&&(await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{}));let s;if(t.selector){let i=await n.$(t.selector);if(!i)return c(`Element not found: ${t.selector}`,!0);s=await i.screenshot({type:"png"})}else s=await B(n,t.fullPage);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),message:`Screenshot captured (${t.fullPage?"full page":"viewport"})`})},{type:"image",data:s.toString("base64"),mimeType:"image/png"}]}}else if(t.action==="snapshot"){let s=await V(n);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:s})}]}}let r=await V(n),o=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:r})}];if(t.includeScreenshot){let s=await B(n);o.push({type:"image",data:s.toString("base64"),mimeType:"image/png"})}return{content:o}}}});import{z as He}from"zod";var Ke,ze,Ge=u(()=>{"use strict";C();P();Ke=`# Mistflow CLI reference
42
42
 
43
43
  The Mistflow CLI handles local execution and long-running operations that
44
44
  would hit the MCP 60s tool-call ceiling. Every command below is invokable
@@ -209,8 +209,8 @@ and decides the next command. Example end-to-end chain:
209
209
  mist seed /Users/you/projects/habit-tracker --json
210
210
  mist qa https://your-app.mistflow.app --json
211
211
  `,ze={name:"mist_help",description:le,inputSchema:He.object({command:He.string().optional().describe("Optional: name of a specific command to get focused reference for. Omit to get the full catalog.")}),handler:async e=>{let{command:t}=e;if(!t)return c(Ke);let n=Ke.split(`
212
- `),o=new RegExp(`^### \`mist ${t}`),r=-1,s=n.length;for(let i=0;i<n.length;i++)if(o.test(n[i]))r=i;else if(r>=0&&n[i].startsWith("### ")){s=i;break}else if(r>=0&&n[i].startsWith("## ")&&i>r){s=i;break}return r<0?c(`No command named '${t}' found. Call mist_help with no args to see the full catalog.`,!0):c(n.slice(r,s).join(`
213
- `).trim())}}});var mn={};import{Server as an}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as ln}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as cn,ListToolsRequestSchema as pn}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as dn}from"zod-to-json-schema";async function un(){let e=process.argv.indexOf("--api-url");e!==-1&&process.argv[e+1]&&(process.env.MISTFLOW_API_URL=process.argv[e+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let t=new ln;await J.connect(t),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}var J,Qe,Ye=u(()=>{"use strict";R();P();Ce();qe();We();Ge();J=new an({name:"mistflow",version:"0.3.0"},{capabilities:{tools:{}},instructions:ce()}),Qe=[Re,Ne,Je,ze];J.setRequestHandler(pn,async()=>({tools:Qe.map(e=>({name:e.name,description:e.description,inputSchema:dn(e.inputSchema)}))}));J.setRequestHandler(cn,async e=>{let t=Qe.find(n=>n.name===e.params.name);if(!t)return c(`Unknown tool: ${e.params.name}`,!0);try{let n=t.inputSchema.safeParse(e.params.arguments);if(!n.success){let s=n.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join(", ");return c(`Invalid input: ${s}`,!0)}let o=e.params._meta?.progressToken,r={server:J,progressToken:o};try{return await t.handler(n.data,r)}finally{r.cleanup?.()}}catch(n){let o=n instanceof Error?n.message:"An unexpected error occurred";return console.error("Tool error:",n),c(o,!0)}});un().catch(e=>{console.error("Fatal error:",e),process.exit(1)})});import{readFileSync as fn}from"fs";import{dirname as gn,join as hn}from"path";import{fileURLToPath as yn}from"url";var v=process.argv[2];if(v==="--version"||v==="-v"){try{let e=gn(yn(import.meta.url)),t=hn(e,"..","package.json"),n=JSON.parse(fn(t,"utf-8"));console.log(n.version)}catch{console.log("unknown")}process.exit(0)}(v==="--help"||v==="-h")&&(console.log(`@mistflow-ai/mcp \u2014 Mistflow MCP server
212
+ `),r=new RegExp(`^### \`mist ${t}`),o=-1,s=n.length;for(let i=0;i<n.length;i++)if(r.test(n[i]))o=i;else if(o>=0&&n[i].startsWith("### ")){s=i;break}else if(o>=0&&n[i].startsWith("## ")&&i>o){s=i;break}return o<0?c(`No command named '${t}' found. Call mist_help with no args to see the full catalog.`,!0):c(n.slice(o,s).join(`
213
+ `).trim())}}});var fn={};import{Server as ln}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as cn}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as pn,ListToolsRequestSchema as dn}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as un}from"zod-to-json-schema";async function mn(){let e=process.argv.indexOf("--api-url");e!==-1&&process.argv[e+1]&&(process.env.MISTFLOW_API_URL=process.argv[e+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let t=new cn;await J.connect(t),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}var J,Qe,Ye=u(()=>{"use strict";C();P();Re();qe();We();Ge();J=new ln({name:"mistflow",version:"0.3.0"},{capabilities:{tools:{}},instructions:ce()}),Qe=[Ce,Ne,Je,ze];J.setRequestHandler(dn,async()=>({tools:Qe.map(e=>({name:e.name,description:e.description,inputSchema:un(e.inputSchema)}))}));J.setRequestHandler(pn,async e=>{let t=Qe.find(n=>n.name===e.params.name);if(!t)return c(`Unknown tool: ${e.params.name}`,!0);try{let n=t.inputSchema.safeParse(e.params.arguments);if(!n.success){let s=n.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join(", ");return c(`Invalid input: ${s}`,!0)}let r=e.params._meta?.progressToken,o={server:J,progressToken:r};try{return await t.handler(n.data,o)}finally{o.cleanup?.()}}catch(n){let r=n instanceof Error?n.message:"An unexpected error occurred";return console.error("Tool error:",n),c(r,!0)}});mn().catch(e=>{console.error("Fatal error:",e),process.exit(1)})});import{readFileSync as gn}from"fs";import{dirname as hn,join as yn}from"path";import{fileURLToPath as wn}from"url";var v=process.argv[2];if(v==="--version"||v==="-v"){try{let e=hn(wn(import.meta.url)),t=yn(e,"..","package.json"),n=JSON.parse(gn(t,"utf-8"));console.log(n.version)}catch{console.log("unknown")}process.exit(0)}(v==="--help"||v==="-h")&&(console.log(`@mistflow-ai/mcp \u2014 Mistflow MCP server
214
214
 
215
215
  Usage:
216
216
  npx @mistflow-ai/mcp Start the MCP server on stdio (default; invoked by editors)
@@ -222,4 +222,4 @@ To install the server into your editor config, use the installer:
222
222
  Use the installer package instead:
223
223
 
224
224
  npx -y mistflow-ai ${v}
225
- `),process.exit(1));await Promise.resolve().then(()=>(Ye(),mn));
225
+ `),process.exit(1));await Promise.resolve().then(()=>(Ye(),fn));
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
- var Ve=Object.defineProperty;var S=(e,t)=>()=>(e&&(t=e(e=0)),t);var te=(e,t)=>{for(var n in t)Ve(e,n,{get:t[n],enumerable:!0})};import{existsSync as W,readFileSync as pe,writeFileSync as Ye,mkdirSync as Xe}from"fs";import{join as B,dirname as J}from"path";import{homedir as Ze}from"os";import{fileURLToPath as et}from"url";function R(){if(U)return U;try{let e=et(import.meta.url),t=J(e);for(let n=0;n<6;n++){let o=B(t,"package.json");if(W(o)){let s=JSON.parse(pe(o,"utf-8"));if(s.name==="@mistflow-ai/mcp"&&typeof s.version=="string")return U=s.version,s.version}let r=J(t);if(r===t)break;t=r}}catch{}return U="0.0.0","0.0.0"}function E(e){let t=/^(\d+)\.(\d+)\.(\d+)/.exec(e.trim());return t?[parseInt(t[1],10),parseInt(t[2],10),parseInt(t[3],10)]:null}function ae(e,t){let n=E(e),o=E(t);if(!n||!o)return 0;for(let r=0;r<3;r++){if(n[r]<o[r])return-1;if(n[r]>o[r])return 1}return 0}function tt(e,t,n){if(n&&ae(e,n)<0)return"unsupported";if(!t||ae(e,t)>=0)return"none";let r=E(e),s=E(t);return!r||!s?"none":r[0]<s[0]?"major":r[1]<s[1]?"minor":"patch"}function C(e){let t=e.get("x-mistflow-mcp-latest")??"",n=e.get("x-mistflow-mcp-min-supported")??"",o=e.get("x-mistflow-mcp-changelog-url")??"";!t&&!n||(f={latest:t,minSupported:n,changelogUrl:o})}function de(){let e=process.env.MISTFLOW_STATE_DIR||B(Ze(),".mistflow");return B(e,"upgrade-state.json")}function nt(){try{let e=de();return W(e)?JSON.parse(pe(e,"utf-8")):{}}catch{return{}}}function rt(e){try{let t=de(),n=J(t);W(n)||Xe(n,{recursive:!0}),Ye(t,JSON.stringify(e,null,2)+`
2
- `,{mode:384})}catch{}}function ot(e){return e==="patch"?7*864e5:e==="minor"?1*864e5:0}function ue(){if(process.env.MISTFLOW_NO_UPGRADE_CHECK==="1"||!f)return null;let e=R();if(e==="0.0.0")return null;let t=tt(e,f.latest,f.minSupported);if(t==="none")return null;if(t==="unsupported")return ce(t,e,f);if(le)return null;let n=nt(),o=Date.now(),r=ot(t);return n.dismissedForVersion===f.latest&&t!=="major"||n.lastLatestSeen===f.latest&&n.lastShownMs&&o-n.lastShownMs<r?null:(le=!0,rt({...n,lastShownMs:o,lastLatestSeen:f.latest}),ce(t,e,f))}function ce(e,t,n){let o="npx -y mistflow-ai install",r=n.changelogUrl?`
1
+ var Ve=Object.defineProperty;var S=(e,t)=>()=>(e&&(t=e(e=0)),t);var te=(e,t)=>{for(var n in t)Ve(e,n,{get:t[n],enumerable:!0})};import{existsSync as W,readFileSync as pe,writeFileSync as Xe,mkdirSync as Ze}from"fs";import{join as B,dirname as J}from"path";import{homedir as et}from"os";import{fileURLToPath as tt}from"url";function C(){if(U)return U;try{let e=tt(import.meta.url),t=J(e);for(let n=0;n<6;n++){let o=B(t,"package.json");if(W(o)){let s=JSON.parse(pe(o,"utf-8"));if(s.name==="@mistflow-ai/mcp"&&typeof s.version=="string")return U=s.version,s.version}let r=J(t);if(r===t)break;t=r}}catch{}return U="0.0.0","0.0.0"}function E(e){let t=/^(\d+)\.(\d+)\.(\d+)/.exec(e.trim());return t?[parseInt(t[1],10),parseInt(t[2],10),parseInt(t[3],10)]:null}function ae(e,t){let n=E(e),o=E(t);if(!n||!o)return 0;for(let r=0;r<3;r++){if(n[r]<o[r])return-1;if(n[r]>o[r])return 1}return 0}function nt(e,t,n){if(n&&ae(e,n)<0)return"unsupported";if(!t||ae(e,t)>=0)return"none";let r=E(e),s=E(t);return!r||!s?"none":r[0]<s[0]?"major":r[1]<s[1]?"minor":"patch"}function x(e){let t=e.get("x-mistflow-mcp-latest")??"",n=e.get("x-mistflow-mcp-min-supported")??"",o=e.get("x-mistflow-mcp-changelog-url")??"";!t&&!n||(f={latest:t,minSupported:n,changelogUrl:o})}function de(){let e=process.env.MISTFLOW_STATE_DIR||B(et(),".mistflow");return B(e,"upgrade-state.json")}function rt(){try{let e=de();return W(e)?JSON.parse(pe(e,"utf-8")):{}}catch{return{}}}function ot(e){try{let t=de(),n=J(t);W(n)||Ze(n,{recursive:!0}),Xe(t,JSON.stringify(e,null,2)+`
2
+ `,{mode:384})}catch{}}function st(e){return e==="patch"?7*864e5:e==="minor"?1*864e5:0}function ue(){if(process.env.MISTFLOW_NO_UPGRADE_CHECK==="1"||!f)return null;let e=C();if(e==="0.0.0")return null;let t=nt(e,f.latest,f.minSupported);if(t==="none")return null;if(t==="unsupported")return ce(t,e,f);if(le)return null;let n=rt(),o=Date.now(),r=st(t);return n.dismissedForVersion===f.latest&&t!=="major"||n.lastLatestSeen===f.latest&&n.lastShownMs&&o-n.lastShownMs<r?null:(le=!0,ot({...n,lastShownMs:o,lastLatestSeen:f.latest}),ce(t,e,f))}function ce(e,t,n){let o="npx -y mistflow-ai install",r=n.changelogUrl?`
3
3
  What's new: ${n.changelogUrl}`:"";return e==="unsupported"?`
4
4
 
5
5
  ---
@@ -19,9 +19,9 @@ This is a major update. Run \`${o}\` and restart your editor.${r}
19
19
  --- Mistflow update available: ${t} -> ${n.latest} ---
20
20
  Run \`${o}\` to upgrade, then restart your editor.${r}`:`
21
21
 
22
- (Mistflow ${n.latest} is out, you have ${t}. Run \`${o}\` when convenient.)`}var U,f,le,D=S(()=>{"use strict";U=null;f=null;le=!1});import{readFileSync as st,existsSync as fe,writeFileSync as it,mkdirSync as at,renameSync as lt,unlinkSync as ct}from"fs";import{join as ge,dirname as pt}from"path";import{homedir as dt}from"os";import{randomBytes as ut}from"crypto";function he(){return ge(dt(),".mistflow","credentials.json")}function O(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function ye(){let e=he();if(!fe(e))return null;try{let t=JSON.parse(st(e,"utf-8"));return typeof t.apiKey=="string"?{[mt]:t}:t}catch{return null}}function H(){let e=process.env.MISTFLOW_API_KEY;if(e)return{ok:!0,creds:{apiKey:e,orgId:"",orgSlug:"env"}};let t=ye();if(!t)return{ok:!1,reason:"missing"};let n=O(),o=t[n];return o&&typeof o.apiKey=="string"&&o.apiKey&&typeof o.orgId=="string"?{ok:!0,creds:o}:{ok:!1,reason:"missing"}}function K(e){let t=he(),n=pt(t);fe(n)||at(n,{recursive:!0});let o=ye()??{},r=O();o[r]=e;let s=ge(n,`.credentials.tmp.${ut(8).toString("hex")}`);try{it(s,JSON.stringify(o,null,2)+`
23
- `,{mode:384}),lt(s,t)}catch(i){try{ct(s)}catch{}throw i}}function z(){return H().ok}var mt,G=S(()=>{"use strict";mt="https://api.mistflow.ai"});function m(){return O()}function x(){let e=H();if(!e.ok)throw new u("auth_missing","No Mistflow credentials found.",401);return ft(e.creds)}function ft(e){return{Authorization:`ApiKey ${e.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()}}function gt(e){try{C(e.headers)}catch{}}async function ht(e,t,n,o){for(let r=0;r<2;r++)try{return await fetch(e,{...t,signal:AbortSignal.timeout(n)})}catch(s){let i=s instanceof Error&&s.name==="TimeoutError",a=s instanceof TypeError;if(o&&r===0&&(i||a)){console.error(`[api] Retrying ${e} after ${i?"timeout":"network error"}`);continue}throw s}throw new Error("fetchWithRetry: exhausted retries")}async function yt(e){let t=null;try{t=await e.json()}catch{t=null}let n=t&&typeof t.code=="string"?t.code:void 0,o=t&&typeof t.message=="string"?t.message:t&&typeof t.detail=="string"?t.detail:e.statusText||"Request failed";if(n)return new u(n,o,e.status,t?.details);let r=e.status;return r===401?new u("auth_invalid",o,r):r===403?new u("permission_denied",o,r):r===404?new u("not_found",o,r):r===409?new u("conflict",o,r):r===422?new u("validation_error",o,r):r===429?new u("rate_limited",o,r):r>=500?new u("server_error",e.statusText||"Internal server error",r):new u("client_error",o,r)}async function wt(e,t={}){let n=x(),{timeoutMs:o,idempotent:r,...s}=t,i=o??3e4,a=(s.method??"GET").toUpperCase(),p=r??(a==="GET"||a==="HEAD"),l;try{l=await ht(`${m()}${e}`,{...s,headers:{...n,...s.headers}},i,p)}catch(b){throw b instanceof Error&&b.name==="TimeoutError"?new u("network_error","Request timed out. Try again in a moment."):new u("network_error","Cannot reach Mistflow servers. Check your network.")}if(gt(l),!l.ok)throw await yt(l);return l.json()}async function we(e,t,n="neon",o){return wt("/api/projects",{method:"POST",body:JSON.stringify({name:e,template:t,db_provider:n,requested_subdomain:o})})}var u,bn,M=S(()=>{"use strict";G();D();u=class extends Error{constructor(n,o,r,s){super(o);this.code=n;this.statusCode=r;this.details=s;this.name="MistflowApiError"}get isAuth(){return this.code.startsWith("auth_")}get isTransient(){return this.code==="server_error"||this.code==="upstream_error"||this.code==="network_error"||this.code==="rate_limited"}};bn=300*1e3});var ee={};te(ee,{emptyState:()=>Z,fetchRemoteState:()=>Ut,fuzzyMatch:()=>Dt,getLocalStatePath:()=>Y,readLocalState:()=>Tt,syncRemoteState:()=>Et,writeLocalState:()=>X});import{existsSync as Re,readFileSync as Pt,writeFileSync as jt,mkdirSync as It}from"fs";import{join as xe}from"path";function Y(e){return xe(e,".mistflow","state.json")}function Tt(e){let t=Y(e);if(!Re(t))return null;try{return JSON.parse(Pt(t,"utf-8"))}catch{return null}}function X(e,t){let n=xe(e,".mistflow");Re(n)||It(n,{recursive:!0}),jt(Y(e),JSON.stringify(t,null,2)+`
24
- `)}function Z(e,t){return{projectId:e,name:t,template:"",features:[],dbSchema:[],deployCount:0,decisions:[],provenance:[]}}async function Ut(e){let t;try{t=x()}catch{return null}try{let n=await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{headers:{...t,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()}});try{C(n.headers)}catch{}return n.ok?await n.json():null}catch{return null}}async function Et(e,t){let n;try{n=x()}catch{return!1}try{let o=await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...n,"Content-Type":"application/json","X-Mistflow-MCP-Version":R()},body:JSON.stringify(t)});try{C(o.headers)}catch{}return o.ok}catch{return!1}}function Dt(e,t){let n=e.toLowerCase(),o=t.toLowerCase();return o.includes(n)||n.includes(o)?!0:n.split(/\s+/).some(s=>s.length>=3&&o.includes(s))}var L=S(()=>{"use strict";M();D()});var je={};te(je,{ensureBackendRegistered:()=>qt,ensureShadcnComponents:()=>Ft});import{existsSync as Pe,readFileSync as Ot,writeFileSync as Mt}from"fs";import{join as A}from"path";import{spawn as Lt}from"child_process";function At(e,t,n,o,r){return new Promise(s=>{let i=Lt(e,t,{cwd:n,stdio:["pipe","pipe","pipe"],timeout:o,...r?{env:{...process.env,...r}}:{}}),a="",p="";i.stdout?.on("data",l=>{a+=l.toString()}),i.stderr?.on("data",l=>{p+=l.toString()}),i.on("close",l=>s({success:l===0,stdout:a,stderr:p})),i.on("error",l=>s({success:!1,stdout:a,stderr:p+l.message}))})}function $t(e){let t=A(e,"mistflow.json");if(!Pe(t))return null;try{return JSON.parse(Ot(t,"utf-8"))}catch{return null}}function Nt(e,t){Mt(A(e,"mistflow.json"),JSON.stringify(t,null,2))}async function Ce(e,t){try{let n=t.features,o=t.steps,r={plan:t};Array.isArray(n)&&n.length>0&&(r.features=n.map(s=>s.name)),Array.isArray(o)&&o.length>0&&(r.provenance=o.map(s=>({feature:s.name??s.title??`Step ${s.number??"?"}`,user_intent:(s.description??"").slice(0,500),decisions:"Seeded from plan",tradeoffs:"",files_affected:[]}))),await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...x(),"Content-Type":"application/json"},body:JSON.stringify(r)})}catch(n){console.error("[self-heal] state sync failed:",n instanceof Error?n.message:String(n))}}async function qt(e,t={}){let n=$t(e);if(n){if(!z())return n.projectId;if(!n.projectId)try{let r=n.plan?.requestedSubdomain,s=await we(n.name,void 0,n.dbProvider??"neon",r);return n.projectId=s.id,Nt(e,n),X(e,Z(s.id,n.name)),n.plan&&await Ce(s.id,n.plan),console.error(`[self-heal] registered project ${s.id.slice(0,8)} with backend`),s.id}catch(o){console.error("[self-heal] createProject failed:",o instanceof Error?o.message:String(o));return}return t.forceSync&&n.plan&&n.projectId&&await Ce(n.projectId,n.plan),n.projectId}}async function Ft(e,t){let n=["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"],o=t&&t.length>0?t:n,r=A(e,"components","ui"),s=[],i=[];for(let l of o)Pe(A(r,`${l}.tsx`))?s.push(l):i.push(l);if(i.length===0)return{installed:[],alreadyPresent:s};let a={NPM_CONFIG_LEGACY_PEER_DEPS:"true"},p=await At("npx",["--yes","shadcn@latest","add","-y","-o",...i],e,18e4,a);return p.success?{installed:i,alreadyPresent:s}:{installed:[],alreadyPresent:s,failed:`shadcn add failed for: ${i.join(", ")}. ${p.stderr.slice(-300)}`.trim()}}var Ie=S(()=>{"use strict";M();L()});async function Kt(){try{return await import("playwright")}catch{throw new Error("Playwright is not installed. Run: cd packages/mcp-server && pnpm add playwright && npx playwright install chromium")}}async function zt(){let e=await Kt();return(!v||!v.isConnected())&&(v=await e.chromium.launch({headless:!0})),w&&(await w.close().catch(()=>{}),w=null),w=await v.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),g=await w.newPage(),g}async function Oe(){return g&&!g.isClosed()?g:($||($=zt().finally(()=>{$=null})),$)}async function Me(){g&&!g.isClosed()&&await g.close().catch(()=>{}),w&&await w.close().catch(()=>{}),v?.isConnected()&&await v.close().catch(()=>{}),g=null,w=null,v=null}async function N(e){return await e.locator("body").ariaSnapshot()}async function q(e,t=!1){return await e.screenshot({fullPage:t,type:"png"})}var v,w,g,$,Le=S(()=>{"use strict";v=null,w=null,g=null,$=null;process.once("SIGTERM",()=>{Me().finally(()=>process.exit(0))});process.once("SIGINT",()=>{Me().finally(()=>process.exit(0))})});import{Server as Qt}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Yt}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Xt,ListToolsRequestSchema as Zt}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as en}from"zod-to-json-schema";var Be="When invoking `mist plan` through your shell/bash tool, give it at least a 2 minute budget before assuming it stalled. `mist plan` commonly takes 30-150s. Heavier commands like install/build/qa/deploy can need a longer budget (up to about 5 minutes).",Je='Treat the CLI\'s returned JSON as authoritative. If `mist plan --describe ...` returns `status: "clarify"`, the planning call completed and is waiting on user answers. Do NOT rerun the same command or describe it as "still generating". Only poll again when status is `"design_clarify_pending"`, and then use `mist plan-directions --cid <id> --wait --json`.',We='When submitting discovery answers back to `mist plan --token ... --answers-stdin`, prefer an array payload like `{"answers":[{"question":"...","decisionKey":"...","answer":"..."}]}`. Do NOT collapse answers into a `{decisionKey: answer}` map because multiple discovery questions can share the same decision key.',He="Before scaffolding a NEW app, resolve the destination path explicitly. If the user asked to create/build a new app and the current directory is not already that Mistflow project, ask whether to scaffold in the current folder or a new subfolder here (unless the user already gave a path). Do NOT inspect sibling directories and silently adopt one as the base just because it looks similar. Reuse an existing Mistflow project only when the user explicitly asks to continue/edit that project.",Ke="If `mist plan` fails with a message like `Request to /api/plan timed out after 60s`, the host AI should suspect a stale CLI binary before blaming the backend. Check `mist --version`. If the installed CLI is behind the backend's advertised latest version, run `mist upgrade` (for the self-installed CLI in `~/.mistflow/bin/mist`) or retry with `npx -y @mistflow-ai/cli@latest ...`.",ze="`mist init` is all-or-nothing for normal users: it registers the cloud project first, scaffolds in a temp directory, then moves the finished app into place only after both steps succeed. If auth, quota, or network registration fails, stop before any app appears locally. Do NOT suggest reusing another app unless the user explicitly asks.",Ge="If `mist init` fails, stop before any cloud command and explain why. Do NOT default to reusing some other existing app as recovery unless the user explicitly asked to continue that app.",Qe='IMPORTANT \u2014 chaining discipline: once the user approves the plan, the init \u2192 install \u2192 implement (repeat) \u2192 build \u2192 deploy \u2192 seed (when needed) \u2192 qa chain is expected. Do NOT pause between these calls to ask the user "should I continue?" or offer options like "full build vs step-by-step." The tool itself will return a status requiring user input when it actually needs one (e.g. confirm_new_project, confirm_dark_theme, awaiting promotion). Otherwise, chain calls continuously. Brief one-line status updates are fine and encouraged; permission requests are not.',ne="Connect the user's Mistflow account. Call this ONLY when: (a) the user has literally never signed in, or (b) a previous tool call returned error code 'auth_missing' or 'auth_revoked'. DO NOT call this tool in response to 500 errors, 404 errors, network errors, or any generic failure \u2014 those are backend issues, not auth issues. Running mist_setup when not needed wastes the user's time and creates login fatigue. Once signed in, the MCP persists a long-lived API key and never asks again. Two-phase device code flow: (1) Call without deviceCode \u2014 opens browser, returns status 'pending' with deviceCode and userCode. Tell the user the verification code and that they need to approve in the browser. (2) Call again with deviceCode after ~15 seconds \u2014 polls for approval. Also accepts an apiKey for headless auth (skips device code entirely).",re="Read or update Mistflow project state. 'get' loads plan progress, env vars, and deploy info \u2014 call this at the start of an incremental change so you understand the current app before editing. 'update' marks plan steps complete or adds env vars (note: `mist implement` in the CLI auto-marks the previous step, so manual updates are rarely needed).",oe="Unified browser tool for navigating, interacting with, and capturing the app. Use 'navigate' to open a URL, interaction actions (click/type/fill/etc.) to test flows, 'snapshot' to inspect the accessibility tree, and 'screenshot' for a visual capture. Use after mist_preview to verify UI, test flows, and iterate on design.",se="Returns the Mistflow CLI command reference. Call this ONCE at session start (or whenever you're unsure which tool to use) to learn every `mist` CLI command, when to prefer it over an MCP tool, and how to chain calls. Results are static \u2014 no backend round-trip, safe to call frequently.";function ie(){let e=[];return e.push("Mistflow is a full-stack app builder that creates and deploys web apps from natural language descriptions. When a user asks to build, create, or make a web app, website, landing page, dashboard, internal tool, marketplace, content site, or browser game, use Mistflow tools. Mistflow creates NEW apps from scratch. It does NOT modify existing non-Mistflow codebases."),e.push(""),e.push("Call `mist_help` at any point for the full CLI command reference. The 4 MCP tools handle short, structured, AI-native flows (auth, project state, browser automation, CLI discovery). Everything else is the `mist` CLI \u2014 invoke via your shell/bash tool."),e.push(""),e.push(Be),e.push(""),e.push(Je),e.push(""),e.push(We),e.push(""),e.push(He),e.push(""),e.push(ze),e.push(""),e.push(Ke),e.push(""),e.push("New app workflow (entirely CLI-driven):"),e.push("1. Choose destination: if the user did not already specify a path, ask whether to scaffold in the current folder or a new subfolder here. Resolve the absolute path before `mist init`."),e.push('2. Plan: run `mist plan --describe "<user\'s description>" --json` via your shell/bash tool. Pass the user\'s description EXACTLY as written \u2014 do NOT expand, rephrase, or add features. Relay any returned questions to the user, then submit answers via `echo \'<answers-json>\' | mist plan --token <id> --answers-stdin --json`. When status becomes "design_clarify_pending", poll with `mist plan-directions --cid <id> --wait --json`. When directions are ready, the CLI writes `<cwd>/.mistflow/design-directions.html` with each direction rendered in its own fonts + palette + hero treatment \u2014 run `open "<path>"` for the user so they can see visual options, THEN ask them to pick one by name. The sentinel payload (stderr) includes the `previewPath`. Finalize with `echo \'<pick-json>\' | mist plan --cid <id> --pick-stdin --json`. If the CLI returns status "confirm_new_project" (safety gate when inside an existing codebase), ask the user whether to scaffold a new Mistflow app or edit the existing code.'),e.push("3. Mockup (optional): run `mist mockup --plan-id <id>` via your shell/bash tool \u2014 generates a visual HTML wireframe for user preview. Iterative: pass --feedback to refine, --approved to lock in the design."),e.push("4. Scaffold: run `mist init --plan-id <id> --path <absolute-path>` via your shell/bash tool. `mist init` is transactional: it registers the cloud project first, scaffolds in a temp directory, and only moves the completed app into place after both steps succeed. If it fails before that move, stop and fix the error instead of continuing to cloud commands. Returns fast; does NOT run npm install."),e.push("5. Install dependencies: run `mist install <projectPath>` via your shell/bash tool (streams output)."),e.push("6. Implement: run `mist implement <absolute-path>` via your shell/bash tool \u2014 executes plan steps one at a time. Call repeatedly until all steps are done; it auto-marks the previous step as completed on each call."),e.push("7. Deploy: run `mist deploy [path]` via your shell/bash tool \u2014 tars, uploads, polls status with live streaming. Subcommands: `mist deploy promote` (staging\u2192prod), `mist deploy preview` (local tunnel), `mist deploy rollback <id>`, `mist deploy verify <url>`, `mist deploy redeploy`."),e.push("8. QA: run `mist qa <live-url>` via your shell/bash tool, or just `mist qa` from inside the project if mistflow.json already has deploy.url. Call AFTER deploy. Do NOT show the URL to the user until QA passes."),e.push("9. Seed sample data (optional but recommended before QA when acceptance criteria depend on populated tables/lists): run `mist seed <absolute-path>` via your shell/bash tool. This defaults to local-only seeding against PGlite; use `--allow-remote` only when you intentionally want to seed a remote environment. Use `--reset` to clear the matched tables first."),e.push(""),e.push("Companion CLI (`@mistflow-ai/cli`, invoke as `mist` or via `npx -y @mistflow-ai/cli`) is the primary path for EVERYTHING except the 4 MCP tools below:"),e.push("- `mist plan` / `mist plan-directions` \u2014 plan an app."),e.push("- `mist init` \u2014 scaffold a new project from a plan (fast, ~10s)."),e.push("- `mist install` / `mist build` / `mist mockup` / `mist implement` / `mist debug` / `mist seed` / `mist qa` \u2014 local project lifecycle."),e.push("- `mist deploy` (+ promote/preview/rollback/verify/redeploy subcommands) \u2014 deploy orchestration."),e.push("- `mist status` / `mist fix` \u2014 feature manifest viewer + iteration loop."),e.push("- `mist contracts` \u2014 integration-contract layer management."),e.push("- `mist doctor` \u2014 project health diagnostics."),e.push("- `mist login` / `mist projects` / `mist logs` / `mist env` / `mist domains` / `mist rollback` \u2014 cloud-coordination commands."),e.push("- Call mist_help for the full reference."),e.push(""),e.push(Qe),e.push(""),e.push(Ge),e.push(""),e.push("Design presets (optional, between steps 2 and 3): run `mist projects designs`, `mist projects app-styles`, `mist projects integrations` via your shell/bash tool to browse catalogs. After `mist plan` generates a plan, it may recommend designs and styles \u2014 present these to the user before calling `mist init`."),e.push(""),e.push("Updating an existing Mistflow app:"),e.push("- Cosmetic or single-file changes: edit files directly, then `mist deploy` to publish."),e.push("- New page or feature (no new data model): mist_project action=get for context, build it, then `mist deploy`."),e.push('- Feature needing new data model: ask product questions, call `mist_project action=get` for context, then run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist deploy`.'),e.push('- Integration addition: ask product questions, call `mist_project action=get`, optionally browse `mist projects integrations`, run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist env` to set required keys before deploy, then `mist deploy`, then `mist qa`.'),e.push("- Bug fix: run `mist debug <absolute-path>` to analyze, fix the code, then `mist deploy`."),e.push(""),e.push("Template forking: use the Mistflow dashboard UI (app.mistflow.ai) to fork templates for now. CLI-side template-fork plumbing is in place but the API-client bridge lands in a follow-up release."),e.push(""),e.push("The 4 MCP tools:"),e.push("- mist_setup: authentication. Only call when user has never signed in or a tool returned 'auth_missing'/'auth_revoked'. Do NOT call for 500s, 404s, or network errors. Also accepts an apiKey parameter for headless auth."),e.push("- mist_project: read/write project state (actions: 'get' / 'update'). Other project queries (errors, logs, deployments, share, version, catalog browsing) moved to `mist projects <subcommand>` in the CLI."),e.push("- mist_browser: navigate, interact with, and screenshot the app during preview or after deploy. Returns screenshots inline in tool results \u2014 the one tool that genuinely needs the MCP transport."),e.push("- mist_help: returns the full CLI command reference. Call once per session to learn the available `mist` commands."),e.join(`
22
+ (Mistflow ${n.latest} is out, you have ${t}. Run \`${o}\` when convenient.)`}var U,f,le,D=S(()=>{"use strict";U=null;f=null;le=!1});import{readFileSync as it,existsSync as fe,writeFileSync as at,mkdirSync as lt,renameSync as ct,unlinkSync as pt}from"fs";import{join as ge,dirname as dt}from"path";import{homedir as ut}from"os";import{randomBytes as mt}from"crypto";function he(){return ge(ut(),".mistflow","credentials.json")}function O(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function ye(){let e=he();if(!fe(e))return null;try{let t=JSON.parse(it(e,"utf-8"));return typeof t.apiKey=="string"?{[ft]:t}:t}catch{return null}}function H(){let e=process.env.MISTFLOW_API_KEY;if(e)return{ok:!0,creds:{apiKey:e,orgId:"",orgSlug:"env"}};let t=ye();if(!t)return{ok:!1,reason:"missing"};let n=O(),o=t[n];return o&&typeof o.apiKey=="string"&&o.apiKey&&typeof o.orgId=="string"?{ok:!0,creds:o}:{ok:!1,reason:"missing"}}function K(e){let t=he(),n=dt(t);fe(n)||lt(n,{recursive:!0});let o=ye()??{},r=O();o[r]=e;let s=ge(n,`.credentials.tmp.${mt(8).toString("hex")}`);try{at(s,JSON.stringify(o,null,2)+`
23
+ `,{mode:384}),ct(s,t)}catch(i){try{pt(s)}catch{}throw i}}function z(){return H().ok}var ft,G=S(()=>{"use strict";ft="https://api.mistflow.ai"});function m(){return O()}function R(){let e=H();if(!e.ok)throw new u("auth_missing","No Mistflow credentials found.",401);return gt(e.creds)}function gt(e){return{Authorization:`ApiKey ${e.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()}}function ht(e){try{x(e.headers)}catch{}}async function yt(e,t,n,o){for(let r=0;r<2;r++)try{return await fetch(e,{...t,signal:AbortSignal.timeout(n)})}catch(s){let i=s instanceof Error&&s.name==="TimeoutError",a=s instanceof TypeError;if(o&&r===0&&(i||a)){console.error(`[api] Retrying ${e} after ${i?"timeout":"network error"}`);continue}throw s}throw new Error("fetchWithRetry: exhausted retries")}async function wt(e){let t=null;try{t=await e.json()}catch{t=null}let n=t&&typeof t.code=="string"?t.code:void 0,o=t&&typeof t.message=="string"?t.message:t&&typeof t.detail=="string"?t.detail:e.statusText||"Request failed";if(n)return new u(n,o,e.status,t?.details);let r=e.status;return r===401?new u("auth_invalid",o,r):r===403?new u("permission_denied",o,r):r===404?new u("not_found",o,r):r===409?new u("conflict",o,r):r===422?new u("validation_error",o,r):r===429?new u("rate_limited",o,r):r>=500?new u("server_error",e.statusText||"Internal server error",r):new u("client_error",o,r)}async function bt(e,t={}){let n=R(),{timeoutMs:o,idempotent:r,...s}=t,i=o??3e4,a=(s.method??"GET").toUpperCase(),p=r??(a==="GET"||a==="HEAD"),l;try{l=await yt(`${m()}${e}`,{...s,headers:{...n,...s.headers}},i,p)}catch(b){throw b instanceof Error&&b.name==="TimeoutError"?new u("network_error","Request timed out. Try again in a moment."):new u("network_error","Cannot reach Mistflow servers. Check your network.")}if(ht(l),!l.ok)throw await wt(l);return l.json()}async function we(e,t,n="neon",o){return bt("/api/projects",{method:"POST",body:JSON.stringify({name:e,template:t,db_provider:n,requested_subdomain:o})})}var u,vn,L=S(()=>{"use strict";G();D();u=class extends Error{constructor(n,o,r,s){super(o);this.code=n;this.statusCode=r;this.details=s;this.name="MistflowApiError"}get isAuth(){return this.code.startsWith("auth_")}get isTransient(){return this.code==="server_error"||this.code==="upstream_error"||this.code==="network_error"||this.code==="rate_limited"}};vn=300*1e3});var ee={};te(ee,{emptyState:()=>Z,fetchRemoteState:()=>Et,fuzzyMatch:()=>Ot,getLocalStatePath:()=>Y,readLocalState:()=>Ut,syncRemoteState:()=>Dt,writeLocalState:()=>X});import{existsSync as Ce,readFileSync as jt,writeFileSync as It,mkdirSync as Tt}from"fs";import{join as Re}from"path";function Y(e){return Re(e,".mistflow","state.json")}function Ut(e){let t=Y(e);if(!Ce(t))return null;try{return JSON.parse(jt(t,"utf-8"))}catch{return null}}function X(e,t){let n=Re(e,".mistflow");Ce(n)||Tt(n,{recursive:!0}),It(Y(e),JSON.stringify(t,null,2)+`
24
+ `)}function Z(e,t){return{projectId:e,name:t,template:"",features:[],dbSchema:[],deployCount:0,decisions:[],provenance:[]}}async function Et(e){let t;try{t=R()}catch{return null}try{let n=await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{headers:{...t,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()}});try{x(n.headers)}catch{}return n.ok?await n.json():null}catch{return null}}async function Dt(e,t){let n;try{n=R()}catch{return!1}try{let o=await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...n,"Content-Type":"application/json","X-Mistflow-MCP-Version":C()},body:JSON.stringify(t)});try{x(o.headers)}catch{}return o.ok}catch{return!1}}function Ot(e,t){let n=e.toLowerCase(),o=t.toLowerCase();return o.includes(n)||n.includes(o)?!0:n.split(/\s+/).some(s=>s.length>=3&&o.includes(s))}var M=S(()=>{"use strict";L();D()});var je={};te(je,{ensureBackendRegistered:()=>Ft,ensureShadcnComponents:()=>Vt});import{existsSync as Pe,readFileSync as Lt,writeFileSync as Mt}from"fs";import{join as A}from"path";import{spawn as At}from"child_process";function Nt(e,t,n,o,r){return new Promise(s=>{let i=At(e,t,{cwd:n,stdio:["pipe","pipe","pipe"],timeout:o,...r?{env:{...process.env,...r}}:{}}),a="",p="";i.stdout?.on("data",l=>{a+=l.toString()}),i.stderr?.on("data",l=>{p+=l.toString()}),i.on("close",l=>s({success:l===0,stdout:a,stderr:p})),i.on("error",l=>s({success:!1,stdout:a,stderr:p+l.message}))})}function $t(e){let t=A(e,"mistflow.json");if(!Pe(t))return null;try{return JSON.parse(Lt(t,"utf-8"))}catch{return null}}function qt(e,t){Mt(A(e,"mistflow.json"),JSON.stringify(t,null,2))}async function xe(e,t){try{let n=t.features,o=t.steps,r={plan:t};Array.isArray(n)&&n.length>0&&(r.features=n.map(s=>s.name)),Array.isArray(o)&&o.length>0&&(r.provenance=o.map(s=>({feature:s.name??s.title??`Step ${s.number??"?"}`,user_intent:(s.description??"").slice(0,500),decisions:"Seeded from plan",tradeoffs:"",files_affected:[]}))),await fetch(`${m()}/api/projects/${encodeURIComponent(e)}/state`,{method:"PUT",headers:{...R(),"Content-Type":"application/json"},body:JSON.stringify(r)})}catch(n){console.error("[self-heal] state sync failed:",n instanceof Error?n.message:String(n))}}async function Ft(e,t={}){let n=$t(e);if(n){if(!z())return n.projectId;if(!n.projectId)try{let r=n.plan?.requestedSubdomain,s=await we(n.name,void 0,n.dbProvider??"neon",r);return n.projectId=s.id,qt(e,n),X(e,Z(s.id,n.name)),n.plan&&await xe(s.id,n.plan),console.error(`[self-heal] registered project ${s.id.slice(0,8)} with backend`),s.id}catch(o){console.error("[self-heal] createProject failed:",o instanceof Error?o.message:String(o));return}return t.forceSync&&n.plan&&n.projectId&&await xe(n.projectId,n.plan),n.projectId}}async function Vt(e,t){let n=["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"],o=t&&t.length>0?t:n,r=A(e,"components","ui"),s=[],i=[];for(let l of o)Pe(A(r,`${l}.tsx`))?s.push(l):i.push(l);if(i.length===0)return{installed:[],alreadyPresent:s};let a={NPM_CONFIG_LEGACY_PEER_DEPS:"true"},p=await Nt("npx",["--yes","shadcn@latest","add","-y","-o",...i],e,18e4,a);return p.success?{installed:i,alreadyPresent:s}:{installed:[],alreadyPresent:s,failed:`shadcn add failed for: ${i.join(", ")}. ${p.stderr.slice(-300)}`.trim()}}var Ie=S(()=>{"use strict";L();M()});async function zt(){try{return await import("playwright")}catch{throw new Error("Playwright is not installed. Run: cd packages/mcp-server && pnpm add playwright && npx playwright install chromium")}}async function Gt(){let e=await zt();return(!v||!v.isConnected())&&(v=await e.chromium.launch({headless:!0})),w&&(await w.close().catch(()=>{}),w=null),w=await v.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),g=await w.newPage(),g}async function Oe(){return g&&!g.isClosed()?g:(N||(N=Gt().finally(()=>{N=null})),N)}async function Le(){g&&!g.isClosed()&&await g.close().catch(()=>{}),w&&await w.close().catch(()=>{}),v?.isConnected()&&await v.close().catch(()=>{}),g=null,w=null,v=null}async function $(e){return await e.locator("body").ariaSnapshot()}async function q(e,t=!1){return await e.screenshot({fullPage:t,type:"png"})}var v,w,g,N,Me=S(()=>{"use strict";v=null,w=null,g=null,N=null;process.once("SIGTERM",()=>{Le().finally(()=>process.exit(0))});process.once("SIGINT",()=>{Le().finally(()=>process.exit(0))})});import{Server as Yt}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Xt}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Zt,ListToolsRequestSchema as en}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as tn}from"zod-to-json-schema";var Be="When invoking `mist plan` through your shell/bash tool, give it at least a 2 minute budget before assuming it stalled. `mist plan` commonly takes 30-150s. Heavier commands like install/build/qa/deploy can need a longer budget (up to about 5 minutes).",Je='Treat the CLI\'s returned JSON as authoritative. If `mist plan --describe ...` returns `status: "clarify"`, the planning call completed and is waiting on user answers. Do NOT rerun the same command or describe it as "still generating". Only poll again when status is `"design_clarify_pending"`, and then use `mist plan-directions --cid <id> --wait --json`.',We='When submitting discovery answers back to `mist plan --token ... --answers-stdin`, prefer an array payload like `{"answers":[{"question":"...","decisionKey":"...","answer":"..."}]}`. Do NOT collapse answers into a `{decisionKey: answer}` map because multiple discovery questions can share the same decision key.',He="Before scaffolding a NEW app, resolve the destination path explicitly. If the user asked to create/build a new app and the current directory is not already that Mistflow project, ask whether to scaffold in the current folder or a new subfolder here (unless the user already gave a path). Do NOT inspect sibling directories and silently adopt one as the base just because it looks similar. Reuse an existing Mistflow project only when the user explicitly asks to continue/edit that project.",Ke="If `mist plan` fails with a message like `Request to /api/plan timed out after 60s`, the host AI should suspect a stale CLI binary before blaming the backend. Check `mist --version`. If the installed CLI is behind the backend's advertised latest version, run `mist upgrade` (for the self-installed CLI in `~/.mistflow/bin/mist`) or retry with `npx -y @mistflow-ai/cli@latest ...`.",ze="`mist init` is all-or-nothing for normal users: it registers the cloud project first, scaffolds in a temp directory, then moves the finished app into place only after both steps succeed. If auth, quota, or network registration fails, stop before any app appears locally. Do NOT suggest reusing another app unless the user explicitly asks.",Ge="If `mist init` fails, stop before any cloud command and explain why. Do NOT default to reusing some other existing app as recovery unless the user explicitly asked to continue that app.",Qe="When a `mist` CLI command emits a line on stderr starting with `::mistflow-discovery-prompt::`, `::mistflow-design-picker::`, or `::mistflow-upgrade-prompt::`, parse the JSON payload AFTER the marker and surface it via your native structured-question UI \u2014 `AskUserQuestion` in Claude Code, quick pick in Cursor, equivalents in other hosts. Do NOT just print the stdout questions as plain numbered text; the sentinel exists specifically so you can render proper radio-button-style choices. Payload shapes: discovery has `questions[]` each with `id`/`decisionKey`/`question`/`options[]` (each option: `label`, `description`) plus a `recommended` hint and a `followUpCmd` to run with the user's answers; design-picker has `directions[]` with `id`/`name`/`description` + a `previewPath` to open and a `followUpCmd` for submitting the pick; upgrade-prompt has `actions[]` with `id`/`label`/`cmd`. Collect the answers, then run the `followUpCmd` \u2014 don't ask the user to run it themselves.",Ye='IMPORTANT \u2014 chaining discipline: once the user approves the plan, the init \u2192 install \u2192 implement (repeat) \u2192 build \u2192 deploy \u2192 seed (when needed) \u2192 qa chain is expected. Do NOT pause between these calls to ask the user "should I continue?" or offer options like "full build vs step-by-step." The tool itself will return a status requiring user input when it actually needs one (e.g. confirm_new_project, confirm_dark_theme, awaiting promotion). Otherwise, chain calls continuously. Brief one-line status updates are fine and encouraged; permission requests are not.',ne="Connect the user's Mistflow account. Call this ONLY when: (a) the user has literally never signed in, or (b) a previous tool call returned error code 'auth_missing' or 'auth_revoked'. DO NOT call this tool in response to 500 errors, 404 errors, network errors, or any generic failure \u2014 those are backend issues, not auth issues. Running mist_setup when not needed wastes the user's time and creates login fatigue. Once signed in, the MCP persists a long-lived API key and never asks again. Two-phase device code flow: (1) Call without deviceCode \u2014 opens browser, returns status 'pending' with deviceCode and userCode. Tell the user the verification code and that they need to approve in the browser. (2) Call again with deviceCode after ~15 seconds \u2014 polls for approval. Also accepts an apiKey for headless auth (skips device code entirely).",re="Read or update Mistflow project state. 'get' loads plan progress, env vars, and deploy info \u2014 call this at the start of an incremental change so you understand the current app before editing. 'update' marks plan steps complete or adds env vars (note: `mist implement` in the CLI auto-marks the previous step, so manual updates are rarely needed).",oe="Unified browser tool for navigating, interacting with, and capturing the app. Use 'navigate' to open a URL, interaction actions (click/type/fill/etc.) to test flows, 'snapshot' to inspect the accessibility tree, and 'screenshot' for a visual capture. Use after mist_preview to verify UI, test flows, and iterate on design.",se="Returns the Mistflow CLI command reference. Call this ONCE at session start (or whenever you're unsure which tool to use) to learn every `mist` CLI command, when to prefer it over an MCP tool, and how to chain calls. Results are static \u2014 no backend round-trip, safe to call frequently.";function ie(){let e=[];return e.push("Mistflow is a full-stack app builder that creates and deploys web apps from natural language descriptions. When a user asks to build, create, or make a web app, website, landing page, dashboard, internal tool, marketplace, content site, or browser game, use Mistflow tools. Mistflow creates NEW apps from scratch. It does NOT modify existing non-Mistflow codebases."),e.push(""),e.push("Call `mist_help` at any point for the full CLI command reference. The 4 MCP tools handle short, structured, AI-native flows (auth, project state, browser automation, CLI discovery). Everything else is the `mist` CLI \u2014 invoke via your shell/bash tool."),e.push(""),e.push(Be),e.push(""),e.push(Je),e.push(""),e.push(We),e.push(""),e.push(He),e.push(""),e.push(Qe),e.push(""),e.push(ze),e.push(""),e.push(Ke),e.push(""),e.push("New app workflow (entirely CLI-driven):"),e.push("1. Choose destination: if the user did not already specify a path, ask whether to scaffold in the current folder or a new subfolder here. Resolve the absolute path before `mist init`."),e.push('2. Plan: run `mist plan --describe "<user\'s description>" --json` via your shell/bash tool. Pass the user\'s description EXACTLY as written \u2014 do NOT expand, rephrase, or add features. Relay any returned questions to the user, then submit answers via `echo \'<answers-json>\' | mist plan --token <id> --answers-stdin --json`. When status becomes "design_clarify_pending", poll with `mist plan-directions --cid <id> --wait --json`. When directions are ready, the CLI writes `<cwd>/.mistflow/design-directions.html` with each direction rendered in its own fonts + palette + hero treatment \u2014 run `open "<path>"` for the user so they can see visual options, THEN ask them to pick one by name. The sentinel payload (stderr) includes the `previewPath`. Finalize with `echo \'<pick-json>\' | mist plan --cid <id> --pick-stdin --json`. If the CLI returns status "confirm_new_project" (safety gate when inside an existing codebase), ask the user whether to scaffold a new Mistflow app or edit the existing code.'),e.push("3. Mockup (optional): run `mist mockup --plan-id <id>` via your shell/bash tool \u2014 generates a visual HTML wireframe for user preview. Iterative: pass --feedback to refine, --approved to lock in the design."),e.push("4. Scaffold: run `mist init --plan-id <id> --path <absolute-path>` via your shell/bash tool. `mist init` is transactional: it registers the cloud project first, scaffolds in a temp directory, and only moves the completed app into place after both steps succeed. If it fails before that move, stop and fix the error instead of continuing to cloud commands. Returns fast; does NOT run npm install."),e.push("5. Install dependencies: run `mist install <projectPath>` via your shell/bash tool (streams output)."),e.push("6. Implement: run `mist implement <absolute-path>` via your shell/bash tool \u2014 executes plan steps one at a time. Call repeatedly until all steps are done; it auto-marks the previous step as completed on each call."),e.push("7. Deploy: run `mist deploy [path]` via your shell/bash tool \u2014 tars, uploads, polls status with live streaming. Subcommands: `mist deploy promote` (staging\u2192prod), `mist deploy preview` (local tunnel), `mist deploy rollback <id>`, `mist deploy verify <url>`, `mist deploy redeploy`."),e.push("8. QA: run `mist qa <live-url>` via your shell/bash tool, or just `mist qa` from inside the project if mistflow.json already has deploy.url. Call AFTER deploy. Do NOT show the URL to the user until QA passes."),e.push("9. Seed sample data (optional but recommended before QA when acceptance criteria depend on populated tables/lists): run `mist seed <absolute-path>` via your shell/bash tool. This defaults to local-only seeding against PGlite; use `--allow-remote` only when you intentionally want to seed a remote environment. Use `--reset` to clear the matched tables first."),e.push(""),e.push("Companion CLI (`@mistflow-ai/cli`, invoke as `mist` or via `npx -y @mistflow-ai/cli`) is the primary path for EVERYTHING except the 4 MCP tools below:"),e.push("- `mist plan` / `mist plan-directions` \u2014 plan an app."),e.push("- `mist init` \u2014 scaffold a new project from a plan (fast, ~10s)."),e.push("- `mist install` / `mist build` / `mist mockup` / `mist implement` / `mist debug` / `mist seed` / `mist qa` \u2014 local project lifecycle."),e.push("- `mist deploy` (+ promote/preview/rollback/verify/redeploy subcommands) \u2014 deploy orchestration."),e.push("- `mist status` / `mist fix` \u2014 feature manifest viewer + iteration loop."),e.push("- `mist contracts` \u2014 integration-contract layer management."),e.push("- `mist doctor` \u2014 project health diagnostics."),e.push("- `mist login` / `mist projects` / `mist logs` / `mist env` / `mist domains` / `mist rollback` \u2014 cloud-coordination commands."),e.push("- Call mist_help for the full reference."),e.push(""),e.push(Ye),e.push(""),e.push(Ge),e.push(""),e.push("Design presets (optional, between steps 2 and 3): run `mist projects designs`, `mist projects app-styles`, `mist projects integrations` via your shell/bash tool to browse catalogs. After `mist plan` generates a plan, it may recommend designs and styles \u2014 present these to the user before calling `mist init`."),e.push(""),e.push("Updating an existing Mistflow app:"),e.push("- Cosmetic or single-file changes: edit files directly, then `mist deploy` to publish."),e.push("- New page or feature (no new data model): mist_project action=get for context, build it, then `mist deploy`."),e.push('- Feature needing new data model: ask product questions, call `mist_project action=get` for context, then run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist deploy`.'),e.push('- Integration addition: ask product questions, call `mist_project action=get`, optionally browse `mist projects integrations`, run `mist plan --describe "<change request>" --existing-plan-id <id>`, then `mist implement`, then `mist env` to set required keys before deploy, then `mist deploy`, then `mist qa`.'),e.push("- Bug fix: run `mist debug <absolute-path>` to analyze, fix the code, then `mist deploy`."),e.push(""),e.push("Template forking: use the Mistflow dashboard UI (app.mistflow.ai) to fork templates for now. CLI-side template-fork plumbing is in place but the API-client bridge lands in a follow-up release."),e.push(""),e.push("The 4 MCP tools:"),e.push("- mist_setup: authentication. Only call when user has never signed in or a tool returned 'auth_missing'/'auth_revoked'. Do NOT call for 500s, 404s, or network errors. Also accepts an apiKey parameter for headless auth."),e.push("- mist_project: read/write project state (actions: 'get' / 'update'). Other project queries (errors, logs, deployments, share, version, catalog browsing) moved to `mist projects <subcommand>` in the CLI."),e.push("- mist_browser: navigate, interact with, and screenshot the app during preview or after deploy. Returns screenshots inline in tool results \u2014 the one tool that genuinely needs the MCP transport."),e.push("- mist_help: returns the full CLI command reference. Call once per session to learn the available `mist` commands."),e.join(`
25
25
  `)}D();function c(e,t=!1){let n=e;try{let o=ue();o&&(n=e+o)}catch{}return{content:[{type:"text",text:n}],isError:t}}function me(e){return c(`This is not a Mistflow project (no mistflow.json found at ${e}).
26
26
 
27
27
  Mistflow creates new projects from scratch \u2014 it doesn't work inside existing codebases.
@@ -31,13 +31,13 @@ To get started:
31
31
  2. Run mist init --plan-id <planId> --path <absolute-path>
32
32
  3. Run mist install <absolute-path>, then mist implement <absolute-path>
33
33
 
34
- If you want to deploy an existing project, use your framework's deploy tools directly.`,!0)}import{z as Q}from"zod";import{platform as bt}from"os";import{execFile as be}from"child_process";M();G();var vt=Q.object({apiKey:Q.string().optional().describe("API key (mist_...) for headless auth. Skips the device code flow entirely. Generate one at app.mistflow.ai/mcp-keys."),deviceCode:Q.string().optional().describe("Resume polling for a pending device code. Returned by a previous mist_setup call with status 'pending'. Call mist_setup again with this value after ~15 seconds to check if the user approved.")});function _t(e){return"error"in e}function _e(e){return new Promise(t=>setTimeout(t,e))}function kt(e){return new Promise(t=>{let n=bt();n==="win32"?be("cmd.exe",["/c","start","",e],o=>{o&&console.error("Could not open browser:",o.message),t(!o)}):be(n==="darwin"?"open":"xdg-open",[e],r=>{r&&console.error("Could not open browser:",r.message),t(!r)}),setTimeout(()=>t(!1),5e3)})}var St={fetch:globalThis.fetch,openBrowser:kt,sleep:_e};async function ve(e,t,n,o){let r=n,s=o.sleep??_e;for(let i=0;i<t;i++){await s(r);let a;try{let l=await o.fetch(`${m()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e})});if(!l.ok)continue;a=await l.json()}catch{continue}if(_t(a))switch(a.error){case"authorization_pending":continue;case"slow_down":r+=5e3;continue;case"expired_token":return c("The sign-in link expired. Run mist_setup again to get a new code.",!0);case"access_denied":return c("Sign-in was cancelled. Run mist_setup again to try again.",!0);case"already_exchanged":return c("This sign-in link was already used. Run mist_setup again to get a new code.",!0)}let p=a.email||a.org_name||a.org_slug;return K({apiKey:a.api_key,apiKeyId:a.api_key_id,apiKeyName:a.api_key_name,orgId:a.org_id,orgSlug:a.org_slug,email:a.email}),c(`Connected to Mistflow as ${p}. You are ready to build and deploy.`)}return null}async function Rt(e,t=St){let n=e;if(n?.apiKey)try{let i=await t.fetch(`${m()}/api/org`,{headers:{Authorization:`ApiKey ${n.apiKey}`}});if(!i.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await i.json();return K({apiKey:n.apiKey,orgId:a.id,orgSlug:a.slug}),c(`Connected to Mistflow as ${a.slug} via API key. You are ready to build and deploy.`)}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}if(n?.deviceCode){let i=await ve(n.deviceCode,6,5e3,t);return i||c(JSON.stringify({status:"pending",deviceCode:n.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let o;try{let i=await t.fetch(`${m()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!i.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);o=await i.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let r=`${o.verification_uri}?code=${o.user_code}`;console.error(`
34
+ If you want to deploy an existing project, use your framework's deploy tools directly.`,!0)}import{z as Q}from"zod";import{platform as vt}from"os";import{execFile as be}from"child_process";L();G();var _t=Q.object({apiKey:Q.string().optional().describe("API key (mist_...) for headless auth. Skips the device code flow entirely. Generate one at app.mistflow.ai/mcp-keys."),deviceCode:Q.string().optional().describe("Resume polling for a pending device code. Returned by a previous mist_setup call with status 'pending'. Call mist_setup again with this value after ~15 seconds to check if the user approved.")});function kt(e){return"error"in e}function _e(e){return new Promise(t=>setTimeout(t,e))}function St(e){return new Promise(t=>{let n=vt();n==="win32"?be("cmd.exe",["/c","start","",e],o=>{o&&console.error("Could not open browser:",o.message),t(!o)}):be(n==="darwin"?"open":"xdg-open",[e],r=>{r&&console.error("Could not open browser:",r.message),t(!r)}),setTimeout(()=>t(!1),5e3)})}var Ct={fetch:globalThis.fetch,openBrowser:St,sleep:_e};async function ve(e,t,n,o){let r=n,s=o.sleep??_e;for(let i=0;i<t;i++){await s(r);let a;try{let l=await o.fetch(`${m()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:e})});if(!l.ok)continue;a=await l.json()}catch{continue}if(kt(a))switch(a.error){case"authorization_pending":continue;case"slow_down":r+=5e3;continue;case"expired_token":return c("The sign-in link expired. Run mist_setup again to get a new code.",!0);case"access_denied":return c("Sign-in was cancelled. Run mist_setup again to try again.",!0);case"already_exchanged":return c("This sign-in link was already used. Run mist_setup again to get a new code.",!0)}let p=a.email||a.org_name||a.org_slug;return K({apiKey:a.api_key,apiKeyId:a.api_key_id,apiKeyName:a.api_key_name,orgId:a.org_id,orgSlug:a.org_slug,email:a.email}),c(`Connected to Mistflow as ${p}. You are ready to build and deploy.`)}return null}async function Rt(e,t=Ct){let n=e;if(n?.apiKey)try{let i=await t.fetch(`${m()}/api/org`,{headers:{Authorization:`ApiKey ${n.apiKey}`}});if(!i.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await i.json();return K({apiKey:n.apiKey,orgId:a.id,orgSlug:a.slug}),c(`Connected to Mistflow as ${a.slug} via API key. You are ready to build and deploy.`)}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}if(n?.deviceCode){let i=await ve(n.deviceCode,6,5e3,t);return i||c(JSON.stringify({status:"pending",deviceCode:n.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let o;try{let i=await t.fetch(`${m()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!i.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);o=await i.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let r=`${o.verification_uri}?code=${o.user_code}`;console.error(`
35
35
  Sign in at: ${r}
36
36
  Your code: ${o.user_code}
37
- `);try{await t.openBrowser(r)}catch{}let s=await ve(o.device_code,6,5e3,t);return s||c(JSON.stringify({status:"pending",deviceCode:o.device_code,signInUrl:r,userCode:o.user_code,instruction:"The user hasn't approved yet. Wait ~15 seconds, then call mist_setup again with deviceCode='"+o.device_code+"' to check if they approved."}))}var ke={name:"mist_setup",description:ne,inputSchema:vt,handler:e=>Rt(e)};import{z as y}from"zod";import{z as h}from"zod";import{resolve as Vt,join as Te}from"path";import{existsSync as Bt,readFileSync as Ue,writeFileSync as Jt}from"fs";import{existsSync as xt,readFileSync as Ct}from"fs";function Se(e){let t=new Set;if(!xt(e))return t;let n=Ct(e,"utf-8");for(let o of n.split(`
38
- `)){let r=o.trim();if(!r||r.startsWith("#"))continue;let s=r.indexOf("=");if(s>0){let i=r.slice(0,s).trim(),a=r.slice(s+1).trim();a&&a!=='""'&&a!=="''"&&t.add(i)}}return t}var Wt=h.object({action:h.enum(["get","update"]).default("get").describe("'get' reads current project state. 'update' modifies it."),projectPath:h.string().optional().describe("Path to the project directory (default: current working directory)"),completedStep:h.number().optional().describe("(update only) Mark a plan step as completed by step number"),addEnvVar:h.object({key:h.string(),description:h.string().optional(),setupUrl:h.string().optional()}).optional().describe("(update only) Add a required env var to the project manifest")}),Ee={name:"mist_state",description:"Read or update project state in mistflow.json. Use action='get' to load plan progress, env var status, and deploy info. Use action='update' to mark plan steps complete or add required env vars. Use when the user says 'mist status', 'mist state', or 'mist update state'.",inputSchema:Wt,handler:async e=>{let t=e,n=Vt(t.projectPath??process.cwd()),o=Te(n,"mistflow.json");if(!Bt(o))return me(n);let r;try{r=JSON.parse(Ue(o,"utf-8"))}catch{return c("Failed to parse mistflow.json.",!0)}if(t.action==="get"){if(!r.projectId)try{let{ensureBackendRegistered:d}=await Promise.resolve().then(()=>(Ie(),je));await d(n)&&(r=JSON.parse(Ue(o,"utf-8")))}catch{}let a=r.plan,p=a?.steps?.filter(d=>d.status==="completed").length??0,l=a?.steps?.length??0,b=Se(Te(n,".env.local")),P=r.env?.required?Object.entries(r.env.required).map(([d,T])=>({name:d,description:T?.description,configured:b.has(d)})):[];r.projectId&&Promise.resolve().then(()=>(L(),ee)).then(({fetchRemoteState:d})=>d(r.projectId)).catch(()=>{});let k=[`Project: ${r.name}`];if(a){k.push(`Plan: ${a.summary??a.name??"unnamed"} \u2014 ${p}/${l} steps complete`);for(let d of a.steps){let T=d.status==="completed"?"\u2713":d.status==="in_progress"?"\u2192":" ";k.push(` [${T}] ${d.number}. ${d.name}`)}}let j=P.filter(d=>!d.configured);j.length>0&&k.push(`Missing env vars: ${j.map(d=>d.name).join(", ")}`),r.deploy?.url?k.push(`Deployed: ${r.deploy.url} (${r.deploy.count??0} deploys)`):k.push("Not deployed yet");let I=[],V=a?.steps?.find(d=>d.status!=="completed");return V?I.push(`NEXT: Run mist implement <absolute-path> to work on step ${V.number} (${V.name}).`):a&&p===l&&(r.deploy?.url||I.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT ask the user \u2014 just deploy.")),j.length>0&&I.push(`Missing env vars in .env.local: ${j.map(d=>d.name).join(", ")}`),c(JSON.stringify({name:r.name,projectId:r.projectId,planProgress:a?{name:a.name,summary:a.summary,totalSteps:l,completedSteps:p,steps:a.steps}:null,envStatus:P,deploy:r.deploy??null,contextMessage:k.join(`
39
- `),nextSteps:I}))}let s=[];if(t.completedStep!==void 0){let a=r.plan;if(a?.steps){let p=a.steps.findIndex(l=>l.number===t.completedStep);if(p===-1)return c(`Step ${t.completedStep} not found in the plan.`,!0);a.steps[p].status="completed",s.push(`Step ${t.completedStep} marked as completed`)}}t.addEnvVar&&(r.env||(r.env={required:{}}),r.env.required||(r.env.required={}),r.env.required[t.addEnvVar.key]={description:t.addEnvVar.description,setupUrl:t.addEnvVar.setupUrl},s.push(`Added required env var: ${t.addEnvVar.key}`)),Jt(o,JSON.stringify(r,null,2)+`
40
- `),r.projectId&&Promise.resolve().then(()=>(L(),ee)).then(async({readLocalState:a,syncRemoteState:p})=>{let l=a(n);l&&await p(r.projectId,l)}).catch(()=>{});let i=[];if(t.completedStep!==void 0){let p=r.plan?.steps?.find(l=>l.status!=="completed");p?i.push(`NEXT: Run mist implement <absolute-path> to work on step ${p.number} (${p.name}). Do this now.`):i.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT suggest localhost.")}return t.addEnvVar&&(i.push(`Add ${t.addEnvVar.key} to your .env.local file`),t.addEnvVar.setupUrl&&i.push(`Get the value from: ${t.addEnvVar.setupUrl}`)),c(JSON.stringify({updated:!0,changes:s,message:s.length>0?`Project state saved. ${s.join(". ")}.`:"No changes made.",nextSteps:i.length>0?i:void 0}))}};var Ht=y.object({action:y.enum(["get","update"]).default("get").describe("'get' reads current project state (context oracle \u2014 call before making decisions in an existing project). 'update' marks steps complete or adds env vars. All other project queries moved to the CLI in MCP 0.6.0: `mist projects share`, `mist projects errors`, `mist projects logs`, `mist projects deployments`, `mist projects version`, `mist projects designs`, `mist projects app-styles`, `mist projects integrations`."),projectPath:y.string().optional().describe("Path to the project directory (default: cwd)"),completedStep:y.number().optional().describe("(update) Mark a plan step as completed by step number"),addEnvVar:y.object({key:y.string(),description:y.string().optional(),setupUrl:y.string().optional()}).optional().describe("(update) Add a required env var to the project manifest")}),De={name:"mist_project",description:re,inputSchema:Ht,handler:async e=>{let t=e;return Ee.handler({action:t.action,projectPath:t.projectPath,completedStep:t.completedStep,addEnvVar:t.addEnvVar})}};import{z as _}from"zod";Le();var Gt=_.object({action:_.enum(["navigate","go_back","go_forward","click","type","fill","select_option","press_key","hover","screenshot","snapshot"]).describe("Action to perform. Navigation: navigate|go_back|go_forward. Interaction: click|type|fill|select_option|press_key|hover. Visual: screenshot (returns image) | snapshot (returns accessibility tree)."),url:_.string().optional().describe("URL to navigate to. Required for 'navigate'; optional for 'screenshot' (navigates before capturing)."),selector:_.string().optional().describe("CSS selector of the target element. Required for: click, type, fill, select_option, hover. Optional for screenshot (captures just that element)."),value:_.string().optional().describe("Text to type/fill, option to select, or key to press (e.g. 'Enter', 'Tab'). Required for: type, fill, select_option, press_key."),fullPage:_.boolean().default(!1).describe("For 'screenshot': capture the full scrollable page instead of just the viewport."),includeScreenshot:_.boolean().default(!1).describe("For navigate/interact actions: also return a screenshot alongside the accessibility snapshot.")}),Ae={name:"mist_browser",description:oe,inputSchema:Gt,handler:async e=>{let t=e,n=await Oe();if(t.action==="navigate"){if(!t.url)return c("URL is required for 'navigate'.",!0);let s=[],i=l=>{l.type()==="error"&&s.push(l.text())};n.on("console",i),await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{});let a=[],p=l=>a.push(l.message);if(n.on("pageerror",p),await n.waitForTimeout(500),n.removeListener("console",i),n.removeListener("pageerror",p),s.length>0||a.length>0){let l=await N(n),b=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:l,consoleErrors:s,pageErrors:a,hasErrors:!0})}];if(t.includeScreenshot){let P=await q(n);b.push({type:"image",data:P.toString("base64"),mimeType:"image/png"})}return{content:b}}}else if(t.action==="go_back")await n.goBack({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="go_forward")await n.goForward({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="click"){if(!t.selector)return c("Selector is required for 'click'.",!0);await n.click(t.selector,{timeout:1e4}),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="type"){if(!t.selector)return c("Selector is required for 'type'.",!0);if(!t.value)return c("Value is required for 'type'.",!0);await n.type(t.selector,t.value,{delay:50})}else if(t.action==="fill"){if(!t.selector)return c("Selector is required for 'fill'.",!0);if(!t.value)return c("Value is required for 'fill'.",!0);await n.fill(t.selector,t.value)}else if(t.action==="select_option"){if(!t.selector)return c("Selector is required for 'select_option'.",!0);if(!t.value)return c("Value is required for 'select_option'.",!0);await n.selectOption(t.selector,t.value)}else if(t.action==="hover"){if(!t.selector)return c("Selector is required for 'hover'.",!0);await n.hover(t.selector,{timeout:1e4})}else if(t.action==="press_key"){if(!t.value)return c("Value is required for 'press_key' (e.g. 'Enter').",!0);await n.keyboard.press(t.value),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="screenshot"){t.url&&(await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{}));let s;if(t.selector){let i=await n.$(t.selector);if(!i)return c(`Element not found: ${t.selector}`,!0);s=await i.screenshot({type:"png"})}else s=await q(n,t.fullPage);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),message:`Screenshot captured (${t.fullPage?"full page":"viewport"})`})},{type:"image",data:s.toString("base64"),mimeType:"image/png"}]}}else if(t.action==="snapshot"){let s=await N(n);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:s})}]}}let o=await N(n),r=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:o})}];if(t.includeScreenshot){let s=await q(n);r.push({type:"image",data:s.toString("base64"),mimeType:"image/png"})}return{content:r}}};import{z as $e}from"zod";var Ne=`# Mistflow CLI reference
37
+ `);try{await t.openBrowser(r)}catch{}let s=await ve(o.device_code,6,5e3,t);return s||c(JSON.stringify({status:"pending",deviceCode:o.device_code,signInUrl:r,userCode:o.user_code,instruction:"The user hasn't approved yet. Wait ~15 seconds, then call mist_setup again with deviceCode='"+o.device_code+"' to check if they approved."}))}var ke={name:"mist_setup",description:ne,inputSchema:_t,handler:e=>Rt(e)};import{z as y}from"zod";import{z as h}from"zod";import{resolve as Bt,join as Te}from"path";import{existsSync as Jt,readFileSync as Ue,writeFileSync as Wt}from"fs";import{existsSync as xt,readFileSync as Pt}from"fs";function Se(e){let t=new Set;if(!xt(e))return t;let n=Pt(e,"utf-8");for(let o of n.split(`
38
+ `)){let r=o.trim();if(!r||r.startsWith("#"))continue;let s=r.indexOf("=");if(s>0){let i=r.slice(0,s).trim(),a=r.slice(s+1).trim();a&&a!=='""'&&a!=="''"&&t.add(i)}}return t}var Ht=h.object({action:h.enum(["get","update"]).default("get").describe("'get' reads current project state. 'update' modifies it."),projectPath:h.string().optional().describe("Path to the project directory (default: current working directory)"),completedStep:h.number().optional().describe("(update only) Mark a plan step as completed by step number"),addEnvVar:h.object({key:h.string(),description:h.string().optional(),setupUrl:h.string().optional()}).optional().describe("(update only) Add a required env var to the project manifest")}),Ee={name:"mist_state",description:"Read or update project state in mistflow.json. Use action='get' to load plan progress, env var status, and deploy info. Use action='update' to mark plan steps complete or add required env vars. Use when the user says 'mist status', 'mist state', or 'mist update state'.",inputSchema:Ht,handler:async e=>{let t=e,n=Bt(t.projectPath??process.cwd()),o=Te(n,"mistflow.json");if(!Jt(o))return me(n);let r;try{r=JSON.parse(Ue(o,"utf-8"))}catch{return c("Failed to parse mistflow.json.",!0)}if(t.action==="get"){if(!r.projectId)try{let{ensureBackendRegistered:d}=await Promise.resolve().then(()=>(Ie(),je));await d(n)&&(r=JSON.parse(Ue(o,"utf-8")))}catch{}let a=r.plan,p=a?.steps?.filter(d=>d.status==="completed").length??0,l=a?.steps?.length??0,b=Se(Te(n,".env.local")),P=r.env?.required?Object.entries(r.env.required).map(([d,T])=>({name:d,description:T?.description,configured:b.has(d)})):[];r.projectId&&Promise.resolve().then(()=>(M(),ee)).then(({fetchRemoteState:d})=>d(r.projectId)).catch(()=>{});let k=[`Project: ${r.name}`];if(a){k.push(`Plan: ${a.summary??a.name??"unnamed"} \u2014 ${p}/${l} steps complete`);for(let d of a.steps){let T=d.status==="completed"?"\u2713":d.status==="in_progress"?"\u2192":" ";k.push(` [${T}] ${d.number}. ${d.name}`)}}let j=P.filter(d=>!d.configured);j.length>0&&k.push(`Missing env vars: ${j.map(d=>d.name).join(", ")}`),r.deploy?.url?k.push(`Deployed: ${r.deploy.url} (${r.deploy.count??0} deploys)`):k.push("Not deployed yet");let I=[],V=a?.steps?.find(d=>d.status!=="completed");return V?I.push(`NEXT: Run mist implement <absolute-path> to work on step ${V.number} (${V.name}).`):a&&p===l&&(r.deploy?.url||I.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT ask the user \u2014 just deploy.")),j.length>0&&I.push(`Missing env vars in .env.local: ${j.map(d=>d.name).join(", ")}`),c(JSON.stringify({name:r.name,projectId:r.projectId,planProgress:a?{name:a.name,summary:a.summary,totalSteps:l,completedSteps:p,steps:a.steps}:null,envStatus:P,deploy:r.deploy??null,contextMessage:k.join(`
39
+ `),nextSteps:I}))}let s=[];if(t.completedStep!==void 0){let a=r.plan;if(a?.steps){let p=a.steps.findIndex(l=>l.number===t.completedStep);if(p===-1)return c(`Step ${t.completedStep} not found in the plan.`,!0);a.steps[p].status="completed",s.push(`Step ${t.completedStep} marked as completed`)}}t.addEnvVar&&(r.env||(r.env={required:{}}),r.env.required||(r.env.required={}),r.env.required[t.addEnvVar.key]={description:t.addEnvVar.description,setupUrl:t.addEnvVar.setupUrl},s.push(`Added required env var: ${t.addEnvVar.key}`)),Wt(o,JSON.stringify(r,null,2)+`
40
+ `),r.projectId&&Promise.resolve().then(()=>(M(),ee)).then(async({readLocalState:a,syncRemoteState:p})=>{let l=a(n);l&&await p(r.projectId,l)}).catch(()=>{});let i=[];if(t.completedStep!==void 0){let p=r.plan?.steps?.find(l=>l.status!=="completed");p?i.push(`NEXT: Run mist implement <absolute-path> to work on step ${p.number} (${p.name}). Do this now.`):i.push("NEXT: All steps complete! Run mist deploy <absolute-path> to deploy the app now. Do NOT suggest localhost.")}return t.addEnvVar&&(i.push(`Add ${t.addEnvVar.key} to your .env.local file`),t.addEnvVar.setupUrl&&i.push(`Get the value from: ${t.addEnvVar.setupUrl}`)),c(JSON.stringify({updated:!0,changes:s,message:s.length>0?`Project state saved. ${s.join(". ")}.`:"No changes made.",nextSteps:i.length>0?i:void 0}))}};var Kt=y.object({action:y.enum(["get","update"]).default("get").describe("'get' reads current project state (context oracle \u2014 call before making decisions in an existing project). 'update' marks steps complete or adds env vars. All other project queries moved to the CLI in MCP 0.6.0: `mist projects share`, `mist projects errors`, `mist projects logs`, `mist projects deployments`, `mist projects version`, `mist projects designs`, `mist projects app-styles`, `mist projects integrations`."),projectPath:y.string().optional().describe("Path to the project directory (default: cwd)"),completedStep:y.number().optional().describe("(update) Mark a plan step as completed by step number"),addEnvVar:y.object({key:y.string(),description:y.string().optional(),setupUrl:y.string().optional()}).optional().describe("(update) Add a required env var to the project manifest")}),De={name:"mist_project",description:re,inputSchema:Kt,handler:async e=>{let t=e;return Ee.handler({action:t.action,projectPath:t.projectPath,completedStep:t.completedStep,addEnvVar:t.addEnvVar})}};import{z as _}from"zod";Me();var Qt=_.object({action:_.enum(["navigate","go_back","go_forward","click","type","fill","select_option","press_key","hover","screenshot","snapshot"]).describe("Action to perform. Navigation: navigate|go_back|go_forward. Interaction: click|type|fill|select_option|press_key|hover. Visual: screenshot (returns image) | snapshot (returns accessibility tree)."),url:_.string().optional().describe("URL to navigate to. Required for 'navigate'; optional for 'screenshot' (navigates before capturing)."),selector:_.string().optional().describe("CSS selector of the target element. Required for: click, type, fill, select_option, hover. Optional for screenshot (captures just that element)."),value:_.string().optional().describe("Text to type/fill, option to select, or key to press (e.g. 'Enter', 'Tab'). Required for: type, fill, select_option, press_key."),fullPage:_.boolean().default(!1).describe("For 'screenshot': capture the full scrollable page instead of just the viewport."),includeScreenshot:_.boolean().default(!1).describe("For navigate/interact actions: also return a screenshot alongside the accessibility snapshot.")}),Ae={name:"mist_browser",description:oe,inputSchema:Qt,handler:async e=>{let t=e,n=await Oe();if(t.action==="navigate"){if(!t.url)return c("URL is required for 'navigate'.",!0);let s=[],i=l=>{l.type()==="error"&&s.push(l.text())};n.on("console",i),await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{});let a=[],p=l=>a.push(l.message);if(n.on("pageerror",p),await n.waitForTimeout(500),n.removeListener("console",i),n.removeListener("pageerror",p),s.length>0||a.length>0){let l=await $(n),b=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:l,consoleErrors:s,pageErrors:a,hasErrors:!0})}];if(t.includeScreenshot){let P=await q(n);b.push({type:"image",data:P.toString("base64"),mimeType:"image/png"})}return{content:b}}}else if(t.action==="go_back")await n.goBack({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="go_forward")await n.goForward({waitUntil:"domcontentloaded",timeout:1e4});else if(t.action==="click"){if(!t.selector)return c("Selector is required for 'click'.",!0);await n.click(t.selector,{timeout:1e4}),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="type"){if(!t.selector)return c("Selector is required for 'type'.",!0);if(!t.value)return c("Value is required for 'type'.",!0);await n.type(t.selector,t.value,{delay:50})}else if(t.action==="fill"){if(!t.selector)return c("Selector is required for 'fill'.",!0);if(!t.value)return c("Value is required for 'fill'.",!0);await n.fill(t.selector,t.value)}else if(t.action==="select_option"){if(!t.selector)return c("Selector is required for 'select_option'.",!0);if(!t.value)return c("Value is required for 'select_option'.",!0);await n.selectOption(t.selector,t.value)}else if(t.action==="hover"){if(!t.selector)return c("Selector is required for 'hover'.",!0);await n.hover(t.selector,{timeout:1e4})}else if(t.action==="press_key"){if(!t.value)return c("Value is required for 'press_key' (e.g. 'Enter').",!0);await n.keyboard.press(t.value),await n.waitForLoadState("domcontentloaded").catch(()=>{}),await n.waitForTimeout(500)}else if(t.action==="screenshot"){t.url&&(await n.goto(t.url,{waitUntil:"domcontentloaded",timeout:3e4}),await n.waitForLoadState("networkidle").catch(()=>{}));let s;if(t.selector){let i=await n.$(t.selector);if(!i)return c(`Element not found: ${t.selector}`,!0);s=await i.screenshot({type:"png"})}else s=await q(n,t.fullPage);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),message:`Screenshot captured (${t.fullPage?"full page":"viewport"})`})},{type:"image",data:s.toString("base64"),mimeType:"image/png"}]}}else if(t.action==="snapshot"){let s=await $(n);return{content:[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:s})}]}}let o=await $(n),r=[{type:"text",text:JSON.stringify({url:n.url(),title:await n.title(),snapshot:o})}];if(t.includeScreenshot){let s=await q(n);r.push({type:"image",data:s.toString("base64"),mimeType:"image/png"})}return{content:r}}};import{z as Ne}from"zod";var $e=`# Mistflow CLI reference
41
41
 
42
42
  The Mistflow CLI handles local execution and long-running operations that
43
43
  would hit the MCP 60s tool-call ceiling. Every command below is invokable
@@ -207,6 +207,6 @@ and decides the next command. Example end-to-end chain:
207
207
  mist deploy /Users/you/projects/habit-tracker --json
208
208
  mist seed /Users/you/projects/habit-tracker --json
209
209
  mist qa https://your-app.mistflow.app --json
210
- `,qe={name:"mist_help",description:se,inputSchema:$e.object({command:$e.string().optional().describe("Optional: name of a specific command to get focused reference for. Omit to get the full catalog.")}),handler:async e=>{let{command:t}=e;if(!t)return c(Ne);let n=Ne.split(`
210
+ `,qe={name:"mist_help",description:se,inputSchema:Ne.object({command:Ne.string().optional().describe("Optional: name of a specific command to get focused reference for. Omit to get the full catalog.")}),handler:async e=>{let{command:t}=e;if(!t)return c($e);let n=$e.split(`
211
211
  `),o=new RegExp(`^### \`mist ${t}`),r=-1,s=n.length;for(let i=0;i<n.length;i++)if(o.test(n[i]))r=i;else if(r>=0&&n[i].startsWith("### ")){s=i;break}else if(r>=0&&n[i].startsWith("## ")&&i>r){s=i;break}return r<0?c(`No command named '${t}' found. Call mist_help with no args to see the full catalog.`,!0):c(n.slice(r,s).join(`
212
- `).trim())}};var F=new Qt({name:"mistflow",version:"0.3.0"},{capabilities:{tools:{}},instructions:ie()}),Fe=[ke,De,Ae,qe];F.setRequestHandler(Zt,async()=>({tools:Fe.map(e=>({name:e.name,description:e.description,inputSchema:en(e.inputSchema)}))}));F.setRequestHandler(Xt,async e=>{let t=Fe.find(n=>n.name===e.params.name);if(!t)return c(`Unknown tool: ${e.params.name}`,!0);try{let n=t.inputSchema.safeParse(e.params.arguments);if(!n.success){let s=n.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join(", ");return c(`Invalid input: ${s}`,!0)}let o=e.params._meta?.progressToken,r={server:F,progressToken:o};try{return await t.handler(n.data,r)}finally{r.cleanup?.()}}catch(n){let o=n instanceof Error?n.message:"An unexpected error occurred";return console.error("Tool error:",n),c(o,!0)}});async function tn(){let e=process.argv.indexOf("--api-url");e!==-1&&process.argv[e+1]&&(process.env.MISTFLOW_API_URL=process.argv[e+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let t=new Yt;await F.connect(t),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}tn().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
212
+ `).trim())}};var F=new Yt({name:"mistflow",version:"0.3.0"},{capabilities:{tools:{}},instructions:ie()}),Fe=[ke,De,Ae,qe];F.setRequestHandler(en,async()=>({tools:Fe.map(e=>({name:e.name,description:e.description,inputSchema:tn(e.inputSchema)}))}));F.setRequestHandler(Zt,async e=>{let t=Fe.find(n=>n.name===e.params.name);if(!t)return c(`Unknown tool: ${e.params.name}`,!0);try{let n=t.inputSchema.safeParse(e.params.arguments);if(!n.success){let s=n.error.issues.map(i=>`${i.path.join(".")}: ${i.message}`).join(", ");return c(`Invalid input: ${s}`,!0)}let o=e.params._meta?.progressToken,r={server:F,progressToken:o};try{return await t.handler(n.data,r)}finally{r.cleanup?.()}}catch(n){let o=n instanceof Error?n.message:"An unexpected error occurred";return console.error("Tool error:",n),c(o,!0)}});async function nn(){let e=process.argv.indexOf("--api-url");e!==-1&&process.argv[e+1]&&(process.env.MISTFLOW_API_URL=process.argv[e+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let t=new Xt;await F.connect(t),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}nn().catch(e=>{console.error("Fatal error:",e),process.exit(1)});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mistflow-ai/mcp",
3
- "version": "0.7.4",
3
+ "version": "0.7.5",
4
4
  "description": "Mistflow MCP server for AI coding editors. Installed into Claude Code, Cursor, Codex CLI, and VS Code Copilot by the mistflow-ai installer.",
5
5
  "license": "Elastic-2.0",
6
6
  "type": "module",