@shiplightai/mcp 0.1.32 → 0.1.33

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 +1 -1
package/dist/index.js CHANGED
@@ -8726,7 +8726,7 @@ The flow is executed statement by statement:
8726
8726
  - IF_ELSE: evaluates condition, then executes the matching branch
8727
8727
  - WHILE_LOOP: loops while condition is true (respects timeout_ms)
8728
8728
 
8729
- IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' resource for the flow format.`,inputSchema:Bli(CD.object({session_id:CD.string().describe("Session ID from new_session"),flow:CD.any().describe("Test flow JSON object (must match TestFlow schema)")}),{$refStrategy:"none"})};async runTestFlow(t){let{session_id:r,flow:n}=CD.object({session_id:CD.string(),flow:CD.any()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let s;try{s=G1.parse(n)}catch(f){throw f instanceof CD.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(f.errors)}`):f}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 qA.DRAFT:return await this.executeDraft(t,r,n,s);case qA.ACTION:return await this.executeAction(t,r,n,s);case qA.STEP:return await this.executeStep(t,r,n,s);case qA.IF_ELSE:return await this.executeIfElse(t,r,n,s);case qA.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=VF(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??$v,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 f=[],p=await this.executeStatements(t.body,r,n,f);if(l.push(...f),!p)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 qA.DRAFT:case qA.ACTION:case qA.STEP:return t.description||t.type;case qA.IF_ELSE:return`IF ${t.condition.expression}`;case qA.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=[dcr.runTestFlowTool]}});wPe();Nf();UA();import{Server as Hli}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Gli}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as $li,ListToolsRequestSchema as jli,ListResourcesRequestSchema as Vli,ReadResourceRequestSchema as Wli,ListPromptsRequestSchema as Yli,GetPromptRequestSchema as Jli,ErrorCode as Vq,McpError as Wq}from"@modelcontextprotocol/sdk/types.js";import gcr from"axios";var CPe=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)}},kli=CPe.getInstance(),vD=kli;import{createHash as Rli}from"node:crypto";import{hostname as Nli,userInfo as Qli,platform as pcr,arch as Fli}from"node:os";import{PostHog as Mli}from"posthog-node";var Lli="phc_5Va2dHamGwJWX9qZqyRka5Lann5ATsg3LL4uyU63qin",Oli="https://us.i.posthog.com",Pli=process.env.SHIPLIGHT_TELEMETRY==="0"||process.env.DO_NOT_TRACK==="1",vPe=null,fcr=!1;function Uli(){return Pli?null:(vPe||(vPe=new Mli(Lli,{host:Oli,flushAt:1,flushInterval:3e4})),vPe)}function qli(){let e=`${Nli()}:${Qli().username}:${pcr()}:${Fli()}`;return Rli("sha256").update(e).digest("hex")}function Acr(e,t){let r=Uli();if(r){fcr||(vD.info("Anonymous usage telemetry enabled. Set SHIPLIGHT_TELEMETRY=0 to disable."),fcr=!0);try{r.capture({distinctId:qli(),event:"mcp_new_session",properties:{product:"mcp-server",version:e,platform:pcr(),nodeVersion:process.version,cloudMode:t,$geoip_disable:!0,$ip:null}}),r.flush().catch(()=>{})}catch{}}}process.env.PWDEBUG="console";var _Pe=(...e)=>console.error(...e);console.log=_Pe;console.info=_Pe;console.debug=_Pe;process.on("uncaughtException",e=>{console.error("[MCP] Uncaught exception (non-fatal):",e)});process.on("unhandledRejection",e=>{console.error("[MCP] Unhandled rejection (non-fatal):",e)});async function mcr(){let{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,TestResultTools:i,DataTools:s,LocalTestTools:o,SessionManager:a,ExtensionRelayServer:u}=await Promise.resolve().then(()=>(wPe(),hcr));return{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,TestResultTools:i,DataTools:s,LocalTestTools:o,SessionManager:a,ExtensionRelayServer:u}}var ycr="shiplight://environments",IPe=class{constructor(t=!1,r=!1,n=!1,i=null){this.cloudMode=t;this.cloudOnlyMode=r;this.debugMode=n;this.relayPort=i;let s=process.env.API_BASE_URL||"https://api.shiplight.ai";if(this.server=new Hli({name:"shiplight-mcp",version:"1.0.0"},{capabilities:{tools:{},resources:{},prompts:{}}}),this.registry=new X$,this.cloudOnlyMode){process.env.API_TOKEN||(console.error("[MCP] Cloud-only mode requires API_TOKEN. Set it in your MCP server configuration."),process.exit(1)),this.apiClient=new iM({apiBaseUrl:s,getApiToken:()=>process.env.API_TOKEN}),this.testCaseTools=new wD(this.apiClient),this.registry.registerTools(wD,this.testCaseTools,["saveTestCase","saveTemplate","saveFunction"]);return}this.apiClient=this.cloudMode&&process.env.API_TOKEN?new iM({apiBaseUrl:s,getApiToken:()=>process.env.API_TOKEN}):null}server;registry;sessionBackend=null;apiClient;sessionTools=null;browserTools=null;debugTools=null;testCaseTools=null;testResultTools=null;dataTools=null;localTestTools=null;relayTools=null;relayServer=null;async initBrowserTools(){if(this.cloudOnlyMode)return;let t=K0e(process.env),r=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null,n={};process.env.GOOGLE_API_KEY&&(n.GOOGLE_API_KEY=process.env.GOOGLE_API_KEY),process.env.ANTHROPIC_API_KEY&&(n.ANTHROPIC_API_KEY=process.env.ANTHROPIC_API_KEY),Object.keys(n).length>0&&Jq({env:n});let{SessionTools:i,BrowserTools:s,DebugTools:o,TestResultTools:a,DataTools:u,LocalTestTools:l,SessionManager:c}=await mcr();this.sessionBackend=new c({runDir:void 0,terminationTimeout:r}),this.sessionTools=new i(this.sessionBackend,this.apiClient,t),this.browserTools=new s(this.sessionBackend),this.debugTools=new o(this.sessionBackend),this.localTestTools=new l(this.sessionBackend),this.registry.registerAll(i,this.sessionTools).registerAll(s,this.browserTools).registerAll(o,this.debugTools).registerAll(l,this.localTestTools),this.cloudMode&&(this.testCaseTools=new wD(this.apiClient),this.testResultTools=new a(this.apiClient),this.dataTools=new u(this.apiClient),this.registry.registerAll(wD,this.testCaseTools).registerAll(a,this.testResultTools).registerAll(u,this.dataTools))}async startRelayServer(){if(this.relayPort===null||this.cloudOnlyMode)return!1;let t=this.relayPort,{RelayTools:r,ExtensionRelayServer:n}=await mcr();this.relayServer=new n;try{return await this.relayServer.start(t),vD.info(`[MCP] Chrome Extension Relay ready on port ${t}`),this.relayTools=new r(this.sessionBackend,this.relayServer),this.registry.registerAll(r,this.relayTools),this.debugMode&&this.registry.registerAll({toolDefinitions:r.debugToolDefinitions},this.relayTools),!0}catch(i){let s=i;return s.message&&s.message.includes("EADDRINUSE")?vD.warn(`[MCP] Port ${t} already in use. Relay disabled for this instance.`):vD.error("[MCP] Failed to start relay server:",i),this.relayServer=null,!1}}setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(jli,async()=>({tools:t})),this.server.setRequestHandler($li,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&Acr("0.1.32",this.cloudMode),{content:[{type:"text",text:o}]}}catch(i){let s=i instanceof Error?i.message:String(i);throw gcr.isAxiosError(i)&&i.response?.status===401&&(s="Authentication required. Contact info@shiplight.ai to get access to cloud services and advanced features."),new Wq(Vq.InternalError,s)}}),this.server.setRequestHandler(Vli,async()=>{let n=new Set(["shiplight://schemas/testflow-json-v1.2.0"]),i=this.cloudMode?sM():sM().filter(s=>!n.has(s.uri));return this.cloudMode&&i.push({uri:ycr,name:"Environments",description:"List testing environments (same data as the list_environments tool).",mimeType:"application/json"}),{resources:i}}),this.server.setRequestHandler(Wli,async n=>{let{uri:i}=n.params;if(i===ycr){if(!this.apiClient)throw new Wq(Vq.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 gcr.isAxiosError(o)&&o.response?.status===401&&(a="Authentication required. Provide API_TOKEN in the MCP server configuration to access cloud resources."),new Wq(Vq.InternalError,a)}}let s=await ej(i);if(!s)throw new Wq(Vq.InvalidRequest,`Unknown resource: ${i}`);return{contents:[{uri:i,mimeType:"text/markdown",text:s}]}}),this.server.setRequestHandler(Yli,async()=>({prompts:K$().map(i=>({name:i.name,description:i.description}))})),this.server.setRequestHandler(Jli,async n=>{let{name:i}=n.params,s=z$(i);if(!s)throw new Wq(Vq.InvalidRequest,`Unknown prompt: ${i}`);return{messages:[{role:"user",content:{type:"text",text:s}}]}})}async run(){await this.initBrowserTools(),await this.startRelayServer(),this.setupHandlers();let t=new Gli;await this.server.connect(t),vD.info("Shiplight MCP Server running on stdio")}};if(process.argv.includes("--version")||process.argv.includes("-v")){let e="0.1.32",t=e==="unknown"||process.argv[1]?.includes("/monots");process.stdout.write(`shiplight-mcp ${t?`${e}-local`:e}
8729
+ IMPORTANT: Read 'shiplight://schemas/testflow-json-v1.2.0' resource for the flow format.`,inputSchema:Bli(CD.object({session_id:CD.string().describe("Session ID from new_session"),flow:CD.any().describe("Test flow JSON object (must match TestFlow schema)")}),{$refStrategy:"none"})};async runTestFlow(t){let{session_id:r,flow:n}=CD.object({session_id:CD.string(),flow:CD.any()}).parse(t);if(!this.backend.getSession(r))throw new Error(`Session ${r} not found`);let s;try{s=G1.parse(n)}catch(f){throw f instanceof CD.ZodError?new Error(`Invalid TestFlow schema: ${JSON.stringify(f.errors)}`):f}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 qA.DRAFT:return await this.executeDraft(t,r,n,s);case qA.ACTION:return await this.executeAction(t,r,n,s);case qA.STEP:return await this.executeStep(t,r,n,s);case qA.IF_ELSE:return await this.executeIfElse(t,r,n,s);case qA.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=VF(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??$v,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 f=[],p=await this.executeStatements(t.body,r,n,f);if(l.push(...f),!p)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 qA.DRAFT:case qA.ACTION:case qA.STEP:return t.description||t.type;case qA.IF_ELSE:return`IF ${t.condition.expression}`;case qA.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=[dcr.runTestFlowTool]}});wPe();Nf();UA();import{Server as Hli}from"@modelcontextprotocol/sdk/server/index.js";import{StdioServerTransport as Gli}from"@modelcontextprotocol/sdk/server/stdio.js";import{CallToolRequestSchema as $li,ListToolsRequestSchema as jli,ListResourcesRequestSchema as Vli,ReadResourceRequestSchema as Wli,ListPromptsRequestSchema as Yli,GetPromptRequestSchema as Jli,ErrorCode as Vq,McpError as Wq}from"@modelcontextprotocol/sdk/types.js";import gcr from"axios";var CPe=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)}},kli=CPe.getInstance(),vD=kli;import{createHash as Rli}from"node:crypto";import{hostname as Nli,userInfo as Qli,platform as pcr,arch as Fli}from"node:os";import{PostHog as Mli}from"posthog-node";var Lli="phc_5Va2dHamGwJWX9qZqyRka5Lann5ATsg3LL4uyU63qin",Oli="https://us.i.posthog.com",Pli=process.env.SHIPLIGHT_TELEMETRY==="0"||process.env.DO_NOT_TRACK==="1",vPe=null,fcr=!1;function Uli(){return Pli?null:(vPe||(vPe=new Mli(Lli,{host:Oli,flushAt:1,flushInterval:3e4})),vPe)}function qli(){let e=`${Nli()}:${Qli().username}:${pcr()}:${Fli()}`;return Rli("sha256").update(e).digest("hex")}function Acr(e,t){let r=Uli();if(r){fcr||(vD.info("Anonymous usage telemetry enabled. Set SHIPLIGHT_TELEMETRY=0 to disable."),fcr=!0);try{r.capture({distinctId:qli(),event:"mcp_new_session",properties:{product:"mcp-server",version:e,platform:pcr(),nodeVersion:process.version,cloudMode:t,$geoip_disable:!0,$ip:null}}),r.flush().catch(()=>{})}catch{}}}process.env.PWDEBUG="console";var _Pe=(...e)=>console.error(...e);console.log=_Pe;console.info=_Pe;console.debug=_Pe;process.on("uncaughtException",e=>{console.error("[MCP] Uncaught exception (non-fatal):",e)});process.on("unhandledRejection",e=>{console.error("[MCP] Unhandled rejection (non-fatal):",e)});async function mcr(){let{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,TestResultTools:i,DataTools:s,LocalTestTools:o,SessionManager:a,ExtensionRelayServer:u}=await Promise.resolve().then(()=>(wPe(),hcr));return{SessionTools:e,RelayTools:t,BrowserTools:r,DebugTools:n,TestResultTools:i,DataTools:s,LocalTestTools:o,SessionManager:a,ExtensionRelayServer:u}}var ycr="shiplight://environments",IPe=class{constructor(t=!1,r=!1,n=!1,i=null){this.cloudMode=t;this.cloudOnlyMode=r;this.debugMode=n;this.relayPort=i;let s=process.env.API_BASE_URL||"https://api.shiplight.ai";if(this.server=new Hli({name:"shiplight-mcp",version:"1.0.0"},{capabilities:this.cloudOnlyMode?{tools:{}}:{tools:{},resources:{},prompts:{}}}),this.registry=new X$,this.cloudOnlyMode){process.env.API_TOKEN||(console.error("[MCP] Cloud-only mode requires API_TOKEN. Set it in your MCP server configuration."),process.exit(1)),this.apiClient=new iM({apiBaseUrl:s,getApiToken:()=>process.env.API_TOKEN}),this.testCaseTools=new wD(this.apiClient),this.registry.registerTools(wD,this.testCaseTools,["saveTestCase","saveTemplate","saveFunction"]);return}this.apiClient=this.cloudMode&&process.env.API_TOKEN?new iM({apiBaseUrl:s,getApiToken:()=>process.env.API_TOKEN}):null}server;registry;sessionBackend=null;apiClient;sessionTools=null;browserTools=null;debugTools=null;testCaseTools=null;testResultTools=null;dataTools=null;localTestTools=null;relayTools=null;relayServer=null;async initBrowserTools(){if(this.cloudOnlyMode)return;let t=K0e(process.env),r=process.env.TERMINATION_TIMEOUT?parseInt(process.env.TERMINATION_TIMEOUT,10):null,n={};process.env.GOOGLE_API_KEY&&(n.GOOGLE_API_KEY=process.env.GOOGLE_API_KEY),process.env.ANTHROPIC_API_KEY&&(n.ANTHROPIC_API_KEY=process.env.ANTHROPIC_API_KEY),Object.keys(n).length>0&&Jq({env:n});let{SessionTools:i,BrowserTools:s,DebugTools:o,TestResultTools:a,DataTools:u,LocalTestTools:l,SessionManager:c}=await mcr();this.sessionBackend=new c({runDir:void 0,terminationTimeout:r}),this.sessionTools=new i(this.sessionBackend,this.apiClient,t),this.browserTools=new s(this.sessionBackend),this.debugTools=new o(this.sessionBackend),this.localTestTools=new l(this.sessionBackend),this.registry.registerAll(i,this.sessionTools).registerAll(s,this.browserTools).registerAll(o,this.debugTools).registerAll(l,this.localTestTools),this.cloudMode&&(this.testCaseTools=new wD(this.apiClient),this.testResultTools=new a(this.apiClient),this.dataTools=new u(this.apiClient),this.registry.registerAll(wD,this.testCaseTools).registerAll(a,this.testResultTools).registerAll(u,this.dataTools))}async startRelayServer(){if(this.relayPort===null||this.cloudOnlyMode)return!1;let t=this.relayPort,{RelayTools:r,ExtensionRelayServer:n}=await mcr();this.relayServer=new n;try{return await this.relayServer.start(t),vD.info(`[MCP] Chrome Extension Relay ready on port ${t}`),this.relayTools=new r(this.sessionBackend,this.relayServer),this.registry.registerAll(r,this.relayTools),this.debugMode&&this.registry.registerAll({toolDefinitions:r.debugToolDefinitions},this.relayTools),!0}catch(i){let s=i;return s.message&&s.message.includes("EADDRINUSE")?vD.warn(`[MCP] Port ${t} already in use. Relay disabled for this instance.`):vD.error("[MCP] Failed to start relay server:",i),this.relayServer=null,!1}}setupHandlers(){let{tools:t,handleToolCall:r}=this.registry.build();this.server.setRequestHandler(jli,async()=>({tools:t})),this.server.setRequestHandler($li,async n=>{try{let{name:i,arguments:s}=n.params,o=await r(i,s);return i==="new_session"&&Acr("0.1.33",this.cloudMode),{content:[{type:"text",text:o}]}}catch(i){let s=i instanceof Error?i.message:String(i);throw gcr.isAxiosError(i)&&i.response?.status===401&&(s="Authentication required. Contact info@shiplight.ai to get access to cloud services and advanced features."),new Wq(Vq.InternalError,s)}}),this.cloudOnlyMode||(this.server.setRequestHandler(Vli,async()=>{let n=new Set(["shiplight://schemas/testflow-json-v1.2.0"]),i=this.cloudMode?sM():sM().filter(s=>!n.has(s.uri));return this.cloudMode&&i.push({uri:ycr,name:"Environments",description:"List testing environments (same data as the list_environments tool).",mimeType:"application/json"}),{resources:i}}),this.server.setRequestHandler(Wli,async n=>{let{uri:i}=n.params;if(i===ycr){if(!this.apiClient)throw new Wq(Vq.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 gcr.isAxiosError(o)&&o.response?.status===401&&(a="Authentication required. Provide API_TOKEN in the MCP server configuration to access cloud resources."),new Wq(Vq.InternalError,a)}}let s=await ej(i);if(!s)throw new Wq(Vq.InvalidRequest,`Unknown resource: ${i}`);return{contents:[{uri:i,mimeType:"text/markdown",text:s}]}}),this.server.setRequestHandler(Yli,async()=>({prompts:K$().map(i=>({name:i.name,description:i.description}))})),this.server.setRequestHandler(Jli,async n=>{let{name:i}=n.params,s=z$(i);if(!s)throw new Wq(Vq.InvalidRequest,`Unknown prompt: ${i}`);return{messages:[{role:"user",content:{type:"text",text:s}}]}}))}async run(){await this.initBrowserTools(),await this.startRelayServer(),this.setupHandlers();let t=new Gli;await this.server.connect(t),vD.info("Shiplight MCP Server running on stdio")}};if(process.argv.includes("--version")||process.argv.includes("-v")){let e="0.1.33",t=e==="unknown"||process.argv[1]?.includes("/monots");process.stdout.write(`shiplight-mcp ${t?`${e}-local`:e}
8730
8730
  `),process.exit(0)}var bcr=process.argv.includes("--cloud-only"),zli=bcr||process.argv.includes("--cloud"),Kli=process.argv.includes("--debug"),Ecr=process.argv.indexOf("--relay-port"),Xli=Ecr!==-1&&parseInt(process.argv[Ecr+1],10)||null,Zli=new IPe(zli,bcr,Kli,Xli);await Zli.run();
8731
8731
  /*! Bundled license information:
8732
8732
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shiplightai/mcp",
3
- "version": "0.1.32",
3
+ "version": "0.1.33",
4
4
  "type": "module",
5
5
  "description": "Shiplight MCP server for AI-powered test automation",
6
6
  "main": "dist/index.js",