mcp-remotetouch
v0.2.0
Published
MCP server for remote touch input via SSH to any Linux device
Maintainers
Readme
mcp-remotetouch
An MCP server for remotely controlling a touchscreen on any Linux device over SSH.
Injects tap, swipe, long press, double tap, and keyboard events directly into the device. The daemon auto-detects the touchscreen and screen resolution. Keyboard input is injected via a virtual keyboard device created through /dev/uinput. No installation required on the remote device — the Python daemon is sent via stdin over SSH, using only Python's standard library.
Architecture
Stdio mode (default)
Dev Machine Remote Linux Device
┌──────────────────┐ SSH (persistent) ┌──────────────────┐
│ MCP Server (TS) │ ──────────────────> │ Python daemon │
│ stdio transport │ JSON-line proto │ (stdlib only) │
│ │ <────────────────── │ │
│ touch_tap │ │ Auto-detect │
│ touch_swipe │ │ touchscreen │
│ touch_long_press │ │ ↓ │
│ touch_double_tap │ │ /dev/input/eventN│
│ key_press │ │ ↓ │
│ key_type │ │ /dev/uinput (kbd)│
│ touch_disconnect │ │ ↓ │
│ │ │ Linux Input │
└──────────────────┘ └──────────────────┘The daemon scans /proc/bus/input/devices to find the physical touchscreen (by checking INPUT_PROP_DIRECT and ABS_MT_POSITION_X), then injects events directly into it. This works reliably with containerized compositors (e.g., Torizon with Qt EGLFS) where virtual uinput devices may not be detected.
HTTP server mode (--server)
AI Agent (remote) ──HTTP/SSE──> Express + StreamableHTTPServerTransport
│
McpServer (per MCP session)
│
SshTouchSessionManager (shared)
│
SSH ──> Linux DevicePrerequisites
Dev Machine
- Node.js 18+
- SSH client
Remote Device
- Any Linux device with a touchscreen (Raspberry Pi, SBC, embedded system, etc.)
- Python 3
- Read/write access to
/dev/input/eventN(the touchscreen device) - Write access to
/dev/uinput(for keyboard input — optional, touch works without it)
Add the user to the input group on the remote device:
sudo usermod -aG input $USERRe-login for the change to take effect. Alternatively, use the useSudo option.
Installation
npm install -g mcp-remotetouchOr run directly with npx:
npx mcp-remotetouchUsage
Add to your MCP client configuration (e.g. Claude Desktop's claude_desktop_config.json):
{
"mcpServers": {
"remotetouch": {
"command": "npx",
"args": ["mcp-remotetouch"],
"env": {}
}
}
}Screen resolution is auto-detected from the device. You can override it with REMOTETOUCH_SCREEN_WIDTH and REMOTETOUCH_SCREEN_HEIGHT if needed.
Environment Variables
| Variable | Default | Description |
|---|---|---|
| REMOTETOUCH_SSH_HOST | (none) | SSH host of the remote device |
| REMOTETOUCH_SSH_USER | pi | SSH username |
| REMOTETOUCH_SSH_PORT | 22 | SSH port |
| REMOTETOUCH_SSH_KEY | (none) | Path to SSH private key |
| REMOTETOUCH_SCREEN_WIDTH | auto-detected | Screen width in pixels |
| REMOTETOUCH_SCREEN_HEIGHT | auto-detected | Screen height in pixels |
| REMOTETOUCH_USE_SUDO | false | Run daemon with sudo |
Tools
touch_connect
Connect to a remote Linux device via SSH and start the touch daemon. Returns a session ID.
| Parameter | Type | Description |
|---|---|---|
| host | string? | SSH host |
| user | string? | SSH username |
| port | number? | SSH port |
| sshKey | string? | Path to SSH private key |
| screenWidth | number? | Screen width (auto-detected if omitted) |
| screenHeight | number? | Screen height (auto-detected if omitted) |
| useSudo | boolean? | Run with sudo |
touch_tap
Tap at the given coordinates.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| x | number | X coordinate |
| y | number | Y coordinate |
| duration_ms | number? | Tap duration (default: 50ms) |
touch_swipe
Swipe from (x1, y1) to (x2, y2).
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| x1 | number | Start X coordinate |
| y1 | number | Start Y coordinate |
| x2 | number | End X coordinate |
| y2 | number | End Y coordinate |
| duration_ms | number? | Swipe duration (default: 300ms) |
| steps | number? | Number of interpolation steps |
touch_long_press
Long press at the given coordinates.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| x | number | X coordinate |
| y | number | Y coordinate |
| duration_ms | number? | Press duration (default: 800ms) |
touch_double_tap
Double tap at the given coordinates.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| x | number | X coordinate |
| y | number | Y coordinate |
key_press
Press a key with optional modifier keys. Requires /dev/uinput access on the remote device.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| key | string | Key name (e.g. enter, a, tab, f1, up, space) |
| modifiers | string[]? | Modifier keys to hold (e.g. ["ctrl"], ["ctrl", "shift"]) |
key_type
Type a string of text by simulating individual key presses. Requires /dev/uinput access on the remote device.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
| text | string | Text to type (e.g. Hello, World!) |
touch_disconnect
Disconnect a session and clean up the remote daemon.
| Parameter | Type | Description |
|---|---|---|
| sessionId | string | Session ID |
touch_list_sessions
List all active sessions. No parameters.
HTTP Server Mode
Instead of running as a stdio MCP server, you can run mcp-remotetouch as an HTTP server that AI agents can connect to remotely over HTTP.
Starting the server
# Default: listen on 0.0.0.0:3000
npx mcp-remotetouch --server
# Custom port and host
npx mcp-remotetouch --server --port 8080 --host 127.0.0.1CLI arguments
| Argument | Default | Description |
|---|---|---|
| --server | (off) | Enable HTTP server mode |
| --port <N> | 3000 (or REMOTETOUCH_PORT env) | HTTP listen port |
| --host <addr> | 0.0.0.0 | Bind address |
Without --server, the process runs in stdio mode (the default, backward-compatible behavior).
Workflow
A typical session from Claude Desktop:
touch_connect— connect to the remote devicetouch_tap/touch_swipe/touch_long_press/touch_double_tap— interact with the screenkey_press/key_type— send keyboard inputtouch_disconnect— end the session
Troubleshooting
Permission denied
The user on the remote device needs access to /dev/input/eventN. Either:
- Add the user to the
inputgroup:sudo usermod -aG input $USER(re-login required) - Or set
REMOTETOUCH_USE_SUDO=true
No physical touchscreen device found
The daemon could not find a touchscreen in /proc/bus/input/devices. Verify:
- The device has a touchscreen connected and its driver is loaded
- The device shows
INPUT_PROP_DIRECTand hasABS_MT_POSITION_Xcapability
Keyboard input not available
The key_press and key_type tools require write access to /dev/uinput. If keyboard is reported as unavailable:
- Add a udev rule to grant access:
echo 'KERNEL=="uinput", GROUP="input", MODE="0660"' | sudo tee /etc/udev/rules.d/99-uinput.rules sudo udevadm control --reload-rules && sudo udevadm trigger - Ensure the user is in the
inputgroup:sudo usermod -aG input $USER(re-login required) - Or set
REMOTETOUCH_USE_SUDO=true
Touch tools continue to work even if /dev/uinput is not accessible.
SSH connection fails
- Ensure SSH public key authentication is configured for the remote device (password authentication is not supported since the connection uses
BatchMode=yes) - Verify the hostname and port are correct
License
MIT
