windows-mcp 0.5.9__py3-none-any.whl → 0.6.1__py3-none-any.whl

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.
windows_mcp/vdm/core.py CHANGED
@@ -12,43 +12,8 @@ from comtypes import GUID, IUnknown, COMMETHOD, STDMETHOD
12
12
 
13
13
  logger = logging.getLogger(__name__)
14
14
 
15
- import secrets
16
- import string
17
-
18
15
  _thread_local = threading.local()
19
16
 
20
- # Global mapping for Simple ID (Short) <-> GUID (Long)
21
- _SIMPLE_TO_GUID = {}
22
- _GUID_TO_SIMPLE = {}
23
- _MAP_LOCK = threading.Lock()
24
-
25
- def _get_simple_id(guid_str: str) -> str:
26
- """Gets or creates a simple 8-char ID for a given GUID string."""
27
- guid_str = guid_str.upper() # Normalize GUIDs
28
- with _MAP_LOCK:
29
- if guid_str in _GUID_TO_SIMPLE:
30
- return _GUID_TO_SIMPLE[guid_str]
31
-
32
- # Generate unique short ID
33
- while True:
34
- # 8 char random hex-like string (easy to read)
35
- alphabet = string.ascii_lowercase + string.digits
36
- short_id = ''.join(secrets.choice(alphabet) for _ in range(8))
37
- if short_id not in _SIMPLE_TO_GUID:
38
- break
39
-
40
- _SIMPLE_TO_GUID[short_id] = guid_str
41
- _GUID_TO_SIMPLE[guid_str] = short_id
42
- return short_id
43
-
44
- def _resolve_guid(simple_id: str) -> str:
45
- """Resolves a simple ID to its GUID string."""
46
- with _MAP_LOCK:
47
- if simple_id in _SIMPLE_TO_GUID:
48
- return _SIMPLE_TO_GUID[simple_id]
49
- # Fallback: maybe the user passed a real GUID?
50
- return simple_id
51
-
52
17
  def _get_manager():
53
18
  if not hasattr(_thread_local, "manager"):
54
19
  _thread_local.manager = VirtualDesktopManager()
@@ -77,7 +42,7 @@ class IVirtualDesktopManager(IUnknown):
77
42
  (['out', 'retval'], POINTER(GUID), "desktopId")),
78
43
  COMMETHOD([], HRESULT, "MoveWindowToDesktop",
79
44
  (['in'], HWND, "topLevelWindow"),
80
- (['in'], GUID, "desktopId")),
45
+ (['in'], POINTER(GUID), "desktopId")),
81
46
  ]
82
47
 
83
48
  # Internal COM Interfaces for Windows 11
@@ -89,8 +54,8 @@ class IServiceProvider(IUnknown):
89
54
  _iid_ = IID_IServiceProvider
90
55
  _methods_ = [
91
56
  COMMETHOD([], HRESULT, "QueryService",
92
- (['in'], GUID, "guidService"),
93
- (['in'], GUID, "riid"),
57
+ (['in'], POINTER(GUID), "guidService"),
58
+ (['in'], POINTER(GUID), "riid"),
94
59
  (['out'], POINTER(POINTER(IUnknown)), "ppvObject")),
95
60
  ]
96
61
 
@@ -102,7 +67,7 @@ class IObjectArray(IUnknown):
102
67
  (['out'], POINTER(UINT), "pcObjects")),
103
68
  COMMETHOD([], HRESULT, "GetAt",
104
69
  (['in'], UINT, "uiIndex"),
105
- (['in'], GUID, "riid"),
70
+ (['in'], POINTER(GUID), "riid"),
106
71
  (['out'], POINTER(POINTER(IUnknown)), "ppv")),
107
72
  ]
108
73
 
@@ -239,7 +204,7 @@ class VirtualDesktopManager:
239
204
  # Initialize Internal Manager
240
205
  try:
241
206
  service_provider = comtypes.client.CreateObject(CLSID_ImmersiveShell, interface=IServiceProvider)
242
- unk = service_provider.QueryService(CLSID_VirtualDesktopManagerInternal, IVirtualDesktopManagerInternal._iid_)
207
+ unk = service_provider.QueryService(byref(CLSID_VirtualDesktopManagerInternal), byref(IVirtualDesktopManagerInternal._iid_))
243
208
  self._internal_manager = unk.QueryInterface(IVirtualDesktopManagerInternal)
244
209
  except Exception as e:
245
210
  logger.warning(f"Failed to initialize VirtualDesktopManagerInternal: {e}")
@@ -267,27 +232,81 @@ class VirtualDesktopManager:
267
232
  return ""
268
233
  try:
269
234
  guid = self._manager.GetWindowDesktopId(hwnd)
270
- return _get_simple_id(str(guid))
235
+ return str(guid)
271
236
  except Exception:
272
237
  return ""
273
238
 
274
- def move_window_to_desktop(self, hwnd: int, desktop_id: str):
239
+ def _get_name_from_registry(self, guid_str: str) -> str:
275
240
  """
276
- Moves a window to the specified virtual desktop (by GUID string).
241
+ Retrieves the user-friendly name of a desktop from the Registry.
242
+ Returns None if no custom name is set.
243
+ """
244
+ try:
245
+ import winreg
246
+ path = f"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops\\Desktops\\{guid_str}"
247
+ with winreg.OpenKey(winreg.HKEY_CURRENT_USER, path) as key:
248
+ name, _ = winreg.QueryValueEx(key, "Name")
249
+ return name
250
+ except Exception:
251
+ return None
252
+
253
+ def _resolve_to_guid(self, name: str) -> str:
254
+ """
255
+ Resolves a desktop Name to a GUID string.
256
+ Also supports passing the GUID string directly if needed, but prioritizes Name.
257
+ """
258
+ # 1. Get current state (Names and GUIDs)
259
+ # We need to map Names to GUIDs.
260
+ desktops_map = {} # Name -> GUID
261
+
262
+ try:
263
+ desktops_array = self._internal_manager.GetDesktops()
264
+ count = desktops_array.GetCount()
265
+
266
+ for i in range(count):
267
+ unk = desktops_array.GetAt(i, byref(IVirtualDesktop._iid_))
268
+ desktop = unk.QueryInterface(IVirtualDesktop)
269
+ guid = getattr(desktop, "GetID", lambda: None)()
270
+ if not guid: continue
271
+ guid_str = str(guid)
272
+
273
+ # Determine Name
274
+ reg_name = self._get_name_from_registry(guid_str)
275
+ display_name = reg_name if reg_name else f"Desktop {i+1}"
276
+
277
+ desktops_map[display_name.lower()] = guid_str
278
+ # Also verify if the input IS the GUID (fallback support)
279
+ if name.lower() == guid_str.lower():
280
+ return guid_str
281
+
282
+ except Exception as e:
283
+ logger.error(f"Error scanning desktops for resolution: {e}")
284
+ return None
285
+
286
+ if name.lower() in desktops_map:
287
+ return desktops_map[name.lower()]
288
+
289
+ return None
290
+
291
+ def move_window_to_desktop(self, hwnd: int, desktop_name: str):
292
+ """
293
+ Moves a window to the specified virtual desktop (by Name).
277
294
  """
278
295
  if not self._manager:
279
296
  return
280
297
  try:
281
- target_guid_str = _resolve_guid(desktop_id)
298
+ target_guid_str = self._resolve_to_guid(desktop_name)
299
+ if not target_guid_str:
300
+ logger.error(f"Desktop '{desktop_name}' not found.")
301
+ return
282
302
  guid = GUID(target_guid_str)
283
- self._manager.MoveWindowToDesktop(hwnd, guid)
303
+ self._manager.MoveWindowToDesktop(hwnd, byref(guid))
284
304
  except Exception as e:
285
305
  logger.error(f"Failed to move window to desktop: {e}")
286
306
 
287
307
  def create_desktop(self, name: str = None) -> str:
288
308
  """
289
- Creates a new virtual desktop and returns its ID.
290
- Optionally sets the name of the new desktop.
309
+ Creates a new virtual desktop and returns its Name.
291
310
  """
292
311
  if not self._internal_manager:
293
312
  raise RuntimeError("Internal VDM not initialized")
@@ -296,30 +315,37 @@ class VirtualDesktopManager:
296
315
  guid = desktop.GetID()
297
316
  guid_str = str(guid)
298
317
 
299
- # Get simple ID
300
- simple_id = _get_simple_id(guid_str)
301
-
318
+ # If name is provided, set it immediately
302
319
  if name:
303
- self.rename_desktop(simple_id, name) # Use simple ID internally too now
304
-
305
- return simple_id
306
-
307
- def remove_desktop(self, desktop_id: str):
320
+ # We need to use the GUID to rename because we just created it
321
+ # But the external API returns the Name.
322
+ # We can try to rename using our helper
323
+ self.rename_desktop_by_guid(guid_str, name)
324
+ return name
325
+ else:
326
+ # If no name provided, determine what its default name is
327
+ # We can calculate it by checking total count
328
+ desktops = self.get_all_desktops()
329
+ return desktops[-1]['name'] # Assume it's the last one
330
+
331
+ def remove_desktop(self, desktop_name: str):
308
332
  """
309
- Removes a virtual desktop by ID.
310
- Will try to fallback to the first available desktop that is not the one being deleted.
333
+ Removes a virtual desktop by Name.
311
334
  """
312
335
  if not self._internal_manager:
313
336
  raise RuntimeError("Internal VDM not initialized")
314
337
 
315
- target_guid_str = _resolve_guid(desktop_id)
338
+ target_guid_str = self._resolve_to_guid(desktop_name)
339
+ if not target_guid_str:
340
+ logger.error(f"Desktop '{desktop_name}' not found.")
341
+ return
342
+
316
343
  target_guid = GUID(target_guid_str)
317
344
 
318
- # We need the IVirtualDesktop object for the target
319
345
  try:
320
346
  target_desktop = self._internal_manager.FindDesktop(target_guid)
321
347
  except Exception:
322
- logger.error(f"Could not find desktop with ID {desktop_id}")
348
+ logger.error(f"Could not find desktop with GUID {target_guid_str}")
323
349
  return
324
350
 
325
351
  # Find a fallback desktop
@@ -328,7 +354,7 @@ class VirtualDesktopManager:
328
354
  fallback_desktop = None
329
355
 
330
356
  for i in range(count):
331
- unk = desktops_array.GetAt(i, IVirtualDesktop._iid_)
357
+ unk = desktops_array.GetAt(i, byref(IVirtualDesktop._iid_))
332
358
  candidate = unk.QueryInterface(IVirtualDesktop)
333
359
  candidate_id = candidate.GetID()
334
360
  if str(candidate_id) != str(target_guid):
@@ -336,31 +362,37 @@ class VirtualDesktopManager:
336
362
  break
337
363
 
338
364
  if not fallback_desktop:
339
- # If no other desktop, we can't delete the only one? Or create one?
340
- # Windows usually prevents deleting the last one.
341
365
  logger.error("No fallback desktop found (cannot delete the only desktop)")
342
366
  return
343
367
 
344
368
  self._internal_manager.RemoveDesktop(target_desktop, fallback_desktop)
345
369
 
346
- def rename_desktop(self, desktop_id: str, new_name: str):
370
+ def rename_desktop(self, desktop_name: str, new_name: str):
347
371
  """
348
- Renames a virtual desktop.
372
+ Renames a virtual desktop (identified by current Name).
349
373
  """
350
- if not self._internal_manager:
351
- raise RuntimeError("Internal VDM not initialized")
374
+ target_guid_str = self._resolve_to_guid(desktop_name)
375
+ if not target_guid_str:
376
+ logger.error(f"Desktop '{desktop_name}' not found.")
377
+ return
352
378
 
353
- target_guid_str = _resolve_guid(desktop_id)
354
- target_guid = GUID(target_guid_str)
379
+ self.rename_desktop_by_guid(target_guid_str, new_name)
380
+
381
+ def rename_desktop_by_guid(self, guid_str: str, new_name: str):
382
+ """
383
+ Internal helper to rename by GUID.
384
+ """
385
+ if not self._internal_manager:
386
+ return
387
+
388
+ target_guid = GUID(guid_str)
355
389
  try:
356
390
  target_desktop = self._internal_manager.FindDesktop(target_guid)
357
391
  except Exception:
358
- logger.error(f"Could not find desktop with ID {desktop_id}")
359
392
  return
360
393
 
361
394
  hs_name = create_hstring(new_name)
362
395
  try:
363
- # Check if SetName method exists (it might not on Windows 10)
364
396
  if hasattr(self._internal_manager, "SetName"):
365
397
  self._internal_manager.SetName(target_desktop, hs_name)
366
398
  else:
@@ -370,30 +402,34 @@ class VirtualDesktopManager:
370
402
  finally:
371
403
  delete_hstring(hs_name)
372
404
 
373
- def switch_desktop(self, desktop_id: str):
405
+ def switch_desktop(self, desktop_name: str):
374
406
  """
375
- Switches to the specified virtual desktop.
407
+ Switches to the specified virtual desktop (by Name).
376
408
  """
377
409
  if not self._internal_manager:
378
410
  raise RuntimeError("Internal VDM not initialized")
379
411
 
380
- target_guid_str = _resolve_guid(desktop_id)
412
+ target_guid_str = self._resolve_to_guid(desktop_name)
413
+ if not target_guid_str:
414
+ logger.error(f"Desktop '{desktop_name}' not found")
415
+ return
416
+
381
417
  target_guid = GUID(target_guid_str)
382
418
  try:
383
419
  target_desktop = self._internal_manager.FindDesktop(target_guid)
384
- except Exception:
385
- logger.error(f"Could not find desktop with ID {desktop_id}")
386
- return
387
-
388
- self._internal_manager.SwitchDesktop(target_desktop)
420
+ self._internal_manager.SwitchDesktop(target_desktop)
421
+ except Exception as e:
422
+ logger.error(f"Failed to switch desktop: {e}")
389
423
 
390
424
  def get_all_desktops(self) -> list[dict]:
391
425
  """
392
426
  Returns a list of all virtual desktops.
393
- Each entry is a dict: {'id': str, 'name': str}
427
+ Returns [{'name': 'Desktop 1', 'id': '...'}, ...]
428
+ Note: ID is kept for internal robustness but name is preferred.
394
429
  """
395
430
  if not self._internal_manager:
396
- raise RuntimeError("Internal VDM not initialized")
431
+ # Fallback for Server/unsupported builds
432
+ return [{'id': '00000000-0000-0000-0000-000000000000', 'name': 'Default Desktop'}]
397
433
 
398
434
  desktops_array = self._internal_manager.GetDesktops()
399
435
  count = desktops_array.GetCount()
@@ -401,25 +437,22 @@ class VirtualDesktopManager:
401
437
  result = []
402
438
  for i in range(count):
403
439
  try:
404
- unk = desktops_array.GetAt(i, IVirtualDesktop._iid_)
440
+ unk = desktops_array.GetAt(i, byref(IVirtualDesktop._iid_))
405
441
  desktop = unk.QueryInterface(IVirtualDesktop)
406
- guid = desktop.GetID()
407
- simple_id = _get_simple_id(str(guid))
408
-
409
- name = ""
410
- try:
411
- # Windows 10 interface might not support GetName commonly or it might fail
412
- if hasattr(desktop, "GetName"):
413
- hname = desktop.GetName()
414
- name = ctypes.wstring_at(hname)
415
- delete_hstring(hname)
416
- except Exception:
417
- pass # Name retrieval failed, ignore
442
+ guid = getattr(desktop, "GetID", lambda: None)()
443
+ if not guid: continue
444
+
445
+ guid_str = str(guid)
446
+ # simple_id = _get_simple_id(guid_str)
418
447
 
419
- if not name:
448
+ # Get Name from Registry or Fallback
449
+ reg_name = self._get_name_from_registry(guid_str)
450
+ if reg_name:
451
+ name = reg_name
452
+ else:
420
453
  name = f"Desktop {i+1}"
421
454
 
422
- result.append({'id': simple_id, 'name': name})
455
+ result.append({'id': guid_str, 'name': name})
423
456
  except Exception as e:
424
457
  logger.error(f"Error retrieving desktop at index {i}: {e}")
425
458
  continue
@@ -430,61 +463,40 @@ class VirtualDesktopManager:
430
463
  def get_current_desktop(self) -> dict:
431
464
  """
432
465
  Returns info about the current virtual desktop.
433
- Returns: {'id': str, 'name': str}
466
+ Returns: {'name': str, 'id': str}
434
467
  """
435
468
  if not self._internal_manager:
436
- raise RuntimeError("Internal VDM not initialized")
469
+ # Fallback for Server/unsupported builds
470
+ return {'id': '00000000-0000-0000-0000-000000000000', 'name': 'Default Desktop'}
437
471
 
438
472
  current_desktop = self._internal_manager.GetCurrentDesktop()
439
473
  guid = current_desktop.GetID()
440
- simple_id = _get_simple_id(str(guid))
474
+ guid_str = str(guid)
475
+ # simple_id = _get_simple_id(guid_str)
441
476
 
442
- name = ""
443
- try:
444
- # Windows 10 interface might not support GetName commonly or it might fail
445
- if hasattr(current_desktop, "GetName"):
446
- hname = current_desktop.GetName()
447
- name = ctypes.wstring_at(hname)
448
- delete_hstring(hname)
449
- except Exception:
450
- pass
477
+ # We need the index to determine fallback name if registry is empty
478
+ # But scanning all is easier to reuse logic
479
+ all_desktops = self.get_all_desktops()
480
+ for d in all_desktops:
481
+ if d['id'] == guid_str:
482
+ return d
451
483
 
452
- if not name:
453
- # Fallback logic
454
- desktops_array = self._internal_manager.GetDesktops()
455
- count = desktops_array.GetCount()
456
- current_guid_str = str(guid)
457
-
458
- found_name = "Current Desktop"
459
- for i in range(count):
460
- try:
461
- unk = desktops_array.GetAt(i, IVirtualDesktop._iid_)
462
- candidate = unk.QueryInterface(IVirtualDesktop)
463
- candidate_guid_str = str(candidate.GetID())
464
- if candidate_guid_str == current_guid_str:
465
- found_name = f"Desktop {i+1}"
466
- break
467
- except Exception:
468
- continue
469
- name = found_name
470
-
471
- return {'id': simple_id, 'name': name}
484
+ return {'id': guid_str, 'name': "Unknown"}
472
485
 
473
486
  def create_desktop(name: str = None) -> str:
474
487
  return _get_manager().create_desktop(name)
475
488
 
476
- def remove_desktop(desktop_id: str):
477
- _get_manager().remove_desktop(desktop_id)
489
+ def remove_desktop(desktop_name: str):
490
+ _get_manager().remove_desktop(desktop_name)
478
491
 
479
- def rename_desktop(desktop_id: str, new_name: str):
480
- _get_manager().rename_desktop(desktop_id, new_name)
492
+ def rename_desktop(desktop_name: str, new_name: str):
493
+ _get_manager().rename_desktop(desktop_name, new_name)
481
494
 
482
- def switch_desktop(desktop_id: str):
483
- _get_manager().switch_desktop(desktop_id)
495
+ def switch_desktop(desktop_name: str):
496
+ _get_manager().switch_desktop(desktop_name)
484
497
 
485
498
  def get_all_desktops() -> list[dict]:
486
499
  return _get_manager().get_all_desktops()
487
500
 
488
501
  def get_current_desktop() -> dict:
489
502
  return _get_manager().get_current_desktop()
490
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: windows-mcp
3
- Version: 0.5.9
3
+ Version: 0.6.1
4
4
  Summary: Lightweight MCP Server for interacting with Windows Operating System.
5
5
  Project-URL: homepage, https://github.com/CursorTouch
6
6
  Author-email: Jeomon George <jeogeoalukka@gmail.com>
@@ -73,7 +73,7 @@ Description-Content-Type: text/markdown
73
73
  mcp-name: io.github.CursorTouch/Windows-MCP
74
74
 
75
75
  ## Updates
76
- - Windows-MCP reached 1M+ Users in [Claude Desktop Extensiosn](https://claude.ai/directory).
76
+ - Windows-MCP reached `1M+ Users` in [Claude Desktop Extensiosn](https://claude.ai/directory).
77
77
  - Windows-MCP is now available on [PyPI](https://pypi.org/project/windows-mcp/) (thus supports `uvx windows-mcp`)
78
78
  - Windows-MCP is added to [MCP Registry](https://github.com/modelcontextprotocol/registry)
79
79
  - Try out 🪟[Windows-Use](https://github.com/CursorTouch/Windows-Use)!!, an agent built using Windows-MCP.
@@ -110,7 +110,7 @@ mcp-name: io.github.CursorTouch/Windows-MCP
110
110
  Easily adapt or extend tools to suit your unique automation or AI integration needs.
111
111
 
112
112
  - **Real-Time Interaction**
113
- Typical latency between actions (e.g., from one mouse click to the next) ranges from **0.4 to 1.2 secs**, and may slightly vary based on the number of active applications and system load, also the inferencing speed of the llm.
113
+ Typical latency between actions (e.g., from one mouse click to the next) ranges from **0.2 to 0.9 secs**, and may slightly vary based on the number of active applications and system load, also the inferencing speed of the llm.
114
114
 
115
115
  - **DOM Mode for Browser Automation**
116
116
  Special `use_dom=True` mode for State-Tool that focuses exclusively on web page content, filtering out browser UI elements for cleaner, more efficient web automation.
@@ -347,8 +347,7 @@ MCP Client can access the following tools to interact with Windows:
347
347
  - `Click`: Click on the screen at the given coordinates.
348
348
  - `Type`: Type text on an element (optionally clears existing text).
349
349
  - `Scroll`: Scroll vertically or horizontally on the window or specific regions.
350
- - `Drag`: Drag from one point to another.
351
- - `Move`: Move mouse pointer.
350
+ - `Move`: Move mouse pointer or drag (set drag=True) to coordinates.
352
351
  - `Shortcut`: Press keyboard shortcuts (`Ctrl+c`, `Alt+Tab`, etc).
353
352
  - `Wait`: Pause for a defined duration.
354
353
  - `Snapshot`: Combined snapshot of default language, browser, active apps and interactive, textual and scrollable elements along with screenshot of the desktop. Supports `use_dom=True` for browser content extraction (web page elements only) and `use_vision=True` for including screenshots.
@@ -1,29 +1,29 @@
1
1
  windows_mcp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- windows_mcp/__main__.py,sha256=fWKa82Rp-xbsfpiEHKkv0C4AckKI7Rz6flE11qxirIY,12993
2
+ windows_mcp/__main__.py,sha256=_Zh_MBFb1sETzkVz-TSxMS1M6yz3Yb4UbFEJH2DKJNU,14547
3
3
  windows_mcp/analytics.py,sha256=yir5IWAI_YN9dmy9KOVIRYsZbeAO12INcxvY2WJSWCU,6307
4
4
  windows_mcp/desktop/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
5
  windows_mcp/desktop/config.py,sha256=LxMWSyYOUfMKzkk5ts46dV1NrAnukS2zHjTfyEKRc-A,364
6
- windows_mcp/desktop/service.py,sha256=oT0fDW-uz3p3xdexPS88Y5PvTkfrLwa5boW_sFkJl7M,26142
7
- windows_mcp/desktop/views.py,sha256=5EEeG4aPDFPqxx0Fhs8ejfHC-eC7Bt2ezOYpOerVBwM,1578
6
+ windows_mcp/desktop/service.py,sha256=BAy13hqUktHhelqbqmC_13lp5eilSbu9OLB_PiDMra8,30433
7
+ windows_mcp/desktop/views.py,sha256=pkIJQrriAoKyCxdWP1li4MoThB_Us0xFn21Pbm7eHJ4,2265
8
8
  windows_mcp/tree/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  windows_mcp/tree/cache_utils.py,sha256=xuS4Gt96Az8eYoo9cu464NRZWuGQngDCgAhT2iYX-j8,5361
10
10
  windows_mcp/tree/config.py,sha256=2UbH76pA5VdlbFQ8-PCog-MoGxLmk5Pv1mvfAAg_9HQ,1496
11
- windows_mcp/tree/service.py,sha256=KWFfH8Setzf0YAO1S4sVcMsRHbpQamD5_tba8rUdEz0,30518
12
- windows_mcp/tree/utils.py,sha256=YaUqg_pK4pnii0Idzo0bwYcf7Xo3FQsxzwGNL7Qh1L4,893
13
- windows_mcp/tree/views.py,sha256=OHxjuF2FpxdSZeD6CIO0Ec64jaZSEBXIH_dcvmq0CmA,4794
11
+ windows_mcp/tree/service.py,sha256=hcRwAU4ahUGeOIWyaVg4_Un_pIXNx8_PS2-rTY91hds,30656
12
+ windows_mcp/tree/utils.py,sha256=Sfy9i7JGxwpynYbU-t_fgTNgDshLX8brO6Z23ySaN1w,914
13
+ windows_mcp/tree/views.py,sha256=C_3Cmm2t7oeEvbsAz8Qk8KNOo5v2Mj289sUj5m-9KXQ,4840
14
14
  windows_mcp/uia/__init__.py,sha256=ePdeJOHmTihMedolZUEL59nKDXsBVyofT80miP_5G-Y,93
15
- windows_mcp/uia/controls.py,sha256=xIRMJkktj0UzTeaxPO8g51aBV8Y9wL_EbrUZt77SgQY,223941
16
- windows_mcp/uia/core.py,sha256=sgtzb8QmevNWuv_nORF3F_wU97TxCjZWZlpYPYWcoS8,132131
15
+ windows_mcp/uia/controls.py,sha256=u8Z8-HNtquzeLM_MS7ASiOiTAq0pY1OO_rqi0LTppwU,221908
16
+ windows_mcp/uia/core.py,sha256=0GIKuTATu4Rd1FXRKfb5TXnYZHeENdFJrSINn1AIuLQ,92943
17
17
  windows_mcp/uia/enums.py,sha256=DYcypTL8zkygdjZUezE2jgz9RMBM9AWe8ofvubLHRCg,83577
18
18
  windows_mcp/uia/events.py,sha256=9Xwcn-X1dy2t6WlbwDsIedcKq1SIIHGZ183qpohfFBk,4726
19
19
  windows_mcp/uia/patterns.py,sha256=CShOYqYMv7wdwDpNYZZZU3WZuLMvYhAAmnbzQ2Hx7aA,102692
20
20
  windows_mcp/vdm/__init__.py,sha256=nE8jJjGJaKuJKCyuf6QLfrj8xPj8IqGKeH2VXP3FMzY,21
21
- windows_mcp/vdm/core.py,sha256=OQFgkmt-hscUJc-fzBOS_klmCiax-wSTPRaX3TNDJbQ,21404
21
+ windows_mcp/vdm/core.py,sha256=E5GxlWAxrhXMZm635oXQ_vLFo0tBkPuM0JFwtW7nANE,22216
22
22
  windows_mcp/watchdog/__init__.py,sha256=ExC350_KZXwTENsLQfESSPUJZfwsEjrAvGtLRPCqqjk,31
23
23
  windows_mcp/watchdog/event_handlers.py,sha256=mHw2msgAjkGuYwTp-U6tYX-gL4S7N1J1HQNmyQ-sdVk,2052
24
24
  windows_mcp/watchdog/service.py,sha256=9Tpoq8Ma3MF0Zq7yJKkLOx8NCm4bcUeJY_P1GPkjeLk,9099
25
- windows_mcp-0.5.9.dist-info/METADATA,sha256=OlwcJWkX4z-ZDOLdwAjGqiRxzNupISf0WvFHhRq8F5A,14545
26
- windows_mcp-0.5.9.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
- windows_mcp-0.5.9.dist-info/entry_points.txt,sha256=wW8NcVQ_OJK5e5GemZSE_nOKyxfUtBPq2acFLszRwaw,58
28
- windows_mcp-0.5.9.dist-info/licenses/LICENSE.md,sha256=U1UM4Xi_IX-jHnHjGT0rETNia-Ck8gd92iSQMqQ6a8Y,1089
29
- windows_mcp-0.5.9.dist-info/RECORD,,
25
+ windows_mcp-0.6.1.dist-info/METADATA,sha256=msCbxd1tnvZGVJNy5Dird6u7a6kGcxevuVwkFPXrQr0,14544
26
+ windows_mcp-0.6.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
27
+ windows_mcp-0.6.1.dist-info/entry_points.txt,sha256=wW8NcVQ_OJK5e5GemZSE_nOKyxfUtBPq2acFLszRwaw,58
28
+ windows_mcp-0.6.1.dist-info/licenses/LICENSE.md,sha256=U1UM4Xi_IX-jHnHjGT0rETNia-Ck8gd92iSQMqQ6a8Y,1089
29
+ windows_mcp-0.6.1.dist-info/RECORD,,