Skip to main content
Glama

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 Device

Prerequisites

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 $USER

Re-login for the change to take effect. Alternatively, use the useSudo option.

Installation

npm install -g mcp-remotetouch

Or run directly with npx:

npx mcp-remotetouch

Usage

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.1

CLI 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:

  1. touch_connect — connect to the remote device

  2. touch_tap / touch_swipe / touch_long_press / touch_double_tap — interact with the screen

  3. key_press / key_type — send keyboard input

  4. touch_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 input group: 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_DIRECT and has ABS_MT_POSITION_X capability

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 input group: 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

-
security - not tested
A
license - permissive license
-
quality - not tested

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/signal-slot/mcp-remotetouch'

If you have feedback or need assistance with the MCP directory API, please join our Discord server