You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
add a read-only DisplayInventory tool for active Windows monitors
return a native top-level array with stable active-display indices, device names, virtual-screen bounds, work areas, resolution, orientation, effective DPI, and scale
reuse the existing monitor enumeration path and preserve negative virtual-screen coordinates
read current display mode through EnumDisplaySettingsW
use per-monitor effective DPI with a system-DPI fallback when the per-monitor API is unavailable
Why
Agents can select displays for capture, but they cannot currently inspect the monitor layout and DPI metadata before choosing coordinates or validating a DPI-specific run. A structured inventory makes that state explicit without changing existing screenshot or input behavior.
Add DisplayInventory tool for per-monitor layout, work area, and DPI metadata
✨ Enhancement🧪 Tests📝 Documentation🕐 40+ Minutes
AI Description
• Add a read-only DisplayInventory tool that returns active monitor layout and DPI metadata.
• Extend monitor enumeration to include work area, effective DPI/scale, and orientation.
• Add focused tests for tool output, DPI fallback behavior, and orientation detection.
The following are alternative approaches to this PR:
1. Use typed ctypes structures for DEVMODEW (avoid manual offsets)
➕ Less brittle than hard-coded byte offsets when reading width/height
➕ Self-documenting field names reduce maintenance risk
➖ More code to define/maintain structs across 32/64-bit and packing nuances
➖ Still depends on Win32 API availability/behavior
2. Use QueryDisplayConfig for orientation/mode metadata
➕ More authoritative for modern display topology and rotation state
➕ Potentially richer metadata (paths/modes) for future extensions
➖ Significantly more complex API surface and parsing logic
➖ May require additional compatibility handling across Windows versions
Recommendation: Current approach is reasonable for a lightweight, read-only inventory tool: it reuses the existing monitor enumeration path and adds pragmatic DPI/orientation enrichment with safe fallbacks. If this tool becomes heavily relied upon, consider replacing the DEVMODE byte-offset parsing with a proper ctypes DEVMODEW struct first (lowest-risk hardening), and only move to QueryDisplayConfig if richer topology data is needed.
• Introduces a read-only 'DisplayInventory' tool that returns a JSON payload with display index, device name, bounds, work area, resolution, orientation, effective DPI, and scale. Includes a helper to serialize Rect-like objects while preserving negative virtual-screen coordinates.
core.pyEnrich DisplayInfo with work area, DPI/scale, and orientation+89/-0
Enrich DisplayInfo with work area, DPI/scale, and orientation
• Extends 'DisplayInfo' to include 'work_rect', 'effective_dpi', 'scale', and 'orientation'. Augments monitor enumeration to populate work area, compute effective per-monitor DPI with a system-DPI fallback, and infer orientation using 'EnumDisplaySettingsW' with bounds-based fallback.
test_display_inventory_tool.pyAdd tests for DisplayInventory output and DPI/orientation fallbacks+105/-0
Add tests for DisplayInventory output and DPI/orientation fallbacks
• Adds unit tests validating the tool’s JSON output shape, DPI fallback behavior when per-monitor DPI is unavailable, and orientation inference using current display mode with a bounds fallback.
1. DisplayInventory not JSON array 📎 Requirement gap≡ Correctness
Description
The DisplayInventory tool returns an object with displays/count instead of a top-level JSON
array of per-monitor records. This violates the required output contract and may break clients
expecting an array response.
No historical evidence enforcing array-only DisplayInventory output contract.
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
PR Compliance ID 222811 requires a DisplayInventory tool that returns a JSON array of per-monitor
objects. The implementation instead returns json.dumps(payload) where payload is a dict
containing displays and count.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
`DisplayInventory` currently returns a JSON object containing `displays` and `count`, but the compliance requirement specifies that the tool must return a top-level JSON array with one object per active monitor.
## Issue Context
Keeping a stable tool response shape matters for MCP clients. If `count` is still desired, consider adding it via a separate tool or embedding it in each record is not appropriate; the rule explicitly calls for a top-level array.
## Fix Focus Areas
- src/windows_mcp/tools/display.py[49-66]
- tests/test_display_inventory_tool.py[40-75]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
2. Long assert line 📘 Rule violation✧ Quality
Description
A newly added test assertion appears to exceed the 100 character maximum line length. This violates
the style requirement and can reduce readability in reviews and diffs.
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
PR Compliance ID 222796 enforces a maximum line length of 100 characters for non-comment code lines.
The added assertion line is long enough to exceed this limit and should be wrapped.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
A newly added line exceeds the 100 character maximum.
## Issue Context
Wrap the assertion using parentheses and line breaks at natural boundaries (e.g., after commas) to keep each line within 100 characters.
## Fix Focus Areas
- tests/test_display_inventory_tool.py[98-98]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
3. hMonitor not snake_case 📘 Rule violation✧ Quality
Description
The new function parameter hMonitor uses mixed casing rather than snake_case. This reduces
consistency with Python naming conventions required by the checklist.
No past reviews found about renaming hMonitor-style Win32 handle params.
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
PR Compliance ID 222797 requires snake_case for function/variable identifiers. The new parameter
hMonitor in _get_monitor_effective_dpi is not snake_case.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
A newly added identifier (`hMonitor`) violates the snake_case naming requirement for function/variable identifiers.
## Issue Context
This is a Windows handle parameter, but the rule still requires snake_case in Python code. Rename consistently and update all internal references.
## Fix Focus Areas
- src/windows_mcp/uia/core.py[711-726]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
DisplayInventory returns a JSON-formatted string via json.dumps, making the tool result text-only
rather than a native structured response like Snapshot/Screenshot; this forces consumers to
JSON-parse manually and makes tool outputs inconsistent across the toolset.
No past reviews found about avoiding json.dumps in tool outputs.
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
The tool explicitly returns json.dumps(...) (string). Snapshot/Screenshot paths demonstrate the
codebase already supports returning structured content (a list with text/image parts), highlighting
the inconsistency.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
### Issue description
`DisplayInventory` currently returns `json.dumps(payload, indent=2)` (a string). This makes the tool output inconsistent with other tools that return structured content (e.g., Snapshot returns a list of content parts), and it requires clients/agents to manually parse JSON to use the data programmatically.
### Issue Context
The tool already builds a fully JSON-serializable `payload` dict; the only question is the most appropriate return type for FastMCP/MCP consumption.
### Fix Focus Areas
- src/windows_mcp/tools/display.py[47-66]
### Suggested fix
Return `payload` directly (or, if the MCP framework expects content parts, return `[json.dumps(payload)]` consistently with other text-returning tools). Ensure tests are updated to match the chosen return type.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
ⓘ Recommendations generated based on similar findings in past PRs
Evidence
PR Compliance ID 222802 requires Google-style docstrings on public functions/classes in changed
files. register is a public function (no leading underscore) and has no docstring immediately
under its definition.
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution
## Issue description
The public `register` function is missing a Google-style docstring describing purpose, arguments, and behavior.
## Issue Context
This module defines an MCP tool. The registration entry point is part of the module's public surface and should be documented per the checklist.
## Fix Focus Areas
- src/windows_mcp/tools/display.py[25-30]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
DisplayInventorytool for active Windows monitorsEnumDisplaySettingsWWhy
Agents can select displays for capture, but they cannot currently inspect the monitor layout and DPI metadata before choosing coordinates or validating a DPI-specific run. A structured inventory makes that state explicit without changing existing screenshot or input behavior.
Output shape
[ { "index": 0, "device": "\\\\.\\DISPLAY1", "primary": true, "bounds": {"left": 0, "top": 0, "right": 1920, "bottom": 1080, "width": 1920, "height": 1080}, "work_area": {"left": 0, "top": 0, "right": 1920, "bottom": 1040, "width": 1920, "height": 1040}, "resolution": "1920x1080", "orientation": "landscape", "effective_dpi": 96, "scale": 1.0 } ]Duplicate and overlap check
ScreenInfosummary; it does not expose per-monitor work areas, orientation, or effective DPI records.main.Testing
ruff checkon all changed Python files: passedruff format --checkon all changed Python files: passed4 passed322 passed, 3 failedtests/test_iserror_compliance.pyimport failures reproduce on unmodifiedupstream/main1920x1080, DPI96, scale1.0,landscapeDependencies
None. This branch is based directly on current
mainand does not depend on the deterministic-drag PR.Closes #327