miosa-mcp 0.2.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.
@@ -0,0 +1,72 @@
1
+ # Elixir/Erlang
2
+ /_build/
3
+ /cover/
4
+ /deps/
5
+ /doc/
6
+ /.fetch
7
+ erl_crash.dump
8
+ *.ez
9
+ .elixir_ls/
10
+
11
+ # macOS
12
+ .DS_Store
13
+ .AppleDouble
14
+ .LSOverride
15
+ Thumbs.db
16
+
17
+ # Editors
18
+ .idea/
19
+ .vscode/
20
+ *.swp
21
+ *.swo
22
+ *~
23
+
24
+ # Compiled binaries
25
+ *.exe
26
+ *.dll
27
+ *.so
28
+ *.dylib
29
+
30
+ # Env files (keep .env.example)
31
+ .env
32
+ .env.*
33
+ !.env.example
34
+
35
+ # Node
36
+ node_modules/
37
+
38
+ # Local rescue/database dumps and generated Python bytecode
39
+ .rescue-backups/
40
+ *.sql.gz
41
+ *.rdb
42
+ __pycache__/
43
+ *.py[cod]
44
+
45
+ # Compute engine (separate deployment, has own repo on server)
46
+ /miosa-compute/
47
+
48
+ # OSA checkout (separate local repo; do not accidentally add to root)
49
+ /miosa-platform/OSA/
50
+
51
+ # Astro/Starlight docs build
52
+ docs-site/dist/
53
+ docs-site/.astro/
54
+ docs-site/node_modules/
55
+
56
+ # Temp
57
+ tmp/
58
+ temp/
59
+ *.log
60
+ *.pid
61
+
62
+ # WireGuard cluster mesh — private keys must NEVER be committed.
63
+ # Generated configs (.conf) embed PrivateKey in plaintext, so exclude entire dir.
64
+ out/wg/
65
+
66
+ # Cluster SSH key — local-only, must NEVER be committed
67
+ scripts/cluster/miosa-cluster-key
68
+ scripts/cluster/miosa-cluster-key.private
69
+ !scripts/cluster/miosa-cluster-key.pub
70
+
71
+ # Local agent worktrees / tooling state
72
+ .claire/
@@ -0,0 +1,188 @@
1
+ Metadata-Version: 2.4
2
+ Name: miosa-mcp
3
+ Version: 0.2.0
4
+ Summary: MCP server that exposes MIOSA computer-use tools to Claude Code
5
+ Project-URL: Homepage, https://miosa.ai
6
+ Project-URL: Documentation, https://miosa.ai/docs/mcp
7
+ Author-email: MIOSA <dev@miosa.ai>
8
+ License-Expression: MIT
9
+ Keywords: agents,ai,claude,computer-use,desktop,mcp,miosa
10
+ Classifier: Development Status :: 5 - Production/Stable
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
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
+ Requires-Python: >=3.10
19
+ Requires-Dist: mcp>=1.0.0
20
+ Requires-Dist: miosa>=1.2.0
21
+ Description-Content-Type: text/markdown
22
+
23
+ # miosa-mcp
24
+
25
+ MCP (Model Context Protocol) bridge that exposes MIOSA cloud sandboxes &
26
+ desktops to any MCP-aware client (Claude Code, Cursor, Gemini CLI, etc.).
27
+
28
+ ## Two ways to run it
29
+
30
+ ### 1. Hosted (recommended) — no install
31
+
32
+ MIOSA ships a public MCP endpoint at `https://api.miosa.ai/api/v1/mcp`. Point
33
+ any MCP client at it with your `msk_u_*` API key as a Bearer token:
34
+
35
+ ```bash
36
+ claude mcp add --transport http miosa \
37
+ https://api.miosa.ai/api/v1/mcp \
38
+ --header "Authorization: Bearer msk_u_your_key_here"
39
+ ```
40
+
41
+ Full guide: [`docs/api/mcp-connect.md`](../docs/api/mcp-connect.md).
42
+
43
+ ### 2. Local stdio (this Python package)
44
+
45
+ Install:
46
+
47
+ ```bash
48
+ pip install miosa-mcp
49
+ ```
50
+
51
+ Add to `~/.claude/mcp.json`:
52
+
53
+ ```json
54
+ {
55
+ "mcpServers": {
56
+ "miosa": {
57
+ "command": "python",
58
+ "args": ["-m", "miosa_mcp"],
59
+ "env": {
60
+ "MIOSA_API_KEY": "msk_u_your_key_here"
61
+ }
62
+ }
63
+ }
64
+ }
65
+ ```
66
+
67
+ Use stdio when you need to wrap the MCP layer with custom local logic, or
68
+ your client doesn't yet support remote MCP. Both modes hit the same MIOSA
69
+ REST API under the hood.
70
+
71
+ Get your API key at <https://miosa.ai/dashboard/api-keys>.
72
+
73
+ ## Tools
74
+
75
+ ### Lifecycle
76
+
77
+ | Tool | Description |
78
+ |------|-------------|
79
+ | `computer_create(name, template_type?, size?)` | Create a computer and start it. Becomes the active computer. |
80
+ | `computer_list()` | List all computers in your tenant. |
81
+ | `computer_destroy(computer_id?)` | Permanently destroy a computer. |
82
+
83
+ ### Desktop — Visual
84
+
85
+ | Tool | Description |
86
+ |------|-------------|
87
+ | `computer_screenshot(computer_id?)` | Capture a PNG screenshot. Claude can see and reason about it. |
88
+ | `computer_get_screen_size(computer_id?)` | Get screen resolution in pixels. |
89
+ | `computer_get_cursor_position(computer_id?)` | Get current cursor x/y. |
90
+
91
+ ### Desktop — Pointer
92
+
93
+ | Tool | Description |
94
+ |------|-------------|
95
+ | `computer_click(x, y, button?, computer_id?)` | Click at coordinates. |
96
+ | `computer_double_click(x, y, computer_id?)` | Double-click at coordinates. |
97
+ | `computer_move_cursor(x, y, computer_id?)` | Move cursor without clicking. |
98
+ | `computer_drag(from_x, from_y, to_x, to_y, computer_id?)` | Click-drag between positions. |
99
+ | `computer_scroll(direction?, clicks?, x?, y?, computer_id?)` | Scroll up/down/left/right. |
100
+
101
+ ### Desktop — Keyboard
102
+
103
+ | Tool | Description |
104
+ |------|-------------|
105
+ | `computer_type(text, computer_id?)` | Type text into the focused field. |
106
+ | `computer_key(key, computer_id?)` | Press a single key (Return, Tab, Escape, etc.). |
107
+ | `computer_hotkey(keys, computer_id?)` | Press a key combo (e.g. `["ctrl", "c"]`). |
108
+
109
+ ### Clipboard
110
+
111
+ | Tool | Description |
112
+ |------|-------------|
113
+ | `computer_get_clipboard(computer_id?)` | Read clipboard text. |
114
+ | `computer_set_clipboard(text, computer_id?)` | Write clipboard text. |
115
+
116
+ ### Window Management
117
+
118
+ | Tool | Description |
119
+ |------|-------------|
120
+ | `computer_windows(computer_id?)` | List open windows with IDs, titles, positions. |
121
+ | `computer_launch(app, computer_id?)` | Launch an app by name (firefox, gedit, xterm…). |
122
+
123
+ ### Shell & Files
124
+
125
+ | Tool | Description |
126
+ |------|-------------|
127
+ | `computer_bash(command, timeout?, computer_id?)` | Run a bash command; returns stdout, stderr, exit_code. |
128
+ | `computer_write_file(path, content, computer_id?)` | Write a file inside the VM. |
129
+ | `computer_read_file(path, computer_id?)` | Read a file from inside the VM. |
130
+
131
+ ## Active Computer
132
+
133
+ All tools accept an optional `computer_id`. When omitted, the server uses the most recently created or accessed computer automatically. This means you can `computer_create` once and omit the ID for the rest of the session.
134
+
135
+ ## Example session
136
+
137
+ ```
138
+ > computer_create(name="my-dev-box")
139
+ Created computer 'my-dev-box' (id=comp_abc123, status=running). This is now the active computer.
140
+
141
+ > computer_screenshot()
142
+ [PNG image of the desktop appears in Claude's context]
143
+
144
+ > computer_bash(command="ls /home")
145
+ stdout:
146
+ ubuntu
147
+ exit_code: 0
148
+
149
+ > computer_launch(app="firefox")
150
+ Launched: firefox
151
+
152
+ > computer_screenshot()
153
+ [Firefox is now open]
154
+
155
+ > computer_click(x=640, y=50)
156
+ Clicked (640, 50) button=left
157
+
158
+ > computer_type(text="https://miosa.ai")
159
+ Typed: 'https://miosa.ai'
160
+
161
+ > computer_key(key="Return")
162
+ Pressed key: Return
163
+ ```
164
+
165
+ ## Development
166
+
167
+ ```bash
168
+ # Install deps (requires Python 3.10+)
169
+ pip install -e ".[dev]"
170
+
171
+ # Type-check
172
+ mypy miosa_mcp/
173
+
174
+ # Lint
175
+ ruff check miosa_mcp/
176
+ ```
177
+
178
+ ## Architecture
179
+
180
+ The server is a single async Python process that:
181
+ 1. Reads `MIOSA_API_KEY` from the environment
182
+ 2. Initializes an `AsyncMiosa` client
183
+ 3. Maintains an in-process cache of `AsyncComputer` objects
184
+ 4. Serves MCP tools over stdio (the protocol Claude Code uses)
185
+ 5. Maps every tool call to the corresponding MIOSA SDK method
186
+ 6. Returns screenshots as base64-encoded PNG images (MCP `ImageContent`)
187
+
188
+ All desktop action tools (`click`, `type`, `key`, etc.) call the MIOSA platform API which proxies commands through to the running VM's envd daemon at port 49983.
@@ -0,0 +1,166 @@
1
+ # miosa-mcp
2
+
3
+ MCP (Model Context Protocol) bridge that exposes MIOSA cloud sandboxes &
4
+ desktops to any MCP-aware client (Claude Code, Cursor, Gemini CLI, etc.).
5
+
6
+ ## Two ways to run it
7
+
8
+ ### 1. Hosted (recommended) — no install
9
+
10
+ MIOSA ships a public MCP endpoint at `https://api.miosa.ai/api/v1/mcp`. Point
11
+ any MCP client at it with your `msk_u_*` API key as a Bearer token:
12
+
13
+ ```bash
14
+ claude mcp add --transport http miosa \
15
+ https://api.miosa.ai/api/v1/mcp \
16
+ --header "Authorization: Bearer msk_u_your_key_here"
17
+ ```
18
+
19
+ Full guide: [`docs/api/mcp-connect.md`](../docs/api/mcp-connect.md).
20
+
21
+ ### 2. Local stdio (this Python package)
22
+
23
+ Install:
24
+
25
+ ```bash
26
+ pip install miosa-mcp
27
+ ```
28
+
29
+ Add to `~/.claude/mcp.json`:
30
+
31
+ ```json
32
+ {
33
+ "mcpServers": {
34
+ "miosa": {
35
+ "command": "python",
36
+ "args": ["-m", "miosa_mcp"],
37
+ "env": {
38
+ "MIOSA_API_KEY": "msk_u_your_key_here"
39
+ }
40
+ }
41
+ }
42
+ }
43
+ ```
44
+
45
+ Use stdio when you need to wrap the MCP layer with custom local logic, or
46
+ your client doesn't yet support remote MCP. Both modes hit the same MIOSA
47
+ REST API under the hood.
48
+
49
+ Get your API key at <https://miosa.ai/dashboard/api-keys>.
50
+
51
+ ## Tools
52
+
53
+ ### Lifecycle
54
+
55
+ | Tool | Description |
56
+ |------|-------------|
57
+ | `computer_create(name, template_type?, size?)` | Create a computer and start it. Becomes the active computer. |
58
+ | `computer_list()` | List all computers in your tenant. |
59
+ | `computer_destroy(computer_id?)` | Permanently destroy a computer. |
60
+
61
+ ### Desktop — Visual
62
+
63
+ | Tool | Description |
64
+ |------|-------------|
65
+ | `computer_screenshot(computer_id?)` | Capture a PNG screenshot. Claude can see and reason about it. |
66
+ | `computer_get_screen_size(computer_id?)` | Get screen resolution in pixels. |
67
+ | `computer_get_cursor_position(computer_id?)` | Get current cursor x/y. |
68
+
69
+ ### Desktop — Pointer
70
+
71
+ | Tool | Description |
72
+ |------|-------------|
73
+ | `computer_click(x, y, button?, computer_id?)` | Click at coordinates. |
74
+ | `computer_double_click(x, y, computer_id?)` | Double-click at coordinates. |
75
+ | `computer_move_cursor(x, y, computer_id?)` | Move cursor without clicking. |
76
+ | `computer_drag(from_x, from_y, to_x, to_y, computer_id?)` | Click-drag between positions. |
77
+ | `computer_scroll(direction?, clicks?, x?, y?, computer_id?)` | Scroll up/down/left/right. |
78
+
79
+ ### Desktop — Keyboard
80
+
81
+ | Tool | Description |
82
+ |------|-------------|
83
+ | `computer_type(text, computer_id?)` | Type text into the focused field. |
84
+ | `computer_key(key, computer_id?)` | Press a single key (Return, Tab, Escape, etc.). |
85
+ | `computer_hotkey(keys, computer_id?)` | Press a key combo (e.g. `["ctrl", "c"]`). |
86
+
87
+ ### Clipboard
88
+
89
+ | Tool | Description |
90
+ |------|-------------|
91
+ | `computer_get_clipboard(computer_id?)` | Read clipboard text. |
92
+ | `computer_set_clipboard(text, computer_id?)` | Write clipboard text. |
93
+
94
+ ### Window Management
95
+
96
+ | Tool | Description |
97
+ |------|-------------|
98
+ | `computer_windows(computer_id?)` | List open windows with IDs, titles, positions. |
99
+ | `computer_launch(app, computer_id?)` | Launch an app by name (firefox, gedit, xterm…). |
100
+
101
+ ### Shell & Files
102
+
103
+ | Tool | Description |
104
+ |------|-------------|
105
+ | `computer_bash(command, timeout?, computer_id?)` | Run a bash command; returns stdout, stderr, exit_code. |
106
+ | `computer_write_file(path, content, computer_id?)` | Write a file inside the VM. |
107
+ | `computer_read_file(path, computer_id?)` | Read a file from inside the VM. |
108
+
109
+ ## Active Computer
110
+
111
+ All tools accept an optional `computer_id`. When omitted, the server uses the most recently created or accessed computer automatically. This means you can `computer_create` once and omit the ID for the rest of the session.
112
+
113
+ ## Example session
114
+
115
+ ```
116
+ > computer_create(name="my-dev-box")
117
+ Created computer 'my-dev-box' (id=comp_abc123, status=running). This is now the active computer.
118
+
119
+ > computer_screenshot()
120
+ [PNG image of the desktop appears in Claude's context]
121
+
122
+ > computer_bash(command="ls /home")
123
+ stdout:
124
+ ubuntu
125
+ exit_code: 0
126
+
127
+ > computer_launch(app="firefox")
128
+ Launched: firefox
129
+
130
+ > computer_screenshot()
131
+ [Firefox is now open]
132
+
133
+ > computer_click(x=640, y=50)
134
+ Clicked (640, 50) button=left
135
+
136
+ > computer_type(text="https://miosa.ai")
137
+ Typed: 'https://miosa.ai'
138
+
139
+ > computer_key(key="Return")
140
+ Pressed key: Return
141
+ ```
142
+
143
+ ## Development
144
+
145
+ ```bash
146
+ # Install deps (requires Python 3.10+)
147
+ pip install -e ".[dev]"
148
+
149
+ # Type-check
150
+ mypy miosa_mcp/
151
+
152
+ # Lint
153
+ ruff check miosa_mcp/
154
+ ```
155
+
156
+ ## Architecture
157
+
158
+ The server is a single async Python process that:
159
+ 1. Reads `MIOSA_API_KEY` from the environment
160
+ 2. Initializes an `AsyncMiosa` client
161
+ 3. Maintains an in-process cache of `AsyncComputer` objects
162
+ 4. Serves MCP tools over stdio (the protocol Claude Code uses)
163
+ 5. Maps every tool call to the corresponding MIOSA SDK method
164
+ 6. Returns screenshots as base64-encoded PNG images (MCP `ImageContent`)
165
+
166
+ All desktop action tools (`click`, `type`, `key`, etc.) call the MIOSA platform API which proxies commands through to the running VM's envd daemon at port 49983.
@@ -0,0 +1,6 @@
1
+ """MIOSA MCP server — exposes MIOSA computer-use tools to Claude Code."""
2
+
3
+ from .server import main
4
+
5
+ __all__ = ["main"]
6
+ __version__ = "0.1.0"
@@ -0,0 +1,6 @@
1
+ """Allow running the MCP server as a module: python -m miosa_mcp"""
2
+
3
+ from .server import main
4
+
5
+ if __name__ == "__main__":
6
+ main()