@github/computer-use-mcp 0.1.17 → 0.1.18
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/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{McpServer as
|
|
1
|
+
import{McpServer as G}from"@modelcontextprotocol/sdk/server/mcp.js";import{existsSync as R,mkdirSync as M,readFileSync as W,writeFileSync as k}from"fs";import{homedir as j}from"os";import{join as P}from"path";var C="<!-- LOG -->",w=class{constructor(e,o=P(j(),".copilot","logs","github-computer-use-mcp")){this.inner=e;this.logDir=o,this.path=P(this.logDir,`${this.timestamp()}.html`),R(this.logDir)||M(this.logDir,{recursive:!0}),k(this.path,`<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
3
|
<head>
|
|
4
4
|
<meta charset="utf-8">
|
|
@@ -16,11 +16,13 @@ import{McpServer as q}from"@modelcontextprotocol/sdk/server/mcp.js";import{exist
|
|
|
16
16
|
<body>
|
|
17
17
|
<table>
|
|
18
18
|
<tr><th>Time</th><th>Action</th><th>Arguments</th></tr>
|
|
19
|
-
${
|
|
19
|
+
${C}
|
|
20
20
|
</table>
|
|
21
21
|
</body>
|
|
22
22
|
</html>
|
|
23
|
-
`)}inner;logDir;path;startTime=performance.now();timestamp(){let e=new Date,
|
|
24
|
-
`)}async click(e,
|
|
25
|
-
`)}else this.row("screenshot",'<span class="error">failed</span>');return
|
|
23
|
+
`)}inner;logDir;path;startTime=performance.now();timestamp(){let e=new Date,o=(n,t=2)=>String(n).padStart(t,"0");return`${e.getFullYear()}${o(e.getMonth()+1)}${o(e.getDate())}-${o(e.getHours())}${o(e.getMinutes())}${o(e.getSeconds())}.${o(Math.floor(e.getMilliseconds()/10))}`}elapsed(){return`${((performance.now()-this.startTime)/1e3).toFixed(2)}s`}insert(e){let o=W(this.path,"utf-8");k(this.path,o.replace(C,e+C))}row(e,o){this.insert(`<tr><td class="time">${this.elapsed()}</td><td class="action">${e}</td><td>${o}</td></tr>
|
|
24
|
+
`)}async click(e,o,n,t){await this.inner.click(e,o,n,t),this.row("click",`(${e}, ${o}) button=${n} count=${t}`)}async move(e,o){await this.inner.move(e,o),this.row("move",`(${e}, ${o})`)}async drag(e,o,n,t){await this.inner.drag(e,o,n,t),this.row("drag",`(${e}, ${o}) \u2192 (${n}, ${t})`)}async mouseDown(e,o){await this.inner.mouseDown(e,o),this.row("mouseDown",`(${e}, ${o})`)}async mouseUp(e,o){await this.inner.mouseUp(e,o),this.row("mouseUp",`(${e}, ${o})`)}async type(e){await this.inner.type(e);let o=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");this.row("type",`"${o}"`)}async key(e){await this.inner.key(e),this.row("key",e)}async scroll(e,o,n,t){await this.inner.scroll(e,o,n,t),this.row("scroll",`(${e}, ${o}) dx=${n} dy=${t}`)}async cursorPosition(){let e=await this.inner.cursorPosition();return this.row("cursorPosition",`(${e.x}, ${e.y})`),e}async getClipboard(){let e=await this.inner.getClipboard(),o=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");return this.row("getClipboard",`"${o.slice(0,200)}${o.length>200?"\u2026":""}"`),e}async setClipboard(e){await this.inner.setClipboard(e);let o=e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""");this.row("setClipboard",`"${o.slice(0,200)}${o.length>200?"\u2026":""}" (${e.length} chars)`)}async screenshot(e,o,n,t,i,s){let a=await this.inner.screenshot(e,o,n,t,i,s);if(a){let c=s===void 0?"png":"jpg",u=`${this.timestamp()}.${c}`;k(P(this.logDir,u),a);let d=n&&t?` (${n}\xD7${t})`:"",h=i?` crop=[${i.join(",")}]`:"";this.insert(`<tr><td class="time">${this.elapsed()}</td><td class="action">screenshot</td><td>${d}${h}<br><img src="${u}"></td></tr>
|
|
25
|
+
`)}else this.row("screenshot",'<span class="error">failed</span>');return a}};import{createRequire as I}from"module";import{dirname as A,join as q}from"path";import{fileURLToPath as B}from"url";var U=I(import.meta.url),E=A(B(import.meta.url)),x=class r{constructor(e){this.native=e}native;scaleX=1;scaleY=1;width=0;height=0;static create(){let e=q(E,"prebuilds",`${process.platform}-${process.arch}`,"computer.node"),o;try{o=U(e)}catch(n){let t=n instanceof Error?n.message:String(n);throw new Error(`Native computer bindings not available for ${process.platform}-${process.arch}: ${t} (path: ${e})`,{cause:n})}return o.display(),new r(o)}toNative(e,o){if(this.width>0&&this.height>0&&(e<0||e>=this.width||o<0||o>=this.height))throw new Error(`Coordinates (${e}, ${o}) are out of bounds. Screenshot dimensions are ${this.width}x${this.height}.`);return[e/this.scaleX,o/this.scaleY]}async click(e,o,n,t){let[i,s]=this.toNative(e,o);this.native.click(i,s,n,t)}async move(e,o){let[n,t]=this.toNative(e,o);this.native.move(n,t)}async drag(e,o,n,t){let[i,s]=this.toNative(e,o),[a,c]=this.toNative(n,t);this.native.drag(i,s,a,c)}async mouseDown(e,o){let[n,t]=this.toNative(e,o);this.native.mouseDown(n,t)}async mouseUp(e,o){let[n,t]=this.toNative(e,o);this.native.mouseUp(n,t)}async type(e){this.native.type(e)}async key(e){this.native.key(e)}async scroll(e,o,n,t){let[i,s]=this.toNative(e,o);this.native.scroll(i,s,n,t)}async cursorPosition(){let e=this.native.cursorPosition();return{x:Math.round(e.x*this.scaleX),y:Math.round(e.y*this.scaleY)}}async screenshot(e,o,n,t,i,s){let{width:a,height:c}=this.native.display();if(n>0&&t>0)this.width=n,this.height=t;else{let b=Math.min(1,1568/Math.max(a,c),Math.sqrt(115e4/(a*c)));this.width=Math.floor(a*b),this.height=Math.floor(c*b)}this.scaleX=this.width/a,this.scaleY=this.height/c;let u=s??-1;if(i){let[d,h]=this.toNative(i[0],i[1]),[b,$]=this.toNative(i[2],i[3]);return this.native.screenshot(e,o,0,0,d,h,b,$,u)}return this.native.screenshot(e,o,this.width,this.height,0,0,0,0,u)}async capabilities(){return this.native.capabilities()}async listDisplays(){return this.native.listDisplays()}async listWindows(){return this.native.listWindows()}async activateWindow(e){return this.native.activateWindow(e)}async minimizeWindow(e){return this.native.minimizeWindow(e)}async restoreWindow(e){return this.native.restoreWindow(e)}async getClipboard(){return this.native.getClipboard()}async setClipboard(e){this.native.setClipboard(e)}};import{z as p}from"zod";var z={screenshot:"screen-read",cursor_position:"screen-read",zoom:"screen-read",get_clipboard:"screen-read",left_click:"computer-control",right_click:"computer-control",middle_click:"computer-control",double_click:"computer-control",triple_click:"computer-control",mouse_move:"computer-control",left_click_drag:"computer-control",left_mouse_down:"computer-control",left_mouse_up:"computer-control",type:"computer-control",key:"computer-control",hold_key:"computer-control",scroll:"computer-control",wait:"computer-control",set_clipboard:"computer-control"},L={"screen-read":{message:["","Computer Use wants to observe your screen. This includes:","","- Capturing screenshots","- Reading the clipboard","","No mouse clicks, keyboard input, or other actions will be performed."].join(`
|
|
26
|
+
`)},"computer-control":{message:["","Computer Use wants to observer and control your computer. This includes:","","- Capturing screenshots","- Clicking, typing, scrolling, and dragging","- Pressing keyboard shortcuts","- Reading and modifying the clipboard","","These actions interact with your desktop just as if you were performing them yourself."].join(`
|
|
27
|
+
`)}},g={"screen-read":void 0,"computer-control":void 0};function _(r){return{content:[{type:"text",text:r}],isError:!0}}async function O(r,e){let o=L[e];if(!r.server.getClientCapabilities()?.elicitation?.form)return g[e]=!0,!0;try{let t=await r.server.elicitInput({message:o.message,requestedSchema:{type:"object",properties:{decision:{type:"string",title:`Allow ${e==="screen-read"?"screen observation":"computer control"} for this session?`,enum:["allow","deny"],enumNames:["Allow for this session","Deny"]}},required:["decision"]}});return t.action==="accept"&&t.content?.decision==="allow"?(g[e]=!0,!0):(g[e]=!1,!1)}catch{return g[e]=!0,!0}}async function l(r,e){let o=z[e];if(!o)return null;let n=g[o];return n===!0?null:n===!1?_(`Permission denied: ${o} was declined for this session. Restart the session to be prompted again.`):await O(r,o)?(o==="computer-control"&&(g["screen-read"]=!0),null):_(`Permission denied: user declined ${o} access. Restart the session to be prompted again.`)}var H=new Set(["ctrl","control","shift","alt","option","super","meta","cmd","command","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","0","1","2","3","4","5","6","7","8","9","return","enter","tab","space","backspace","delete","forwarddelete","escape","esc","up","down","left","right","home","end","pageup","pagedown","insert","capslock","f1","f2","f3","f4","f5","f6","f7","f8","f9","f10","f11","f12","-","minus","=","equal","[","]","\\",";","'",",",".","/","`"]),Y={arrowup:"up",arrowdown:"down",arrowleft:"left",arrowright:"right",page_up:"pageup",page_down:"pagedown",backslash:"\\",semicolon:";",slash:"/",grave:"`",bracketleft:"[",bracketright:"]",super_l:"super",gui:"super",caps_lock:"capslock",caps:"capslock",del:"delete"};function T(r){let e=r.split("+").map(n=>n.trim().toLowerCase()).filter(Boolean);if(e.length===0)throw new Error("Key combo must contain at least one key.");return e.map(n=>{let t=Y[n]??n;if(!H.has(t))throw new Error(`Unknown key "${n}" in combo "${r}".`);return t}).join("+")}function m(r,e){let o=[{type:"text",text:r}];return e?{content:o,isError:!0}:{content:o}}var v=.8;function S(r,e,o){return r?{content:[{type:"image",data:r.toString("base64"),mimeType:o!==void 0?"image/jpeg":"image/png",_meta:{screenshot:!0}}]}:m(e,!0)}var y=p.coerce.number().transform(Math.round),f=p.object({x:y.describe("Horizontal pixel coordinate."),y:y.describe("Vertical pixel coordinate.")}),F=p.object({x1:y.describe("Left edge of the region in screenshot pixel coordinates."),y1:y.describe("Top edge of the region in screenshot pixel coordinates."),x2:y.describe("Right edge of the region in screenshot pixel coordinates."),y2:y.describe("Bottom edge of the region in screenshot pixel coordinates.")}).refine(({x1:r,x2:e})=>e>r,{message:"x2 must be greater than x1.",path:["x2"]}).refine(({y1:r,y2:e})=>e>r,{message:"y2 must be greater than y1.",path:["y2"]});function D(r,e){r.registerTool("screenshot",{description:"Capture the current screen. Take a screenshot before clicking to determine coordinates and after each action to verify the result."},async()=>{let t=await l(r,"screenshot");if(t)return t;let s=await(await e()).screenshot("",[],0,0,void 0,v);return S(s,"Screenshot failed",v)}),r.registerTool("cursor_position",{description:"Get the current cursor position in pixel coordinates. Returns {x, y}."},async()=>{let t=await l(r,"cursor_position");if(t)return t;let s=await(await e()).cursorPosition();return m(`${s.x},${s.y}`)});let o={coordinate:f.optional().describe("{x, y} pixel coordinate to click at. Clicks at current cursor position if omitted.")},n=(t,i,s,a)=>{r.registerTool(t,{description:i,inputSchema:o},async({coordinate:c})=>{let u=await l(r,t);if(u)return u;let d=await e();c&&await d.move(c.x,c.y);let h=c??await d.cursorPosition();return await d.click(h.x,h.y,s,a),m(`${t}${c?` at (${c.x},${c.y})`:""}`)})};n("left_click","Click the left mouse button. Optionally move to a coordinate first.","left",1),n("right_click","Click the right mouse button. Optionally move to a coordinate first.","right",1),n("middle_click","Click the middle mouse button. Optionally move to a coordinate first.","middle",1),n("double_click","Double-click the left mouse button. Optionally move to a coordinate first.","left",2),n("triple_click","Triple-click the left mouse button. Optionally move to a coordinate first.","left",3),r.registerTool("mouse_move",{description:"Move the mouse cursor to the specified pixel coordinate.",inputSchema:{coordinate:f.describe("{x, y} pixel coordinate to move the cursor to.")}},async({coordinate:t})=>{let i=await l(r,"mouse_move");return i||(await(await e()).move(t.x,t.y),m(`Moved to (${t.x},${t.y})`))}),r.registerTool("left_click_drag",{description:"Click and drag from a start coordinate to an end coordinate.",inputSchema:{start_coordinate:f.describe("{x, y} pixel coordinate to start the drag from."),coordinate:f.describe("{x, y} pixel coordinate to drag to.")}},async({start_coordinate:t,coordinate:i})=>{let s=await l(r,"left_click_drag");return s||(await(await e()).drag(t.x,t.y,i.x,i.y),m(`Dragged (${t.x},${t.y}) -> (${i.x},${i.y})`))}),r.registerTool("left_mouse_down",{description:"Press and hold the left mouse button at the current cursor position."},async()=>{let t=await l(r,"left_mouse_down");if(t)return t;let i=await e(),s=await i.cursorPosition();return await i.mouseDown(s.x,s.y),m(`Mouse down at (${s.x},${s.y})`)}),r.registerTool("left_mouse_up",{description:"Release the left mouse button at the current cursor position."},async()=>{let t=await l(r,"left_mouse_up");if(t)return t;let i=await e(),s=await i.cursorPosition();return await i.mouseUp(s.x,s.y),m(`Mouse up at (${s.x},${s.y})`)}),r.registerTool("type",{description:"Type a string of text using the keyboard.",inputSchema:{text:p.string().describe("The text to type.")}},async({text:t})=>{let i=await l(r,"type");return i||(await(await e()).type(t),m(`Typed ${t.length} chars`))}),r.registerTool("key",{description:"Press a key or key combination. Examples: 'Return', 'ctrl+s', 'alt+Tab', 'BackSpace'.",inputSchema:{text:p.string().describe("Key combo to press (e.g. 'Return', 'ctrl+s', 'alt+Tab').")}},async({text:t})=>{let i=await l(r,"key");if(i)return i;let s=T(t);return await(await e()).key(s),m(`Pressed ${s}`)}),r.registerTool("hold_key",{description:"Hold a key down for a specified duration in seconds.",inputSchema:{text:p.string().describe("Key name to hold (e.g. 'shift', 'ctrl')."),duration:p.number().nonnegative().max(100).describe("Seconds to hold the key (max 100).")}},async({text:t,duration:i})=>{let s=await l(r,"hold_key");if(s)return s;let a=T(t);return await(await e()).key(a),m(`Held ${a} for ${i}s`)}),r.registerTool("scroll",{description:"Scroll the screen in a given direction at an optional coordinate.",inputSchema:{scroll_direction:p.enum(["up","down","left","right"]).describe("Direction to scroll."),coordinate:f.optional().describe("{x, y} pixel coordinate to scroll at. Scrolls at current cursor position if omitted."),scroll_amount:p.number().int().nonnegative().max(100).optional().describe("Number of scroll clicks (default 3).")}},async({scroll_direction:t,coordinate:i,scroll_amount:s})=>{let a=await l(r,"scroll");if(a)return a;let c=await e(),u=s??3,d=await c.cursorPosition(),h=i?.x??d.x,b=i?.y??d.y,$=t==="left"?-u:t==="right"?u:0,N=t==="down"?u:t==="up"?-u:0;return await c.scroll(h,b,$,N),m(`Scrolled ${t} ${u} at (${h},${b})`)}),r.registerTool("wait",{description:"Pause for a specified duration in seconds.",inputSchema:{duration:p.number().nonnegative().max(100).describe("Seconds to wait (max 100).")}},async({duration:t})=>{let i=await l(r,"wait");return i||(await new Promise(s=>setTimeout(s,t*1e3)),m(`Waited ${t}s`))}),r.registerTool("get_clipboard",{description:"Get the current text contents of the system clipboard."},async()=>{let t=await l(r,"get_clipboard");if(t)return t;let s=await(await e()).getClipboard();return m(s)}),r.registerTool("set_clipboard",{description:"Set the system clipboard to the specified text.",inputSchema:{text:p.string().describe("The text to copy to the clipboard.")}},async({text:t})=>{let i=await l(r,"set_clipboard");return i||(await(await e()).setClipboard(t),m(`Clipboard set (${t.length} chars)`))}),r.registerTool("zoom",{description:"Capture a specific region of the screen at full resolution for detailed inspection. The region is defined by top-left (x1, y1) and bottom-right (x2, y2) coordinates in the screenshot coordinate space.",inputSchema:{region:F.describe("{x1, y1, x2, y2} coordinates defining top-left and bottom-right corners of the region to capture.")}},async({region:t})=>{let i=await l(r,"zoom");if(i)return i;let a=await(await e()).screenshot("",[],0,0,[t.x1,t.y1,t.x2,t.y2],v);return S(a,"Zoom screenshot failed",v)})}function de(){let r=new G({name:"computer-use",version:"1.0.0"}),e;return D(r,async()=>(e||(e=x.create(),process.env.DEBUG&&(e=new w(e))),e)),r}export{de as createServer};
|
|
26
28
|
//# sourceMappingURL=index.js.map
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|