MCEC for Home Automation & Remote Control

MCEC (Model Context Environment Controller) began life as MCE Controller, and its original job is still first-class: it is a robust, battle-tested way to control a Windows PC from a home-automation or remote-control system. It runs in the background listening on the network (or a serial port) for Commands, and translates them into actions on the PC: keystrokes, text input, mouse movement, window messages, and launching programs.

Any remote control, home-control system, or application that can send text strings over TCP/IP or an RS-232 serial port can use MCEC to drive a Windows PC. It works great with systems such as Control4, iRule, Crestron, and Premise Home Control.

MCEC was originally built to integrate a Windows Media Center home-theater PC (HTPC) into a Crestron whole-house A/V system, but it is general enough for any control system that can send text to a TCP/IP port or serial port.

Looking for the agent/AI side? MCEC 3.0 is also an opt-in automation server for AI agents over the Model Context Protocol (MCP): see the Environment Controller and Configuration chapters. This page covers the classic remote-control features, which are unchanged and remain the default behavior.

For example:

The set of commands MCEC supports is extensible through a configuration file (mcec.commands). If MCEC does not natively support a function you want, you can add new commands easily.

Windows PC Control Capabilities

By default MCEC supports over 250 built-in commands for controlling a Windows PC remotely. The command engine can:

Same vocabulary, two front doors. This command language is shared. A home-automation system sends these commands over TCP/serial; an AI agent can send the very same raw command strings through the MCP send_command tool. Everything on this page applies to both.

Transports: Client, Server, and Serial

MCEC can act as a TCP/IP client, a TCP/IP server, and/or a serial server; simultaneously if you like. All are configured from the File ▸ Settings… dialog, and each transport’s status shows on the main window’s status bar (green = connected, red = active but not connected, gray = inactive; double-click a status to toggle it).

The Client tab

When acting as a client, MCEC repeatedly tries to connect to a host and waits for commands to be sent to it. MCEC sends nothing to the host by default.

Client

The Server tab

By default MCEC acts as a TCP/IP server listening on port 5150. When acting as a server, MCEC opens the port and waits for clients to connect, then processes incoming commands until the client disconnects. The server supports any number of simultaneous connections and speaks the Telnet protocol.

Server

Restricting the Server to this machine (bind address)

The command server has no socket authentication; anything that can reach the port can send commands that press keys, move the mouse, and start processes. By default the server binds to all network interfaces (0.0.0.0), so it is reachable from every host on your LAN/VPN (and from anywhere the port is forwarded). This preserves the long-standing behavior for setups driven from another machine on a trusted network.

If nothing off this machine needs to connect (for example, another local app talks to MCEC over localhost), restrict the server to loopback so the unauthenticated port is not exposed on the network. Edit mcec.settings and set:

<SocketServerBindAddress>127.0.0.1</SocketServerBindAddress>

Accepted values (case-insensitive):

Value Binds to
0.0.0.0, any, *, or empty/blank All interfaces (default; LAN/VPN reachable)
:: All interfaces, IPv6 only (binds IPv6 Any)
127.0.0.1, localhost, loopback This machine only (recommended for single-machine setups)
::1 IPv6 loopback (this machine only)
a specific local IP (e.g. 192.168.1.50) That interface only

When the resolved bind is not loopback (e.g. the 0.0.0.0 default), MCEC writes a loud WARN to the log at startup noting the command port is unauthenticated and reachable off-box, with the recommendation to set 127.0.0.1. An unparseable value is rejected with an error in the log and falls back to loopback (127.0.0.1) rather than silently exposing the port. Restart MCEC after editing the setting.

The Serial Server tab

When the Serial Server is enabled, MCEC opens the specified COM port (e.g. COM1) and waits for commands.

Serial

User Activity Monitor

MCEC’s User Activity Monitor sends a command (activity by default) to your home-automation system when a user is using the PC. It knows the PC is in use by watching keyboard and mouse activity; if the mouse is moving or keys are being pressed, the PC is in use. This is useful for adding context to a room occupancy sensor.

Activity Monitor

See the Control4 User Activity Driver for an example Control4 driver that uses this feature.

Enabling or Disabling Commands

By default all commands are disabled, to reduce the surface area MCEC exposes on the network. Use the Commands Window (Commands ▸ Enable and Test Commands…) to enable/disable commands.

Commands

Clicking Save mcec.commands file saves changes immediately. The .commands file is not saved automatically on exit; MCEC only writes it in response to that explicit action, so a crash or power loss can never corrupt it mid-write on the way out.

Testing MCEC

MCEC’s built-in TCP/IP client can send commands to another instance of MCEC on the same or a different PC. If both the Client and Server in a single instance are pointed at localhost on the same port, they can connect to each other, an easy way to test commands.

To configure “test mode”:

  1. Open File ▸ Settings….
  2. On the Client tab, check Enable Client and enter localhost as the Host.
  3. On the Server tab, check Enable Server.
  4. Click OK.
  5. Open Commands ▸ Enable and Test Commands… and start testing.

Commands

The Commands Window lists every command MCEC is configured to listen for, so you can see the full set and test them:

As a quick test, send these three lines (the 2nd line is a single space):

shiftdown:lwin
x
shiftup:lwin

This pops up the Windows Quick Link Menu, just as if the user typed Win-X.

Turn on the Activity Monitor while in test mode and you’ll see events in the log when activity is detected.

Using PuTTY

PuTTY is a free terminal emulator (and Telnet/SSH client) that works well for testing MCEC.

TCP/IP: Run PuTTY, set Host Name to localhost (or the PC running MCEC), set Port to MCEC’s listen port (e.g. 5150), set Connection Type to Raw, and click Open. Type commands and watch how MCEC reacts.

Serial: PuTTY can also connect over serial; set the COM-port settings and choose the Serial connection type.

The Command Language

MCEC works with Commands: text strings like greenbutton, hibernate, and winkey that MCEC listens for and acts on. Each command has a Type. When MCEC receives a command it performs an action on the PC it is running on; the action depends on the command’s type and parameters.

Security: As of version 2.2.1, all commands are disabled by default to reduce the network surface area. Use the Commands Window to enable the ones you need.

Command Types

Type Purpose
StartProcess Starts a process (executable, shortcut, or URI). Supports embedded nextCommand elements to run other commands after the process starts.
SetForegroundWindow Brings the specified window to the foreground.
Shutdown Shuts down, restarts, sleeps, or hibernates the host.
SendMessage Sends Windows messages to windows (e.g. mcemaximize sends Media Center full-screen).
SendInput Sends keyboard input as though typed on a keyboard.
Chars Sends text.
Mouse Sends mouse movement and button actions.
Pause Pauses before the next command runs (in milliseconds).
Built-in Single characters, VK_ codes, chars:, shiftdown:, shiftup:, pause:, and mcec:.

MCEC command names (Cmd values) are not case-sensitive; VK_UP equals vk_up, and shutdown equals ShutDown.

Simulating Keyboard Input

Any Windows virtual key code is supported by default, in the form VK_<key name>. For example:

VK_ESCAPE
VK_LWIN
VK_VOLUME_MUTE
VK_VOLUME_UP
VK_MEDIA_PLAY_PAUSE
VK_F1

A full list of virtual key codes is on this MSDN page.

Since Windows 10, VK_MEDIA_* keys (play/pause, next/prev track, volume) are only delivered to the foreground application; this is a Windows platform behavior, not something MCEC controls. If a media key seems to do nothing, bring the target app to the foreground first (e.g. with SetForegroundWindow or a launch sequence), then send the key.

Sending chars: plus text simulates typing that text. chars:3 types 3; chars:Hello types the letters H-e-l-l-o (including the shift for the capital). The text is typed literally, exactly as given; there is no escape processing, so chars:\ sends a single backslash and a Windows path types straight through: chars:C:\Users\me\file.txt types C:\Users\me\file.txt (no backslash doubling). Unicode characters pass through as-is: chars:☺ sends , chars:€ sends .

How chars: interacts with modifier keys (shift/ctrl/alt/win) is app-dependent; for fine-grained control use SendInput commands instead.

Sending a single character without chars: (e.g. just c) is equivalent to a SendInput command (a single key press). There is no difference between sending a and A; use shiftdown:/shiftup: to hold modifier keys. (The chars: command must be enabled for single-character commands to work.)

Simulating Shift, Control, Alt, and Windows keys

To hold or release a modifier key, send a shiftdown: or shiftup: command:

shiftdown:[shift|ctrl|alt|lwin|rwin]
shiftup:[shift|ctrl|alt|lwin|rwin]

For example, to type Test!:

shiftdown:shift
t
shiftup:shift
e
s
t
shiftdown:shift
1
shiftup:shift

This is the same as sending chars:Test!. The scheme also sends ctrl-, alt-, and win- chords; e.g. ctrl-s:

shiftdown:ctrl
s
shiftup:ctrl

Mouse Commands

The general format is:

mouse:<action>[,<param>,...,<param>]
Action Meaning
lbc / lbdc / lbd / lbu Left button click / double-click / down / up
rbc, rbdc, rbd, rbu Same for the right button
mbc, mbdc, mbd, mbu Same for the middle button
xbc,n (etc.) X-button n click (mouse:xbc,3)
mm,x,y Move the mouse x, y pixels relative (mouse:mm,7,-3 → right 7, up 3)
mt,x,y Move to an absolute position on the primary display in 0–65535 units (mouse:mt,0,65535 → bottom-left corner)
mtv,x,y Move to an absolute position on the virtual desktop in 0–65535 units (mouse:mtv,65535,0 → top-right corner)
mtp,x,y Move to an absolute screen pixel; the same coordinate space the agent query/find/displays tools use. Takes real pixels and normalizes across the virtual desktop, so negative or secondary-monitor coordinates land correctly (mouse:mtp,812,562).
hs,n Horizontal scroll n clicks (positive = right)
vs,n Vertical scroll n clicks (positive = forward/away)
drag,x1,y1,x2,y2[,x3,y3,…] Press at the first point, move through every subsequent point with the button held, and release at the last; a full press → move-path → release gesture dispatched atomically (nothing else interleaves). Coordinates are absolute screen pixels (normalized across the virtual desktop internally). Use it to resize a window by its border, move one by its title bar, drag a slider, marquee-select, or reorder (mouse:drag,400,300,700,500). Agents get a higher-level drag tool that also accepts UI Automation elements as endpoints.

When sending mouse movements it helps to hide the MCEC window; the live log display consumes resources and can make motion jerky.

mcec: Commands

The following commands control MCEC itself. Values are returned as command=value:

Defining Your Own Commands

MCEC ships with nearly 300 built-in commands. The first time it runs, it creates an mcec.commands file containing all built-in commands with Enabled="false" on every one. You can then edit mcec.commands to enable, override, or add commands. (Use Commands ▸ Open commands folder… to find the file.)

Deleting a built-in command from the file does not remove it permanently; MCEC re-adds built-ins whenever it saves, but with Enabled="false", which is functionally equivalent to deleting them.

File Format

The file is XML and must include the headers. Commands are defined within the <commands> element:

<?xml version="1.0"?>
<mcecontroller xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0.0">
  <commands xmlns="http://www.kindel.com/products/mcecontroller">
    ...
  </commands>
</mcecontroller>

Whenever mcec.commands changes it is reloaded; no restart needed. The general form of a command is:

<type Cmd="text to trigger on" Args="optional args" ... />

Case sensitivity: XML element and attribute names are case-insensitive (ctrl = Ctrl), and the Cmd value is case-insensitive (MonitorOff = monitoroff). Some attribute values are case-sensitive; true/false must be lowercase, and in SendInput, Ctrl="true" works but Ctrl="False" does not.

Do not define a command whose name is a single character; it interferes with single-character key presses.

Nesting

Commands can chain by nesting elements. Nested commands run after the started application begins processing window messages. For example, launch Notepad, wait 1 second, then type text:

<StartProcess Cmd="notepad" File="notepad.exe">
    <Pause Args="1000"/>
    <Chars Cmd="test" Args="this is a test." />
</StartProcess>

SendInput Commands

SendInput commands simulate key presses. Any combination of shift, ctrl, alt, and left/right Windows keys can accompany any virtual key code. SendInput accepts single characters (e.g. x or ` ), hex codes (e.g. 0x2a), decimal codes, or VK_ names. Under the covers the Windows SendInput()` API is used; keystrokes always go to the foreground window.

<SendInput Cmd="mypictures" vk="P" Shift="false" Ctrl="true" Alt="false" />
<SendInput Cmd="winx" vk="VK_X" Win="true"/>

Each of these does the same thing (a space), illustrating the equivalent key encodings:

<SendInput Cmd="space" vk="VK_SPACE" Enabled="true"/>
<SendInput Cmd="space" vk=" " Enabled="true"/>
<SendInput Cmd="space" vk="\u0020" Enabled="true"/>
<SendInput Cmd="space" vk="0x20" Enabled="true"/>

SendMessage Commands

SendMessage commands send a Windows message (via the SendMessage() API) to the foreground window; or to a specific window if its class name is specified. Msg, wParam, and lParam must be in decimal (not hex).

For example, WM_SYSCOMMAND with SC_MAXIMIZE (274 / 61488) maximizes the window whose class is ehshell:

<SendMessage Cmd="mce_maximize" ClassName="ehshell" Msg="274" wParam="61488" lParam="0" />

Other useful examples:

<!-- WM_SYSCOMMAND, SC_SCREENSAVE -->
<SendMessage Cmd="screensaver" Msg="274" wParam="61760" lParam="0" />
<!-- WM_SYSCOMMAND, SC_MONITORPOWER, 2 = off, -1 = on -->
<SendMessage Cmd="monitoroff" Msg="274" wParam="61808" lParam="2" />
<SendMessage Cmd="monitoron"  Msg="274" wParam="61808" lParam="-1" />

See the MSDN WM_SYSCOMMAND docs for more.

StartProcess Commands

StartProcess commands start programs and support chaining via nested command elements (the first embedded command runs after the app starts processing window messages).

<StartProcess Cmd="code"    File="code" Arguments="foo.cs" />
<StartProcess Cmd="tada"    File="C:\Windows\Media\tada.wav" Verb="Open" />
<StartProcess Cmd="term"    File="shell:AppsFolder\Microsoft.WindowsTerminal_8wekyb3d8bbwe!App" />
<StartProcess Cmd="netflix" File="shell:AppsFolder\4DF9E0F8.Netflix_mcm4njqhnhss8!Netflix.App" />

Shutdown Commands

<Shutdown Cmd="shutdown"  Type="shutdown" Timeout="30"/>
<Shutdown Cmd="restart"   Type="restart"/>
<Shutdown Cmd="abort"     Type="abort"/>
<Shutdown Cmd="standby"   Type="standby"/>
<Shutdown Cmd="hibernate" Type="hibernate"/>

SetForegroundWindow Commands

The SetForegroundWindow command sets a process’s main window to the foreground:

<SetForegroundWindow Cmd="activatenotepad" AppName="Notepad"/>

AppName is the “friendly process name” of an app (the name shown in Task Manager’s Details tab). MCEC uses GetProcessesByName and picks the first process that has a main window.

Note: the ClassName attribute is mis-named and preserved only for backwards compatibility. Since Windows Vista, one app cannot set arbitrary windows of another app to the foreground.

Chars Commands

<Chars Cmd="foo" Args="bar"/> defines foo so that receiving foo types bar, exactly as if chars:bar had been received.

Pause Commands

<Pause Cmd="pause3sec" Args="3000"/> pauses 3 seconds, the same as sending pause:3000. Pause delays add to any delay from the Default command pacing setting.

Disabling All Internal Commands

To force MCEC to listen only to commands defined in mcec.commands, create the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Kindel\MCE Controller and set the DWORD value DisableInternalCommands to anything other than 0. (The “MCE Controller” key name and the Kindel Systems fallback are kept for back-compat.) This is a machine-wide setting affecting all instances of MCEC.

Usage Notes (Media Center)

More Examples

See Example Commands for community-contributed mcec.commands recipes (Netflix, HDHomeRun, Media Center, window tricks, and more).