Files
hoelee-blog/src/content/posts/plugging-windows-desktop-control-into-four-ai-agents.md
T
hoelee 68771101ea edit(content): review batch-1 editorial pass across 24 posts (EN + ZH)
- voice: first-person throughout (we/our -> I/my), matching the post guideline
- privacy: internal LAN IPs replaced with placeholder hostnames
  (n8n.internal, gpu-node.internal); one compose volume path generalised
- ZH twins: Traditional -> Simplified characters (site serves zh-Hans),
  whole-file renormalisation where the twin was still Traditional
- dynamicCta: true on 12 posts so the contextual dual-track CTA renders
- long configs wrapped in <details class="tech-deep-dive"> with a summary
  naming the artefact and line count
- self-hosted-tts: token refresh now writes .tmp + atomic mv, with a note on
  the 401 race the old truncating redirect created
2026-10-27 03:29:03 +08:00

6.5 KiB

title, description, pubDate, updatedDate, category, tags, ogImage, banner, draft, dynamicCta
title description pubDate updatedDate category tags ogImage banner draft dynamicCta
Plugging Windows Desktop Control into Four AI Agents: Hermes, OpenCode, Claw, and Claude How to configure, verify, and standardize windows-mcp across Hermes Agent, OpenCode CLI, Claw Code, and Claude Code without config drift or tool sprawl. 2025-12-23 2026-10-25 ai
windows
mcp
ai-agents
hermes
opencode
claw-code
/og/plugging-windows-desktop-control-into-four-ai-agents.jpg /banners/plugging-windows-desktop-control-into-four-ai-agents.jpg false true

In a multi-agent development environment, running different agent frameworks for specialized tasks is standard practice. On the Windows workstation I manage, I orchestrate four distinct AI coding agents:

  • Hermes Agent: Built by Nous Research, powering primary multi-modal orchestration and terminal tooling.
  • OpenCode: A flexible, provider-agnostic autonomous coding agent with a terminal UI.
  • Claw Code: The clean-room Rust CLI implementation of Claude Code.
  • Claude Code: Anthropic's flagship coding agent.

While all four agents excel at editing files and running shell commands, none of them come with out-of-the-box support for manipulating legacy Windows desktop GUIs, interacting with system file dialogs, or capturing desktop window state.

Enter windows-mcp, an open-source Model Context Protocol server exposing Windows UIAutomation, mouse, keyboard, and window management tools. Here is how I unified this server across all four agent platforms without configuration drift.


The Python 3.14+ Baseline

windows-mcp has one strict prerequisite: it requires Python 3.14+. On Windows, managing Python versions manually across different environments can easily turn into path conflicts.

The cleanest execution strategy is relying on uv's uvx ephemeral launcher. With uvx, each agent invokes:

uvx windows-mcp serve

uvx fetches the isolated environment on demand, installs pre-built binary wheels for PyWin32 and Pydantic, and runs the server over standard input/output (stdio) without polluting the global system interpreter.


1. Hermes Agent

Hermes Agent features a native MCP client configured through ~/.hermes/config.yaml.

You can register it directly via the Hermes CLI tool discovery mechanism:

printf 'y\n' | hermes mcp add windows-mcp --command uvx \
  --env WINDOWS_MCP_CONTROL=false WINDOWS_MCP_SCREENSHOT_SCALE=0.5 WINDOWS_MCP_DISABLE_FLASH=1 WINDOWS_MCP_EXCLUDE_PROCESSES=Code.exe,Cursor.exe ANONYMIZED_TELEMETRY=false \
  --args windows-mcp serve --exclude-tools PowerShell,Registry

Under the hood, this writes the following block to ~/.hermes/config.yaml:

mcp_servers:
  windows-mcp:
    command: uvx
    args:
      - windows-mcp
      - serve
      - --exclude-tools
      - PowerShell,Registry
    env:
      WINDOWS_MCP_CONTROL: "false"
      WINDOWS_MCP_SCREENSHOT_SCALE: "0.5"
      WINDOWS_MCP_DISABLE_FLASH: "1"
      WINDOWS_MCP_EXCLUDE_PROCESSES: Code.exe,Cursor.exe
      ANONYMIZED_TELEMETRY: "false"

Verify the connection:

$ hermes mcp list
MCP Servers:
  Name             Transport              Tools    Status    
  ──────────────── ────────────────────── ──────── ──────────
  windows-mcp      uvx windows-mcp serve  all      ✓ enabled

2. OpenCode

OpenCode reads its MCP configuration from ~/.config/opencode/opencode.jsonc.

Add the windows-mcp server entry inside the top-level "mcp" dictionary:

{
  "$schema": "https://opencode.ai/config.json",
  "mcp": {
    "windows-mcp": {
      "type": "local",
      "command": ["uvx", "windows-mcp", "serve", "--exclude-tools", "PowerShell,Registry"],
      "enabled": true,
      "environment": {
        "WINDOWS_MCP_CONTROL": "false",
        "WINDOWS_MCP_SCREENSHOT_SCALE": "0.5",
        "WINDOWS_MCP_DISABLE_FLASH": "1",
        "WINDOWS_MCP_EXCLUDE_PROCESSES": "Code.exe,Cursor.exe",
        "ANONYMIZED_TELEMETRY": "false"
      }
    }
  }
}

Verify that OpenCode connects cleanly:

$ opencode mcp list
┌  MCP Servers
│
●  ✓ windows-mcp connected
│      uvx windows-mcp serve --exclude-tools PowerShell,Registry
│
└  1 server(s)

3. Claw Code (claw.exe)

Claw Code (v0.1.7) looks for MCP definitions in .claw/settings.json (project-level) or ~/.claw/settings.json (user-level):

{
  "mcpServers": {
    "windows-mcp": {
      "command": "uvx",
      "args": [
        "windows-mcp",
        "serve",
        "--exclude-tools",
        "PowerShell,Registry"
      ],
      "env": {
        "WINDOWS_MCP_CONTROL": "false",
        "WINDOWS_MCP_SCREENSHOT_SCALE": "0.5",
        "WINDOWS_MCP_DISABLE_FLASH": "1",
        "WINDOWS_MCP_EXCLUDE_PROCESSES": "Code.exe,Cursor.exe",
        "ANONYMIZED_TELEMETRY": "false"
      }
    }
  }
}

Verify in Claw Code:

$ claw mcp
MCP
  Working directory C:\Users\workstation
  Configured servers 1
  Total entries     1
  Invalid entries   0

  windows-mcp      stdio         user    uvx windows-mcp serve --exclude-tools PowerShell,Registry

4. Claude Code

Claude Code shares the exact same schema in ~/.claude.json. Mirror the windows-mcp block into ~/.claude.json:

{
  "mcpServers": {
    "windows-mcp": {
      "command": "uvx",
      "args": ["windows-mcp", "serve", "--exclude-tools", "PowerShell,Registry"],
      "env": {
        "WINDOWS_MCP_CONTROL": "false",
        "WINDOWS_MCP_SCREENSHOT_SCALE": "0.5",
        "WINDOWS_MCP_DISABLE_FLASH": "1",
        "WINDOWS_MCP_EXCLUDE_PROCESSES": "Code.exe,Cursor.exe",
        "ANONYMIZED_TELEMETRY": "false"
      }
    }
  }
}

Proving End-to-End Operation

Rather than hoping the configurations work, I ran an automated probe script via Python's standard mcp SDK to exercise three critical tools end-to-end:

  1. DisplayInventory: Queried my dual-screen setup (1080p primary + 1440p secondary) and returned correct virtual desktop boundaries (left: -313, top: -1440, right: 2247, bottom: 1080).
  2. Screenshot: Captured the active screen buffer with downscaling enabled, validating that cursor coordinates were correctly logged (1318, -714).
  3. Notification: Dispatched a native Windows 11 toast notification to the notification center.

With identical arguments and environment variables mirrored across all four agent configs, any of my coding agents can now seamlessly interact with native Windows software when code or APIs alone cannot bridge the gap.