@mistflow-ai/mcp 1.0.1 → 1.0.2
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 +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -3389,7 +3389,7 @@ child.on('error', (err) => {
|
|
|
3389
3389
|
process.exit(1);
|
|
3390
3390
|
});
|
|
3391
3391
|
`});import{z as To}from"zod";import{resolve as Bc}from"path";import{existsSync as zc}from"fs";import{join as Hc}from"path";var Wc,Qr,Xr=x(()=>{"use strict";W();dn();Wc=To.object({projectPath:To.string().optional().describe("Absolute path to the project. Required for the first call (to start the install)."),jobId:To.string().optional().describe("Job ID returned from a previous call. Present means poll; absent means start.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start an install, or jobId to poll an existing one."}),Qr={name:"mist_install",description:"Install a Mistflow project's npm dependencies with the fire-and-poll pattern. First call with { projectPath } starts the install and returns a jobId. Subsequent calls with { jobId } poll for progress (status: 'running' | 'complete' | 'failed'). Re-call while status is 'running' \u2014 each response is <1s so there is no 60s timeout risk.",inputSchema:Wc,handler:async t=>{let e=t;if(e.jobId){let i=await at(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"Still running. Call mist_install with the same jobId in ~15-30s to check progress."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"Dependencies installed. Run mist_implement next to start executing plan steps."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"npm install failed. Read the logTail for the error and fix it \u2014 usually a missing native dep or a version conflict. After fixing, start a new install with { projectPath }."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No install job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=Bc(e.projectPath);if(!zc(Hc(o,"package.json")))return c(`No package.json at ${o}. Confirm the path and that mist_init has scaffolded the project.`,!0);let a=`npm install && (${`npx --yes shadcn@latest add -y -o ${["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"].join(" ")}`} || echo 'shadcn add failed \u2014 implement will retry lazily')`,r=await it({type:"install",cmd:"sh",args:["-c",a],cwd:o,env:{NPM_CONFIG_LEGACY_PEER_DEPS:"true"}});return c(JSON.stringify({status:"running",jobId:r.id,startedAt:r.startedAt,cwd:o,nextAction:"Install started in the background (npm install + shadcn components). Call mist_install again with { jobId: '"+r.id+"' } in ~15-30s to check progress. Typical duration: 30-90s."}))}}});import{z as un}from"zod";import{resolve as Gc,join as lt}from"path";import{existsSync as ct,readFileSync as Zr}from"fs";function Jc(t){let e=lt(pn(),t,"stdout.log"),o=lt(pn(),t,"stderr.log"),n="";try{ct(e)&&(n+=Zr(e,"utf-8"))}catch{}try{ct(o)&&(n+=`
|
|
3392
|
-
`+Zr(o,"utf-8"))}catch{}return n}function Kc(t){let e=/Module not found:\s*(?:Error:\s*)?Can't resolve ['"]([^'"]+)['"]/g,o=new Set;for(let n of t.matchAll(e)){let s=n[1];if(s.startsWith(".")||s.startsWith("@/")||s.startsWith("~/"))continue;let a=s.startsWith("@")?s.split("/").slice(0,2).join("/"):s.split("/")[0];a&&o.add(a)}return[...o]}var Vc,ei,ti=x(()=>{"use strict";W();dn();io();Vc=un.object({projectPath:un.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:un.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),script:un.string().optional().describe("Optional override: run `npm run <script>` instead of the Cloudflare adapter. Default behavior is `npx @opennextjs/cloudflare build` when open-next.config.ts exists, else `npm run build`. Ignored on poll calls.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a build, or jobId to poll an existing one."});ei={name:"mist_build",description:"Run a Mistflow project's production build with the fire-and-poll pattern. First call with { projectPath } starts `npm run build` and returns a jobId. Subsequent calls with { jobId } poll status. On failure, the response surfaces structured errors (from parseBuildErrors) and any missingModules[] \u2014 chain into mist_install with those modules, then mist_build again, without asking the user.",inputSchema:Vc,handler:async t=>{let e=t;if(e.jobId){let l=await at(e.jobId);if(!l)return c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No build job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0);if(l.status==="running"||l.status==="starting")return c(JSON.stringify({status:"running",jobId:l.id,elapsed:l.elapsed,logTail:l.logTail,nextAction:"Build still running. Call mist_build again with the same jobId in ~20-40s."}));if(l.status==="complete")return c(JSON.stringify({status:"complete",jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,nextAction:"Build passed. Run mist_deploy next to ship \u2014 do NOT ask the user to confirm, the build is the approval gate."}));let p=Jc(l.id),m=Zt(p),u=Kc(p),d=u.length>0?`Build failed with missing modules: ${u.join(", ")}. Call mist_install with these packages (or chain mist_install { projectPath } to reinstall all), then call mist_build again. Do NOT ask the user.`:m.length>0?"Build failed with structured errors (see errors[]). Fix the code, then call mist_build again.":"Build failed. Read the logTail for the error, or call mist_debug with the failed jobId to extract structured errors.";return c(JSON.stringify({status:l.status,jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,errors:m,missingModules:u,logTail:l.logTail,nextAction:d}),!0)}let o=Gc(e.projectPath);if(!ct(lt(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!ct(lt(o,"node_modules")))return c(`node_modules not installed. Run mist_install { projectPath: '${o}' } first.`,!0);let n,s,a,r=ct(lt(o,"open-next.config.ts"))||ct(lt(o,"open-next.config.js"));e.script?(n="npm",s=["run",e.script],a=e.script):r?(n="npx",s=["-y","@opennextjs/cloudflare","build"],a="@opennextjs/cloudflare build"):(n="npm",s=["run","build"],a="build");let i=await it({type:"build",cmd:n,args:s,cwd:o});return c(JSON.stringify({status:"running",jobId:i.id,startedAt:i.startedAt,cwd:o,script:a,nextAction:`Build started. Call mist_build again with { jobId: '${i.id}' } in ~30s to check progress. Typical duration: 30-90s on a fresh scaffold (Cloudflare adapter), 10-30s on subsequent builds.`}))}}});import{z as Nt}from"zod";import{resolve as Yc,join as Ro}from"path";import{existsSync as Ao}from"fs";var Qc,ni,oi=x(()=>{"use strict";W();dn();Qc=Nt.object({projectPath:Nt.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:Nt.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),baseUrl:Nt.string().optional().describe("Override the URL Playwright tests hit \u2014 defaults to the project's configured base URL."),grep:Nt.string().optional().describe("Pass-through to `playwright test -g`. Useful for running a single scenario.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a QA run, or jobId to poll an existing one."}),ni={name:"mist_qa",description:"Run a Mistflow project's Playwright QA suite with the fire-and-poll pattern. First call with { projectPath, baseUrl? } starts the run and returns a jobId. Subsequent calls with { jobId } poll status. Call AFTER mist_deploy \u2014 the QA suite targets the deployed URL. Do NOT show the deploy URL to the user until mist_qa reports status: 'complete' with exitCode 0.",inputSchema:Qc,handler:async t=>{let e=t;if(e.jobId){let i=await at(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"QA still running. Call mist_qa again with the same jobId in ~15-30s."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"QA passed. Surface the deploy URL to the user now \u2014 the app is verified."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"QA failed. Read the logTail for which scenarios broke. Do NOT show the deploy URL to the user. Fix the code, redeploy (mist_deploy), then re-run mist_qa."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No QA job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=Yc(e.projectPath);if(!Ao(Ro(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!(Ao(Ro(o,"playwright.config.ts"))||Ao(Ro(o,"playwright.config.js"))))return c(`No playwright.config.ts at ${o}. Mistflow projects scaffold with Playwright; if missing, run mist_implement to regenerate or add one manually.`,!0);let s=["playwright","test"];e.grep&&s.push("-g",e.grep);let a={};e.baseUrl&&(a.BASE_URL=e.baseUrl);let r=await it({type:"qa",cmd:"npx",args:s,cwd:o,env:a});return c(JSON.stringify({status:"running",jobId:r.id,startedAt:r.startedAt,cwd:o,baseUrl:e.baseUrl??"(from project config)",nextAction:`QA started. Call mist_qa again with { jobId: '${r.id}' } in ~20s. Typical duration: 30-120s depending on scenario count.`}))}}});import{existsSync as mn,readdirSync as Xc,statSync as si,unlinkSync as ri}from"fs";import{join as We}from"path";import{execFile as Zc}from"child_process";function ep(t,e){let o=0;for(let n of e){let s=We(t,n);if(mn(s))try{let a=si(s);if(a.isFile())o++;else if(a.isDirectory()){let r=[s];for(;r.length;){let i=r.pop(),l=Xc(i,{withFileTypes:!0});for(let p of l){let m=We(i,p.name);p.isDirectory()?r.push(m):o++}}}}catch{}}return o}function ii(t,e,o){return new Promise(n=>{Zc("tar",t,{cwd:e,timeout:o,maxBuffer:10*1024*1024},(s,a,r)=>{n({success:!s,stderr:r?.toString()??""})})})}async function ai(t){let e=We(t,".open-next-build.tar.gz"),o=[".open-next"];mn(We(t,"db"))&&o.push("db"),mn(We(t,"drizzle.config.ts"))&&o.push("drizzle.config.ts"),mn(We(t,"package.json"))&&o.push("package.json");let n=ep(t,o),s=await ii(["-czf",e,"-C",t,...o],t,12e4);if(!s.success){try{ri(e)}catch{}throw new Error("Failed to create build archive. Check disk space and permissions."+(s.stderr?`
|
|
3392
|
+
`+Zr(o,"utf-8"))}catch{}return n}function Kc(t){let e=/Module not found:\s*(?:Error:\s*)?Can't resolve ['"]([^'"]+)['"]/g,o=new Set;for(let n of t.matchAll(e)){let s=n[1];if(s.startsWith(".")||s.startsWith("@/")||s.startsWith("~/"))continue;let a=s.startsWith("@")?s.split("/").slice(0,2).join("/"):s.split("/")[0];a&&o.add(a)}return[...o]}var Vc,ei,ti=x(()=>{"use strict";W();dn();io();Vc=un.object({projectPath:un.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:un.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),script:un.string().optional().describe("Optional override: run `npm run <script>` instead of the Cloudflare adapter. Default behavior is `npx @opennextjs/cloudflare build` when open-next.config.ts exists, else `npm run build`. Ignored on poll calls.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a build, or jobId to poll an existing one."});ei={name:"mist_build",description:"Run a Mistflow project's production build with the fire-and-poll pattern. First call with { projectPath } starts `npm run build` and returns a jobId. Subsequent calls with { jobId } poll status. On failure, the response surfaces structured errors (from parseBuildErrors) and any missingModules[] \u2014 chain into mist_install with those modules, then mist_build again, without asking the user.",inputSchema:Vc,handler:async t=>{let e=t;if(e.jobId){let l=await at(e.jobId);if(!l)return c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No build job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0);if(l.status==="running"||l.status==="starting")return c(JSON.stringify({status:"running",jobId:l.id,elapsed:l.elapsed,logTail:l.logTail,nextAction:"Build still running. Call mist_build again with the same jobId in ~20-40s."}));if(l.status==="complete")return c(JSON.stringify({status:"complete",jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,nextAction:"Build passed. Run mist_deploy next to ship \u2014 do NOT ask the user to confirm, the build is the approval gate."}));let p=Jc(l.id),m=Zt(p),u=Kc(p),d=u.length>0?`Build failed with missing modules: ${u.join(", ")}. Call mist_install with these packages (or chain mist_install { projectPath } to reinstall all), then call mist_build again. Do NOT ask the user.`:m.length>0?"Build failed with structured errors (see errors[]). Fix the code, then call mist_build again.":"Build failed. Read the logTail for the error, or call mist_debug with the failed jobId to extract structured errors.";return c(JSON.stringify({status:l.status,jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,errors:m,missingModules:u,logTail:l.logTail,nextAction:d}),!0)}let o=Gc(e.projectPath);if(!ct(lt(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!ct(lt(o,"node_modules")))return c(`node_modules not installed. Run mist_install { projectPath: '${o}' } first.`,!0);let n,s,a,r=ct(lt(o,"open-next.config.ts"))||ct(lt(o,"open-next.config.js"));e.script?(n="npm",s=["run",e.script],a=e.script):r?(n="npx",s=["-y","@opennextjs/cloudflare","build"],a="@opennextjs/cloudflare build"):(n="npm",s=["run","build"],a="build");let i=await it({type:"build",cmd:n,args:s,cwd:o});return c(JSON.stringify({status:"running",jobId:i.id,startedAt:i.startedAt,cwd:o,script:a,nextAction:`Build started. Call mist_build again with { jobId: '${i.id}' } in ~30s to check progress. Typical duration: 30-90s on a fresh scaffold (Cloudflare adapter), 10-30s on subsequent builds.`}))}}});import{z as Nt}from"zod";import{resolve as Yc,join as Ro}from"path";import{existsSync as Ao}from"fs";var Qc,ni,oi=x(()=>{"use strict";W();dn();Qc=Nt.object({projectPath:Nt.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:Nt.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),baseUrl:Nt.string().optional().describe("Override the URL Playwright tests hit \u2014 defaults to the project's configured base URL."),grep:Nt.string().optional().describe("Pass-through to `playwright test -g`. Useful for running a single scenario.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a QA run, or jobId to poll an existing one."}),ni={name:"mist_qa",description:"Run a Mistflow project's Playwright QA suite with the fire-and-poll pattern. First call with { projectPath, baseUrl? } starts the run and returns a jobId. Subsequent calls with { jobId } poll status. Call AFTER mist_deploy \u2014 the QA suite targets the deployed URL. Do NOT show the deploy URL to the user until mist_qa reports status: 'complete' with exitCode 0.",inputSchema:Qc,handler:async t=>{let e=t;if(e.jobId){let i=await at(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"QA still running. Call mist_qa again with the same jobId in ~15-30s."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"QA passed. Surface the deploy URL to the user now \u2014 the app is verified."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"QA failed. Read the logTail for which scenarios broke. Do NOT show the deploy URL to the user. Fix the code, redeploy (mist_deploy), then re-run mist_qa."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No QA job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=Yc(e.projectPath);if(!Ao(Ro(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!(Ao(Ro(o,"playwright.config.ts"))||Ao(Ro(o,"playwright.config.js"))))return c(`No playwright.config.ts at ${o}. Mistflow projects scaffold with Playwright; if missing, run mist_implement to regenerate or add one manually.`,!0);let s=["playwright","test"];e.grep&&s.push("-g",e.grep);let a={};e.baseUrl&&(a.BASE_URL=e.baseUrl);let r=await it({type:"qa",cmd:"npx",args:s,cwd:o,env:a});return c(JSON.stringify({status:"running",jobId:r.id,startedAt:r.startedAt,cwd:o,baseUrl:e.baseUrl??"(from project config)",nextAction:`QA started. Call mist_qa again with { jobId: '${r.id}' } in ~20s. Typical duration: 30-120s depending on scenario count.`}))}}});import{existsSync as mn,readdirSync as Xc,statSync as si,unlinkSync as ri}from"fs";import{join as We}from"path";import{execFile as Zc}from"child_process";function ep(t,e){let o=0;for(let n of e){let s=We(t,n);if(mn(s))try{let a=si(s);if(a.isFile())o++;else if(a.isDirectory()){let r=[s];for(;r.length;){let i=r.pop(),l=Xc(i,{withFileTypes:!0});for(let p of l){let m=We(i,p.name);p.isDirectory()?r.push(m):o++}}}}catch{}}return o}function ii(t,e,o){return new Promise(n=>{Zc("tar",t,{cwd:e,timeout:o,maxBuffer:10*1024*1024,env:{...process.env,COPYFILE_DISABLE:"1"}},(s,a,r)=>{n({success:!s,stderr:r?.toString()??""})})})}async function ai(t){let e=We(t,".open-next-build.tar.gz"),o=[".open-next"];mn(We(t,"db"))&&o.push("db"),mn(We(t,"drizzle.config.ts"))&&o.push("drizzle.config.ts"),mn(We(t,"package.json"))&&o.push("package.json");let n=ep(t,o),s=await ii(["-czf",e,"-C",t,...o],t,12e4);if(!s.success){try{ri(e)}catch{}throw new Error("Failed to create build archive. Check disk space and permissions."+(s.stderr?`
|
|
3393
3393
|
${s.stderr.slice(-500)}`:""))}let a=0;try{a=si(e).size}catch{}return{path:e,sizeBytes:a,fileCount:n}}async function li(t){let e=We(t,".mistflow-source.tar.gz");return(await ii(["-czf",e,"-C",t,"--exclude",".open-next","--exclude","node_modules","--exclude",".git","--exclude",".next","--exclude",".open-next-build.tar.gz","--exclude",".mistflow-source.tar.gz","."],t,12e4)).success?e:null}function Co(t){if(t)try{ri(t)}catch{}}function ci(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(1)}MB`}function pi(t){switch(t){case"pending":return"Provisioning...";case"building":return"Building your app...";case"deploying":return"Deploying to Mistflow Cloud...";case"verifying":return"Verifying deployment...";case"live":return"Live!";case"failed":return"Failed";default:return`Status: ${t}`}}var di=x(()=>{"use strict"});import{z as pt}from"zod";import{resolve as tp,join as np}from"path";import{existsSync as op}from"fs";function rp(t){return op(np(t,".open-next"))}function ip(t){return Ae(t)?.deploy?.strategy==="staging"?"preview":null}async function ap(t){let e=tp(t.projectPath);if(!J())return c("Not signed in. Call mist_setup first.",!0);let n=Ae(e)?.projectId;if(!n)return c(`No projectId in mistflow.json at ${e}. Run mist_init first.`,!0);if(!rp(e))return c(`No .open-next build output at ${e}. Run mist_build first \u2014 the deploy tool ships the build artifact, not the raw source.`,!0);let s=t.environment??ip(e)??"production",a=null,r=null;try{a=await ai(e),r=await li(e);let i=await Cn(n,a.path,s,t.adminEmail,void 0,r??void 0,void 0);return c(JSON.stringify({status:"running",jobId:i.deployment_id,deploymentId:i.deployment_id,environment:i.environment??s,buildSize:ci(a.sizeBytes),buildFileCount:a.fileCount,nextAction:`Upload complete. Call mist_deploy { action: 'status', deploymentId: '${i.deployment_id}' } in ~5-10s to poll deployment progress. Do NOT surface the URL to the user until mist_qa passes.`}))}catch(i){let l=i instanceof C||i instanceof Error?i.message:String(i);return c(`Deploy upload failed: ${l}`,!0)}finally{Co(a?.path),Co(r)}}async function lp(t){try{let e=await xt(t),o=pi(e.status);return e.status==="live"?c(JSON.stringify({status:"complete",jobId:e.id,deploymentId:e.id,url:e.url,completedAt:e.completedAt,qaRequired:!0,nextAction:`Deployment is live. Call mist_qa { projectPath, baseUrl: '${e.url??""}' } next. Do NOT show the URL to the user until mist_qa returns status: 'complete'.`})):e.status==="failed"?c(JSON.stringify({status:"failed",jobId:e.id,deploymentId:e.id,error:e.error,phase:o,nextAction:"Deployment failed. Read the error message, fix the code, then call mist_deploy { action: 'deploy', projectPath } again."}),!0):c(JSON.stringify({status:"running",jobId:e.id,deploymentId:e.id,phase:o,phaseCode:e.status,nextAction:`Still ${e.status}. Call mist_deploy { action: 'status', deploymentId: '${e.id}' } again in ~5-10s.`}))}catch(e){let o=e instanceof C||e instanceof Error?e.message:String(e);return c(`Could not fetch deploy status: ${o}`,!0)}}async function cp(t,e){if(!J())return c("Not signed in. Call mist_setup first.",!0);let n=Ae(t)?.projectId;if(!n)return c(`No projectId in mistflow.json at ${t}. Run mist_init first.`,!0);let s=e;if(!s)try{let r=(await Qe(n)).find(i=>i.environment==="preview"&&i.status==="live");if(!r)return c("No live preview deployment to promote. Deploy to preview first with { action: 'deploy', environment: 'preview' }.",!0);s=r.id}catch(a){let r=a instanceof C?a.message:String(a);return c(`Could not list deployments: ${r}`,!0)}try{let a=await Fn(n,s);return c(JSON.stringify({status:"running",jobId:a.deployment_id,deploymentId:a.deployment_id,promotedFrom:s,nextAction:`Promote started. Call mist_deploy { action: 'status', deploymentId: '${a.deployment_id}' } to poll. Promotion re-uses the preview artifact so it typically completes in ~10s.`}))}catch(a){let r=a instanceof C||a instanceof Error?a.message:String(a);return c(`Promote failed: ${r}`,!0)}}async function pp(t){if(!J())return c("Not signed in. Call mist_setup first.",!0);try{let e=await qn(t);return c(JSON.stringify({status:"running",jobId:e.deployment_id,deploymentId:e.deployment_id,rollbackFrom:e.rollback_from,nextAction:`Rollback started. Call mist_deploy { action: 'status', deploymentId: '${e.deployment_id}' } to poll.`}))}catch(e){let o=e instanceof C||e instanceof Error?e.message:String(e);return c(`Rollback failed: ${o}`,!0)}}var sp,ui,mi=x(()=>{"use strict";W();le();Je();di();sp=pt.object({action:pt.enum(["deploy","promote","rollback","status"]).default("deploy").describe("'deploy' (default) tars + uploads + starts a deployment. 'promote' promotes a staging preview to production. 'rollback' rolls back to a specific deployment. 'status' polls an in-flight deployment by id."),projectPath:pt.string().optional().describe("Absolute path to the project. Required for 'deploy' and 'promote'."),deploymentId:pt.string().optional().describe("Deployment id \u2014 required for 'rollback' and 'status'; the preview id for 'promote'."),environment:pt.enum(["production","preview"]).optional().describe("Deploy target. Defaults to 'production'; auto-redirects to 'preview' when the project uses staging mode."),adminEmail:pt.string().optional().describe("Admin email injected as BETTER_AUTH_ADMIN_EMAIL on first deploy of an auth-enabled project.")});ui={name:"mist_deploy",description:"Deploy a Mistflow project. action='deploy' (default) tars + uploads + starts backend orchestration; action='status' polls an in-flight deployment; action='promote' ships a staging preview to prod; action='rollback' reverts to a previous deployment. Fire-and-poll: deploy/promote/rollback return a jobId immediately; poll with { action: 'status', deploymentId }. Do NOT show the deploy URL to the user until mist_qa passes \u2014 qaRequired=true is returned on completion.",inputSchema:sp,handler:async t=>{let e=t;switch(e.action??"deploy"){case"deploy":return e.projectPath?ap({projectPath:e.projectPath,environment:e.environment,adminEmail:e.adminEmail}):c("projectPath is required for action='deploy'.",!0);case"status":return e.deploymentId?lp(e.deploymentId):c("deploymentId is required for action='status'.",!0);case"promote":return e.projectPath?cp(e.projectPath,e.deploymentId):c("projectPath is required for action='promote'.",!0);case"rollback":return e.deploymentId?pp(e.deploymentId):c("deploymentId is required for action='rollback'.",!0)}}}});var yp={};import{Server as dp}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as up}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as mp,ListToolsRequestSchema as hp}from"@modelcontextprotocol/sdk/types.js";import{zodToJsonSchema as gp}from"zod-to-json-schema";async function fp(){let t=process.argv.indexOf("--api-url");t!==-1&&process.argv[t+1]&&(process.env.MISTFLOW_API_URL=process.argv[t+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let e=new up;await hn.connect(e),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}var hn,hi,gi=x(()=>{"use strict";Te();W();ls();_s();Rs();Ns();ro();Bs();tr();pr();jr();Lr();Xr();ti();oi();mi();hn=new dp({name:"mistflow",version:"1.0.0"},{capabilities:{tools:{}},instructions:$o()}),hi=[as,Is,Ts,Es,er,cr,Ls,Nr,qs,$r,Qr,ei,ni,ui];hn.setRequestHandler(hp,async()=>({tools:hi.map(t=>({name:t.name,description:t.description,inputSchema:gp(t.inputSchema)}))}));hn.setRequestHandler(mp,async t=>{let e=hi.find(o=>o.name===t.params.name);if(!e)return c(`Unknown tool: ${t.params.name}`,!0);try{let o=e.inputSchema.safeParse(t.params.arguments);if(!o.success){let a=o.error.issues.map(r=>`${r.path.join(".")}: ${r.message}`).join(", ");return c(`Invalid input: ${a}`,!0)}let n=t.params._meta?.progressToken,s={server:hn,progressToken:n};try{return await e.handler(o.data,s)}finally{s.cleanup?.()}}catch(o){let n=o instanceof Error?o.message:"An unexpected error occurred";return console.error("Tool error:",o),c(n,!0)}});fp().catch(t=>{console.error("Fatal error:",t),process.exit(1)})});import{readFileSync as bp}from"fs";import{dirname as wp,join as vp}from"path";import{fileURLToPath as xp}from"url";var Oe=process.argv[2];if(Oe==="--version"||Oe==="-v"){try{let t=wp(xp(import.meta.url)),e=vp(t,"..","package.json"),o=JSON.parse(bp(e,"utf-8"));console.log(o.version)}catch{console.log("unknown")}process.exit(0)}(Oe==="--help"||Oe==="-h")&&(console.log(`@mistflow-ai/mcp \u2014 Mistflow MCP server
|
|
3394
3394
|
|
|
3395
3395
|
Usage:
|
package/dist/index.js
CHANGED
|
@@ -3388,5 +3388,5 @@ child.on('error', (err) => {
|
|
|
3388
3388
|
`).slice(-e).map(a=>`[out] ${a}`)),n.trim()&&r.push(...n.split(`
|
|
3389
3389
|
`).slice(-e).map(a=>`[err] ${a}`)),r.filter(a=>a.trim().length>0).join(`
|
|
3390
3390
|
`)}async function rt(t){let e=Ql(t);if(!e)return null;let o=e;return(e.status==="running"||e.status==="starting")&&!Zl(e)&&(o={...e,status:"unknown_exit",endedAt:e.endedAt??new Date().toISOString()}),{...o,elapsed:ec(o.startedAt,o.endedAt),logTail:tc(t)}}var sc=yo.object({projectPath:yo.string().optional().describe("Absolute path to the project. Required for the first call (to start the install)."),jobId:yo.string().optional().describe("Job ID returned from a previous call. Present means poll; absent means start.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start an install, or jobId to poll an existing one."}),ys={name:"mist_install",description:"Install a Mistflow project's npm dependencies with the fire-and-poll pattern. First call with { projectPath } starts the install and returns a jobId. Subsequent calls with { jobId } poll for progress (status: 'running' | 'complete' | 'failed'). Re-call while status is 'running' \u2014 each response is <1s so there is no 60s timeout risk.",inputSchema:sc,handler:async t=>{let e=t;if(e.jobId){let i=await rt(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"Still running. Call mist_install with the same jobId in ~15-30s to check progress."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"Dependencies installed. Run mist_implement next to start executing plan steps."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"npm install failed. Read the logTail for the error and fix it \u2014 usually a missing native dep or a version conflict. After fixing, start a new install with { projectPath }."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No install job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=nc(e.projectPath);if(!oc(rc(o,"package.json")))return c(`No package.json at ${o}. Confirm the path and that mist_init has scaffolded the project.`,!0);let a=`npm install && (${`npx --yes shadcn@latest add -y -o ${["button","card","input","label","form","dialog","table","dropdown-menu","badge","separator","skeleton","sheet","tabs","avatar","select","textarea","checkbox","switch","tooltip","popover","sonner"].join(" ")}`} || echo 'shadcn add failed \u2014 implement will retry lazily')`,s=await ot({type:"install",cmd:"sh",args:["-c",a],cwd:o,env:{NPM_CONFIG_LEGACY_PEER_DEPS:"true"}});return c(JSON.stringify({status:"running",jobId:s.id,startedAt:s.startedAt,cwd:o,nextAction:"Install started in the background (npm install + shadcn components). Call mist_install again with { jobId: '"+s.id+"' } in ~15-30s to check progress. Typical duration: 30-90s."}))}};import{z as an}from"zod";import{resolve as ic,join as st}from"path";import{existsSync as it,readFileSync as bs}from"fs";var ac=an.object({projectPath:an.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:an.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),script:an.string().optional().describe("Optional override: run `npm run <script>` instead of the Cloudflare adapter. Default behavior is `npx @opennextjs/cloudflare build` when open-next.config.ts exists, else `npm run build`. Ignored on poll calls.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a build, or jobId to poll an existing one."});function lc(t){let e=st(sn(),t,"stdout.log"),o=st(sn(),t,"stderr.log"),n="";try{it(e)&&(n+=bs(e,"utf-8"))}catch{}try{it(o)&&(n+=`
|
|
3391
|
-
`+bs(o,"utf-8"))}catch{}return n}function cc(t){let e=/Module not found:\s*(?:Error:\s*)?Can't resolve ['"]([^'"]+)['"]/g,o=new Set;for(let n of t.matchAll(e)){let r=n[1];if(r.startsWith(".")||r.startsWith("@/")||r.startsWith("~/"))continue;let a=r.startsWith("@")?r.split("/").slice(0,2).join("/"):r.split("/")[0];a&&o.add(a)}return[...o]}var ws={name:"mist_build",description:"Run a Mistflow project's production build with the fire-and-poll pattern. First call with { projectPath } starts `npm run build` and returns a jobId. Subsequent calls with { jobId } poll status. On failure, the response surfaces structured errors (from parseBuildErrors) and any missingModules[] \u2014 chain into mist_install with those modules, then mist_build again, without asking the user.",inputSchema:ac,handler:async t=>{let e=t;if(e.jobId){let l=await rt(e.jobId);if(!l)return c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No build job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0);if(l.status==="running"||l.status==="starting")return c(JSON.stringify({status:"running",jobId:l.id,elapsed:l.elapsed,logTail:l.logTail,nextAction:"Build still running. Call mist_build again with the same jobId in ~20-40s."}));if(l.status==="complete")return c(JSON.stringify({status:"complete",jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,nextAction:"Build passed. Run mist_deploy next to ship \u2014 do NOT ask the user to confirm, the build is the approval gate."}));let p=lc(l.id),m=Kt(p),u=cc(p),d=u.length>0?`Build failed with missing modules: ${u.join(", ")}. Call mist_install with these packages (or chain mist_install { projectPath } to reinstall all), then call mist_build again. Do NOT ask the user.`:m.length>0?"Build failed with structured errors (see errors[]). Fix the code, then call mist_build again.":"Build failed. Read the logTail for the error, or call mist_debug with the failed jobId to extract structured errors.";return c(JSON.stringify({status:l.status,jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,errors:m,missingModules:u,logTail:l.logTail,nextAction:d}),!0)}let o=ic(e.projectPath);if(!it(st(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!it(st(o,"node_modules")))return c(`node_modules not installed. Run mist_install { projectPath: '${o}' } first.`,!0);let n,r,a,s=it(st(o,"open-next.config.ts"))||it(st(o,"open-next.config.js"));e.script?(n="npm",r=["run",e.script],a=e.script):s?(n="npx",r=["-y","@opennextjs/cloudflare","build"],a="@opennextjs/cloudflare build"):(n="npm",r=["run","build"],a="build");let i=await ot({type:"build",cmd:n,args:r,cwd:o});return c(JSON.stringify({status:"running",jobId:i.id,startedAt:i.startedAt,cwd:o,script:a,nextAction:`Build started. Call mist_build again with { jobId: '${i.id}' } in ~30s to check progress. Typical duration: 30-90s on a fresh scaffold (Cloudflare adapter), 10-30s on subsequent builds.`}))}};import{z as At}from"zod";import{resolve as pc,join as bo}from"path";import{existsSync as wo}from"fs";var dc=At.object({projectPath:At.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:At.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),baseUrl:At.string().optional().describe("Override the URL Playwright tests hit \u2014 defaults to the project's configured base URL."),grep:At.string().optional().describe("Pass-through to `playwright test -g`. Useful for running a single scenario.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a QA run, or jobId to poll an existing one."}),vs={name:"mist_qa",description:"Run a Mistflow project's Playwright QA suite with the fire-and-poll pattern. First call with { projectPath, baseUrl? } starts the run and returns a jobId. Subsequent calls with { jobId } poll status. Call AFTER mist_deploy \u2014 the QA suite targets the deployed URL. Do NOT show the deploy URL to the user until mist_qa reports status: 'complete' with exitCode 0.",inputSchema:dc,handler:async t=>{let e=t;if(e.jobId){let i=await rt(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"QA still running. Call mist_qa again with the same jobId in ~15-30s."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"QA passed. Surface the deploy URL to the user now \u2014 the app is verified."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"QA failed. Read the logTail for which scenarios broke. Do NOT show the deploy URL to the user. Fix the code, redeploy (mist_deploy), then re-run mist_qa."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No QA job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=pc(e.projectPath);if(!wo(bo(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!(wo(bo(o,"playwright.config.ts"))||wo(bo(o,"playwright.config.js"))))return c(`No playwright.config.ts at ${o}. Mistflow projects scaffold with Playwright; if missing, run mist_implement to regenerate or add one manually.`,!0);let r=["playwright","test"];e.grep&&r.push("-g",e.grep);let a={};e.baseUrl&&(a.BASE_URL=e.baseUrl);let s=await ot({type:"qa",cmd:"npx",args:r,cwd:o,env:a});return c(JSON.stringify({status:"running",jobId:s.id,startedAt:s.startedAt,cwd:o,baseUrl:e.baseUrl??"(from project config)",nextAction:`QA started. Call mist_qa again with { jobId: '${s.id}' } in ~20s. Typical duration: 30-120s depending on scenario count.`}))}};import{z as at}from"zod";import{resolve as gc,join as fc}from"path";import{existsSync as yc}from"fs";ie();We();import{existsSync as ln,readdirSync as uc,statSync as xs,unlinkSync as ks}from"fs";import{join as qe}from"path";import{execFile as mc}from"child_process";function hc(t,e){let o=0;for(let n of e){let r=qe(t,n);if(ln(r))try{let a=xs(r);if(a.isFile())o++;else if(a.isDirectory()){let s=[r];for(;s.length;){let i=s.pop(),l=uc(i,{withFileTypes:!0});for(let p of l){let m=qe(i,p.name);p.isDirectory()?s.push(m):o++}}}}catch{}}return o}function Ss(t,e,o){return new Promise(n=>{mc("tar",t,{cwd:e,timeout:o,maxBuffer:10*1024*1024},(r,a,s)=>{n({success:!r,stderr:s?.toString()??""})})})}async function Ps(t){let e=qe(t,".open-next-build.tar.gz"),o=[".open-next"];ln(qe(t,"db"))&&o.push("db"),ln(qe(t,"drizzle.config.ts"))&&o.push("drizzle.config.ts"),ln(qe(t,"package.json"))&&o.push("package.json");let n=hc(t,o),r=await Ss(["-czf",e,"-C",t,...o],t,12e4);if(!r.success){try{ks(e)}catch{}throw new Error("Failed to create build archive. Check disk space and permissions."+(r.stderr?`
|
|
3391
|
+
`+bs(o,"utf-8"))}catch{}return n}function cc(t){let e=/Module not found:\s*(?:Error:\s*)?Can't resolve ['"]([^'"]+)['"]/g,o=new Set;for(let n of t.matchAll(e)){let r=n[1];if(r.startsWith(".")||r.startsWith("@/")||r.startsWith("~/"))continue;let a=r.startsWith("@")?r.split("/").slice(0,2).join("/"):r.split("/")[0];a&&o.add(a)}return[...o]}var ws={name:"mist_build",description:"Run a Mistflow project's production build with the fire-and-poll pattern. First call with { projectPath } starts `npm run build` and returns a jobId. Subsequent calls with { jobId } poll status. On failure, the response surfaces structured errors (from parseBuildErrors) and any missingModules[] \u2014 chain into mist_install with those modules, then mist_build again, without asking the user.",inputSchema:ac,handler:async t=>{let e=t;if(e.jobId){let l=await rt(e.jobId);if(!l)return c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No build job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0);if(l.status==="running"||l.status==="starting")return c(JSON.stringify({status:"running",jobId:l.id,elapsed:l.elapsed,logTail:l.logTail,nextAction:"Build still running. Call mist_build again with the same jobId in ~20-40s."}));if(l.status==="complete")return c(JSON.stringify({status:"complete",jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,nextAction:"Build passed. Run mist_deploy next to ship \u2014 do NOT ask the user to confirm, the build is the approval gate."}));let p=lc(l.id),m=Kt(p),u=cc(p),d=u.length>0?`Build failed with missing modules: ${u.join(", ")}. Call mist_install with these packages (or chain mist_install { projectPath } to reinstall all), then call mist_build again. Do NOT ask the user.`:m.length>0?"Build failed with structured errors (see errors[]). Fix the code, then call mist_build again.":"Build failed. Read the logTail for the error, or call mist_debug with the failed jobId to extract structured errors.";return c(JSON.stringify({status:l.status,jobId:l.id,elapsed:l.elapsed,exitCode:l.exitCode,errors:m,missingModules:u,logTail:l.logTail,nextAction:d}),!0)}let o=ic(e.projectPath);if(!it(st(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!it(st(o,"node_modules")))return c(`node_modules not installed. Run mist_install { projectPath: '${o}' } first.`,!0);let n,r,a,s=it(st(o,"open-next.config.ts"))||it(st(o,"open-next.config.js"));e.script?(n="npm",r=["run",e.script],a=e.script):s?(n="npx",r=["-y","@opennextjs/cloudflare","build"],a="@opennextjs/cloudflare build"):(n="npm",r=["run","build"],a="build");let i=await ot({type:"build",cmd:n,args:r,cwd:o});return c(JSON.stringify({status:"running",jobId:i.id,startedAt:i.startedAt,cwd:o,script:a,nextAction:`Build started. Call mist_build again with { jobId: '${i.id}' } in ~30s to check progress. Typical duration: 30-90s on a fresh scaffold (Cloudflare adapter), 10-30s on subsequent builds.`}))}};import{z as At}from"zod";import{resolve as pc,join as bo}from"path";import{existsSync as wo}from"fs";var dc=At.object({projectPath:At.string().optional().describe("Absolute path to the project. Required for the first call."),jobId:At.string().optional().describe("Job ID from a previous call. Present means poll; absent means start."),baseUrl:At.string().optional().describe("Override the URL Playwright tests hit \u2014 defaults to the project's configured base URL."),grep:At.string().optional().describe("Pass-through to `playwright test -g`. Useful for running a single scenario.")}).refine(t=>!!t.projectPath||!!t.jobId,{message:"Pass projectPath to start a QA run, or jobId to poll an existing one."}),vs={name:"mist_qa",description:"Run a Mistflow project's Playwright QA suite with the fire-and-poll pattern. First call with { projectPath, baseUrl? } starts the run and returns a jobId. Subsequent calls with { jobId } poll status. Call AFTER mist_deploy \u2014 the QA suite targets the deployed URL. Do NOT show the deploy URL to the user until mist_qa reports status: 'complete' with exitCode 0.",inputSchema:dc,handler:async t=>{let e=t;if(e.jobId){let i=await rt(e.jobId);return i?i.status==="running"||i.status==="starting"?c(JSON.stringify({status:"running",jobId:i.id,elapsed:i.elapsed,logTail:i.logTail,nextAction:"QA still running. Call mist_qa again with the same jobId in ~15-30s."})):i.status==="complete"?c(JSON.stringify({status:"complete",jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,nextAction:"QA passed. Surface the deploy URL to the user now \u2014 the app is verified."})):c(JSON.stringify({status:i.status,jobId:i.id,elapsed:i.elapsed,exitCode:i.exitCode,logTail:i.logTail,nextAction:"QA failed. Read the logTail for which scenarios broke. Do NOT show the deploy URL to the user. Fix the code, redeploy (mist_deploy), then re-run mist_qa."}),!0):c(JSON.stringify({status:"not_found",jobId:e.jobId,message:`No QA job found for jobId '${e.jobId}'. Start a new one with { projectPath }.`}),!0)}let o=pc(e.projectPath);if(!wo(bo(o,"package.json")))return c(`No package.json at ${o}. Run mist_init first.`,!0);if(!(wo(bo(o,"playwright.config.ts"))||wo(bo(o,"playwright.config.js"))))return c(`No playwright.config.ts at ${o}. Mistflow projects scaffold with Playwright; if missing, run mist_implement to regenerate or add one manually.`,!0);let r=["playwright","test"];e.grep&&r.push("-g",e.grep);let a={};e.baseUrl&&(a.BASE_URL=e.baseUrl);let s=await ot({type:"qa",cmd:"npx",args:r,cwd:o,env:a});return c(JSON.stringify({status:"running",jobId:s.id,startedAt:s.startedAt,cwd:o,baseUrl:e.baseUrl??"(from project config)",nextAction:`QA started. Call mist_qa again with { jobId: '${s.id}' } in ~20s. Typical duration: 30-120s depending on scenario count.`}))}};import{z as at}from"zod";import{resolve as gc,join as fc}from"path";import{existsSync as yc}from"fs";ie();We();import{existsSync as ln,readdirSync as uc,statSync as xs,unlinkSync as ks}from"fs";import{join as qe}from"path";import{execFile as mc}from"child_process";function hc(t,e){let o=0;for(let n of e){let r=qe(t,n);if(ln(r))try{let a=xs(r);if(a.isFile())o++;else if(a.isDirectory()){let s=[r];for(;s.length;){let i=s.pop(),l=uc(i,{withFileTypes:!0});for(let p of l){let m=qe(i,p.name);p.isDirectory()?s.push(m):o++}}}}catch{}}return o}function Ss(t,e,o){return new Promise(n=>{mc("tar",t,{cwd:e,timeout:o,maxBuffer:10*1024*1024,env:{...process.env,COPYFILE_DISABLE:"1"}},(r,a,s)=>{n({success:!r,stderr:s?.toString()??""})})})}async function Ps(t){let e=qe(t,".open-next-build.tar.gz"),o=[".open-next"];ln(qe(t,"db"))&&o.push("db"),ln(qe(t,"drizzle.config.ts"))&&o.push("drizzle.config.ts"),ln(qe(t,"package.json"))&&o.push("package.json");let n=hc(t,o),r=await Ss(["-czf",e,"-C",t,...o],t,12e4);if(!r.success){try{ks(e)}catch{}throw new Error("Failed to create build archive. Check disk space and permissions."+(r.stderr?`
|
|
3392
3392
|
${r.stderr.slice(-500)}`:""))}let a=0;try{a=xs(e).size}catch{}return{path:e,sizeBytes:a,fileCount:n}}async function Is(t){let e=qe(t,".mistflow-source.tar.gz");return(await Ss(["-czf",e,"-C",t,"--exclude",".open-next","--exclude","node_modules","--exclude",".git","--exclude",".next","--exclude",".open-next-build.tar.gz","--exclude",".mistflow-source.tar.gz","."],t,12e4)).success?e:null}function vo(t){if(t)try{ks(t)}catch{}}function _s(t){return t<1024?`${t}B`:t<1024*1024?`${(t/1024).toFixed(1)}KB`:`${(t/(1024*1024)).toFixed(1)}MB`}function Ts(t){switch(t){case"pending":return"Provisioning...";case"building":return"Building your app...";case"deploying":return"Deploying to Mistflow Cloud...";case"verifying":return"Verifying deployment...";case"live":return"Live!";case"failed":return"Failed";default:return`Status: ${t}`}}var bc=at.object({action:at.enum(["deploy","promote","rollback","status"]).default("deploy").describe("'deploy' (default) tars + uploads + starts a deployment. 'promote' promotes a staging preview to production. 'rollback' rolls back to a specific deployment. 'status' polls an in-flight deployment by id."),projectPath:at.string().optional().describe("Absolute path to the project. Required for 'deploy' and 'promote'."),deploymentId:at.string().optional().describe("Deployment id \u2014 required for 'rollback' and 'status'; the preview id for 'promote'."),environment:at.enum(["production","preview"]).optional().describe("Deploy target. Defaults to 'production'; auto-redirects to 'preview' when the project uses staging mode."),adminEmail:at.string().optional().describe("Admin email injected as BETTER_AUTH_ADMIN_EMAIL on first deploy of an auth-enabled project.")});function wc(t){return yc(fc(t,".open-next"))}function vc(t){return _e(t)?.deploy?.strategy==="staging"?"preview":null}async function xc(t){let e=gc(t.projectPath);if(!G())return c("Not signed in. Call mist_setup first.",!0);let n=_e(e)?.projectId;if(!n)return c(`No projectId in mistflow.json at ${e}. Run mist_init first.`,!0);if(!wc(e))return c(`No .open-next build output at ${e}. Run mist_build first \u2014 the deploy tool ships the build artifact, not the raw source.`,!0);let r=t.environment??vc(e)??"production",a=null,s=null;try{a=await Ps(e),s=await Is(e);let i=await In(n,a.path,r,t.adminEmail,void 0,s??void 0,void 0);return c(JSON.stringify({status:"running",jobId:i.deployment_id,deploymentId:i.deployment_id,environment:i.environment??r,buildSize:_s(a.sizeBytes),buildFileCount:a.fileCount,nextAction:`Upload complete. Call mist_deploy { action: 'status', deploymentId: '${i.deployment_id}' } in ~5-10s to poll deployment progress. Do NOT surface the URL to the user until mist_qa passes.`}))}catch(i){let l=i instanceof A||i instanceof Error?i.message:String(i);return c(`Deploy upload failed: ${l}`,!0)}finally{vo(a?.path),vo(s)}}async function kc(t){try{let e=await bt(t),o=Ts(e.status);return e.status==="live"?c(JSON.stringify({status:"complete",jobId:e.id,deploymentId:e.id,url:e.url,completedAt:e.completedAt,qaRequired:!0,nextAction:`Deployment is live. Call mist_qa { projectPath, baseUrl: '${e.url??""}' } next. Do NOT show the URL to the user until mist_qa returns status: 'complete'.`})):e.status==="failed"?c(JSON.stringify({status:"failed",jobId:e.id,deploymentId:e.id,error:e.error,phase:o,nextAction:"Deployment failed. Read the error message, fix the code, then call mist_deploy { action: 'deploy', projectPath } again."}),!0):c(JSON.stringify({status:"running",jobId:e.id,deploymentId:e.id,phase:o,phaseCode:e.status,nextAction:`Still ${e.status}. Call mist_deploy { action: 'status', deploymentId: '${e.id}' } again in ~5-10s.`}))}catch(e){let o=e instanceof A||e instanceof Error?e.message:String(e);return c(`Could not fetch deploy status: ${o}`,!0)}}async function Sc(t,e){if(!G())return c("Not signed in. Call mist_setup first.",!0);let n=_e(t)?.projectId;if(!n)return c(`No projectId in mistflow.json at ${t}. Run mist_init first.`,!0);let r=e;if(!r)try{let s=(await Je(n)).find(i=>i.environment==="preview"&&i.status==="live");if(!s)return c("No live preview deployment to promote. Deploy to preview first with { action: 'deploy', environment: 'preview' }.",!0);r=s.id}catch(a){let s=a instanceof A?a.message:String(a);return c(`Could not list deployments: ${s}`,!0)}try{let a=await On(n,r);return c(JSON.stringify({status:"running",jobId:a.deployment_id,deploymentId:a.deployment_id,promotedFrom:r,nextAction:`Promote started. Call mist_deploy { action: 'status', deploymentId: '${a.deployment_id}' } to poll. Promotion re-uses the preview artifact so it typically completes in ~10s.`}))}catch(a){let s=a instanceof A||a instanceof Error?a.message:String(a);return c(`Promote failed: ${s}`,!0)}}async function Pc(t){if(!G())return c("Not signed in. Call mist_setup first.",!0);try{let e=await Mn(t);return c(JSON.stringify({status:"running",jobId:e.deployment_id,deploymentId:e.deployment_id,rollbackFrom:e.rollback_from,nextAction:`Rollback started. Call mist_deploy { action: 'status', deploymentId: '${e.deployment_id}' } to poll.`}))}catch(e){let o=e instanceof A||e instanceof Error?e.message:String(e);return c(`Rollback failed: ${o}`,!0)}}var Rs={name:"mist_deploy",description:"Deploy a Mistflow project. action='deploy' (default) tars + uploads + starts backend orchestration; action='status' polls an in-flight deployment; action='promote' ships a staging preview to prod; action='rollback' reverts to a previous deployment. Fire-and-poll: deploy/promote/rollback return a jobId immediately; poll with { action: 'status', deploymentId }. Do NOT show the deploy URL to the user until mist_qa passes \u2014 qaRequired=true is returned on completion.",inputSchema:bc,handler:async t=>{let e=t;switch(e.action??"deploy"){case"deploy":return e.projectPath?xc({projectPath:e.projectPath,environment:e.environment,adminEmail:e.adminEmail}):c("projectPath is required for action='deploy'.",!0);case"status":return e.deploymentId?kc(e.deploymentId):c("deploymentId is required for action='status'.",!0);case"promote":return e.projectPath?Sc(e.projectPath,e.deploymentId):c("projectPath is required for action='promote'.",!0);case"rollback":return e.deploymentId?Pc(e.deploymentId):c("deploymentId is required for action='rollback'.",!0)}}};var cn=new Ic({name:"mistflow",version:"1.0.0"},{capabilities:{tools:{}},instructions:Ro()}),As=[Qo,ur,mr,fr,Or,zr,Sr,ns,Ir,ss,ys,ws,vs,Rs];cn.setRequestHandler(Rc,async()=>({tools:As.map(t=>({name:t.name,description:t.description,inputSchema:Ac(t.inputSchema)}))}));cn.setRequestHandler(Tc,async t=>{let e=As.find(o=>o.name===t.params.name);if(!e)return c(`Unknown tool: ${t.params.name}`,!0);try{let o=e.inputSchema.safeParse(t.params.arguments);if(!o.success){let a=o.error.issues.map(s=>`${s.path.join(".")}: ${s.message}`).join(", ");return c(`Invalid input: ${a}`,!0)}let n=t.params._meta?.progressToken,r={server:cn,progressToken:n};try{return await e.handler(o.data,r)}finally{r.cleanup?.()}}catch(o){let n=o instanceof Error?o.message:"An unexpected error occurred";return console.error("Tool error:",o),c(n,!0)}});async function Cc(){let t=process.argv.indexOf("--api-url");t!==-1&&process.argv[t+1]&&(process.env.MISTFLOW_API_URL=process.argv[t+1]),process.argv.includes("--local")&&!process.env.MISTFLOW_API_URL&&(process.env.MISTFLOW_API_URL="http://localhost:9100");let e=new _c;await cn.connect(e),console.error(`Mistflow MCP server running on stdio (API: ${process.env.MISTFLOW_API_URL||"https://api.mistflow.ai"})`)}Cc().catch(t=>{console.error("Fatal error:",t),process.exit(1)});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mistflow-ai/mcp",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
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",
|