@mistflow-ai/mcp 1.0.5 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.js CHANGED
@@ -31,7 +31,7 @@ To get started:
31
31
  3. Call mist_install({ projectPath }), then mist_implement({ projectPath })
32
32
 
33
33
  If you want to deploy an existing project, use your framework's deploy tools directly.`,!0)}async function Ks(t,e){try{let{getPage:s,takeScreenshot:n}=await Promise.resolve().then(()=>(qt(),_n)),o=await s();await o.goto(t,{waitUntil:"domcontentloaded",timeout:15e3}),await o.waitForLoadState("networkidle").catch(()=>{});let i=await n(o,!1);return{content:[{type:"text",text:e},{type:"image",data:i.toString("base64"),mimeType:"image/png"}]}}catch{return c(e)}}var K=_(()=>{"use strict";wt()});import{readFileSync as Qs,existsSync as Rn,writeFileSync as Bi,mkdirSync as zi,renameSync as Hi,unlinkSync as Wi}from"fs";import{join as Cn,dirname as Gi}from"path";import{homedir as Vi}from"os";import{randomBytes as Ji}from"crypto";function Xs(){return Cn(Vi(),".mistflow","credentials.json")}function Bt(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function Zs(){let t=Xs();if(!Rn(t))return null;try{let e=JSON.parse(Qs(t,"utf-8"));return typeof e.apiKey=="string"?{[Yi]:e}:e}catch{return null}}function tt(){let t=process.env.MISTFLOW_API_KEY;if(t)return{ok:!0,creds:{apiKey:t,orgId:"",orgSlug:"env"}};let e=Zs();if(!e)return{ok:!1,reason:"missing"};let s=Bt(),n=e[s];return n&&typeof n.apiKey=="string"&&n.apiKey&&typeof n.orgId=="string"?{ok:!0,creds:n}:{ok:!1,reason:"missing"}}function An(t){let e=Xs(),s=Gi(e);Rn(s)||zi(s,{recursive:!0});let n=Zs()??{},o=Bt();n[o]=t;let i=Cn(s,`.credentials.tmp.${Ji(8).toString("hex")}`);try{Bi(i,JSON.stringify(n,null,2)+`
34
- `,{mode:384}),Hi(i,e)}catch(r){try{Wi(i)}catch{}throw r}}function ee(){return tt().ok}function $e(t){let e=Cn(t,"mistflow.json");if(!Rn(e))return null;try{return JSON.parse(Qs(e,"utf-8"))}catch{return null}}var Yi,nt=_(()=>{"use strict";Yi="https://api.mistflow.ai"});var ro={};$t(ro,{MistflowApiError:()=>L,addDomain:()=>Mn,checkAuth:()=>Zi,checkAuthDetailed:()=>so,checkSubdomain:()=>Nn,createDeployment:()=>ta,createProject:()=>St,deleteEnvVar:()=>Bn,discoverDecisions:()=>na,downloadSource:()=>ra,downloadSourceWithToken:()=>oo,fetchDesignDirections:()=>Dn,fetchModule:()=>Yn,fetchPlanConversation:()=>Ht,fetchScaffold:()=>Vn,fetchStepContext:()=>Jn,forkTemplate:()=>Qn,generatePlan:()=>On,getAuthHeaders:()=>Ke,getBaseUrl:()=>te,getDashboardUrl:()=>Ki,getDbCredentials:()=>sa,getDeployLogs:()=>zn,getDeploymentStatus:()=>Pt,getProject:()=>ea,getProjectErrors:()=>Hn,getSeedInfo:()=>Un,getSiteUrl:()=>st,getTemplate:()=>Kn,hasCredentialsOnDisk:()=>ee,hasLocalCredentials:()=>no,listDeployments:()=>rt,listDomains:()=>Ue,listEnvVars:()=>Fn,markLocalSetupDone:()=>ia,modifyPlan:()=>Wt,pingBackend:()=>En,promotePreview:()=>Wn,redeployProject:()=>oa,removeDomain:()=>$n,rollbackDeployment:()=>Gn,shareProject:()=>Xn,uploadAndDeploy:()=>jn,uploadQAResults:()=>Ln,upsertEnvVar:()=>qn,verifyDomain:()=>Gt});function te(){return Bt()}function st(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9102")}return"https://mistflow.ai"}function Ki(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","app.mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9101")}return"https://app.mistflow.ai"}function Ke(){let t=tt();if(!t.ok)throw new L("auth_missing","No Mistflow credentials found.",401);return Qi(t.creds)}function Qi(t){return{Authorization:`ApiKey ${t.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":ve()}}function ot(t){try{bt(t.headers)}catch{}}async function En(){try{let t=await fetch(`${te()}/health`,{method:"GET",signal:AbortSignal.timeout(5e3)});ot(t)}catch{}}async function to(t,e,s,n){for(let o=0;o<2;o++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(s)})}catch(i){let r=i instanceof Error&&i.name==="TimeoutError",a=i instanceof TypeError;if(n&&o===0&&(r||a)){console.error(`[api] Retrying ${t} after ${r?"timeout":"network error"}`);continue}throw i}throw new Error("fetchWithRetry: exhausted retries")}async function kt(t){let e=null;try{e=await t.json()}catch{e=null}let s=e&&typeof e.code=="string"?e.code:void 0,n=e&&typeof e.message=="string"?e.message:e&&typeof e.detail=="string"?e.detail:t.statusText||"Request failed";if(s)return new L(s,n,t.status,e?.details);let o=t.status;return o===401?new L("auth_invalid",n,o):o===403?new L("permission_denied",n,o):o===404?new L("not_found",n,o):o===409?new L("conflict",n,o):o===422?new L("validation_error",n,o):o===429?new L("rate_limited",n,o):o>=500?new L("server_error",t.statusText||"Internal server error",o):new L("client_error",n,o)}async function F(t,e={}){let s=Ke(),{timeoutMs:n,idempotent:o,...i}=e,r=n??3e4,a=(i.method??"GET").toUpperCase(),l=o??(a==="GET"||a==="HEAD"),d;try{d=await to(`${te()}${t}`,{...i,headers:{...s,...i.headers}},r,l)}catch(h){throw h instanceof Error&&h.name==="TimeoutError"?new L("network_error","Request timed out. Try again in a moment."):new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(d),!d.ok)throw await kt(d);return d.json()}function no(){return tt().ok}async function Zi(){return(await so()).ok}async function so(){if(zt!==null&&Date.now()<eo)return zt?{ok:!0}:{ok:!1,reason:"no_credentials"};if(!no())return{ok:!1,reason:"no_credentials"};try{return await F("/api/org"),zt=!0,eo=Date.now()+Xi,{ok:!0}}catch(t){if(zt=null,!(t instanceof L))return{ok:!1,reason:"network_error"};switch(t.code){case"auth_missing":case"auth_revoked":return{ok:!1,reason:"no_credentials"};case"auth_expired":case"auth_invalid":case"auth_org_not_found":return{ok:!1,reason:"expired"};case"network_error":return{ok:!1,reason:"network_error"};case"rate_limited":case"server_error":case"upstream_error":return{ok:!1,reason:"server_error"};default:return{ok:!1,reason:"server_error"}}}}async function ea(t){return F(`/api/projects/${encodeURIComponent(t)}`)}async function Nn(t){return F(`/api/projects/check-subdomain?name=${encodeURIComponent(t)}`)}async function St(t,e,s="neon",n){return F("/api/projects",{method:"POST",body:JSON.stringify({name:t,template:e,db_provider:s,requested_subdomain:n})})}async function ta(t,e){return F("/api/deploy",{method:"POST",body:JSON.stringify({project_id:t,build_output_url:e})})}async function jn(t,e,s="production",n,o,i,r){let{readFileSync:a}=await import("fs"),{basename:l}=await import("path"),d=tt();if(!d.ok)throw new L("auth_missing","No Mistflow credentials found.",401);let h=d.creds,m=a(e),p=new Blob([m],{type:"application/gzip"}),y=new FormData;if(y.append("project_id",t),y.append("build",p,l(e)),s!=="production"&&y.append("environment",s),n&&y.append("admin_email",n),o&&y.append("schema_pushed","true"),i){let{existsSync:f}=await import("fs");if(f(i)){let k=a(i),R=new Blob([k],{type:"application/gzip"});y.append("source",R,"source.tar.gz")}}r&&y.append("git_commit_sha",r);let v;try{v=await fetch(`${te()}/api/deploy/upload`,{method:"POST",headers:{Authorization:`ApiKey ${h.apiKey}`,"X-Mistflow-MCP-Version":ve()},body:y,signal:AbortSignal.timeout(3e5)})}catch{throw new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(v),!v.ok)throw await kt(v);let b=await v.json();return{...b,id:b.deployment_id}}async function Pt(t){return F(`/api/deploy/${encodeURIComponent(t)}/status`)}async function Dn(t){return F(`/api/plan/design-directions/${encodeURIComponent(t)}`,{timeoutMs:15e3})}async function Ht(t,e){let s=e?.waitSeconds??10,n=s>0?`?wait=${s}`:"",o=Math.min(6e4,(s+5)*1e3);return F(`/api/plan/conversations/${encodeURIComponent(t)}${n}`,{timeoutMs:o})}async function On(t,e){let s={description:t,conversation_id:e?.conversationId,answers:e?.answers};e?.autonomous&&(s.autonomous=!0),e?.language&&e.language.toLowerCase()!=="english"&&(s.language=e.language),e?.designConversationId&&(s.design_conversation_id=e.designConversationId),e?.designDirection&&(s.design_direction=e.designDirection);let n=e?.conversationId||e?.answers||e?.designConversationId?18e4:6e4;return F("/api/plan",{method:"POST",body:JSON.stringify(s),timeoutMs:n,idempotent:!1})}async function Wt(t,e){return F("/api/plan/modify",{method:"POST",body:JSON.stringify({existing_plan:t,modification:e})})}async function na(t){return F("/api/plan/discover",{method:"POST",body:JSON.stringify({description:t})})}async function Mn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains`,{method:"POST",body:JSON.stringify({domain:e})})}async function Ue(t){return F(`/api/projects/${encodeURIComponent(t)}/domains`)}async function Gt(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}/verify`)}async function $n(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}`,{method:"DELETE"})}async function sa(t){return F(`/api/projects/${encodeURIComponent(t)}/db-credentials`)}async function Un(t){try{return await F(`/api/projects/${encodeURIComponent(t)}/test-accounts`)}catch(e){return e instanceof L&&(e.statusCode===404||e.code==="not_found")||console.error("[api] Failed to fetch seed info:",e instanceof Error?e.message:e),null}}async function Ln(t,e){try{return await F(`/api/deploy/${encodeURIComponent(t)}/qa-results`,{method:"POST",body:JSON.stringify(e)})}catch(s){return console.error("[api] Failed to upload QA results:",s instanceof Error?s.message:s),null}}async function Fn(t){return F(`/api/projects/${encodeURIComponent(t)}/env`)}async function qn(t,e,s,n){return F(`/api/projects/${encodeURIComponent(t)}/env`,{method:"PUT",body:JSON.stringify({key:e,value:s,category:n?.category??"custom",description:n?.description,setup_url:n?.setupUrl})})}async function Bn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/env/${encodeURIComponent(e)}`,{method:"DELETE"})}async function zn(t){return F(`/api/deploy/${encodeURIComponent(t)}/logs`)}async function Hn(t,e="7d"){return F(`/api/projects/${encodeURIComponent(t)}/errors?period=${encodeURIComponent(e)}`)}async function rt(t){return F(`/api/projects/${encodeURIComponent(t)}/deployments`)}async function oa(t){return F(`/api/deploy/${encodeURIComponent(t)}/redeploy`,{method:"POST"})}async function Wn(t,e){let s=new URLSearchParams({preview_deployment_id:e});return F(`/api/deploy/${encodeURIComponent(t)}/promote`,{method:"POST",body:s.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"}})}async function Gn(t){return F(`/api/deploy/${encodeURIComponent(t)}/rollback`,{method:"POST"})}async function ra(t,e){let s=tt();if(!s.ok)throw new L("auth_missing","Not authenticated.",401);let n=s.creds,o=await fetch(`${te()}/api/deploy/${encodeURIComponent(t)}/source`,{headers:{Authorization:`ApiKey ${n.apiKey}`,"X-Mistflow-MCP-Version":ve()},signal:AbortSignal.timeout(12e4)});if(ot(o),!o.ok)throw await kt(o);let{writeFileSync:i}=await import("fs"),r=Buffer.from(await o.arrayBuffer());i(e,r)}async function Vt(t,e){let{timeoutMs:s,idempotent:n,...o}=e??{},i=s??3e4,r=(o.method??"GET").toUpperCase(),a=n??(r==="GET"||r==="HEAD"),l;try{l=await to(`${te()}${t}`,{headers:{"Content-Type":"application/json","X-Mistflow-MCP-Version":ve()},...o},i,a)}catch(d){throw d instanceof Error&&d.name==="TimeoutError"?new L("network_error","Request timed out. Try again in a moment."):new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(l),!l.ok)throw await kt(l);return l.json()}async function Vn(t="nextjs"){return Vt(`/api/scaffold/${encodeURIComponent(t)}`)}async function Jn(t,e){return Vt(`/api/scaffold/${encodeURIComponent(t)}/context?step_type=${encodeURIComponent(e)}`)}async function Yn(t,e,s,n){return Vt(`/api/scaffold/${encodeURIComponent(t)}/module`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"crud",entity:e,fields:s,entity_plural:n})})}async function Kn(t){return Vt(`/api/templates/${encodeURIComponent(t)}`)}async function Qn(t){return F(`/api/templates/${encodeURIComponent(t)}/fork`,{method:"POST"})}async function oo(t,e,s){let n;try{n=await fetch(`${te()}/api/deploy/${encodeURIComponent(t)}/fork-source?fork_token=${encodeURIComponent(e)}`,{headers:{"X-Mistflow-MCP-Version":ve()},signal:AbortSignal.timeout(12e4)})}catch{throw new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(n),!n.ok)throw n.status===401?new L("validation_error","Fork token expired or invalid. Re-open the project in the dashboard to get a fresh token.",n.status):await kt(n);let{writeFileSync:o}=await import("fs"),i=Buffer.from(await n.arrayBuffer());o(s,i)}async function ia(t){await F(`/api/projects/${encodeURIComponent(t)}`,{method:"PATCH",body:JSON.stringify({local_setup_done:!0})})}async function Xn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/share`,{method:"POST",body:JSON.stringify({is_template:e?.isTemplate??!1,template_description:e?.description})})}var L,zt,eo,Xi,ue=_(()=>{"use strict";nt();wt();L=class extends Error{constructor(s,n,o,i){super(n);this.code=s;this.statusCode=o;this.details=i;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"}};zt=null,eo=0,Xi=300*1e3});import{z as Zn}from"zod";import{platform as aa}from"os";import{execFile as io}from"child_process";function ca(t){return"error"in t}function lo(t){return new Promise(e=>setTimeout(e,t))}function da(t){return new Promise(e=>{let s=aa();s==="win32"?io("cmd.exe",["/c","start","",t],n=>{n&&console.error("Could not open browser:",n.message),e(!n)}):io(s==="darwin"?"open":"xdg-open",[t],o=>{o&&console.error("Could not open browser:",o.message),e(!o)}),setTimeout(()=>e(!1),5e3)})}async function ao(t,e,s,n){let o=s,i=n.sleep??lo;for(let r=0;r<e;r++){await i(o);let a;try{let d=await n.fetch(`${te()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:t})});if(!d.ok)continue;a=await d.json()}catch{continue}if(ca(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 l=a.email||a.org_name||a.org_slug;return An({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 ${l}. You are ready to build and deploy.`)}return null}async function ua(t,e=pa){let s=t;if(s?.apiKey)try{let r=await e.fetch(`${te()}/api/org`,{headers:{Authorization:`ApiKey ${s.apiKey}`}});if(!r.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await r.json();return An({apiKey:s.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(s?.deviceCode){let r=await ao(s.deviceCode,6,5e3,e);return r||c(JSON.stringify({status:"pending",deviceCode:s.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let n;try{let r=await e.fetch(`${te()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!r.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);n=await r.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let o=`${n.verification_uri}?code=${n.user_code}`;console.error(`
34
+ `,{mode:384}),Hi(i,e)}catch(r){try{Wi(i)}catch{}throw r}}function ee(){return tt().ok}function $e(t){let e=Cn(t,"mistflow.json");if(!Rn(e))return null;try{return JSON.parse(Qs(e,"utf-8"))}catch{return null}}var Yi,nt=_(()=>{"use strict";Yi="https://api.mistflow.ai"});var ro={};$t(ro,{MistflowApiError:()=>L,addDomain:()=>Mn,checkAuth:()=>Zi,checkAuthDetailed:()=>so,checkSubdomain:()=>Nn,createDeployment:()=>ta,createProject:()=>St,deleteEnvVar:()=>Bn,discoverDecisions:()=>na,downloadSource:()=>ra,downloadSourceWithToken:()=>oo,fetchDesignDirections:()=>Dn,fetchModule:()=>Yn,fetchPlanConversation:()=>Ht,fetchScaffold:()=>Vn,fetchStepContext:()=>Jn,forkTemplate:()=>Qn,generatePlan:()=>On,getAuthHeaders:()=>Ke,getBaseUrl:()=>te,getDashboardUrl:()=>Ki,getDbCredentials:()=>sa,getDeployLogs:()=>zn,getDeploymentStatus:()=>Pt,getProject:()=>ea,getProjectErrors:()=>Hn,getSeedInfo:()=>Un,getSiteUrl:()=>st,getTemplate:()=>Kn,hasCredentialsOnDisk:()=>ee,hasLocalCredentials:()=>no,listDeployments:()=>rt,listDomains:()=>Ue,listEnvVars:()=>Fn,markLocalSetupDone:()=>ia,modifyPlan:()=>Wt,pingBackend:()=>En,promotePreview:()=>Wn,redeployProject:()=>oa,removeDomain:()=>$n,rollbackDeployment:()=>Gn,shareProject:()=>Xn,uploadAndDeploy:()=>jn,uploadQAResults:()=>Ln,upsertEnvVar:()=>qn,verifyDomain:()=>Gt});function te(){return Bt()}function st(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9102")}return"https://mistflow.ai"}function Ki(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","app.mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9101")}return"https://app.mistflow.ai"}function Ke(){let t=tt();if(!t.ok)throw new L("auth_missing","No Mistflow credentials found.",401);return Qi(t.creds)}function Qi(t){return{Authorization:`ApiKey ${t.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":ve()}}function ot(t){try{bt(t.headers)}catch{}}async function En(){try{let t=await fetch(`${te()}/health`,{method:"GET",signal:AbortSignal.timeout(5e3)});ot(t)}catch{}}async function to(t,e,s,n){for(let o=0;o<2;o++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(s)})}catch(i){let r=i instanceof Error&&i.name==="TimeoutError",a=i instanceof TypeError;if(n&&o===0&&(r||a)){console.error(`[api] Retrying ${t} after ${r?"timeout":"network error"}`);continue}throw i}throw new Error("fetchWithRetry: exhausted retries")}async function kt(t){let e=null;try{e=await t.json()}catch{e=null}let s=e&&typeof e.code=="string"?e.code:void 0,n=e&&typeof e.message=="string"?e.message:e&&typeof e.detail=="string"?e.detail:t.statusText||"Request failed";if(s)return new L(s,n,t.status,e?.details);let o=t.status;return o===401?new L("auth_invalid",n,o):o===403?new L("permission_denied",n,o):o===404?new L("not_found",n,o):o===409?new L("conflict",n,o):o===422?new L("validation_error",n,o):o===429?new L("rate_limited",n,o):o>=500?new L("server_error",t.statusText||"Internal server error",o):new L("client_error",n,o)}async function F(t,e={}){let s=Ke(),{timeoutMs:n,idempotent:o,...i}=e,r=n??3e4,a=(i.method??"GET").toUpperCase(),l=o??(a==="GET"||a==="HEAD"),d;try{d=await to(`${te()}${t}`,{...i,headers:{...s,...i.headers}},r,l)}catch(h){throw h instanceof Error&&h.name==="TimeoutError"?new L("network_error","Request timed out. Try again in a moment."):new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(d),!d.ok)throw await kt(d);return d.json()}function no(){return tt().ok}async function Zi(){return(await so()).ok}async function so(){if(zt!==null&&Date.now()<eo)return zt?{ok:!0}:{ok:!1,reason:"no_credentials"};if(!no())return{ok:!1,reason:"no_credentials"};try{return await F("/api/org"),zt=!0,eo=Date.now()+Xi,{ok:!0}}catch(t){if(zt=null,!(t instanceof L))return{ok:!1,reason:"network_error"};switch(t.code){case"auth_missing":case"auth_revoked":return{ok:!1,reason:"no_credentials"};case"auth_expired":case"auth_invalid":case"auth_org_not_found":return{ok:!1,reason:"expired"};case"network_error":return{ok:!1,reason:"network_error"};case"rate_limited":case"server_error":case"upstream_error":return{ok:!1,reason:"server_error"};default:return{ok:!1,reason:"server_error"}}}}async function ea(t){return F(`/api/projects/${encodeURIComponent(t)}`)}async function Nn(t){return F(`/api/projects/check-subdomain?name=${encodeURIComponent(t)}`)}async function St(t,e,s="neon",n){return F("/api/projects",{method:"POST",body:JSON.stringify({name:t,template:e,db_provider:s,requested_subdomain:n})})}async function ta(t,e){return F("/api/deploy",{method:"POST",body:JSON.stringify({project_id:t,build_output_url:e})})}async function jn(t,e,s="production",n,o,i,r){let{readFileSync:a}=await import("fs"),{basename:l}=await import("path"),d=tt();if(!d.ok)throw new L("auth_missing","No Mistflow credentials found.",401);let h=d.creds,m=a(e),p=new Blob([m],{type:"application/gzip"}),y=new FormData;if(y.append("project_id",t),y.append("build",p,l(e)),s!=="production"&&y.append("environment",s),n&&y.append("admin_email",n),o&&y.append("schema_pushed","true"),i){let{existsSync:f}=await import("fs");if(f(i)){let k=a(i),R=new Blob([k],{type:"application/gzip"});y.append("source",R,"source.tar.gz")}}r&&y.append("git_commit_sha",r);let v;try{v=await fetch(`${te()}/api/deploy/upload`,{method:"POST",headers:{Authorization:`ApiKey ${h.apiKey}`,"X-Mistflow-MCP-Version":ve()},body:y,signal:AbortSignal.timeout(3e5)})}catch{throw new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(v),!v.ok)throw await kt(v);let b=await v.json();return{...b,id:b.deployment_id}}async function Pt(t){return F(`/api/deploy/${encodeURIComponent(t)}/status`)}async function Dn(t){return F(`/api/plan/design-directions/${encodeURIComponent(t)}`,{timeoutMs:15e3})}async function Ht(t,e){let s=e?.waitSeconds??20,n=s>0?`?wait=${s}`:"",o=Math.min(6e4,(s+5)*1e3);return F(`/api/plan/conversations/${encodeURIComponent(t)}${n}`,{timeoutMs:o})}async function On(t,e){let s={description:t,conversation_id:e?.conversationId,answers:e?.answers};e?.autonomous&&(s.autonomous=!0),e?.language&&e.language.toLowerCase()!=="english"&&(s.language=e.language),e?.designConversationId&&(s.design_conversation_id=e.designConversationId),e?.designDirection&&(s.design_direction=e.designDirection);let n=e?.conversationId||e?.answers||e?.designConversationId?18e4:6e4;return F("/api/plan",{method:"POST",body:JSON.stringify(s),timeoutMs:n,idempotent:!1})}async function Wt(t,e){return F("/api/plan/modify",{method:"POST",body:JSON.stringify({existing_plan:t,modification:e})})}async function na(t){return F("/api/plan/discover",{method:"POST",body:JSON.stringify({description:t})})}async function Mn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains`,{method:"POST",body:JSON.stringify({domain:e})})}async function Ue(t){return F(`/api/projects/${encodeURIComponent(t)}/domains`)}async function Gt(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}/verify`)}async function $n(t,e){return F(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}`,{method:"DELETE"})}async function sa(t){return F(`/api/projects/${encodeURIComponent(t)}/db-credentials`)}async function Un(t){try{return await F(`/api/projects/${encodeURIComponent(t)}/test-accounts`)}catch(e){return e instanceof L&&(e.statusCode===404||e.code==="not_found")||console.error("[api] Failed to fetch seed info:",e instanceof Error?e.message:e),null}}async function Ln(t,e){try{return await F(`/api/deploy/${encodeURIComponent(t)}/qa-results`,{method:"POST",body:JSON.stringify(e)})}catch(s){return console.error("[api] Failed to upload QA results:",s instanceof Error?s.message:s),null}}async function Fn(t){return F(`/api/projects/${encodeURIComponent(t)}/env`)}async function qn(t,e,s,n){return F(`/api/projects/${encodeURIComponent(t)}/env`,{method:"PUT",body:JSON.stringify({key:e,value:s,category:n?.category??"custom",description:n?.description,setup_url:n?.setupUrl})})}async function Bn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/env/${encodeURIComponent(e)}`,{method:"DELETE"})}async function zn(t){return F(`/api/deploy/${encodeURIComponent(t)}/logs`)}async function Hn(t,e="7d"){return F(`/api/projects/${encodeURIComponent(t)}/errors?period=${encodeURIComponent(e)}`)}async function rt(t){return F(`/api/projects/${encodeURIComponent(t)}/deployments`)}async function oa(t){return F(`/api/deploy/${encodeURIComponent(t)}/redeploy`,{method:"POST"})}async function Wn(t,e){let s=new URLSearchParams({preview_deployment_id:e});return F(`/api/deploy/${encodeURIComponent(t)}/promote`,{method:"POST",body:s.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"}})}async function Gn(t){return F(`/api/deploy/${encodeURIComponent(t)}/rollback`,{method:"POST"})}async function ra(t,e){let s=tt();if(!s.ok)throw new L("auth_missing","Not authenticated.",401);let n=s.creds,o=await fetch(`${te()}/api/deploy/${encodeURIComponent(t)}/source`,{headers:{Authorization:`ApiKey ${n.apiKey}`,"X-Mistflow-MCP-Version":ve()},signal:AbortSignal.timeout(12e4)});if(ot(o),!o.ok)throw await kt(o);let{writeFileSync:i}=await import("fs"),r=Buffer.from(await o.arrayBuffer());i(e,r)}async function Vt(t,e){let{timeoutMs:s,idempotent:n,...o}=e??{},i=s??3e4,r=(o.method??"GET").toUpperCase(),a=n??(r==="GET"||r==="HEAD"),l;try{l=await to(`${te()}${t}`,{headers:{"Content-Type":"application/json","X-Mistflow-MCP-Version":ve()},...o},i,a)}catch(d){throw d instanceof Error&&d.name==="TimeoutError"?new L("network_error","Request timed out. Try again in a moment."):new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(l),!l.ok)throw await kt(l);return l.json()}async function Vn(t="nextjs"){return Vt(`/api/scaffold/${encodeURIComponent(t)}`)}async function Jn(t,e){return Vt(`/api/scaffold/${encodeURIComponent(t)}/context?step_type=${encodeURIComponent(e)}`)}async function Yn(t,e,s,n){return Vt(`/api/scaffold/${encodeURIComponent(t)}/module`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"crud",entity:e,fields:s,entity_plural:n})})}async function Kn(t){return Vt(`/api/templates/${encodeURIComponent(t)}`)}async function Qn(t){return F(`/api/templates/${encodeURIComponent(t)}/fork`,{method:"POST"})}async function oo(t,e,s){let n;try{n=await fetch(`${te()}/api/deploy/${encodeURIComponent(t)}/fork-source?fork_token=${encodeURIComponent(e)}`,{headers:{"X-Mistflow-MCP-Version":ve()},signal:AbortSignal.timeout(12e4)})}catch{throw new L("network_error","Cannot reach Mistflow servers. Check your network.")}if(ot(n),!n.ok)throw n.status===401?new L("validation_error","Fork token expired or invalid. Re-open the project in the dashboard to get a fresh token.",n.status):await kt(n);let{writeFileSync:o}=await import("fs"),i=Buffer.from(await n.arrayBuffer());o(s,i)}async function ia(t){await F(`/api/projects/${encodeURIComponent(t)}`,{method:"PATCH",body:JSON.stringify({local_setup_done:!0})})}async function Xn(t,e){return F(`/api/projects/${encodeURIComponent(t)}/share`,{method:"POST",body:JSON.stringify({is_template:e?.isTemplate??!1,template_description:e?.description})})}var L,zt,eo,Xi,ue=_(()=>{"use strict";nt();wt();L=class extends Error{constructor(s,n,o,i){super(n);this.code=s;this.statusCode=o;this.details=i;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"}};zt=null,eo=0,Xi=300*1e3});import{z as Zn}from"zod";import{platform as aa}from"os";import{execFile as io}from"child_process";function ca(t){return"error"in t}function lo(t){return new Promise(e=>setTimeout(e,t))}function da(t){return new Promise(e=>{let s=aa();s==="win32"?io("cmd.exe",["/c","start","",t],n=>{n&&console.error("Could not open browser:",n.message),e(!n)}):io(s==="darwin"?"open":"xdg-open",[t],o=>{o&&console.error("Could not open browser:",o.message),e(!o)}),setTimeout(()=>e(!1),5e3)})}async function ao(t,e,s,n){let o=s,i=n.sleep??lo;for(let r=0;r<e;r++){await i(o);let a;try{let d=await n.fetch(`${te()}/auth/poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({device_code:t})});if(!d.ok)continue;a=await d.json()}catch{continue}if(ca(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 l=a.email||a.org_name||a.org_slug;return An({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 ${l}. You are ready to build and deploy.`)}return null}async function ua(t,e=pa){let s=t;if(s?.apiKey)try{let r=await e.fetch(`${te()}/api/org`,{headers:{Authorization:`ApiKey ${s.apiKey}`}});if(!r.ok)return c("Invalid API key. Check the key and try again.",!0);let a=await r.json();return An({apiKey:s.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(s?.deviceCode){let r=await ao(s.deviceCode,6,5e3,e);return r||c(JSON.stringify({status:"pending",deviceCode:s.deviceCode,instruction:"The user hasn't approved yet. Wait ~15 seconds and call mist_setup again with the same deviceCode."}))}let n;try{let r=await e.fetch(`${te()}/auth/device`,{method:"POST",headers:{"Content-Type":"application/json"}});if(!r.ok)return c("Cannot reach Mistflow servers. Check your internet connection.",!0);n=await r.json()}catch{return c("Cannot reach Mistflow servers. Check your internet connection.",!0)}let o=`${n.verification_uri}?code=${n.user_code}`;console.error(`
35
35
  Sign in at: ${o}
36
36
  Your code: ${n.user_code}
37
37
  `);try{await e.openBrowser(o)}catch{}let i=await ao(n.device_code,6,5e3,e);return i||c(JSON.stringify({status:"pending",deviceCode:n.device_code,signInUrl:o,userCode:n.user_code,instruction:"The user hasn't approved yet. Wait ~15 seconds, then call mist_setup again with deviceCode='"+n.device_code+"' to check if they approved."}))}var la,pa,co,po=_(()=>{"use strict";Oe();K();ue();nt();la=Zn.object({apiKey:Zn.string().optional().describe("API key (mist_...) for headless auth. Skips the device code flow entirely. Generate one at app.mistflow.ai/mcp-keys."),deviceCode:Zn.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.")});pa={fetch:globalThis.fetch,openBrowser:da,sleep:lo};co={name:"mist_setup",description:Os,inputSchema:la,handler:t=>ua(t)}});import{existsSync as ma,readFileSync as ha}from"fs";function uo(t){let e=new Set;if(!ma(t))return e;let s=ha(t,"utf-8");for(let n of s.split(`
package/dist/index.js CHANGED
@@ -20,7 +20,7 @@ This is a major update. Run \`${n}\` and restart your editor.${o}
20
20
  Run \`${n}\` to upgrade, then restart your editor.${o}`:`
21
21
 
22
22
  (Mistflow ${s.latest} is out, you have ${e}. Run \`${n}\` when convenient.)`}function vn(){let t=be(),e=ye??{latest:"",minSupported:"",changelogUrl:""},s=Ms(t,e.latest,e.minSupported);return{current:t,latest:e.latest,minSupported:e.minSupported,severity:s,upgradeCmd:"npx -y mistflow-ai install",changelogUrl:e.changelogUrl,backendSignalReceived:ye!==null}}var Ot,ye,js,ft=Qe(()=>{"use strict";Ot=null;ye=null;js=!1});var Sn={};Dt(Sn,{closeBrowser:()=>kn,getIsolatedContext:()=>ti,getPage:()=>xn,getSnapshot:()=>yt,takeScreenshot:()=>bt});async function Ls(){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 ei(){let t=await Ls();return(!we||!we.isConnected())&&(we=await t.chromium.launch({headless:!0})),je&&(await je.close().catch(()=>{}),je=null),je=await we.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),Ie=await je.newPage(),Ie}async function xn(){return Ie&&!Ie.isClosed()?Ie:($t||($t=ei().finally(()=>{$t=null})),$t)}async function kn(){Ie&&!Ie.isClosed()&&await Ie.close().catch(()=>{}),je&&await je.close().catch(()=>{}),we?.isConnected()&&await we.close().catch(()=>{}),Ie=null,je=null,we=null}async function ti(){let t=await Ls();(!we||!we.isConnected())&&(we=await t.chromium.launch({headless:!0}));let e=await we.newContext({viewport:{width:1280,height:720},deviceScaleFactor:1}),s=await e.newPage();return{context:e,page:s}}async function yt(t){return await t.locator("body").ariaSnapshot()}async function bt(t,e=!1){return await t.screenshot({fullPage:e,type:"png"})}var we,je,Ie,$t,Ut=Qe(()=>{"use strict";we=null,je=null,Ie=null,$t=null;process.once("SIGTERM",()=>{kn().finally(()=>process.exit(0))});process.once("SIGINT",()=>{kn().finally(()=>process.exit(0))})});import{readFileSync as qs,existsSync as Pn,writeFileSync as ni,mkdirSync as si,renameSync as oi,unlinkSync as ri}from"fs";import{join as In,dirname as ii}from"path";import{homedir as ai}from"os";import{randomBytes as li}from"crypto";function Bs(){return In(ai(),".mistflow","credentials.json")}function Lt(){return(process.env.MISTFLOW_API_URL||"https://api.mistflow.ai").replace(/\/+$/,"")}function zs(){let t=Bs();if(!Pn(t))return null;try{let e=JSON.parse(qs(t,"utf-8"));return typeof e.apiKey=="string"?{[ci]:e}:e}catch{return null}}function Xe(){let t=process.env.MISTFLOW_API_KEY;if(t)return{ok:!0,creds:{apiKey:t,orgId:"",orgSlug:"env"}};let e=zs();if(!e)return{ok:!1,reason:"missing"};let s=Lt(),n=e[s];return n&&typeof n.apiKey=="string"&&n.apiKey&&typeof n.orgId=="string"?{ok:!0,creds:n}:{ok:!1,reason:"missing"}}function Tn(t){let e=Bs(),s=ii(e);Pn(s)||si(s,{recursive:!0});let n=zs()??{},o=Lt();n[o]=t;let i=In(s,`.credentials.tmp.${li(8).toString("hex")}`);try{ni(i,JSON.stringify(n,null,2)+`
23
- `,{mode:384}),oi(i,e)}catch(r){try{ri(i)}catch{}throw r}}function X(){return Xe().ok}function De(t){let e=In(t,"mistflow.json");if(!Pn(e))return null;try{return JSON.parse(qs(e,"utf-8"))}catch{return null}}var ci,Ze=Qe(()=>{"use strict";ci="https://api.mistflow.ai"});var Ys={};Dt(Ys,{MistflowApiError:()=>U,addDomain:()=>Nn,checkAuth:()=>mi,checkAuthDetailed:()=>Vs,checkSubdomain:()=>Rn,createDeployment:()=>gi,createProject:()=>vt,deleteEnvVar:()=>Un,discoverDecisions:()=>fi,downloadSource:()=>wi,downloadSourceWithToken:()=>Js,fetchDesignDirections:()=>An,fetchModule:()=>Wn,fetchPlanConversation:()=>qt,fetchScaffold:()=>zn,fetchStepContext:()=>Hn,forkTemplate:()=>Vn,generatePlan:()=>En,getAuthHeaders:()=>Ge,getBaseUrl:()=>Z,getDashboardUrl:()=>di,getDbCredentials:()=>yi,getDeployLogs:()=>Ln,getDeploymentStatus:()=>xt,getProject:()=>hi,getProjectErrors:()=>Fn,getSeedInfo:()=>Dn,getSiteUrl:()=>et,getTemplate:()=>Gn,hasCredentialsOnDisk:()=>X,hasLocalCredentials:()=>Gs,listDeployments:()=>nt,listDomains:()=>Oe,listEnvVars:()=>Mn,markLocalSetupDone:()=>vi,modifyPlan:()=>Bt,pingBackend:()=>_n,promotePreview:()=>qn,redeployProject:()=>bi,removeDomain:()=>jn,rollbackDeployment:()=>Bn,shareProject:()=>Jn,uploadAndDeploy:()=>Cn,uploadQAResults:()=>On,upsertEnvVar:()=>$n,verifyDomain:()=>zt});function Z(){return Lt()}function et(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9102")}return"https://mistflow.ai"}function di(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","app.mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9101")}return"https://app.mistflow.ai"}function Ge(){let t=Xe();if(!t.ok)throw new U("auth_missing","No Mistflow credentials found.",401);return pi(t.creds)}function pi(t){return{Authorization:`ApiKey ${t.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":be()}}function tt(t){try{gt(t.headers)}catch{}}async function _n(){try{let t=await fetch(`${Z()}/health`,{method:"GET",signal:AbortSignal.timeout(5e3)});tt(t)}catch{}}async function Ws(t,e,s,n){for(let o=0;o<2;o++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(s)})}catch(i){let r=i instanceof Error&&i.name==="TimeoutError",a=i instanceof TypeError;if(n&&o===0&&(r||a)){console.error(`[api] Retrying ${t} after ${r?"timeout":"network error"}`);continue}throw i}throw new Error("fetchWithRetry: exhausted retries")}async function wt(t){let e=null;try{e=await t.json()}catch{e=null}let s=e&&typeof e.code=="string"?e.code:void 0,n=e&&typeof e.message=="string"?e.message:e&&typeof e.detail=="string"?e.detail:t.statusText||"Request failed";if(s)return new U(s,n,t.status,e?.details);let o=t.status;return o===401?new U("auth_invalid",n,o):o===403?new U("permission_denied",n,o):o===404?new U("not_found",n,o):o===409?new U("conflict",n,o):o===422?new U("validation_error",n,o):o===429?new U("rate_limited",n,o):o>=500?new U("server_error",t.statusText||"Internal server error",o):new U("client_error",n,o)}async function L(t,e={}){let s=Ge(),{timeoutMs:n,idempotent:o,...i}=e,r=n??3e4,a=(i.method??"GET").toUpperCase(),l=o??(a==="GET"||a==="HEAD"),d;try{d=await Ws(`${Z()}${t}`,{...i,headers:{...s,...i.headers}},r,l)}catch(h){throw h instanceof Error&&h.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(tt(d),!d.ok)throw await wt(d);return d.json()}function Gs(){return Xe().ok}async function mi(){return(await Vs()).ok}async function Vs(){if(Ft!==null&&Date.now()<Hs)return Ft?{ok:!0}:{ok:!1,reason:"no_credentials"};if(!Gs())return{ok:!1,reason:"no_credentials"};try{return await L("/api/org"),Ft=!0,Hs=Date.now()+ui,{ok:!0}}catch(t){if(Ft=null,!(t instanceof U))return{ok:!1,reason:"network_error"};switch(t.code){case"auth_missing":case"auth_revoked":return{ok:!1,reason:"no_credentials"};case"auth_expired":case"auth_invalid":case"auth_org_not_found":return{ok:!1,reason:"expired"};case"network_error":return{ok:!1,reason:"network_error"};case"rate_limited":case"server_error":case"upstream_error":return{ok:!1,reason:"server_error"};default:return{ok:!1,reason:"server_error"}}}}async function hi(t){return L(`/api/projects/${encodeURIComponent(t)}`)}async function Rn(t){return L(`/api/projects/check-subdomain?name=${encodeURIComponent(t)}`)}async function vt(t,e,s="neon",n){return L("/api/projects",{method:"POST",body:JSON.stringify({name:t,template:e,db_provider:s,requested_subdomain:n})})}async function gi(t,e){return L("/api/deploy",{method:"POST",body:JSON.stringify({project_id:t,build_output_url:e})})}async function Cn(t,e,s="production",n,o,i,r){let{readFileSync:a}=await import("fs"),{basename:l}=await import("path"),d=Xe();if(!d.ok)throw new U("auth_missing","No Mistflow credentials found.",401);let h=d.creds,m=a(e),p=new Blob([m],{type:"application/gzip"}),y=new FormData;if(y.append("project_id",t),y.append("build",p,l(e)),s!=="production"&&y.append("environment",s),n&&y.append("admin_email",n),o&&y.append("schema_pushed","true"),i){let{existsSync:f}=await import("fs");if(f(i)){let k=a(i),_=new Blob([k],{type:"application/gzip"});y.append("source",_,"source.tar.gz")}}r&&y.append("git_commit_sha",r);let v;try{v=await fetch(`${Z()}/api/deploy/upload`,{method:"POST",headers:{Authorization:`ApiKey ${h.apiKey}`,"X-Mistflow-MCP-Version":be()},body:y,signal:AbortSignal.timeout(3e5)})}catch{throw new U("network_error","Cannot reach Mistflow servers. Check your network.")}if(tt(v),!v.ok)throw await wt(v);let b=await v.json();return{...b,id:b.deployment_id}}async function xt(t){return L(`/api/deploy/${encodeURIComponent(t)}/status`)}async function An(t){return L(`/api/plan/design-directions/${encodeURIComponent(t)}`,{timeoutMs:15e3})}async function qt(t,e){let s=e?.waitSeconds??10,n=s>0?`?wait=${s}`:"",o=Math.min(6e4,(s+5)*1e3);return L(`/api/plan/conversations/${encodeURIComponent(t)}${n}`,{timeoutMs:o})}async function En(t,e){let s={description:t,conversation_id:e?.conversationId,answers:e?.answers};e?.autonomous&&(s.autonomous=!0),e?.language&&e.language.toLowerCase()!=="english"&&(s.language=e.language),e?.designConversationId&&(s.design_conversation_id=e.designConversationId),e?.designDirection&&(s.design_direction=e.designDirection);let n=e?.conversationId||e?.answers||e?.designConversationId?18e4:6e4;return L("/api/plan",{method:"POST",body:JSON.stringify(s),timeoutMs:n,idempotent:!1})}async function Bt(t,e){return L("/api/plan/modify",{method:"POST",body:JSON.stringify({existing_plan:t,modification:e})})}async function fi(t){return L("/api/plan/discover",{method:"POST",body:JSON.stringify({description:t})})}async function Nn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains`,{method:"POST",body:JSON.stringify({domain:e})})}async function Oe(t){return L(`/api/projects/${encodeURIComponent(t)}/domains`)}async function zt(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}/verify`)}async function jn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}`,{method:"DELETE"})}async function yi(t){return L(`/api/projects/${encodeURIComponent(t)}/db-credentials`)}async function Dn(t){try{return await L(`/api/projects/${encodeURIComponent(t)}/test-accounts`)}catch(e){return e instanceof U&&(e.statusCode===404||e.code==="not_found")||console.error("[api] Failed to fetch seed info:",e instanceof Error?e.message:e),null}}async function On(t,e){try{return await L(`/api/deploy/${encodeURIComponent(t)}/qa-results`,{method:"POST",body:JSON.stringify(e)})}catch(s){return console.error("[api] Failed to upload QA results:",s instanceof Error?s.message:s),null}}async function Mn(t){return L(`/api/projects/${encodeURIComponent(t)}/env`)}async function $n(t,e,s,n){return L(`/api/projects/${encodeURIComponent(t)}/env`,{method:"PUT",body:JSON.stringify({key:e,value:s,category:n?.category??"custom",description:n?.description,setup_url:n?.setupUrl})})}async function Un(t,e){return L(`/api/projects/${encodeURIComponent(t)}/env/${encodeURIComponent(e)}`,{method:"DELETE"})}async function Ln(t){return L(`/api/deploy/${encodeURIComponent(t)}/logs`)}async function Fn(t,e="7d"){return L(`/api/projects/${encodeURIComponent(t)}/errors?period=${encodeURIComponent(e)}`)}async function nt(t){return L(`/api/projects/${encodeURIComponent(t)}/deployments`)}async function bi(t){return L(`/api/deploy/${encodeURIComponent(t)}/redeploy`,{method:"POST"})}async function qn(t,e){let s=new URLSearchParams({preview_deployment_id:e});return L(`/api/deploy/${encodeURIComponent(t)}/promote`,{method:"POST",body:s.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"}})}async function Bn(t){return L(`/api/deploy/${encodeURIComponent(t)}/rollback`,{method:"POST"})}async function wi(t,e){let s=Xe();if(!s.ok)throw new U("auth_missing","Not authenticated.",401);let n=s.creds,o=await fetch(`${Z()}/api/deploy/${encodeURIComponent(t)}/source`,{headers:{Authorization:`ApiKey ${n.apiKey}`,"X-Mistflow-MCP-Version":be()},signal:AbortSignal.timeout(12e4)});if(tt(o),!o.ok)throw await wt(o);let{writeFileSync:i}=await import("fs"),r=Buffer.from(await o.arrayBuffer());i(e,r)}async function Ht(t,e){let{timeoutMs:s,idempotent:n,...o}=e??{},i=s??3e4,r=(o.method??"GET").toUpperCase(),a=n??(r==="GET"||r==="HEAD"),l;try{l=await Ws(`${Z()}${t}`,{headers:{"Content-Type":"application/json","X-Mistflow-MCP-Version":be()},...o},i,a)}catch(d){throw d instanceof Error&&d.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(tt(l),!l.ok)throw await wt(l);return l.json()}async function zn(t="nextjs"){return Ht(`/api/scaffold/${encodeURIComponent(t)}`)}async function Hn(t,e){return Ht(`/api/scaffold/${encodeURIComponent(t)}/context?step_type=${encodeURIComponent(e)}`)}async function Wn(t,e,s,n){return Ht(`/api/scaffold/${encodeURIComponent(t)}/module`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"crud",entity:e,fields:s,entity_plural:n})})}async function Gn(t){return Ht(`/api/templates/${encodeURIComponent(t)}`)}async function Vn(t){return L(`/api/templates/${encodeURIComponent(t)}/fork`,{method:"POST"})}async function Js(t,e,s){let n;try{n=await fetch(`${Z()}/api/deploy/${encodeURIComponent(t)}/fork-source?fork_token=${encodeURIComponent(e)}`,{headers:{"X-Mistflow-MCP-Version":be()},signal:AbortSignal.timeout(12e4)})}catch{throw new U("network_error","Cannot reach Mistflow servers. Check your network.")}if(tt(n),!n.ok)throw n.status===401?new U("validation_error","Fork token expired or invalid. Re-open the project in the dashboard to get a fresh token.",n.status):await wt(n);let{writeFileSync:o}=await import("fs"),i=Buffer.from(await n.arrayBuffer());o(s,i)}async function vi(t){await L(`/api/projects/${encodeURIComponent(t)}`,{method:"PATCH",body:JSON.stringify({local_setup_done:!0})})}async function Jn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/share`,{method:"POST",body:JSON.stringify({is_template:e?.isTemplate??!1,template_description:e?.description})})}var U,Ft,Hs,ui,de=Qe(()=>{"use strict";Ze();ft();U=class extends Error{constructor(s,n,o,i){super(n);this.code=s;this.statusCode=o;this.details=i;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"}};Ft=null,Hs=0,ui=300*1e3});var Pt={};Dt(Pt,{emptyState:()=>St,fetchRemoteState:()=>ji,fuzzyMatch:()=>Oi,getLocalStatePath:()=>Kn,readLocalState:()=>Ni,syncRemoteState:()=>Di,writeLocalState:()=>kt});import{existsSync as to,readFileSync as Ci,writeFileSync as Ai,mkdirSync as Ei}from"fs";import{join as no}from"path";function Kn(t){return no(t,".mistflow","state.json")}function Ni(t){let e=Kn(t);if(!to(e))return null;try{return JSON.parse(Ci(e,"utf-8"))}catch{return null}}function kt(t,e){let s=no(t,".mistflow");to(s)||Ei(s,{recursive:!0}),Ai(Kn(t),JSON.stringify(e,null,2)+`
23
+ `,{mode:384}),oi(i,e)}catch(r){try{ri(i)}catch{}throw r}}function X(){return Xe().ok}function De(t){let e=In(t,"mistflow.json");if(!Pn(e))return null;try{return JSON.parse(qs(e,"utf-8"))}catch{return null}}var ci,Ze=Qe(()=>{"use strict";ci="https://api.mistflow.ai"});var Ys={};Dt(Ys,{MistflowApiError:()=>U,addDomain:()=>Nn,checkAuth:()=>mi,checkAuthDetailed:()=>Vs,checkSubdomain:()=>Rn,createDeployment:()=>gi,createProject:()=>vt,deleteEnvVar:()=>Un,discoverDecisions:()=>fi,downloadSource:()=>wi,downloadSourceWithToken:()=>Js,fetchDesignDirections:()=>An,fetchModule:()=>Wn,fetchPlanConversation:()=>qt,fetchScaffold:()=>zn,fetchStepContext:()=>Hn,forkTemplate:()=>Vn,generatePlan:()=>En,getAuthHeaders:()=>Ge,getBaseUrl:()=>Z,getDashboardUrl:()=>di,getDbCredentials:()=>yi,getDeployLogs:()=>Ln,getDeploymentStatus:()=>xt,getProject:()=>hi,getProjectErrors:()=>Fn,getSeedInfo:()=>Dn,getSiteUrl:()=>et,getTemplate:()=>Gn,hasCredentialsOnDisk:()=>X,hasLocalCredentials:()=>Gs,listDeployments:()=>nt,listDomains:()=>Oe,listEnvVars:()=>Mn,markLocalSetupDone:()=>vi,modifyPlan:()=>Bt,pingBackend:()=>_n,promotePreview:()=>qn,redeployProject:()=>bi,removeDomain:()=>jn,rollbackDeployment:()=>Bn,shareProject:()=>Jn,uploadAndDeploy:()=>Cn,uploadQAResults:()=>On,upsertEnvVar:()=>$n,verifyDomain:()=>zt});function Z(){return Lt()}function et(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9102")}return"https://mistflow.ai"}function di(){let t=process.env.MISTFLOW_API_URL;if(t){if(t.includes("mistflow.localhost"))return t.replace("api.mistflow","app.mistflow");if(t.includes("localhost:9100"))return t.replace(":9100",":9101")}return"https://app.mistflow.ai"}function Ge(){let t=Xe();if(!t.ok)throw new U("auth_missing","No Mistflow credentials found.",401);return pi(t.creds)}function pi(t){return{Authorization:`ApiKey ${t.apiKey}`,"Content-Type":"application/json","X-Mistflow-MCP-Version":be()}}function tt(t){try{gt(t.headers)}catch{}}async function _n(){try{let t=await fetch(`${Z()}/health`,{method:"GET",signal:AbortSignal.timeout(5e3)});tt(t)}catch{}}async function Ws(t,e,s,n){for(let o=0;o<2;o++)try{return await fetch(t,{...e,signal:AbortSignal.timeout(s)})}catch(i){let r=i instanceof Error&&i.name==="TimeoutError",a=i instanceof TypeError;if(n&&o===0&&(r||a)){console.error(`[api] Retrying ${t} after ${r?"timeout":"network error"}`);continue}throw i}throw new Error("fetchWithRetry: exhausted retries")}async function wt(t){let e=null;try{e=await t.json()}catch{e=null}let s=e&&typeof e.code=="string"?e.code:void 0,n=e&&typeof e.message=="string"?e.message:e&&typeof e.detail=="string"?e.detail:t.statusText||"Request failed";if(s)return new U(s,n,t.status,e?.details);let o=t.status;return o===401?new U("auth_invalid",n,o):o===403?new U("permission_denied",n,o):o===404?new U("not_found",n,o):o===409?new U("conflict",n,o):o===422?new U("validation_error",n,o):o===429?new U("rate_limited",n,o):o>=500?new U("server_error",t.statusText||"Internal server error",o):new U("client_error",n,o)}async function L(t,e={}){let s=Ge(),{timeoutMs:n,idempotent:o,...i}=e,r=n??3e4,a=(i.method??"GET").toUpperCase(),l=o??(a==="GET"||a==="HEAD"),d;try{d=await Ws(`${Z()}${t}`,{...i,headers:{...s,...i.headers}},r,l)}catch(h){throw h instanceof Error&&h.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(tt(d),!d.ok)throw await wt(d);return d.json()}function Gs(){return Xe().ok}async function mi(){return(await Vs()).ok}async function Vs(){if(Ft!==null&&Date.now()<Hs)return Ft?{ok:!0}:{ok:!1,reason:"no_credentials"};if(!Gs())return{ok:!1,reason:"no_credentials"};try{return await L("/api/org"),Ft=!0,Hs=Date.now()+ui,{ok:!0}}catch(t){if(Ft=null,!(t instanceof U))return{ok:!1,reason:"network_error"};switch(t.code){case"auth_missing":case"auth_revoked":return{ok:!1,reason:"no_credentials"};case"auth_expired":case"auth_invalid":case"auth_org_not_found":return{ok:!1,reason:"expired"};case"network_error":return{ok:!1,reason:"network_error"};case"rate_limited":case"server_error":case"upstream_error":return{ok:!1,reason:"server_error"};default:return{ok:!1,reason:"server_error"}}}}async function hi(t){return L(`/api/projects/${encodeURIComponent(t)}`)}async function Rn(t){return L(`/api/projects/check-subdomain?name=${encodeURIComponent(t)}`)}async function vt(t,e,s="neon",n){return L("/api/projects",{method:"POST",body:JSON.stringify({name:t,template:e,db_provider:s,requested_subdomain:n})})}async function gi(t,e){return L("/api/deploy",{method:"POST",body:JSON.stringify({project_id:t,build_output_url:e})})}async function Cn(t,e,s="production",n,o,i,r){let{readFileSync:a}=await import("fs"),{basename:l}=await import("path"),d=Xe();if(!d.ok)throw new U("auth_missing","No Mistflow credentials found.",401);let h=d.creds,m=a(e),p=new Blob([m],{type:"application/gzip"}),y=new FormData;if(y.append("project_id",t),y.append("build",p,l(e)),s!=="production"&&y.append("environment",s),n&&y.append("admin_email",n),o&&y.append("schema_pushed","true"),i){let{existsSync:f}=await import("fs");if(f(i)){let k=a(i),_=new Blob([k],{type:"application/gzip"});y.append("source",_,"source.tar.gz")}}r&&y.append("git_commit_sha",r);let v;try{v=await fetch(`${Z()}/api/deploy/upload`,{method:"POST",headers:{Authorization:`ApiKey ${h.apiKey}`,"X-Mistflow-MCP-Version":be()},body:y,signal:AbortSignal.timeout(3e5)})}catch{throw new U("network_error","Cannot reach Mistflow servers. Check your network.")}if(tt(v),!v.ok)throw await wt(v);let b=await v.json();return{...b,id:b.deployment_id}}async function xt(t){return L(`/api/deploy/${encodeURIComponent(t)}/status`)}async function An(t){return L(`/api/plan/design-directions/${encodeURIComponent(t)}`,{timeoutMs:15e3})}async function qt(t,e){let s=e?.waitSeconds??20,n=s>0?`?wait=${s}`:"",o=Math.min(6e4,(s+5)*1e3);return L(`/api/plan/conversations/${encodeURIComponent(t)}${n}`,{timeoutMs:o})}async function En(t,e){let s={description:t,conversation_id:e?.conversationId,answers:e?.answers};e?.autonomous&&(s.autonomous=!0),e?.language&&e.language.toLowerCase()!=="english"&&(s.language=e.language),e?.designConversationId&&(s.design_conversation_id=e.designConversationId),e?.designDirection&&(s.design_direction=e.designDirection);let n=e?.conversationId||e?.answers||e?.designConversationId?18e4:6e4;return L("/api/plan",{method:"POST",body:JSON.stringify(s),timeoutMs:n,idempotent:!1})}async function Bt(t,e){return L("/api/plan/modify",{method:"POST",body:JSON.stringify({existing_plan:t,modification:e})})}async function fi(t){return L("/api/plan/discover",{method:"POST",body:JSON.stringify({description:t})})}async function Nn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains`,{method:"POST",body:JSON.stringify({domain:e})})}async function Oe(t){return L(`/api/projects/${encodeURIComponent(t)}/domains`)}async function zt(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}/verify`)}async function jn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/domains/${encodeURIComponent(e)}`,{method:"DELETE"})}async function yi(t){return L(`/api/projects/${encodeURIComponent(t)}/db-credentials`)}async function Dn(t){try{return await L(`/api/projects/${encodeURIComponent(t)}/test-accounts`)}catch(e){return e instanceof U&&(e.statusCode===404||e.code==="not_found")||console.error("[api] Failed to fetch seed info:",e instanceof Error?e.message:e),null}}async function On(t,e){try{return await L(`/api/deploy/${encodeURIComponent(t)}/qa-results`,{method:"POST",body:JSON.stringify(e)})}catch(s){return console.error("[api] Failed to upload QA results:",s instanceof Error?s.message:s),null}}async function Mn(t){return L(`/api/projects/${encodeURIComponent(t)}/env`)}async function $n(t,e,s,n){return L(`/api/projects/${encodeURIComponent(t)}/env`,{method:"PUT",body:JSON.stringify({key:e,value:s,category:n?.category??"custom",description:n?.description,setup_url:n?.setupUrl})})}async function Un(t,e){return L(`/api/projects/${encodeURIComponent(t)}/env/${encodeURIComponent(e)}`,{method:"DELETE"})}async function Ln(t){return L(`/api/deploy/${encodeURIComponent(t)}/logs`)}async function Fn(t,e="7d"){return L(`/api/projects/${encodeURIComponent(t)}/errors?period=${encodeURIComponent(e)}`)}async function nt(t){return L(`/api/projects/${encodeURIComponent(t)}/deployments`)}async function bi(t){return L(`/api/deploy/${encodeURIComponent(t)}/redeploy`,{method:"POST"})}async function qn(t,e){let s=new URLSearchParams({preview_deployment_id:e});return L(`/api/deploy/${encodeURIComponent(t)}/promote`,{method:"POST",body:s.toString(),headers:{"Content-Type":"application/x-www-form-urlencoded"}})}async function Bn(t){return L(`/api/deploy/${encodeURIComponent(t)}/rollback`,{method:"POST"})}async function wi(t,e){let s=Xe();if(!s.ok)throw new U("auth_missing","Not authenticated.",401);let n=s.creds,o=await fetch(`${Z()}/api/deploy/${encodeURIComponent(t)}/source`,{headers:{Authorization:`ApiKey ${n.apiKey}`,"X-Mistflow-MCP-Version":be()},signal:AbortSignal.timeout(12e4)});if(tt(o),!o.ok)throw await wt(o);let{writeFileSync:i}=await import("fs"),r=Buffer.from(await o.arrayBuffer());i(e,r)}async function Ht(t,e){let{timeoutMs:s,idempotent:n,...o}=e??{},i=s??3e4,r=(o.method??"GET").toUpperCase(),a=n??(r==="GET"||r==="HEAD"),l;try{l=await Ws(`${Z()}${t}`,{headers:{"Content-Type":"application/json","X-Mistflow-MCP-Version":be()},...o},i,a)}catch(d){throw d instanceof Error&&d.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(tt(l),!l.ok)throw await wt(l);return l.json()}async function zn(t="nextjs"){return Ht(`/api/scaffold/${encodeURIComponent(t)}`)}async function Hn(t,e){return Ht(`/api/scaffold/${encodeURIComponent(t)}/context?step_type=${encodeURIComponent(e)}`)}async function Wn(t,e,s,n){return Ht(`/api/scaffold/${encodeURIComponent(t)}/module`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({type:"crud",entity:e,fields:s,entity_plural:n})})}async function Gn(t){return Ht(`/api/templates/${encodeURIComponent(t)}`)}async function Vn(t){return L(`/api/templates/${encodeURIComponent(t)}/fork`,{method:"POST"})}async function Js(t,e,s){let n;try{n=await fetch(`${Z()}/api/deploy/${encodeURIComponent(t)}/fork-source?fork_token=${encodeURIComponent(e)}`,{headers:{"X-Mistflow-MCP-Version":be()},signal:AbortSignal.timeout(12e4)})}catch{throw new U("network_error","Cannot reach Mistflow servers. Check your network.")}if(tt(n),!n.ok)throw n.status===401?new U("validation_error","Fork token expired or invalid. Re-open the project in the dashboard to get a fresh token.",n.status):await wt(n);let{writeFileSync:o}=await import("fs"),i=Buffer.from(await n.arrayBuffer());o(s,i)}async function vi(t){await L(`/api/projects/${encodeURIComponent(t)}`,{method:"PATCH",body:JSON.stringify({local_setup_done:!0})})}async function Jn(t,e){return L(`/api/projects/${encodeURIComponent(t)}/share`,{method:"POST",body:JSON.stringify({is_template:e?.isTemplate??!1,template_description:e?.description})})}var U,Ft,Hs,ui,de=Qe(()=>{"use strict";Ze();ft();U=class extends Error{constructor(s,n,o,i){super(n);this.code=s;this.statusCode=o;this.details=i;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"}};Ft=null,Hs=0,ui=300*1e3});var Pt={};Dt(Pt,{emptyState:()=>St,fetchRemoteState:()=>ji,fuzzyMatch:()=>Oi,getLocalStatePath:()=>Kn,readLocalState:()=>Ni,syncRemoteState:()=>Di,writeLocalState:()=>kt});import{existsSync as to,readFileSync as Ci,writeFileSync as Ai,mkdirSync as Ei}from"fs";import{join as no}from"path";function Kn(t){return no(t,".mistflow","state.json")}function Ni(t){let e=Kn(t);if(!to(e))return null;try{return JSON.parse(Ci(e,"utf-8"))}catch{return null}}function kt(t,e){let s=no(t,".mistflow");to(s)||Ei(s,{recursive:!0}),Ai(Kn(t),JSON.stringify(e,null,2)+`
24
24
  `)}function St(t,e){return{projectId:t,name:e,template:"",features:[],dbSchema:[],deployCount:0,decisions:[],provenance:[]}}async function ji(t){let e;try{e=Ge()}catch{return null}try{let s=await fetch(`${Z()}/api/projects/${encodeURIComponent(t)}/state`,{headers:{...e,"Content-Type":"application/json","X-Mistflow-MCP-Version":be()}});try{gt(s.headers)}catch{}return s.ok?await s.json():null}catch{return null}}async function Di(t,e){let s;try{s=Ge()}catch{return!1}try{let n=await fetch(`${Z()}/api/projects/${encodeURIComponent(t)}/state`,{method:"PUT",headers:{...s,"Content-Type":"application/json","X-Mistflow-MCP-Version":be()},body:JSON.stringify(e)});try{gt(n.headers)}catch{}return n.ok}catch{return!1}}function Oi(t,e){let s=t.toLowerCase(),n=e.toLowerCase();return n.includes(s)||s.includes(n)?!0:s.split(/\s+/).some(i=>i.length>=3&&n.includes(i))}var Ve=Qe(()=>{"use strict";de();ft()});var Qn={};Dt(Qn,{ensureBackendRegistered:()=>Bi,ensureShadcnComponents:()=>zi});import{existsSync as oo,readFileSync as Mi,writeFileSync as $i}from"fs";import{join as Wt}from"path";import{spawn as Ui}from"child_process";function Li(t,e,s,n,o){return new Promise(i=>{let r=Ui(t,e,{cwd:s,stdio:["pipe","pipe","pipe"],timeout:n,...o?{env:{...process.env,...o}}:{}}),a="",l="";r.stdout?.on("data",d=>{a+=d.toString()}),r.stderr?.on("data",d=>{l+=d.toString()}),r.on("close",d=>i({success:d===0,stdout:a,stderr:l})),r.on("error",d=>i({success:!1,stdout:a,stderr:l+d.message}))})}function Fi(t){let e=Wt(t,"mistflow.json");if(!oo(e))return null;try{return JSON.parse(Mi(e,"utf-8"))}catch{return null}}function qi(t,e){$i(Wt(t,"mistflow.json"),JSON.stringify(e,null,2))}async function so(t,e){try{let s=e.features,n=e.steps,o={plan:e};Array.isArray(s)&&s.length>0&&(o.features=s.map(i=>i.name)),Array.isArray(n)&&n.length>0&&(o.provenance=n.map(i=>({feature:i.name??i.title??`Step ${i.number??"?"}`,user_intent:(i.description??"").slice(0,500),decisions:"Seeded from plan",tradeoffs:"",files_affected:[]}))),await fetch(`${Z()}/api/projects/${encodeURIComponent(t)}/state`,{method:"PUT",headers:{...Ge(),"Content-Type":"application/json"},body:JSON.stringify(o)})}catch(s){console.error("[self-heal] state sync failed:",s instanceof Error?s.message:String(s))}}async function Bi(t,e={}){let s=Fi(t);if(s){if(!X())return s.projectId;if(!s.projectId)try{let o=s.plan?.requestedSubdomain,i=await vt(s.name,void 0,s.dbProvider??"neon",o);return s.projectId=i.id,qi(t,s),kt(t,St(i.id,s.name)),s.plan&&await so(i.id,s.plan),console.error(`[self-heal] registered project ${i.id.slice(0,8)} with backend`),i.id}catch(n){console.error("[self-heal] createProject failed:",n instanceof Error?n.message:String(n));return}return e.forceSync&&s.plan&&s.projectId&&await so(s.projectId,s.plan),s.projectId}}async function zi(t,e){let s=["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"],n=e&&e.length>0?e:s,o=Wt(t,"components","ui"),i=[],r=[];for(let d of n)oo(Wt(o,`${d}.tsx`))?i.push(d):r.push(d);if(r.length===0)return{installed:[],alreadyPresent:i};let a={NPM_CONFIG_LEGACY_PEER_DEPS:"true"},l=await Li("npx",["--yes","shadcn@latest","add","-y","-o",...r],t,18e4,a);return l.success?{installed:r,alreadyPresent:i}:{installed:[],alreadyPresent:i,failed:`shadcn add failed for: ${r.join(", ")}. ${l.stderr.slice(-300)}`.trim()}}var Xn=Qe(()=>{"use strict";de();Ve()});import{Server as Mc}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as $c}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as Uc,ListToolsRequestSchema as Lc}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as Fc}from"zod-to-json-schema";var Ur="mist_plan uses the fire-and-poll shape: the first call returns quickly with status 'running' and a conversationId while the backend Sonnet ask_questions call runs in the background (that call alone can take 30-150s). Poll by calling mist_plan with just { conversationId } every ~10-15s until status is 'clarify' (questions arrived) or 'ready' (plan generated). Do NOT re-send description or answers while polling \u2014 the conversation is already tracked server-side.",Lr='Treat the tool\'s returned JSON as authoritative. If `mist_plan` returns `status: "clarify"`, the planning call completed and is waiting on user answers. Do NOT rerun the same call or describe it as "still generating". Only poll again when `status: "design_clarify_pending"`.',Fr="When submitting discovery answers back to `mist_plan` (conversationId + answers), prefer an array payload: `answers: [{question, decisionKey, answer}, ...]`. Do NOT collapse into a `{decisionKey: answer}` map \u2014 multiple discovery questions can share the same decision key.",qr="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.",Br='Once the user approves the plan, the mist_init \u2192 mist_install \u2192 mist_implement (repeat) \u2192 mist_build \u2192 mist_deploy \u2192 mist_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." A tool returns a status that requires user input when it genuinely needs one (e.g. confirm_new_project, awaiting promotion). Otherwise chain calls continuously. Brief one-line status updates are fine; permission requests are not.',zr="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.",Hr="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.",Wr='Long-running tools (mist_plan, mist_install, mist_build, mist_qa, mist_deploy) use the fire-and-poll pattern. The first call returns `status: "running"` with a `jobId` or `conversationId`. Every subsequent call with that same id returns the current state \u2014 re-call IMMEDIATELY whenever you see `status: "running"`. DO NOT run `bash sleep`, `setTimeout`, or any wall-clock wait between polls \u2014 Claude Code\'s harness blocks standalone sleeps, and every MCP server poll endpoint holds the connection up to ~10-15s on its side already, returning as soon as state changes. Just call the tool again. Each response is well inside the 60s MCP ceiling. When `status: "complete"` or `"failed"` arrives, the tool is done. Never assume a job stalled because a single call took 10s \u2014 calls return fast, but the work keeps running in the background. Do not ask the user whether to keep polling; polling is how these tools work.',Gr="When `mist_plan` returns a `questions[]` array (or `directions[]` for design picking), you MUST render every question via your native structured-question UI \u2014 `AskUserQuestion` in Claude Code, quick pick in Cursor, equivalent in other hosts \u2014 and wait for the user to actually answer. Do NOT pick the `recommended` option on their behalf. Do NOT print the questions as a markdown list with a 'say the word if you want to change any' fallback. Do NOT proceed without real answers even if you are inside `/loop`, an autonomous agent run, a scheduled wake-up, or any other non-interactive mode \u2014 if the user isn't available, stop and wait; the flow resumes when they respond. Every question is a product decision the user is paying to make, and `recommended` is a hint for them, not a permission slip for you. Each question has `id`/`decisionKey`/`question`/`options[]` (each option: `label`, `description`) plus an optional `recommended` string. Collect the user's actual selections, then submit them back via `mist_plan` with the `conversationId` \u2014 don't ask the user to do that step.",Is="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).",Ts="Read or inspect Mistflow project state. 'get' (default) loads plan progress, env vars, and deploy info \u2014 call before editing. 'update' marks plan steps complete or adds env vars. 'share' creates a forkable template URL. 'landing-designs' / 'integrations' browse curated catalogs (pass presetId / integrationId for full details). 'errors' fetches runtime errors from the deployed app. 'logs' fetches deploy logs. 'deployments' lists history. 'version' reports the installed MCP version + any upgrade available.",_s="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.",Rs="Returns the full Mistflow MCP tool reference. Call ONCE at session start (or whenever unsure which tool to pick) to learn the 14-tool surface, the fire-and-poll pattern, and how to chain end-to-end from mist_plan through mist_qa. Static \u2014 no backend round-trip, safe to call frequently.",Cs="Analyze build errors from a Next.js / TypeScript project. Extracts structured errors with file, line, a human-readable message for the user, and an actionable suggestion. Call with { projectPath } to run `npm run build` and parse the failure; call with { buildOutput } to parse output captured elsewhere (e.g. from a failed mist_build job).",As="Generate a grayscale wireframe sketch of the planned app so the user can review layout + information hierarchy before any code is written. The server returns a structured spec + a wireframePrompt \u2014 the host AI writes the HTML file to .mistflow/mockups/mockup-<planId>.html and opens it. Pass { planId } for the first iteration, { planId, feedback: '...' } to iterate, { planId, approved: true } to lock the design before mist_init. Iterative by design \u2014 expect 1-3 rounds of feedback.";function Es(){let t=[];return t.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."),t.push(""),t.push('Every capability is an MCP tool. There is no companion CLI. Long-running work (install, build, qa, deploy) uses the fire-and-poll pattern: the first call returns a jobId and `status: "running"`; subsequent calls with that jobId return fresh state. Each call responds in under a second \u2014 no 60s timeout risk.'),t.push(""),t.push(Wr),t.push(""),t.push(Ur),t.push(""),t.push(Lr),t.push(""),t.push(Fr),t.push(""),t.push(qr),t.push(""),t.push(Gr),t.push(""),t.push(zr),t.push(""),t.push("New app workflow:"),t.push("1. Choose destination: if the user didn't already give a path, ask whether to scaffold in the current folder or a new subfolder here. Resolve the absolute path before mist_init."),t.push('2. Plan: call mist_plan with the user\'s description EXACTLY as written \u2014 do NOT expand or add features. When the response has `status: "clarify"` with `questions[]`, render them via AskUserQuestion, collect the answers, and submit them back in the next mist_plan call with the `conversationId`. When `status: "design_clarify_pending"`, poll until directions are ready, present them to the user, submit the pick.'),t.push("3. Mockup (optional, recommended): call mist_mockup with the planId \u2014 returns a wireframe prompt. Write the HTML to the returned path, open it for the user, wait for approval. Iterate with { feedback }, lock with { approved: true }."),t.push("4. Scaffold: mist_init with { planId, path }. Transactional \u2014 if it fails before the final move, stop."),t.push("5. Install: mist_install { projectPath } starts; poll with { jobId } until complete. Typical 30\u201390s."),t.push("6. Implement: mist_implement runs one plan step at a time and auto-marks the prior step complete. Call repeatedly until all steps are done."),t.push("7. Build: mist_build { projectPath } starts; poll with { jobId }. On failure, the response has `missingModules[]` \u2014 chain mist_install with those modules then mist_build again without asking."),t.push("8. Deploy: mist_deploy { projectPath } starts tar + upload; poll with { action: 'status', deploymentId }. On complete, response has `qaRequired: true` and a `url` \u2014 do NOT surface the URL to the user until mist_qa passes. Subsequent actions: 'promote' (staging \u2192 prod), 'rollback' (revert to a specific deploymentId)."),t.push("9. QA: mist_qa { projectPath } drives Playwright in-process against the live URL \u2014 single synchronous call (~20\u201345s), returns pass/fail and screenshots inline. Only surface the deploy URL to the user after mist_qa returns status: 'pass'."),t.push(""),t.push(Br),t.push(""),t.push(Hr),t.push(""),t.push("Updating an existing Mistflow app:"),t.push("- Cosmetic or single-file changes: edit files directly, then mist_build \u2192 mist_deploy."),t.push("- New page or feature (no new data model): mist_project action='get' for context, build it, then mist_build \u2192 mist_deploy."),t.push("- Feature needing new data model: ask product questions, call mist_project action='get' for context, call mist_plan with existingPlanId, then mist_implement, then mist_build \u2192 mist_deploy."),t.push("- Integration addition: ask product questions, mist_project action='get', mist_plan with existingPlanId, mist_implement, mist_config resource='env' for keys, mist_build \u2192 mist_deploy \u2192 mist_qa."),t.push("- Bug fix: mist_debug to extract structured errors, fix the code, mist_build \u2192 mist_deploy."),t.push(""),t.push("Tool summary:"),t.push("- mist_setup: authentication. Only call when the 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."),t.push("- mist_project: read/write project state (actions: 'get' / 'update'). Call 'get' before editing any existing Mistflow project to understand its shape."),t.push("- mist_browser: navigate, interact with, and screenshot the app during preview or after deploy. Returns screenshots inline in tool results."),t.push("- mist_help: returns the full tool reference. Call once per session."),t.push("- mist_plan / mist_mockup / mist_init / mist_implement / mist_debug / mist_config: core app-building workflow tools (see step-by-step above)."),t.push("- mist_install / mist_build / mist_deploy: fire-and-poll tools. Always check `status` in the response and keep polling while 'running'."),t.push("- mist_qa: synchronous single call. Drives Playwright in-process against the deployed URL. No jobId / no polling \u2014 one call returns the full QA result with screenshots."),t.join(`
25
25
  `)}ft();function c(t,e=!1){let s=t;try{let n=Us();n&&(s=t+n)}catch{}return{content:[{type:"text",text:s}],isError:e}}function Te(t){return c(`This is not a Mistflow project (no mistflow.json found at ${t}).
26
26
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mistflow-ai/mcp",
3
- "version": "1.0.5",
3
+ "version": "1.0.6",
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",