Skip to content

Commit f840527

Browse files
committed
added resize tool enable to change the location and size of an app
1 parent 83b6b52 commit f840527

File tree

3 files changed

+29
-5
lines changed

3 files changed

+29
-5
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,8 @@ Claude can access the following tools to interact with Windows:
135135
- `Shortcut-Tool`: Press keyboard shortcuts (`Ctrl+c`, `Alt+Tab`, etc).
136136
- `Key-Tool`: Press a single key.
137137
- `Wait-Tool`: Pause for a defined duration.
138-
- `State-Tool`: Combined snapshot of active apps and interactive, textual and scrollable elements along with screenshot of the desktop.
139-
- `Screenshot-Tool`: Capture a screenshot of the desktop.
138+
- `State-Tool`: Combined snapshot of default language, browser, active apps and interactive, textual and scrollable elements along with screenshot of the desktop.
139+
- `Resize-Tool`: Used to change the window size or location of an app.
140140
- `Launch-Tool`: To launch an application from the start menu.
141141
- `Shell-Tool`: To execute PowerShell commands.
142142
- `Scrape-Tool`: To scrape the entire webpage for information.

main.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ def type_tool(loc:tuple[int,int],text:str,clear:bool=False):
127127
pg.typewrite(text,interval=0.1)
128128
return f'Typed {text} on {control.Name} Element with ControlType {control.ControlTypeName} at ({x},{y}).'
129129

130+
@mcp.tool(name='Resize-Tool',description='Resize a specific application window (e.g., "notepad", "calculator", "chrome", etc.) to specific size (WIDTHxHEIGHT) or move to specific location (X,Y).')
131+
def resize_tool(name:str,size:tuple[int,int]=None,loc:tuple[int,int]=None)->str:
132+
response,_=desktop.resize_app(name,size,loc)
133+
return response
134+
130135
@mcp.tool(name='Switch-Tool',description='Switch to a specific application window (e.g., "notepad", "calculator", "chrome", etc.) and bring to foreground.')
131136
def switch_tool(name: str) -> str:
132137
_,status=desktop.switch_app(name)

src/desktop/__init__.py

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from uiautomation import Control, GetRootControl, ControlType, GetFocusedControl, SetWindowTopmost, IsTopLevelWindow, IsZoomed, IsIconic, IsWindowVisible
1+
from uiautomation import Control, GetRootControl, ControlType, GetFocusedControl, SetWindowTopmost, IsTopLevelWindow, IsZoomed, IsIconic, IsWindowVisible, ControlFromHandle
22
from src.desktop.config import EXCLUDED_APPS,BROWSER_NAMES
33
from src.desktop.views import DesktopState,App,Size
44
from fuzzywuzzy import process
@@ -9,7 +9,6 @@
99
from PIL import Image
1010
import subprocess
1111
import pyautogui
12-
import winreg
1312
import csv
1413
import io
1514

@@ -89,8 +88,28 @@ def execute_command(self,command:str)->tuple[str,int]:
8988
def is_app_browser(self,node:Control):
9089
process=Process(node.ProcessId)
9190
return process.name() in BROWSER_NAMES
91+
92+
def resize_app(self,name:str,size:tuple[int,int]=None,loc:tuple[int,int]=None)->tuple[str,int]:
93+
apps=self.get_apps()
94+
matched_app:tuple[App,int]|None=process.extractOne(name,apps)
95+
if matched_app is None:
96+
return (f'Application {name.title()} not found.',1)
97+
app,_=matched_app
98+
app_control=ControlFromHandle(app.handle)
99+
if loc is None:
100+
x=app_control.BoundingRectangle.left
101+
y=app_control.BoundingRectangle.top
102+
loc=(x,y)
103+
if size is None:
104+
width=app_control.BoundingRectangle.width()
105+
height=app_control.BoundingRectangle.height()
106+
size=(width,height)
107+
x,y=loc
108+
width,height=size
109+
app_control.MoveWindow(x,y,width,height)
110+
return (f'Application {name.title()} resized to {width}x{height} at {x},{y}.',0)
92111

93-
def launch_app(self,name:str):
112+
def launch_app(self,name:str)->tuple[str,int]:
94113
apps_map=self.get_apps_from_start_menu()
95114
matched_app=process.extractOne(name,apps_map.keys())
96115
if matched_app is None:

0 commit comments

Comments
 (0)