Skip to main content
Glama

FullRemote MCP

Demo

▶ Watch the FullRemote MCP demo on Viddler

Related MCP server: desktop-touch-mcp

Overview

FullRemote MCP is a Python server for an interactive Windows VM. An AI client can inspect and control the desktop, run commands, manage jobs and transfer files. No separate host-side gateway is required.

Capability

What it supports

Desktop

Screenshots, mouse, keyboard and Windows UI Automation

Commands

PowerShell, managed jobs, logs and process details

Files

Authenticated streaming uploads and downloads

Connections

Streamable HTTP remotely or stdio locally

The remote transport is MCP Streamable HTTP at /mcp. Screenshots use native MCP image content. Large files use authenticated streaming HTTP endpoints.

Guide: Quick start · Connect remotely · Tool reference · Configuration · License

Practical handoff: the Windows VM

This project has been tested on the interactive Windows VM used for the remote session:

Item

Value

OS

Windows 10 Pro, build 19045

Remote address

26.37.15.119 (private VPN address; it may change)

MCP endpoint

http://26.37.15.119:8765/mcp

Health check

http://26.37.15.119:8765/health

Transport

MCP Streamable HTTP

Display

one interactive monitor, approximately 870x869 capture bounds

Session

logged-in interactive session; desktop input is available

Elevation

the server process was running elevated during the test

Workspace

C:\Users\Admin\Desktop

The endpoint is protected by a static bearer token. Do not put the token in source control, screenshots, prompts shared with other people, or chat logs. Set it only in the client secret store or the current process environment. The ready-to-copy client templates are in mcp-configs/; replace <FULLREMOTE_TOKEN> before using them.

Start the host server

On the Windows VM, open an elevated PowerShell in the folder containing the executable. The single-file build does not need Python:

cd C:\Users\Admin\Desktop\fullremoteMCP
$env:FULLREMOTE_TOKEN = (.\dist\fullremote-mcp.exe token)
$env:FULLREMOTE_HOST = '0.0.0.0'
$env:FULLREMOTE_PORT = '8765'
$env:FULLREMOTE_ALLOWED_HOSTS = '26.37.15.119:8765'
.\dist\fullremote-mcp.exe serve --transport http

The environment variables above last for that PowerShell window. To use a fixed token, set it explicitly instead:

$env:FULLREMOTE_TOKEN = '<FULLREMOTE_TOKEN>'

In classic cmd.exe, the equivalent is:

set "FULLREMOTE_TOKEN=<FULLREMOTE_TOKEN>"
set "FULLREMOTE_HOST=0.0.0.0"
set "FULLREMOTE_PORT=8765"
set "FULLREMOTE_ALLOWED_HOSTS=26.37.15.119:8765"
dist\fullremote-mcp.exe serve --transport http

For local-only use, omit the host/allowed-host variables. The default bind is 127.0.0.1:8765. Verify the running instance from another machine with:

$headers = @{ Authorization = "Bearer $env:FULLREMOTE_TOKEN" }
Invoke-RestMethod http://26.37.15.119:8765/health -Headers $headers

If Windows Firewall blocks the private VPN interface, create a narrowly scoped inbound rule in an elevated PowerShell (change the profile or remote address to match the VPN):

New-NetFirewallRule -DisplayName 'FullRemote MCP 8765' -Direction Inbound -Action Allow -Protocol TCP -LocalPort 8765 -Profile Private -RemoteAddress 26.37.15.119

Do not expose this HTTP endpoint directly to the public internet. Use a private VPN, SSH tunnel, or an HTTPS reverse proxy with an additional access-control layer. The bearer token grants the Windows account's desktop, file and process capabilities.

Stop the host server and shut down the VM

Stop the MCP server cleanly with Ctrl+C in the server console. If it was started as a managed job, use the returned job_id with job_cancel. To shut down the Windows VM after closing the server:

Stop-Computer -Force

The shutdown command is intentionally separate from the server stop. It should only be issued when no one else is using the VM.

Add this server to MCP clients

There is no safe one-click way to add a desktop-control server to every AI application. Add the same server once in each client that supports custom MCP servers. Use the client's secret or environment-variable feature for the token. The remote settings are:

Transport: Streamable HTTP
URL:       http://26.37.15.119:8765/mcp
Header:    Authorization: Bearer <FULLREMOTE_TOKEN>

Templates are included for common clients:

  • mcp-configs/cursor.json -- Cursor's project or user MCP configuration.

  • mcp-configs/claude-desktop.json -- Claude Desktop local stdio configuration. It launches the executable on the same Windows machine, so edit the absolute path first. For a remote Claude connection, use its custom remote-MCP UI with the HTTP values above if enabled in that build.

  • mcp-configs/vscode-mcp.json -- VS Code MCP configuration with a prompted secret input.

  • mcp-configs/generic-remote.json -- the transport-neutral shape for Cline, Roo Code, Windsurf, Continue, LibreChat and other clients that expose a remote URL and headers.

For ChatGPT or another cloud-hosted AI, a private 26.37.15.119 URL is not reachable from the cloud. Use a public HTTPS endpoint or a private connector/tunnel supported by that product, then configure the same /mcp URL and bearer header. Do not paste the real token into a normal chat message.

Prompt for the AI controller

Paste the following as a system/developer instruction after adding the MCP server. It tells the model what machine it is controlling without embedding the secret:

You control one interactive Windows 10 Pro VM through the FullRemote Windows MCP server.

Machine facts:
- Private VPN address: 26.37.15.119
- MCP endpoint: http://26.37.15.119:8765/mcp
- OS: Windows 10 Pro, build 19045
- Workspace: C:\\Users\\Admin\\Desktop
- One interactive monitor; screenshots are usually about 870x869 pixels
- Python 3.12.10 and Node.js 24.21.0 are installed
- The desktop session is logged in and input is available; elevation may be enabled

Operating rules:
1. Call system_info once at the start and observe before every desktop action.
2. Use mouse coordinate_space='image' with the latest observation_id. Re-observe after clicks,
   typing, window changes, downloads, installs, or any unexpected result.
3. Use ui_tree when a control exposes a reliable name; otherwise use the screenshot coordinates.
4. Treat a successful mouse/keyboard result as input injection only, not proof that the task
   completed. Verify the resulting screen, file, window, or job output.
5. For long commands use exec or run_process, keep the job_id, and poll job_status.
6. Never reveal, print, save, or send the FULLREMOTE_TOKEN. Never put secrets in source files,
   screenshots, prompts, or chat responses.
7. Do not shut down, restart, delete files, install software, or send external messages unless
   the user explicitly requests that exact action.
8. One AI controls the desktop at a time. Do not blindly retry an action after a timeout; observe
   first because some input may already have been delivered.
9. If the foreground window is not the intended application, use windows/focus_window and verify.
10. Report the concrete result and any verification evidence when the task is complete.

Quick start on the VM

Use Windows 10/11 or Windows Server with Desktop Experience and Python 3.11+. Python 3.12 or 3.13 is recommended. Sign in to the desktop before starting the server.

From PowerShell in this project directory:

.\scripts\setup.ps1 -Dev
.\scripts\start.ps1

Setup creates .venv, installs the project, and creates .env with a random bearer token if the file does not already exist. It preserves an existing .env. To select a Python executable:

.\scripts\setup.ps1 -Python 'C:\Python312\python.exe' -Dev

An equivalent installation using uv:

uv venv --python 3.12 .venv
uv pip install --python .venv\Scripts\python.exe -e '.[dev]'
Copy-Item .env.example .env
.\.venv\Scripts\python.exe -m fullremote_mcp token

For the uv route, put the generated token in FULLREMOTE_TOKEN in .env before starting. Package installation needs network access or a complete local wheel cache.

The default address is http://127.0.0.1:8765/mcp. The server loads .env from its working directory; existing process environment variables take precedence.

Single-file Windows executable

Build on Windows using the project virtual environment:

.\scripts\setup.ps1
.\scripts\build.ps1

PyInstaller produces dist\fullremote-mcp.exe, including Python and the runtime dependencies. Copy just this executable to another Windows x64 machine; Python is not required there. The executable supports the same commands and loads an optional .env from the working directory:

.\dist\fullremote-mcp.exe doctor
$env:FULLREMOTE_TOKEN = & .\dist\fullremote-mcp.exe token
.\dist\fullremote-mcp.exe serve --transport http

For a local MCP client, set the command to the executable's absolute path and the arguments to ["serve", "--transport", "stdio"]. Keep the console build: stdio transport needs stdin/stdout. Build with another Python using scripts\build.ps1 -Python C:\Python312\python.exe; use -SkipInstall if .[build] is already installed in that environment.

Connect from another machine

Connect through a private VPN/SSH tunnel, or serve HTTPS with a certificate. The default loopback binding works with a tunnel. To listen directly on a VM's network interface, edit .env:

FULLREMOTE_HOST=0.0.0.0
FULLREMOTE_ALLOWED_HOSTS=windows-vm:8765,192.168.1.50:8765

Use your actual hostname/IP and port. Requests with another Host header are rejected. If an HTTP client sends an Origin header, add its exact origin to FULLREMOTE_ALLOWED_ORIGINS.

For TLS terminated by this server:

.\scripts\start.ps1 -Certificate C:\certs\vm.crt -PrivateKey C:\certs\vm.key

Configure an MCP client with:

Setting

Value

Transport

Streamable HTTP

URL

http://windows-vm:8765/mcp, or the HTTPS/tunnel equivalent

Header

Authorization: Bearer <FULLREMOTE_TOKEN from the VM>

Image support

Required for the model to see screenshots

This server uses a static bearer token. It does not implement OAuth discovery or interactive login; the client must support supplying the Authorization header. Every HTTP route, including /health and file endpoints, requires authentication. The token grants the capabilities of the Windows account running the server. File paths are not confined to the configured workspace.

The sample client lists tools and optionally saves a screenshot without sending desktop input:

$env:FULLREMOTE_TOKEN = '<token from the VM>'
.\.venv\Scripts\python.exe examples\client.py --url http://windows-vm:8765/mcp --capture vm.png

Local clients can instead launch .venv\Scripts\python.exe with arguments -m fullremote_mcp serve --transport stdio. Set the process working directory to this project. Stdio does not need a bearer token and does not expose the streaming file HTTP endpoints.

Tools

Tools

Behavior

system_info

Python/Windows version, session, elevation, displays, paths and supported keys

observe

PNG screenshot, foreground window, cursor, monitor geometry and observation ID

mouse

Smooth move, click, double-click, drag, vertical/horizontal scroll

keyboard

Unicode typing, clipboard paste or key chords such as ['CTRL', 'S']

desktop_control

Pause/resume desktop input; observation remains available

windows, focus_window

Enumerate windows and request a verified foreground change

ui_tree

Bounded Windows UI Automation tree with control names, IDs and rectangles

clipboard

Read or replace Unicode clipboard text

exec

Run a noninteractive PowerShell script with UTF-8 output

run_process

Run an executable and argument array without shell interpolation

job_status, list_jobs, job_cancel

Poll output, inspect history, terminate a managed process tree

process_info

Inspect PID, command line, working directory, memory and children

list_directory, read_text, write_text

Directory listing and bounded UTF-8 file editing

upload, download

Small base64 transfers with optional SHA-256 and byte-offset reads

transfer_info

Streaming HTTP upload/download URLs for a path

Desktop observation and input

Use observe -> action -> observe. For example:

{"name":"observe","arguments":{"monitor":0,"max_size":1600}}

Then click using coordinates from that screenshot:

{
  "name": "mouse",
  "arguments": {
    "action": "click",
    "x": 420,
    "y": 280,
    "coordinate_space": "image",
    "observation_id": "<ID returned by observe>",
    "duration_ms": 400
  }
}

monitor=0 captures the virtual desktop; positive indices select a monitor. max_size limits the longest image dimension. Image coordinates require an observation ID and are mapped back to physical desktop pixels, including negative monitor coordinates. coordinate_space=desktop uses physical pixels directly. UI Automation rectangles also use desktop coordinates.

Observation IDs expire after 30 seconds and verify the foreground HWND. This cannot detect every layout or application-state change. A successful input call only confirms input injection; inspect the resulting screen or files to confirm the application's result. A failed call can have sent partial input, so observe before retrying.

Desktop operations are serialized, including when an HTTP request is cancelled. Use one AI controller per desktop; the lock serializes individual tool calls, not entire multi-call tasks. Natural mouse motion runs locally at approximately 100 steps/second with an eased curved path.

keyboard(action='type') supports UTF-16 Unicode input, including surrogate pairs. Newlines and tabs send Enter/Tab. For multiline source code, paste or write_text is usually preferable. Paste intentionally leaves the supplied text on the clipboard. Type input is limited to 10,000 characters and 60 seconds of configured delay. Applications with raw/custom input handling may need different keys or paste behavior.

Call desktop_control(action='pause') to interrupt input. Holding Ctrl+Alt+F12 locally during an input action also pauses it. The shortcut is polled while sending input; it is not a global background hotkey. Pressed keys and mouse buttons are released during cleanup. Resume explicitly with desktop_control(action='resume'). Command jobs have a separate job_cancel control.

Command jobs and debugging

exec uses PowerShell 7 when available, otherwise Windows PowerShell. Scripts are passed as an encoded argument, with stdout/stderr configured for UTF-8. run_process is useful for Python, build tools, debuggers and GUI programs that accept command-line arguments.

Both return a job ID. wait_seconds (0..10) controls how long the initial call waits; timeout_seconds (0.1..86400, default 300) limits the job's lifetime. Increase the timeout for interactive applications. Poll job_status until state becomes completed, failed, cancelled or timed_out. The root process's exit code is reported separately.

On Windows, a process is created suspended, assigned to a Job Object, and then resumed. Its descendants remain tracked even if the root exits. Timeout, cancellation, and server exit terminate the managed tree. This does not include processes started by external services or an already-running application through IPC. A server cannot resume a running job after restart; unfinished saved records are reported as interrupted.

Jobs use anonymous pipes and dedicated output-reader threads. They work with Windows event loop policies that cannot launch asyncio subprocesses. Each stdout/stderr log is capped at 8 MiB by default, while a recent 16 KiB tail remains available even after the cap. job_status offsets are byte offsets; a chunk may split a UTF-8 character. Job history and logs are retained under .fullremote/jobs; remove old, completed job directories when no longer needed.

For debugging, combine command output, process_info, screenshots, and file access. For example, run tests/builds or query Get-WinEvent through exec, then inspect the output by job ID. Interactive debugger adapters with breakpoint/stack/variable tools and automatic crash-dump capture are not part of this initial version.

File transfer

Relative paths resolve against FULLREMOTE_WORKSPACE (default: the server working directory). Absolute paths are supported wherever the Windows account has access. Parent directories must already exist; create them using exec when needed. Writes are atomic and require overwrite=true to replace an existing file. SHA-256 mismatch or a disconnected upload leaves the original intact.

Small files can go through MCP upload/download (default inline limit: 1 MiB). For larger files, use the URL returned by transfer_info, on the same origin as the MCP server:

curl.exe --fail-with-body --upload-file .\data.zip `
  --header "Authorization: Bearer $env:FULLREMOTE_TOKEN" `
  'http://127.0.0.1:8765/files/upload?path=C%3A%2Fwork%2Fdata.zip'

curl.exe --fail-with-body --get 'http://127.0.0.1:8765/files/download' `
  --data-urlencode 'path=C:/work/result.zip' `
  --header "Authorization: Bearer $env:FULLREMOTE_TOKEN" `
  --output .\result.zip

Upload supports the optional X-Content-SHA256 header. Add &overwrite=true to explicitly replace a file. The default streaming upload limit is 1 GiB, enforced for Content-Length and chunked bodies. New/replaced files inherit the destination directory's ACL on Windows. Downloads support HTTP Range requests through Starlette's FileResponse.

Windows session and permissions

Run the agent in the logged-in user's desktop session. For automatic startup, use Task Scheduler with Run only when user is logged on, an at-logon trigger, and the project as the working directory. Do not install the desktop agent as a Session 0 Windows service.

Elevation is inherited from the process that launches the server. Launch it elevated when the workflow requires administrator commands or input to elevated applications. It does not bypass UAC secure desktop, logon/lock screens, or Windows input integrity restrictions. Controlling boot and logon screens requires a separate hypervisor-console integration.

Keep the VM desktop session active. Locking it or disconnecting RDP can interrupt capture/input, depending on Windows and the VM display driver. A VM console session is preferable for unattended desktop workflows. UIA support depends on the application; custom-drawn controls may only be usable through screenshots. Screenshot and input do not provide a continuous video stream.

Run one server process per desktop. Multiple Uvicorn workers or servers would have separate locks, observations and job state. The CLI starts exactly one worker.

Configuration

See .env.example for all settings. The main limits are:

Variable

Default

FULLREMOTE_TOKEN

Required for HTTP; generate with fullremote-mcp token

FULLREMOTE_HOST, FULLREMOTE_PORT

127.0.0.1, 8765

FULLREMOTE_ALLOWED_HOSTS

Additional comma-separated host:port entries

FULLREMOTE_ALLOWED_ORIGINS

Additional comma-separated origins

FULLREMOTE_WORKSPACE

Current working directory

FULLREMOTE_DATA_DIR

WORKSPACE/.fullremote

FULLREMOTE_MAX_JOBS

8

FULLREMOTE_MAX_INLINE_BYTES

1048576

FULLREMOTE_MAX_UPLOAD_BYTES

1073741824

FULLREMOTE_MAX_LOG_BYTES

8388608 per stream, per job

Validation

.\.venv\Scripts\python.exe -m fullremote_mcp doctor
.\.venv\Scripts\python.exe -m fullremote_mcp doctor --capture desktop.png
.\.venv\Scripts\python.exe -m unittest discover -s tests -v

The automated suite tests coordinates, Unicode, input cleanup/serialization, token/Host/Origin checks, atomic transfers, output limits, persistent jobs and Windows process-tree termination. MCP protocol tests verify initialization, discovery, image content and jobs surviving between HTTP requests. They explicitly skip if the MCP SDK is missing; such a run is not a complete end-to-end validation. Desktop input tests use a fake Win32 backend and do not click/type into the current desktop. Manually verify real input and UI Automation inside the target VM.

Layout

src/fullremote_mcp/
  __main__.py    CLI, diagnostics and startup
  config.py      Environment settings
  server.py      MCP tool definitions
  http_api.py    Authentication and streaming file endpoints
  desktop.py     Serialized desktop actions and screenshot mappings
  automation.py  Dedicated UI Automation COM worker
  native.py      Win32 input/window/clipboard bindings
  files.py       Atomic file operations
  jobs.py        Process supervision and persistent output
scripts/        Windows setup/start helpers
examples/       MCP client example
tests/          Unit, HTTP, process and MCP protocol tests

License

Licensed under the Apache License 2.0. Original creator attribution and translations: NOTICE.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables AI clients to automate Windows desktop applications through window manipulation, image recognition, OCR, keyboard/mouse simulation, and memory operations via the MCP protocol.
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables AI clients on Windows to control the local mouse, keyboard, and screen understanding via MCP stdio, allowing automated workflows like viewing the screen, locating elements, clicking, typing, and verifying results.
    1
    Apache 2.0
  • F
    license
    Not graded
    quality
    C
    maintenance
    Enables MCP clients to observe and control Windows desktop applications by reading UIA element trees and capturing screenshots, then acting through UIA patterns or synthesized mouse and keyboard input. It runs standalone on an interactive Windows session, without requiring the original host application.
    -