browser-devtools-mcp 0.2.7 → 0.2.8
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/daemon-server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as h}from"./core-
|
|
1
|
+
import{a as h}from"./core-56XWNOCD.js";import{F as E,G as b,H as C,I as y,K as I,L as u,M as c,O as d,a as t}from"./core-IV5QBQ2N.js";import{createRequire as P}from"node:module";import{Command as N,Option as x,InvalidOptionArgumentError as _}from"commander";import{serve as q}from"@hono/node-server";import{Hono as M}from"hono";import{cors as $}from"hono/cors";import{z as F}from"zod";var k=P(import.meta.url),D=0,A=0,i=new M,a=new Map,O="#default",p={get sessionNotFound(){return f(404,"Session Not Found")},get toolNotFound(){return f(404,"Tool Not Found")},get internalServerError(){return f(500,"Internal Server Error")}};function f(n,r){return{error:{code:n,message:r}}}t(f,"_buildErrorResponse");async function S(n){if(n.closed=!0,n.context)try{await n.context.close(),u("Closed MCP session context")}catch(r){d("Error occurred while closing MCP session context",r)}a.delete(n.id)}t(S,"_closeSession");function H(n,r){let s=Date.now(),e={id:r,toolExecutor:h.toolsInfo.createToolExecutor(()=>r),closed:!1,createdAt:s,lastActiveAt:s};return u(`Created session with id ${r}`),e}t(H,"_createSession");function R(n){let r=Date.now();return{id:n.id,createdAt:n.createdAt,lastActiveAt:n.lastActiveAt,idleSeconds:Math.floor((r-n.lastActiveAt)/1e3)}}t(R,"_getSessionInfo");async function j(n){let r=n.req.header("session-id")||O;return a.get(r)}t(j,"_getSession");async function G(n){let r=n.req.header("session-id")||O,s=a.get(r);return s?u(`Reusing session with id ${r}`):(u(`No session could be found with id ${r}`),s=H(n,r),a.set(r,s)),s}t(G,"_getOrCreateSession");function L(){let n=!1;setInterval(t(()=>{let s=Date.now();n&&a.size===0&&(c("No active session found, so terminating daemon server"),process.exit(0));for(let[e,o]of a)u(`Checking whether session with id ${e} is idle or not ...`),s-o.lastActiveAt>b*1e3&&(u(`Session with id ${e} is idle, so it will be closing ...`),S(o).then(()=>{u(`Session with id ${e} was idle, so it has been closed`)}).catch(l=>{d(`Unable to delete idle session with id ${e}`,l)}));n=a.size===0},"sessionCheck"),C*1e3)}t(L,"_scheduleIdleSessionCheck");async function U(n){let r=n.req.raw.clone();u(`Got request: ${await r.json()}`)}t(U,"_logRequest");async function z(n){let r=Object.fromEntries(h.toolsInfo.tools.map(e=>[e.name(),e]));i.use("*",$({origin:"*",allowMethods:["GET","POST","DELETE","OPTIONS"],allowHeaders:["Content-Type","Authorization","session-id"]})),A=n,D=Date.now();let s=t(async e=>{c(`Received ${e}, initiating graceful shutdown...`);let o=[];for(let l of a.values())o.push(S(l));await Promise.allSettled(o),c("All sessions closed, exiting..."),process.exit(0)},"gracefulShutdown");process.on("SIGTERM",()=>s("SIGTERM")),process.on("SIGINT",()=>s("SIGINT")),process.on("uncaughtException",e=>{d("Uncaught exception",e)}),process.on("unhandledRejection",e=>{d("Unhandled rejection",e)}),i.get("/health",e=>e.json({status:"ok"})),i.get("/info",e=>{let o={version:k("../package.json").version,uptime:Math.floor((Date.now()-D)/1e3),sessionCount:a.size,port:A};return e.json(o)}),i.get("/sessions",e=>{let o=[];for(let l of a.values())o.push(R(l));return e.json({sessions:o})}),i.get("/session",async e=>{let o=await j(e);return o?e.json(R(o)):e.json(p.sessionNotFound,404)}),i.post("/shutdown",async e=>{c("Shutdown request received, closing all sessions...");let o=[];for(let l of a.values())o.push(S(l));return await Promise.allSettled(o),c("All sessions closed, shutting down daemon server..."),setTimeout(()=>{process.exit(0)},500),e.json({status:"shutting_down"},200)}),i.post("/call",async e=>{try{I()&&await U(e);let o=await G(e);o.lastActiveAt=Date.now();let l=await e.req.json(),v=r[l.toolName];if(!v)return e.json(p.toolNotFound,404);let T;try{T=F.object(v.inputSchema()).parse(l.toolInput)}catch(g){let m=g.errors&&Array.isArray(g.errors)?g.errors.map(w=>`${w.path?.join(".")||"input"}: ${w.message}`).join("; "):"Invalid tool input";return e.json(f(400,`Invalid Tool Request: ${m}`),400)}try{let m={toolOutput:await o.toolExecutor.executeTool(v,T)};return e.json(m,200)}catch(g){let m={toolError:{code:g.code,message:g.message}};return e.json(m,500)}}catch(o){return d("Error occurred while handling tool call request",o),e.json(p.internalServerError,500)}}),i.delete("/session",async e=>{try{let o=await j(e);return o?(await S(o),e.json({ok:!0},200)):e.json(p.sessionNotFound,404)}catch(o){return d("Error occurred while deleting session",o),e.json(p.internalServerError,500)}}),i.onError((e,o)=>(d("Unhandled error in request handler",e),o.json({error:{code:500,message:"Internal Server Error"}},500))),i.notFound(e=>e.json({error:"Not Found",status:404},404)),q({fetch:i.fetch,port:n},()=>c(`Listening on port ${n}`)),L()}t(z,"startDaemonHTTPServer");var W=import.meta.url===`file://${process.argv[1]}`||import.meta.url===`file://${process.argv[1]}.mjs`||process.argv[1]?.endsWith("daemon-server.js")||process.argv[1]?.endsWith("daemon-server.mjs");if(W){let n=function(e){let o=Number(e);if(!Number.isInteger(o)||o<1||o>65535)throw new _("port must be an integer between 1 and 65535");return o};Z=n,t(n,"parsePort");let s=new N().addOption(new x("--port <number>","port for daemon HTTP server").argParser(n).default(E)).allowUnknownOption().parse(process.argv).opts();y(),c("Starting daemon HTTP server..."),z(s.port).then(()=>{c("Daemon HTTP server started")}).catch(e=>{d("Failed to start daemon HTTP server",e),process.exit(1)})}var Z;export{z as startDaemonHTTPServer};
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as d}from"./core-
|
|
2
|
+
import{a as d}from"./core-56XWNOCD.js";import{I as P,J as b,K as y,L as n,M as u,O as c,a as t,b as T,d as v,e as h,f as C}from"./core-IV5QBQ2N.js";import{createRequire as $}from"node:module";var A=$(import.meta.url),M="browser-devtools-mcp",w=A("../package.json").version;function E(){let r=[];return r.push(d.serverInfo.instructions),r.join(`
|
|
3
3
|
|
|
4
4
|
`).trim()}t(E,"getServerInstructions");function I(){return d.serverInfo.policies}t(I,"getServerPolicies");import q from"node:crypto";import{StreamableHTTPTransport as D}from"@hono/mcp";import{serve as V}from"@hono/node-server";import{McpServer as F}from"@modelcontextprotocol/sdk/server/mcp.js";import{StdioServerTransport as L}from"@modelcontextprotocol/sdk/server/stdio.js";import{Hono as z}from"hono";import{cors as U}from"hono/cors";var W={jsonrpc:"2.0",error:{code:0,message:"N/A"},id:null},p={get sessionNotFound(){return S(-32001,"Session Not Found")},get unauthorized(){return S(-32001,"Unauthorized")},get internalServerError(){return S(-32603,"Internal Server Error")}},g=new Map;function S(r,e){let o={...W};return o.error.code=r,o.error.message=e,o}t(S,"_buildMCPErrorResponse");function G(r){if("image"in r&&r.image!==null&&typeof r.image=="object"&&"data"in r.image&&"mimeType"in r.image&&Buffer.isBuffer(r.image.data)&&typeof r.image.mimeType=="string"){let e=r.image;return delete r.image,e}}t(G,"_getImage");function B(r){let e=G(r),o=[];return o.push({type:"text",text:JSON.stringify(r,null,2)}),e&&(e.mimeType==="image/svg+xml"?o.push({type:"text",text:e.data.toString(),mimeType:e.mimeType}):o.push({type:"image",data:e.data.toString("base64"),mimeType:e.mimeType})),{content:o,structuredContent:r,isError:!1}}t(B,"_toResponse");function J(r){let e=new F({name:M,version:w},{capabilities:{resources:{},tools:{}},instructions:E()}),o=[],s=I();if(s)for(let a of s)o.push({role:"user",content:{type:"text",text:a}});e.registerPrompt("default_system",{title:"Default System Prompt",description:"General behavior for the AI assistant"},async()=>({description:"Defines the assistant's general reasoning and tool usage rules.",messages:o}));let i=d.toolsInfo.createToolExecutor(()=>r.sessionIdProvider?r.sessionIdProvider():""),m=t(a=>async H=>{try{let f=await i.executeTool(a,H);return B(f)}catch(f){return{content:[{type:"text",text:`Error: ${f.message}`}],isError:!0}}},"createToolCallback");return d.toolsInfo.tools.forEach(a=>{n(`Registering tool ${a.name()} ...`),e.registerTool(a.name(),{description:a.description(),inputSchema:a.inputSchema(),outputSchema:a.outputSchema()},m(a))}),e}t(J,"_createServer");async function O(r,e){let o=J({config:e.config,sessionIdProvider:t(()=>r.sessionId,"sessionIdProvider")});return await o.connect(r),o}t(O,"_createAndConnectServer");function R(){return{}}t(R,"_getConfig");function K(r,e,o){let s={transport:e,server:o,closed:!1,lastActiveAt:Date.now()},i=r.env.incoming.socket;return i._mcpRegistered||(i._mcpRegistered=!0,i.on("close",async()=>{n(`Socket, which is for MCP session with id ${e.sessionId}, has been closed`),C&&await e.close()})),Z(e,s.server),n(`Created MCP server session with id ${e.sessionId}`),s}t(K,"_createSession");async function Y(r){let e=R(),o={},s=new D({enableJsonResponse:!0,sessionIdGenerator:t(()=>q.randomUUID(),"sessionIdGenerator"),onsessioninitialized:t(async i=>{let m=K(r,s,o.server);g.set(i,m),n(`MCP session initialized with id ${i}`)},"onsessioninitialized"),onsessionclosed:t(async i=>{n(`Closing MCP session closed with id ${i} ...`),await s.close(),n(`MCP session closed with id ${i}`)},"onsessionclosed")});return o.server=await O(s,{config:e}),s}t(Y,"_createTransport");async function Q(r){let e=r.req.header("mcp-session-id");if(e){let o=g.get(e);if(o)return n(`Reusing MCP session with id ${e}`),o.transport}}t(Q,"_getTransport");async function X(r){let e=r.req.header("mcp-session-id");if(e){let o=g.get(e);if(o)return n(`Reusing MCP session with id ${e}`),o.transport;n(`No MCP session could be found with id ${e}`);return}return await Y(r)}t(X,"_getOrCreateTransport");function Z(r,e){let o=!1;r.onclose=async()=>{if(n(`Closing MCP session with id ${r.sessionId} ...`),o){n(`MCP session with id ${r.sessionId} has already been closed`);return}o=!0;try{await e.close(),n("Closed MCP server")}catch(s){c("Error occurred while closing MCP server",s)}if(r.sessionId){let s=g.get(r.sessionId);if(s&&(s.closed=!0,s.context))try{await s.context.close(),n("Closed MCP session context")}catch(i){c("Error occurred while closing MCP session context",i)}g.delete(r.sessionId)}n(`Closing MCP session with id ${r.sessionId} ...`)}}t(Z,"_registerMCPSessionClose");function ee(){setInterval(t(()=>{let e=Date.now();for(let[o,s]of g)n(`Checking whether session with id ${o} is idle or not ...`),e-s.lastActiveAt>v*1e3&&(n(`Session with id ${o} is idle, so it will be closing ...`),s.transport.close().then(()=>{n(`Session with id ${o} was idle, so it has been closed`)}).catch(i=>{c(`Unable to delete idle session with id ${o}`,i)}))},"sessionCheck"),h*1e3)}t(ee,"_scheduleIdleSessionCheck");async function re(r){let e=r.req.raw.clone();n(`Got request: ${await e.json()}`)}t(re,"_logRequest");function oe(r){let e=r.req.header("mcp-session-id");if(e){let o=g.get(e);o&&(o.lastActiveAt=Date.now())}}t(oe,"_markSessionAsActive");async function _(){let r=new L;await O(r,{config:R()})}t(_,"startStdioServer");var l=new z;async function x(r){l.use("*",U({origin:"*",allowMethods:["GET","POST","OPTIONS"],allowHeaders:["Content-Type","Authorization","MCP-Protocol-Version"]})),l.get("/health",e=>e.json({status:"ok"})),l.get("/ping",e=>e.json({status:"ok",message:"pong"})),l.get("/mcp",e=>e.json({status:"ok",protocol:"model-context-protocol",version:"1.0"})),l.post("/mcp",async e=>{try{y()&&await re(e);let o=await X(e);return o?(oe(e),await o.handleRequest(e)):e.json(p.sessionNotFound,400)}catch(o){return c("Error occurred while handling MCP request",o),e.json(p.internalServerError,500)}}),l.delete("/mcp",async e=>{try{let o=await Q(e);return o?(await o.close(),e.json({ok:!0},200)):e.json(p.sessionNotFound,400)}catch(o){return c("Error occurred while deleting MCP session",o),e.json(p.internalServerError,500)}}),l.notFound(e=>e.json({error:"Not Found",status:404},404)),V({fetch:l.fetch,port:r},()=>u(`Listening on port ${r}`)),ee()}t(x,"startStreamableHTTPServer");import{Command as te,Option as N,InvalidOptionArgumentError as se}from"commander";function ne(r){let e=Number(r);if(!Number.isInteger(e)||e<1||e>65535)throw new se("port must be an integer between 1 and 65535");return e}t(ne,"_parsePort");function ie(){return new te().addOption(new N("--transport <type>","transport type").choices(["stdio","streamable-http"]).default("stdio")).addOption(new N("--port <number>","port for Streamable HTTP transport").argParser(ne).default(T)).allowUnknownOption().parse(process.argv).opts()}t(ie,"_getOptions");async function ae(){let r=ie();r.transport==="stdio"?(b(),await _()):r.transport==="streamable-http"?(u("Starting MCP server..."),await x(r.port),u("Started MCP Server")):(c(`Invalid transport: ${r.transport}`),process.exit(1))}t(ae,"main");ae().catch(r=>{P(),c("MCP server error",r),process.exit(1)});
|