@shiplightai/mcp 0.1.19 → 0.1.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -8116,7 +8116,7 @@ The flow is executed statement by statement:
8116
8116
  - IF_ELSE: evaluates condition, then executes the matching branch
8117
8117
  - WHILE_LOOP: loops while condition is true (respects timeout_ms)
8118
8118
 
8119
- IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' resource for the flow format.`,inputSchema:tpi(av.object({session_id:av.string().describe("Session ID from new_session"),flow:av.any().describe("Test flow JSON object (must match TestFlow schema)")}),{$refStrategy:"none"})};async runTestFlow(t){let{session_id:r,flow:n}=av.object({session_id:av.string(),flow:av.any()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let s;try{s=Y5.parse(n)}catch(p){throw p instanceof av.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(p.errors)}`):p}let o=this.backend.getPage(r),a=this.backend.getWebAgent(r);s.url&&await o.goto(s.url,{waitUntil:"domcontentloaded"});let u=[],l=await this.executeStatements(s.statements,o,a,u),c=this.countResults(u),d={success:l,url:o.url(),results:u,statements_passed:c.passed,statements_failed:c.failed,statements_total:c.total};return JSON.stringify(d)}async executeStatements(t,r,n,i){let s=!0;for(let o of t){let a=await this.executeStatement(o,r,n);if(i.push(a),!a.success){s=!1;break}}return s}async executeStatement(t,r,n){let i=this.getStatementDescription(t),s={uid:t.uid,type:t.type,description:i,success:!1};try{switch(t.type){case H0.DRAFT:return await this.executeDraft(t,r,n,s);case H0.ACTION:return await this.executeAction(t,r,n,s);case H0.STEP:return await this.executeStep(t,r,n,s);case H0.IF_ELSE:return await this.executeIfElse(t,r,n,s);case H0.WHILE_LOOP:return await this.executeWhileLoop(t,r,n,s);default:return{...s,error:`Unknown statement type: ${t.type}`}}}catch(o){return{...s,error:o instanceof Error?o.message:String(o)}}}async executeDraft(t,r,n,i){let s=await n.run(r,t.description);return{...i,success:s.success,error:s.success?void 0:s.details||"Draft execution failed"}}async executeAction(t,r,n,i){if(t.action_entity){let s=t.action_entity.action_data?.action_name;return s?(await n.execAction(s,r,t.action_entity),{...i,success:!0}):{...i,error:"action_entity missing action_data.action_name"}}else{let s=await n.execute(r,t.description);return{...i,success:s.success,error:s.success?void 0:s.details||"Action execution failed"}}}async executeStep(t,r,n,i){let s=Kj(t),o=[],a=!0;for(let u of s)if(!await this.executeStatements(u.statements,r,n,o)){a=!1;break}return{...i,success:a,children:o,error:a?void 0:"One or more child statements failed"}}async executeIfElse(t,r,n,i){let s=t.condition.expression,o=await n.evaluate(r,s),a=[],u=!0;return o&&t.then&&t.then.length>0?u=await this.executeStatements(t.then,r,n,a):!o&&t.else&&t.else.length>0&&(u=await this.executeStatements(t.else,r,n,a)),{...i,success:u,children:a,description:`${i.description} (condition=${o})`}}async executeWhileLoop(t,r,n,i){let o=t.condition.expression,a=t.timeout_ms??RD,u=Date.now(),l=[],c=0;for(;;){if(Date.now()-u>a)return{...i,success:!1,children:l,error:`While loop timed out after ${a}ms (${c} iterations)`};if(c>=100)return{...i,success:!1,children:l,error:"While loop exceeded max iterations (100)"};if(!await n.evaluate(r,o))break;if(t.body&&t.body.length>0){let p=[],f=await this.executeStatements(t.body,r,n,p);if(l.push(...p),!f)return{...i,success:!1,children:l,error:`While loop body failed on iteration ${c+1}`}}c++}return{...i,success:!0,children:l,description:`${i.description} (${c} iterations)`}}getStatementDescription(t){switch(t.type){case H0.DRAFT:case H0.ACTION:case H0.STEP:return t.description||t.type;case H0.IF_ELSE:return`IF ${t.condition.expression}`;case H0.WHILE_LOOP:return`WHILE ${t.condition.expression}`;default:let r=t;return"Unknown statement"}}countResults(t){let r=0,n=0,i=0;for(let s of t)if(i++,s.success?r++:n++,s.children){let o=this.countResults(s.children);r+=o.passed,n+=o.failed,i+=o.total}return{passed:r,failed:n,total:i}}static toolDefinitions=[npr.runTestFlowTool]};tE();var uUe=class e{static _instance;_logLevel;constructor(){switch(process.env.LOG_LEVEL?.toUpperCase()){case"ERROR":this._logLevel=1;break;case"WARN":this._logLevel=2;break;case"INFO":this._logLevel=3;break;case"DEBUG":this._logLevel=4;break;default:this._logLevel=3}}static getInstance(){return e._instance||(e._instance=new e),e._instance}setLevel(t){this._logLevel=t}debug(...t){this._logLevel>=4&&console.error("[DEBUG]",...t)}info(...t){this._logLevel>=3&&console.error("[INFO]",...t)}warn(...t){this._logLevel>=2&&console.error("[WARN]",...t)}error(...t){this._logLevel>=1&&console.error("[ERROR]",...t)}log(...t){this.info(...t)}},rpi=uUe.getInstance(),Ade=rpi;import{createHash as npi}from"node:crypto";import{hostname as ipi,userInfo as spi,platform as spr,arch as opi}from"node:os";import{PostHog as api}from"posthog-node";var upi="phc_5Va2dHamGwJWX9qZqyRka5Lann5ATsg3LL4uyU63qin",lpi="https://us.i.posthog.com",cpi=process.env.SHIPLIGHT_TELEMETRY==="0"||process.env.DO_NOT_TRACK==="1",lUe=null,ipr=!1;function dpi(){return cpi?null:(lUe||(lUe=new api(upi,{host:lpi,flushInterval:5e3})),lUe)}function hpi(){let e=`${ipi()}:${spi().username}:${spr()}:${opi()}`;return npi("sha256").update(e).digest("hex")}function opr(e,t){let r=dpi();if(r){ipr||(Ade.info("Anonymous usage telemetry enabled. Set SHIPLIGHT_TELEMETRY=0 to disable."),ipr=!0);try{r.capture({distinctId:hpi(),event:"mcp_new_session",properties:{product:"mcp-server",version:e,platform:spr(),nodeVersion:process.version,cloudMode:t,$geoip_disable:!0,$ip:null}})}catch{}}}process.env.PWDEBUG="console";var upr="shiplight://environments",cUe=class{constructor(t=!1){this.cloudMode=t;let r=process.env.API_BASE_URL||"https://api.shiplight.ai",n=T6e(),i=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null;this.server=new ppi({name:"shiplight-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{},prompts:{}}});let s={};process.env.GOOGLE_API_KEY&&(s.GOOGLE_API_KEY=process.env.GOOGLE_API_KEY),process.env.ANTHROPIC_API_KEY&&(s.ANTHROPIC_API_KEY=process.env.ANTHROPIC_API_KEY),Object.keys(s).length>0&&yG({env:s}),this.sessionBackend=new k6e({runDir:void 0,terminationTimeout:i}),this.apiClient=this.cloudMode&&process.env.API_TOKEN?new R6e({apiBaseUrl:r,getApiToken:()=>process.env.API_TOKEN}):null,this.sessionTools=new ude(this.sessionBackend,this.apiClient,n),this.browserTools=new lde(this.sessionBackend),this.debugTools=new cde(this.sessionBackend),this.localTestTools=new fde,this.registry=new L6e,this.registry.registerAll(ude,this.sessionTools).registerAll(lde,this.browserTools).registerAll(cde,this.debugTools).registerAll(fde,this.localTestTools),this.cloudMode&&(this.testCaseTools=new hde(this.apiClient),this.testResultTools=new pde(this.apiClient),this.dataTools=new dde(this.apiClient),this.registry.registerAll(hde,this.testCaseTools).registerAll(pde,this.testResultTools).registerAll(dde,this.dataTools)),this.setupHandlers()}server;registry;sessionBackend;apiClient;sessionTools;browserTools;debugTools;testCaseTools=null;testResultTools=null;dataTools=null;localTestTools;setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(mpi,async()=>({tools:t})),this.server.setRequestHandler(Api,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&opr("0.1.19",this.cloudMode),{content:[{type:"text",text:o}]}}catch(i){let s=i instanceof Error?i.message:String(i);throw apr.isAxiosError(i)&&i.response?.status===401&&(s="Authentication required. Contact info@shiplight.ai to get access to cloud services and advanced features."),new gG(mG.InternalError,s)}}),this.server.setRequestHandler(gpi,async()=>{let n=new Set(["shiplight://schemas/testflow-json-v1.2.0"]),i=this.cloudMode?Zj():Zj().filter(s=>!n.has(s.uri));return this.cloudMode&&i.push({uri:upr,name:"Environments",description:"List testing environments (same data as the list_environments tool).",mimeType:"application/json"}),{resources:i}}),this.server.setRequestHandler(Epi,async n=>{let{uri:i}=n.params;if(i===upr){if(!this.apiClient)throw new gG(mG.InternalError,"The environments resource requires a Shiplight API token. Set API_TOKEN in your MCP server configuration.");try{let o=await this.apiClient.listEnvironments();return{contents:[{uri:i,mimeType:"application/json",text:JSON.stringify({environments:o.map(a=>({id:a.id,name:a.name,url:a.url}))},null,2)}]}}catch(o){let a=o instanceof Error?o.message:String(o);throw apr.isAxiosError(o)&&o.response?.status===401&&(a="Authentication required. Provide API_TOKEN in the MCP server configuration to access cloud resources."),new gG(mG.InternalError,a)}}let s=await O6e(i);if(!s)throw new gG(mG.InvalidRequest,`Unknown resource: ${i}`);return{contents:[{uri:i,mimeType:"text/markdown",text:s}]}}),this.server.setRequestHandler(Cpi,async()=>({prompts:M6e().map(i=>({name:i.name,description:i.description}))})),this.server.setRequestHandler(ypi,async n=>{let{name:i}=n.params,s=Q6e(i);if(!s)throw new gG(mG.InvalidRequest,`Unknown prompt: ${i}`);return{messages:[{role:"user",content:{type:"text",text:s}}]}})}async run(){let t=new fpi;await this.server.connect(t),Ade.info("Shiplight MCP Server running on stdio")}},bpi=process.argv.includes("--cloud"),wpi=new cUe(bpi);await wpi.run();
8119
+ IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' resource for the flow format.`,inputSchema:tpi(av.object({session_id:av.string().describe("Session ID from new_session"),flow:av.any().describe("Test flow JSON object (must match TestFlow schema)")}),{$refStrategy:"none"})};async runTestFlow(t){let{session_id:r,flow:n}=av.object({session_id:av.string(),flow:av.any()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let s;try{s=Y5.parse(n)}catch(p){throw p instanceof av.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(p.errors)}`):p}let o=this.backend.getPage(r),a=this.backend.getWebAgent(r);s.url&&await o.goto(s.url,{waitUntil:"domcontentloaded"});let u=[],l=await this.executeStatements(s.statements,o,a,u),c=this.countResults(u),d={success:l,url:o.url(),results:u,statements_passed:c.passed,statements_failed:c.failed,statements_total:c.total};return JSON.stringify(d)}async executeStatements(t,r,n,i){let s=!0;for(let o of t){let a=await this.executeStatement(o,r,n);if(i.push(a),!a.success){s=!1;break}}return s}async executeStatement(t,r,n){let i=this.getStatementDescription(t),s={uid:t.uid,type:t.type,description:i,success:!1};try{switch(t.type){case H0.DRAFT:return await this.executeDraft(t,r,n,s);case H0.ACTION:return await this.executeAction(t,r,n,s);case H0.STEP:return await this.executeStep(t,r,n,s);case H0.IF_ELSE:return await this.executeIfElse(t,r,n,s);case H0.WHILE_LOOP:return await this.executeWhileLoop(t,r,n,s);default:return{...s,error:`Unknown statement type: ${t.type}`}}}catch(o){return{...s,error:o instanceof Error?o.message:String(o)}}}async executeDraft(t,r,n,i){let s=await n.run(r,t.description);return{...i,success:s.success,error:s.success?void 0:s.details||"Draft execution failed"}}async executeAction(t,r,n,i){if(t.action_entity){let s=t.action_entity.action_data?.action_name;return s?(await n.execAction(s,r,t.action_entity),{...i,success:!0}):{...i,error:"action_entity missing action_data.action_name"}}else{let s=await n.execute(r,t.description);return{...i,success:s.success,error:s.success?void 0:s.details||"Action execution failed"}}}async executeStep(t,r,n,i){let s=Kj(t),o=[],a=!0;for(let u of s)if(!await this.executeStatements(u.statements,r,n,o)){a=!1;break}return{...i,success:a,children:o,error:a?void 0:"One or more child statements failed"}}async executeIfElse(t,r,n,i){let s=t.condition.expression,o=await n.evaluate(r,s),a=[],u=!0;return o&&t.then&&t.then.length>0?u=await this.executeStatements(t.then,r,n,a):!o&&t.else&&t.else.length>0&&(u=await this.executeStatements(t.else,r,n,a)),{...i,success:u,children:a,description:`${i.description} (condition=${o})`}}async executeWhileLoop(t,r,n,i){let o=t.condition.expression,a=t.timeout_ms??RD,u=Date.now(),l=[],c=0;for(;;){if(Date.now()-u>a)return{...i,success:!1,children:l,error:`While loop timed out after ${a}ms (${c} iterations)`};if(c>=100)return{...i,success:!1,children:l,error:"While loop exceeded max iterations (100)"};if(!await n.evaluate(r,o))break;if(t.body&&t.body.length>0){let p=[],f=await this.executeStatements(t.body,r,n,p);if(l.push(...p),!f)return{...i,success:!1,children:l,error:`While loop body failed on iteration ${c+1}`}}c++}return{...i,success:!0,children:l,description:`${i.description} (${c} iterations)`}}getStatementDescription(t){switch(t.type){case H0.DRAFT:case H0.ACTION:case H0.STEP:return t.description||t.type;case H0.IF_ELSE:return`IF ${t.condition.expression}`;case H0.WHILE_LOOP:return`WHILE ${t.condition.expression}`;default:let r=t;return"Unknown statement"}}countResults(t){let r=0,n=0,i=0;for(let s of t)if(i++,s.success?r++:n++,s.children){let o=this.countResults(s.children);r+=o.passed,n+=o.failed,i+=o.total}return{passed:r,failed:n,total:i}}static toolDefinitions=[npr.runTestFlowTool]};tE();var uUe=class e{static _instance;_logLevel;constructor(){switch(process.env.LOG_LEVEL?.toUpperCase()){case"ERROR":this._logLevel=1;break;case"WARN":this._logLevel=2;break;case"INFO":this._logLevel=3;break;case"DEBUG":this._logLevel=4;break;default:this._logLevel=3}}static getInstance(){return e._instance||(e._instance=new e),e._instance}setLevel(t){this._logLevel=t}debug(...t){this._logLevel>=4&&console.error("[DEBUG]",...t)}info(...t){this._logLevel>=3&&console.error("[INFO]",...t)}warn(...t){this._logLevel>=2&&console.error("[WARN]",...t)}error(...t){this._logLevel>=1&&console.error("[ERROR]",...t)}log(...t){this.info(...t)}},rpi=uUe.getInstance(),Ade=rpi;import{createHash as npi}from"node:crypto";import{hostname as ipi,userInfo as spi,platform as spr,arch as opi}from"node:os";import{PostHog as api}from"posthog-node";var upi="phc_5Va2dHamGwJWX9qZqyRka5Lann5ATsg3LL4uyU63qin",lpi="https://us.i.posthog.com",cpi=process.env.SHIPLIGHT_TELEMETRY==="0"||process.env.DO_NOT_TRACK==="1",lUe=null,ipr=!1;function dpi(){return cpi?null:(lUe||(lUe=new api(upi,{host:lpi,flushAt:1,flushInterval:3e4})),lUe)}function hpi(){let e=`${ipi()}:${spi().username}:${spr()}:${opi()}`;return npi("sha256").update(e).digest("hex")}function opr(e,t){let r=dpi();if(r){ipr||(Ade.info("Anonymous usage telemetry enabled. Set SHIPLIGHT_TELEMETRY=0 to disable."),ipr=!0);try{r.capture({distinctId:hpi(),event:"mcp_new_session",properties:{product:"mcp-server",version:e,platform:spr(),nodeVersion:process.version,cloudMode:t,$geoip_disable:!0,$ip:null}}),r.flush().catch(()=>{})}catch{}}}process.env.PWDEBUG="console";var upr="shiplight://environments",cUe=class{constructor(t=!1){this.cloudMode=t;let r=process.env.API_BASE_URL||"https://api.shiplight.ai",n=T6e(),i=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null;this.server=new ppi({name:"shiplight-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{},prompts:{}}});let s={};process.env.GOOGLE_API_KEY&&(s.GOOGLE_API_KEY=process.env.GOOGLE_API_KEY),process.env.ANTHROPIC_API_KEY&&(s.ANTHROPIC_API_KEY=process.env.ANTHROPIC_API_KEY),Object.keys(s).length>0&&yG({env:s}),this.sessionBackend=new k6e({runDir:void 0,terminationTimeout:i}),this.apiClient=this.cloudMode&&process.env.API_TOKEN?new R6e({apiBaseUrl:r,getApiToken:()=>process.env.API_TOKEN}):null,this.sessionTools=new ude(this.sessionBackend,this.apiClient,n),this.browserTools=new lde(this.sessionBackend),this.debugTools=new cde(this.sessionBackend),this.localTestTools=new fde,this.registry=new L6e,this.registry.registerAll(ude,this.sessionTools).registerAll(lde,this.browserTools).registerAll(cde,this.debugTools).registerAll(fde,this.localTestTools),this.cloudMode&&(this.testCaseTools=new hde(this.apiClient),this.testResultTools=new pde(this.apiClient),this.dataTools=new dde(this.apiClient),this.registry.registerAll(hde,this.testCaseTools).registerAll(pde,this.testResultTools).registerAll(dde,this.dataTools)),this.setupHandlers()}server;registry;sessionBackend;apiClient;sessionTools;browserTools;debugTools;testCaseTools=null;testResultTools=null;dataTools=null;localTestTools;setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(mpi,async()=>({tools:t})),this.server.setRequestHandler(Api,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&opr("0.1.20",this.cloudMode),{content:[{type:"text",text:o}]}}catch(i){let s=i instanceof Error?i.message:String(i);throw apr.isAxiosError(i)&&i.response?.status===401&&(s="Authentication required. Contact info@shiplight.ai to get access to cloud services and advanced features."),new gG(mG.InternalError,s)}}),this.server.setRequestHandler(gpi,async()=>{let n=new Set(["shiplight://schemas/testflow-json-v1.2.0"]),i=this.cloudMode?Zj():Zj().filter(s=>!n.has(s.uri));return this.cloudMode&&i.push({uri:upr,name:"Environments",description:"List testing environments (same data as the list_environments tool).",mimeType:"application/json"}),{resources:i}}),this.server.setRequestHandler(Epi,async n=>{let{uri:i}=n.params;if(i===upr){if(!this.apiClient)throw new gG(mG.InternalError,"The environments resource requires a Shiplight API token. Set API_TOKEN in your MCP server configuration.");try{let o=await this.apiClient.listEnvironments();return{contents:[{uri:i,mimeType:"application/json",text:JSON.stringify({environments:o.map(a=>({id:a.id,name:a.name,url:a.url}))},null,2)}]}}catch(o){let a=o instanceof Error?o.message:String(o);throw apr.isAxiosError(o)&&o.response?.status===401&&(a="Authentication required. Provide API_TOKEN in the MCP server configuration to access cloud resources."),new gG(mG.InternalError,a)}}let s=await O6e(i);if(!s)throw new gG(mG.InvalidRequest,`Unknown resource: ${i}`);return{contents:[{uri:i,mimeType:"text/markdown",text:s}]}}),this.server.setRequestHandler(Cpi,async()=>({prompts:M6e().map(i=>({name:i.name,description:i.description}))})),this.server.setRequestHandler(ypi,async n=>{let{name:i}=n.params,s=Q6e(i);if(!s)throw new gG(mG.InvalidRequest,`Unknown prompt: ${i}`);return{messages:[{role:"user",content:{type:"text",text:s}}]}})}async run(){let t=new fpi;await this.server.connect(t),Ade.info("Shiplight MCP Server running on stdio")}},bpi=process.argv.includes("--cloud"),wpi=new cUe(bpi);await wpi.run();
8120
8120
  /*! Bundled license information:
8121
8121
 
8122
8122
  node-domexception/index.js:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shiplightai/mcp",
3
- "version": "0.1.19",
3
+ "version": "0.1.20",
4
4
  "type": "module",
5
5
  "description": "Shiplight MCP server for AI-powered test automation",
6
6
  "main": "dist/index.js",
@@ -35,8 +35,8 @@
35
35
  "mcp-tools": "1.0.0",
36
36
  "sdk-internal": "0.1.1",
37
37
  "sdk-core": "0.1.0",
38
- "shiplight-types": "0.1.0",
39
- "shiplight-tools": "1.0.0"
38
+ "shiplight-tools": "1.0.0",
39
+ "shiplight-types": "0.1.0"
40
40
  },
41
41
  "engines": {
42
42
  "node": ">=22.0.0"