Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -719,7 +719,9 @@ MCP Client can access the following tools to interact with Windows:
- `DisplayInventory`: Read display layout, work areas, effective DPI, and scale metadata.
- `Screenshot`: Fast screenshot-first desktop capture with cursor position, active/open windows, and an image. Skips UI tree extraction for speed and should be the default first call when you mainly need visual context. Supports `display=[0]` or `display=[0,1]` using zero-based active Windows display indices. After capture, a brief orange-red glowing border is drawn inside the captured area as a visual confirmation (set `WINDOWS_MCP_DISABLE_FLASH=1` to disable).
- `Snapshot`: Full desktop state capture for workflows that need interactive element ids, scrollable regions, or `use_dom=True` browser extraction. Supports `use_vision=True` for including screenshots and `display=[0]` or `display=[0,1]` using zero-based active Windows display indices.
- `App`: Launch an application by Start Menu name or strictly by executable path with separated argv and optional cwd; resize, move, and switch between windows.
- `App`: Launch an application by Start Menu name or strictly by executable path; resize or
switch windows by convenient name matching; or find, activate, and set outer/client bounds
using exact native window identity.
- `PowerShell`: To execute PowerShell commands.
- `FileSystem`: Read, write, copy, move, delete, list, search, and inspect files and directories.
- `Scrape`: To scrape the entire webpage for information.
Expand Down
2 changes: 1 addition & 1 deletion manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@
"tools": [
{
"name": "App",
"description": "Manages Windows applications with three modes: 'launch' (opens the prescibed application), 'resize' (adjusts the size/position of a named window or the active window if name is omitted), 'switch' (brings specific window into focus)."
"description": "Launches applications and manages windows. Supports Start Menu or exact executable launch, convenient name-based resize and switch, and exact find_window, activate_window, and set_window_bounds modes using native window identity."
},
{
"name": "PowerShell",
Expand Down
57 changes: 57 additions & 0 deletions src/windows_mcp/desktop/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from windows_mcp.tree.service import Tree
from windows_mcp.desktop import screenshot as screenshot_capture
from windows_mcp.desktop import flash_overlay
from windows_mcp.desktop.window import ExactWindowController
from windows_mcp.infrastructure import validate_url
from urllib.parse import urljoin
from locale import getpreferredencoding
Expand Down Expand Up @@ -81,6 +82,7 @@ def __init__(self):
self.encoding = getpreferredencoding()
self.tree = Tree(self)
self.desktop_state = None
self._exact_window = ExactWindowController(self)

def get_state(
self,
Expand Down Expand Up @@ -617,6 +619,61 @@ def bring_window_to_top(self, target_handle: int):
except Exception as e:
logger.exception(f"Failed to bring window to top: {e}")

def find_exact_windows(
self,
title: str | None = None,
title_match: Literal["exact", "contains"] = "contains",
process: str | None = None,
process_id: int | None = None,
handle: int | None = None,
) -> list[dict[str, object]]:
"""Find top-level windows using explicit identity filters."""
return self._exact_window.find_exact_windows(
title=title,
title_match=title_match,
process=process,
process_id=process_id,
handle=handle,
)

def activate_exact_window(
self,
handle: int,
process_id: int | None = None,
process: str | None = None,
title: str | None = None,
title_match: Literal["exact", "contains"] = "contains",
) -> dict[str, object]:
"""Activate an exact window and verify foreground readback."""
return self._exact_window.activate_exact_window(
handle,
process_id,
process,
title,
title_match,
)

def set_exact_window_bounds(
self,
handle: int,
outer: list[int] | None = None,
client: list[int] | None = None,
process_id: int | None = None,
process: str | None = None,
title: str | None = None,
title_match: Literal["exact", "contains"] = "contains",
) -> dict[str, object]:
"""Set an exact window's outer or client bounds."""
return self._exact_window.set_exact_window_bounds(
handle,
outer,
client,
process_id,
process,
title,
title_match,
)

def get_coordinates_from_label(self, label: int) -> tuple[int, int]:
tree_state = self.desktop_state.tree_state
if label < len(tree_state.interactive_nodes):
Expand Down
Loading