oswright 0.1.0__tar.gz
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.
- oswright-0.1.0/LICENSE +21 -0
- oswright-0.1.0/PKG-INFO +369 -0
- oswright-0.1.0/README.md +335 -0
- oswright-0.1.0/oswright/__init__.py +26 -0
- oswright-0.1.0/oswright/__main__.py +5 -0
- oswright-0.1.0/oswright/_input_pynput.py +247 -0
- oswright-0.1.0/oswright/_input_windows.py +307 -0
- oswright-0.1.0/oswright/capture.py +82 -0
- oswright-0.1.0/oswright/core.py +86 -0
- oswright-0.1.0/oswright/detect.py +267 -0
- oswright-0.1.0/oswright/input.py +30 -0
- oswright-0.1.0/oswright/locator.py +365 -0
- oswright-0.1.0/oswright/mcp_server.py +956 -0
- oswright-0.1.0/oswright/py.typed +0 -0
- oswright-0.1.0/oswright/screen.py +259 -0
- oswright-0.1.0/oswright.egg-info/PKG-INFO +369 -0
- oswright-0.1.0/oswright.egg-info/SOURCES.txt +21 -0
- oswright-0.1.0/oswright.egg-info/dependency_links.txt +1 -0
- oswright-0.1.0/oswright.egg-info/entry_points.txt +2 -0
- oswright-0.1.0/oswright.egg-info/requires.txt +13 -0
- oswright-0.1.0/oswright.egg-info/top_level.txt +1 -0
- oswright-0.1.0/pyproject.toml +46 -0
- oswright-0.1.0/setup.cfg +4 -0
oswright-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 OSWright Contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
oswright-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oswright
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Playwright-like automation framework for the operating system
|
|
5
|
+
Author: OSWright Contributors
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Keywords: automation,testing,os,desktop,gui
|
|
8
|
+
Classifier: Development Status :: 3 - Alpha
|
|
9
|
+
Classifier: Intended Audience :: Developers
|
|
10
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Topic :: Software Development :: Testing
|
|
19
|
+
Classifier: Topic :: Desktop Environment
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: mss>=9.0
|
|
24
|
+
Requires-Dist: Pillow>=10.0
|
|
25
|
+
Requires-Dist: opencv-python>=4.8
|
|
26
|
+
Requires-Dist: numpy>=1.24
|
|
27
|
+
Requires-Dist: easyocr>=1.7
|
|
28
|
+
Requires-Dist: mcp[cli]>=1.0
|
|
29
|
+
Requires-Dist: pynput>=1.7; sys_platform != "win32"
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
32
|
+
Requires-Dist: ruff>=0.1; extra == "dev"
|
|
33
|
+
Dynamic: license-file
|
|
34
|
+
|
|
35
|
+
# OSWright
|
|
36
|
+
|
|
37
|
+
A Model Context Protocol (MCP) server that provides **OS-level desktop automation** using OCR and image matching. This server enables LLMs to interact with any desktop application -- click buttons, type text, read screens, and fill forms -- just like [Playwright MCP](https://github.com/microsoft/playwright-mcp) does for browsers.
|
|
38
|
+
|
|
39
|
+
### Key Features
|
|
40
|
+
|
|
41
|
+
- **Cross-platform.** Windows (Win32 API), Linux (pynput/X11), macOS (pynput/Quartz).
|
|
42
|
+
- **OCR-powered.** Finds UI elements by their visible text using EasyOCR.
|
|
43
|
+
- **Image matching.** Locates elements by template image via OpenCV.
|
|
44
|
+
- **Auto-snapshot.** Every action returns a screenshot so the agent always sees current state.
|
|
45
|
+
- **Compound tools.** High-level actions like `click_text`, `fill_field`, `fill_form` reduce round-trips.
|
|
46
|
+
|
|
47
|
+
### Requirements
|
|
48
|
+
|
|
49
|
+
- Python 3.10 or newer
|
|
50
|
+
- VS Code, Cursor, Windsurf, Claude Desktop, or any other MCP client
|
|
51
|
+
|
|
52
|
+
## Getting started
|
|
53
|
+
|
|
54
|
+
First, install the OSWright MCP server with your client.
|
|
55
|
+
|
|
56
|
+
**Standard config** works in most tools:
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{
|
|
60
|
+
"mcpServers": {
|
|
61
|
+
"oswright": {
|
|
62
|
+
"command": "uvx",
|
|
63
|
+
"args": ["oswright"]
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
> **Note:** If you don't have `uvx`, you can use `pip install oswright` and then set `"command": "oswright"` directly.
|
|
70
|
+
|
|
71
|
+
<details>
|
|
72
|
+
<summary>Claude Desktop</summary>
|
|
73
|
+
|
|
74
|
+
Follow the MCP install [guide](https://modelcontextprotocol.io/quickstart/user), use the standard config above.
|
|
75
|
+
|
|
76
|
+
</details>
|
|
77
|
+
|
|
78
|
+
<details>
|
|
79
|
+
<summary>Claude Code</summary>
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
claude mcp add oswright uvx oswright
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
</details>
|
|
86
|
+
|
|
87
|
+
<details>
|
|
88
|
+
<summary>VS Code</summary>
|
|
89
|
+
|
|
90
|
+
Add to your user or workspace `settings.json` under `mcp.servers`:
|
|
91
|
+
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"mcp": {
|
|
95
|
+
"servers": {
|
|
96
|
+
"oswright": {
|
|
97
|
+
"command": "uvx",
|
|
98
|
+
"args": ["oswright"]
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Or use the VS Code CLI:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
code --add-mcp '{"name":"oswright","command":"uvx","args":["oswright"]}'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
</details>
|
|
112
|
+
|
|
113
|
+
<details>
|
|
114
|
+
<summary>Cursor</summary>
|
|
115
|
+
|
|
116
|
+
Go to `Cursor Settings` -> `MCP` -> `Add new MCP Server`. Name it `oswright`, use `command` type with the command `uvx oswright`.
|
|
117
|
+
|
|
118
|
+
</details>
|
|
119
|
+
|
|
120
|
+
<details>
|
|
121
|
+
<summary>Windsurf</summary>
|
|
122
|
+
|
|
123
|
+
Follow Windsurf MCP [documentation](https://docs.windsurf.com/windsurf/cascade/mcp). Use the standard config above.
|
|
124
|
+
|
|
125
|
+
</details>
|
|
126
|
+
|
|
127
|
+
<details>
|
|
128
|
+
<summary>Cline</summary>
|
|
129
|
+
|
|
130
|
+
Add to your `cline_mcp_settings.json`:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"mcpServers": {
|
|
135
|
+
"oswright": {
|
|
136
|
+
"type": "stdio",
|
|
137
|
+
"command": "uvx",
|
|
138
|
+
"args": ["oswright"],
|
|
139
|
+
"disabled": false
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
</details>
|
|
146
|
+
|
|
147
|
+
<details>
|
|
148
|
+
<summary>Goose</summary>
|
|
149
|
+
|
|
150
|
+
Go to `Advanced settings` -> `Extensions` -> `Add custom extension`. Name it `oswright`, use type `STDIO`, and set the `command` to `uvx oswright`.
|
|
151
|
+
|
|
152
|
+
</details>
|
|
153
|
+
|
|
154
|
+
<details>
|
|
155
|
+
<summary>Using pip instead of uvx</summary>
|
|
156
|
+
|
|
157
|
+
If you prefer a standard pip install:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
pip install oswright
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Then use this config:
|
|
164
|
+
|
|
165
|
+
```json
|
|
166
|
+
{
|
|
167
|
+
"mcpServers": {
|
|
168
|
+
"oswright": {
|
|
169
|
+
"command": "oswright"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Or run directly:
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
python -m oswright
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
</details>
|
|
182
|
+
|
|
183
|
+
## Configuration
|
|
184
|
+
|
|
185
|
+
OSWright MCP server supports the following arguments. They can be provided in the JSON configuration as part of the `"args"` list:
|
|
186
|
+
|
|
187
|
+
| Option | Description | Env Variable |
|
|
188
|
+
|--------|-------------|-------------|
|
|
189
|
+
| `--port <port>` | Port for SSE transport. If omitted, uses stdio (default). | `FASTMCP_PORT` |
|
|
190
|
+
| `--host <host>` | Host to bind SSE server to. Default: `localhost`. | `FASTMCP_HOST` |
|
|
191
|
+
| `--transport <mode>` | Transport protocol: `stdio`, `sse`, `streamable-http`. Auto-detected from `--port`. | |
|
|
192
|
+
| `--ocr-languages <langs>` | OCR languages (default: `en`). Example: `--ocr-languages en es fr` | `OSWRIGHT_OCR_LANGUAGES` |
|
|
193
|
+
| `--timeout <seconds>` | Default timeout for auto-wait operations (default: `10`). | `OSWRIGHT_TIMEOUT` |
|
|
194
|
+
| `--log-level <level>` | Logging level: `DEBUG`, `INFO`, `WARNING`, `ERROR`. Default: `INFO`. | `OSWRIGHT_LOG_LEVEL` |
|
|
195
|
+
|
|
196
|
+
### Example: Multi-language OCR
|
|
197
|
+
|
|
198
|
+
```json
|
|
199
|
+
{
|
|
200
|
+
"mcpServers": {
|
|
201
|
+
"oswright": {
|
|
202
|
+
"command": "uvx",
|
|
203
|
+
"args": ["oswright", "--ocr-languages", "en", "es", "fr"]
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Standalone MCP server (SSE)
|
|
210
|
+
|
|
211
|
+
When running from a remote machine or a worker process, use SSE transport:
|
|
212
|
+
|
|
213
|
+
```bash
|
|
214
|
+
uvx oswright --port 8931
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
Then in your MCP client config:
|
|
218
|
+
|
|
219
|
+
```json
|
|
220
|
+
{
|
|
221
|
+
"mcpServers": {
|
|
222
|
+
"oswright": {
|
|
223
|
+
"url": "http://localhost:8931/mcp"
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Platform Notes
|
|
230
|
+
|
|
231
|
+
| Platform | Input Backend | Notes |
|
|
232
|
+
|----------|--------------|-------|
|
|
233
|
+
| Windows | Win32 API (SendInput) | No extra dependencies. Works out of the box. |
|
|
234
|
+
| Linux | pynput (X11) | Requires X11 display server. Wayland has limited support. |
|
|
235
|
+
| macOS | pynput (Quartz) | Grant Accessibility permissions in System Settings > Privacy > Accessibility. |
|
|
236
|
+
|
|
237
|
+
## Tools
|
|
238
|
+
|
|
239
|
+
<details>
|
|
240
|
+
<summary><b>Screen</b></summary>
|
|
241
|
+
|
|
242
|
+
- **screenshot** -- Take a screenshot of the screen or a region. Returns the image as native MCP image content. Optionally saves to a file path.
|
|
243
|
+
- Read-only: **true**
|
|
244
|
+
|
|
245
|
+
- **get_screen_info** -- Get screen dimensions and monitor count.
|
|
246
|
+
- Read-only: **true**
|
|
247
|
+
|
|
248
|
+
</details>
|
|
249
|
+
|
|
250
|
+
<details>
|
|
251
|
+
<summary><b>OCR / Text Finding</b></summary>
|
|
252
|
+
|
|
253
|
+
- **find_text_on_screen** -- Find all occurrences of text on screen using OCR. Returns matches with coordinates and confidence.
|
|
254
|
+
- Parameters: `text`, `exact`, region bounds, `monitor`
|
|
255
|
+
- Read-only: **true**
|
|
256
|
+
|
|
257
|
+
- **read_screen_text** -- Read ALL visible text on the screen using OCR. Returns every detected text element with position.
|
|
258
|
+
- Parameters: region bounds, `monitor`
|
|
259
|
+
- Read-only: **true**
|
|
260
|
+
|
|
261
|
+
</details>
|
|
262
|
+
|
|
263
|
+
<details>
|
|
264
|
+
<summary><b>Image Matching</b></summary>
|
|
265
|
+
|
|
266
|
+
- **find_image_on_screen** -- Find all occurrences of a template image on screen using OpenCV template matching.
|
|
267
|
+
- Parameters: `template_path`, `threshold`, `monitor`
|
|
268
|
+
- Read-only: **true**
|
|
269
|
+
|
|
270
|
+
</details>
|
|
271
|
+
|
|
272
|
+
<details>
|
|
273
|
+
<summary><b>Mouse</b></summary>
|
|
274
|
+
|
|
275
|
+
- **mouse_click** -- Click the mouse at coordinates or current position. Returns screenshot.
|
|
276
|
+
- Parameters: `x`, `y`, `button`, `clicks`
|
|
277
|
+
|
|
278
|
+
- **mouse_double_click** -- Double-click at coordinates or current position. Returns screenshot.
|
|
279
|
+
|
|
280
|
+
- **mouse_move** -- Move the mouse cursor to screen coordinates.
|
|
281
|
+
|
|
282
|
+
- **mouse_scroll** -- Scroll the mouse wheel. Returns screenshot.
|
|
283
|
+
- Parameters: `amount`, `x`, `y`
|
|
284
|
+
|
|
285
|
+
- **mouse_drag** -- Drag from one point to another. Returns screenshot.
|
|
286
|
+
- Parameters: `start_x`, `start_y`, `end_x`, `end_y`, `button`, `duration`
|
|
287
|
+
|
|
288
|
+
- **get_mouse_position** -- Get the current mouse cursor position.
|
|
289
|
+
- Read-only: **true**
|
|
290
|
+
|
|
291
|
+
</details>
|
|
292
|
+
|
|
293
|
+
<details>
|
|
294
|
+
<summary><b>Keyboard</b></summary>
|
|
295
|
+
|
|
296
|
+
- **type_text** -- Type text character by character. Returns screenshot.
|
|
297
|
+
- Parameters: `text`, `delay`
|
|
298
|
+
|
|
299
|
+
- **press_key** -- Press a key or combo like `Enter`, `Ctrl+C`, `Alt+Tab`. Returns screenshot.
|
|
300
|
+
- Parameters: `key`
|
|
301
|
+
|
|
302
|
+
</details>
|
|
303
|
+
|
|
304
|
+
<details>
|
|
305
|
+
<summary><b>Compound Actions</b></summary>
|
|
306
|
+
|
|
307
|
+
- **click_text** -- Find text via OCR and click on it. Auto-retries until found or timeout. Returns screenshot.
|
|
308
|
+
- Parameters: `text`, `exact`, `button`, `timeout`, `poll_interval`, `monitor`
|
|
309
|
+
|
|
310
|
+
- **double_click_text** -- Find text via OCR and double-click on it. Returns screenshot.
|
|
311
|
+
|
|
312
|
+
- **right_click_text** -- Find text via OCR and right-click on it. Returns screenshot.
|
|
313
|
+
|
|
314
|
+
- **hover_text** -- Find text via OCR and hover over it. Returns screenshot.
|
|
315
|
+
|
|
316
|
+
- **fill_field** -- Find a label, click it, clear, and type a value. Returns screenshot.
|
|
317
|
+
- Parameters: `target_text`, `value`, `exact`, `timeout`, `monitor`
|
|
318
|
+
|
|
319
|
+
- **fill_form** -- Fill multiple fields in one call. Reduces round-trips.
|
|
320
|
+
- Parameters: `fields` (list of `{label, value}`), `timeout`, `monitor`
|
|
321
|
+
|
|
322
|
+
- **wait_for_text** -- Wait for text to appear on screen. Polls via OCR.
|
|
323
|
+
- Parameters: `text`, `exact`, `timeout`, `poll_interval`, `monitor`
|
|
324
|
+
- Read-only: **true**
|
|
325
|
+
|
|
326
|
+
- **wait_for_text_gone** -- Wait for text to disappear from screen.
|
|
327
|
+
- Parameters: `text`, `exact`, `timeout`, `poll_interval`, `monitor`
|
|
328
|
+
- Read-only: **true**
|
|
329
|
+
|
|
330
|
+
- **wait_for_time** -- Wait for a specified duration (capped at 30s), then screenshot.
|
|
331
|
+
|
|
332
|
+
</details>
|
|
333
|
+
|
|
334
|
+
## Python Library
|
|
335
|
+
|
|
336
|
+
OSWright also works as a standalone Python library with a Playwright-style API:
|
|
337
|
+
|
|
338
|
+
```python
|
|
339
|
+
from oswright import OSWright
|
|
340
|
+
|
|
341
|
+
with OSWright() as ow:
|
|
342
|
+
screen = ow.screen()
|
|
343
|
+
screen.click(text="Start")
|
|
344
|
+
screen.type_text("Hello World")
|
|
345
|
+
screen.press("Ctrl+S")
|
|
346
|
+
screen.screenshot("desktop.png")
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
See the [examples/](examples/) directory for more.
|
|
350
|
+
|
|
351
|
+
## Architecture
|
|
352
|
+
|
|
353
|
+
```
|
|
354
|
+
oswright/
|
|
355
|
+
__init__.py # Package entry point
|
|
356
|
+
core.py # OSWright class (= Browser)
|
|
357
|
+
screen.py # Screen class (= Page)
|
|
358
|
+
locator.py # Locator + Assertions (= Locator + expect)
|
|
359
|
+
capture.py # Screen capture (mss - cross-platform)
|
|
360
|
+
detect.py # OCR + image matching (easyocr, opencv)
|
|
361
|
+
input.py # Platform dispatcher for input backends
|
|
362
|
+
_input_windows.py # Windows backend (Win32 API)
|
|
363
|
+
_input_pynput.py # Linux/macOS backend (pynput)
|
|
364
|
+
mcp_server.py # MCP server for AI agent integration
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
## License
|
|
368
|
+
|
|
369
|
+
MIT
|