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.
- miosa_mcp-0.2.0/.gitignore +72 -0
- miosa_mcp-0.2.0/PKG-INFO +188 -0
- miosa_mcp-0.2.0/README.md +166 -0
- miosa_mcp-0.2.0/miosa_mcp/__init__.py +6 -0
- miosa_mcp-0.2.0/miosa_mcp/__main__.py +6 -0
- miosa_mcp-0.2.0/miosa_mcp/server.py +3867 -0
- miosa_mcp-0.2.0/miosa_mcp/tools/__init__.py +1 -0
- miosa_mcp-0.2.0/miosa_mcp/tools/egress.py +790 -0
- miosa_mcp-0.2.0/pyproject.toml +47 -0
- miosa_mcp-0.2.0/tests/__init__.py +0 -0
- miosa_mcp-0.2.0/tests/test_egress_tools.py +707 -0
|
@@ -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/
|
miosa_mcp-0.2.0/PKG-INFO
ADDED
|
@@ -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.
|