Claude KVM

๊ณต์‹

๐Ÿค– โšก๏ธ MCP ์„œ๋ฒ„ (๏ฃฟ MacOS) โ€” VNC๋ฅผ ํ†ตํ•ด ์›๊ฒฉ ๋ฐ์Šคํฌํ†ฑ ์ œ์–ด

Claude KVM MCP(์œผ)๋กœ ๋ฌด์—‡์„ ํ•  ์ˆ˜ ์žˆ๋‚˜์š”?

  • ์›๊ฒฉ ํ™”๋ฉด ์บก์ฒ˜ ๋ฐ ๊ฒ€์‚ฌ โ€” ๋งˆ์šฐ์Šค ํฌ์ธํ„ฐ ์ฃผ๋ณ€์˜ ์ „์ฒด screenshot ๋˜๋Š” cursor_crop์„ ์š”์ฒญํ•˜์—ฌ ํ˜„์žฌ ๋ฐ์Šคํฌํ†ฑ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
  • ํ™”๋ฉด์ƒ์˜ ํ…์ŠคํŠธ ๋ฐ UI ์š”์†Œ ๊ฐ์ง€ โ€” detect_elements๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๊ฒฝ๊ณ„ ์ƒ์ž ์ขŒํ‘œ๊ฐ€ ํฌํ•จ๋œ OCR ํ…์ŠคํŠธ๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ํ†ตํ•ด ๋น„์ „ ํ† ํฐ์„ ์†Œ๋ชจํ•˜์ง€ ์•Š๊ณ  ์ •ํ™•ํ•œ ํด๋ฆญ ํƒ€๊ฒŸํŒ…์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
  • ๋งˆ์šฐ์Šค ๋ฐ ํ‚ค๋ณด๋“œ ์›๊ฒฉ ์ œ์–ด โ€” mouse_click, mouse_drag, key_type, key_combo ๋˜๋Š” paste๋ฅผ ์‹คํ–‰ํ•˜์—ฌ ๋Œ€์ƒ ๋จธ์‹ ์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜๊ณผ ์ƒํ˜ธ์ž‘์šฉํ•ฉ๋‹ˆ๋‹ค.
  • ์‹œ๊ฐ์  ๋ณ€๊ฒฝ ์‚ฌํ•ญ์„ ํšจ์œจ์ ์œผ๋กœ ํ™•์ธ โ€” diff_check๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ €์žฅ๋œ set_baseline๊ณผ ํ™”๋ฉด์ด ๋ณ€๊ฒฝ๋˜์—ˆ๋Š”์ง€ ๊ฐ์ง€ํ•˜์—ฌ ๋ถˆํ•„์š”ํ•œ ์ „์ฒด ์ด๋ฏธ์ง€ ์ „์†ก์„ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.
  • ๋Ÿฐํƒ€์ž„์— ํƒ€์ด๋ฐ ๋ฐ ๋””์Šคํ”Œ๋ ˆ์ด ์Šค์ผ€์ผ ์กฐ์ • โ€” configure๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ ๋‹ค์–‘ํ•œ VNC ํ™˜๊ฒฝ์— ๋งž๊ฒŒ ํด๋ฆญ ์œ ์ง€ ์ง€์—ฐ, ๋“œ๋ž˜๊ทธ ๋ณด๊ฐ„ ๋˜๋Š” max_dimension์„ ์กฐ์ •ํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ์„œ

Claude KVM

Claude KVM

์›๊ฒฉ ์ ‘๊ทผ, ์ธ๊ณต์ง€๋Šฅ

claude-kvm.ai

Claude KVM์€ VNC๋ฅผ ํ†ตํ•ด ์›๊ฒฉ ๋ฐ์Šคํฌํ†ฑ ํ™˜๊ฒฝ์„ ์ œ์–ดํ•˜๋Š” MCP ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ์–‡์€ JS ํ”„๋ก์‹œ ๊ณ„์ธต(MCP ์„œ๋ฒ„)๊ณผ macOS ์‹œ์Šคํ…œ์—์„œ ์‹คํ–‰๋˜๋Š” ํ”Œ๋žซํผ ๋„ค์ดํ‹ฐ๋ธŒ Swift VNC ๋ฐ๋ชฌ์œผ๋กœ ๊ตฌ์„ฑ๋ฉ๋‹ˆ๋‹ค.

Claude KVM Demo Claude KVM Demo Mac

[!TIP] Phantom-WG๊ฐ€ ํ›Œ๋ฅญํ•œ ๋Œ€์•ˆ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ž์ฒด ํ˜ธ์ŠคํŒ… VPN ์„ฑ๋Šฅ๊ณผ ์ถ”๊ฐ€์ ์ธ ๊ฐœ์ธ์ •๋ณด ๋ณดํ˜ธ ๊ธฐ๋Šฅ์„ ๋ˆ„๋ฆฌ๋ฉด์„œ ์ž์ฒด ๋„คํŠธ์›Œํฌ ๋‚ด์— VNC ์„œ๋ฒ„๋ฅผ ๊ฒฉ๋ฆฌํ•˜์„ธ์š”.

์‹ค์‹œ๊ฐ„ ํ…Œ์ŠคํŠธ ์‹คํ–‰

[!NOTE] ํ…Œ์ŠคํŠธ๋Š” GitHub Actions์—์„œ ํˆฌ๋ช…ํ•˜๊ฒŒ ์ˆ˜ํ–‰๋˜๋ฉฐ, CI ํ™˜๊ฒฝ์—์„œ ๊ฐ ๋‹จ๊ณ„๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“  ํ…Œ์ŠคํŠธ๊ฐ€ ๋๋‚˜๋ฉด ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ ํ†ต๊ณผ ์—ฌ๋ถ€์™€ ๊ด€๊ณ„์—†์ด ์—์ด์ „ํŠธ๊ฐ€ ์„ธ์…˜ ์ค‘ ์ˆ˜ํ–‰ํ•œ ๊ฐ ๋‹จ๊ณ„์˜ ์Šคํฌ๋ฆฐ์ƒท๊ณผ ์ „์ฒด ์„ธ์…˜์„ ์บก์ฒ˜ํ•œ .mp4 ๋น„๋””์˜ค ๋…นํ™”๋ณธ์„ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ๋…นํ™”๋ณธ๊ณผ ์Šคํฌ๋ฆฐ์ƒท์„ ๊ฒ€ํ† ํ•˜๋ฉด ์—์ด์ „ํŠธ๊ฐ€ ๊ฐ ๋‹จ๊ณ„๋ฅผ ์–ด๋–ป๊ฒŒ ์ง„ํ–‰ํ–ˆ๋Š”์ง€, ์ž‘์—…์— ์†Œ์š”๋œ ์‹œ๊ฐ„, ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ์— ๋”ฐ๋ผ ์–ด๋–ค ๊ฒฐ์ •์„ ๋‚ด๋ ธ๋Š”์ง€ ๊ด€์ฐฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ์˜ˆ์‹œ๋Š” ์ž์ฒด ํ™˜๊ฒฝ์—์„œ MCP ์„œ๋ฒ„๋ฅผ ์œ„ํ•œ ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ๋‚˜ ์ง€์นจ์„ ์ž‘์„ฑํ•  ๋•Œ ์ฐธ๊ณ  ์ž๋ฃŒ๋กœ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

[!WARNING] GitHub์˜ ์•„ํ‹ฐํŒฉํŠธ ๋ณด์กด ์ •์ฑ…์œผ๋กœ ์ธํ•ด ์ด ์‹คํ–‰์— ์ฒจ๋ถ€๋œ ์•„ํ‹ฐํŒฉํŠธ๊ฐ€ ๋งŒ๋ฃŒ๋˜์—ˆ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์˜๊ตฌ ์‚ฌ๋ณธ์€ ์•„ํ‹ฐํŒฉํŠธ ๋ณด์กด ์›Œํฌํ”Œ๋กœ์šฐ๋ฅผ ํ†ตํ•ด ์ค€๋น„๋˜๋ฉฐ, press-kit ๋ธŒ๋žœ์น˜์˜ artifacts/ ๋””๋ ‰ํ„ฐ๋ฆฌ์—์„œ ์‹คํ–‰ ID๋กœ ํ•ญ์ƒ ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์•„ํ‚คํ…์ฒ˜

graph TB
    subgraph MCP["MCP Client (Claude)"]
        AI["Claude"]
    end

    subgraph Proxy["claude-kvm ยท MCP Proxy (stdio)"]
        direction TB
        Server["MCP Server<br/><code>index.js</code>"]
        Tools["Tool Definitions<br/><code>tools/index.js</code>"]
        Server --> Tools
    end

    subgraph Daemon["claude-kvm-daemon ยท Native VNC Client (stdin/stdout)"]
        direction TB
        CMD["Command Handler<br/><i>PC Dispatch</i>"]
        Scale["Display Scaling<br/><i>Scaled โ†” Native</i>"]

        subgraph Screen["Screen"]
            Capture["Frame Capture<br/><i>PNG ยท Crop ยท Diff</i>"]
            OCR["OCR Detection<br/><i>Apple Vision</i>"]
        end

        subgraph InputGroup["Input"]
            Mouse["Mouse<br/><i>Click ยท Drag ยท Move ยท Scroll</i>"]
            KB["Keyboard<br/><i>Tap ยท Combo ยท Type ยท Paste</i>"]
        end

        VNC["VNC Bridge<br/><i>LibVNCClient 0.9.15</i>"]

        CMD --> Scale
        Scale --> Capture
        Scale --> Mouse
        Scale --> KB
        Capture -.->|"framebuffer"| VNC
        Mouse -->|"pointer events"| VNC
        KB -->|"key events"| VNC
    end

    subgraph Target["Target Machine"]
        VNC_Server["VNC Server<br/><i>:5900</i>"]
        Desktop["Desktop Environment"]
        VNC_Server --> Desktop
    end

    AI <-->|"stdio<br/>JSON-RPC"| Server
    Server <-->|"stdin/stdout<br/>PC (NDJSON)"| CMD
    VNC <-->|"RFB Protocol<br/>TCP :5900"| VNC_Server

    classDef proxy fill:#1a1a2e,stroke:#16213e,color:#e5e5e5
    classDef daemon fill:#0f3460,stroke:#533483,color:#e5e5e5
    classDef target fill:#1a1a2e,stroke:#e94560,color:#e5e5e5

    class Server,Tools proxy
    class CMD,Scale,VNC,Capture,Mouse,KB daemon
    class VNC_Server,Desktop target

๊ณ„์ธต

๊ณ„์ธต์–ธ์–ด์—ญํ• ํ†ต์‹  ๋ฐฉ์‹
MCP ํ”„๋ก์‹œJavaScript (Node.js)MCP ํ”„๋กœํ† ์ฝœ์„ ํ†ตํ•ด Claude์™€ ํ†ต์‹ , ๋ฐ๋ชฌ ์ˆ˜๋ช… ์ฃผ๊ธฐ ๊ด€๋ฆฌstdio JSON-RPC
VNC ๋ฐ๋ชฌSwift/C (Apple Silicon)VNC ์—ฐ๊ฒฐ, ํ™”๋ฉด ์บก์ฒ˜, ๋งˆ์šฐ์Šค/ํ‚ค๋ณด๋“œ ์ž…๋ ฅ ์ฃผ์ž…stdin/stdout PC (NDJSON)

PC (ํ”„๋กœ์‹œ์ € ํ˜ธ์ถœ) ํ”„๋กœํ† ์ฝœ

ํ”„๋ก์‹œ์™€ ๋ฐ๋ชฌ ๊ฐ„์˜ ํ†ต์‹ ์€ NDJSON์„ ํ†ตํ•œ PC ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค:

Request:      {"method":"<name>","params":{...},"id":<int|string>}
Response:     {"result":{...},"id":<int|string>}
Error:        {"error":{"code":<int>,"message":"..."},"id":<int|string>}
Notification: {"method":"<name>","params":{...}}

์ขŒํ‘œ ์Šค์ผ€์ผ๋ง

VNC ์„œ๋ฒ„์˜ ๊ธฐ๋ณธ ํ•ด์ƒ๋„๋Š” --max-dimension(๊ธฐ๋ณธ๊ฐ’: 1280px) ๋‚ด์— ๋งž๋„๋ก ์ถ•์†Œ๋ฉ๋‹ˆ๋‹ค. Claude๋Š” ์Šค์ผ€์ผ๋ง๋œ ์ขŒํ‘œ์—์„œ ๋” ์ผ๊ด€๋˜๊ฒŒ ์ž‘๋™ํ•˜๋ฉฐ, ๋ฐ๋ชฌ์ด ๋ฐฑ๊ทธ๋ผ์šด๋“œ์—์„œ ๋ณ€ํ™˜์„ ์ฒ˜๋ฆฌํ•ฉ๋‹ˆ๋‹ค:

Native:  4220 x 2568  (VNC server framebuffer)
Scaled:  1280 x 779   (what Claude sees and targets)

mouse_click(640, 400) โ†’ VNC receives (2110, 1284)

ํ™”๋ฉด ์ „๋žต

Claude๋Š” ์ ์ง„์  ๊ฒ€์ฆ ์ ‘๊ทผ ๋ฐฉ์‹์œผ๋กœ ํ† ํฐ ๋น„์šฉ์„ ์ตœ์†Œํ™”ํ•ฉ๋‹ˆ๋‹ค:

diff_check       โ†’  changeDetected: true/false     ~5ms    (text only, no image)
detect_elements  โ†’  OCR text + bounding boxes      ~50ms   (text only, no image)
cursor_crop      โ†’  crop around cursor              ~50ms   (small image)
screenshot       โ†’  full screen capture             ~200ms  (full image)

detect_elements๋Š” ์˜จ๋””๋ฐ”์ด์Šค OCR์„ ์œ„ํ•ด Apple Vision ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์Šค์ผ€์ผ๋ง๋œ ๊ณต๊ฐ„์—์„œ ๊ฒฝ๊ณ„ ์ƒ์ž ์ขŒํ‘œ์™€ ํ•จ๊ป˜ ํ…์ŠคํŠธ ์ฝ˜ํ…์ธ ๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋น„์ „ ํ† ํฐ์„ ์†Œ๋น„ํ•˜์ง€ ์•Š๊ณ  ์ •๋ฐ€ํ•œ ํด๋ฆญ ํƒ€๊ฒŸํŒ…์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.


์„ค์น˜

์š”๊ตฌ ์‚ฌํ•ญ

  • macOS (Apple Silicon / aarch64)
  • Node.js (LTS)

๋ฐ๋ชฌ

brew tap ARAS-Workspace/tap
brew install claude-kvm-daemon

[!NOTE] claude-kvm-daemon์€ CI(GitHub Actions)๋ฅผ ํ†ตํ•ด ์ปดํŒŒ์ผ ๋ฐ ์ฝ”๋“œ ์„œ๋ช…๋ฉ๋‹ˆ๋‹ค. ๋นŒ๋“œ ์ถœ๋ ฅ๋ฌผ์€ Homebrew ๋ฐฐํฌ์šฉ .tar.gz ์•„์นด์ด๋ธŒ์™€ ๊ณต์ฆ์šฉ .dmg ๋””์Šคํฌ ์ด๋ฏธ์ง€์˜ ๋‘ ๊ฐ€์ง€ ํ˜•์‹์œผ๋กœ ํŒจํ‚ค์ง•๋ฉ๋‹ˆ๋‹ค. DMG๋Š” ๋™์ผํ•œ ์›Œํฌํ”Œ๋กœ์šฐ ๋‚ด์—์„œ ๊ณต์ฆ์„ ์œ„ํ•ด Apple ์„œ๋ฒ„์— ์ œ์ถœ๋˜๋ฉฐ, CI ๋กœ๊ทธ์—์„œ ๊ณผ์ •์„ ์ถ”์ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณต์ฆ๋œ DMG๋Š” CI ์•„ํ‹ฐํŒฉํŠธ๋กœ ์ œ๊ณต๋˜๋ฉฐ, ๋ณด๊ด€๋œ .tar.gz๋„ ์ €์žฅ์†Œ์— ๋ฆด๋ฆฌ์Šค๋กœ ๊ฒŒ์‹œ๋ฉ๋‹ˆ๋‹ค. Homebrew ์„ค์น˜๋Š” ์ด ๋ฆด๋ฆฌ์Šค๋ฅผ ์ถ”์ ํ•ฉ๋‹ˆ๋‹ค.

MCP ๊ตฌ์„ฑ

ํ”„๋กœ์ ํŠธ ๋””๋ ‰ํ„ฐ๋ฆฌ์— .mcp.json ํŒŒ์ผ์„ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค:

{
  "mcpServers": {
    "claude-kvm": {
      "command": "npx",
      "args": ["-y", "claude-kvm"],
      "env": {
        "VNC_HOST": "192.168.1.100",
        "VNC_PORT": "5900",
        "VNC_USERNAME": "user",
        "VNC_PASSWORD": "pass",
        "CLAUDE_KVM_DAEMON_PATH": "/opt/homebrew/bin/claude-kvm-daemon",
        "CLAUDE_KVM_DAEMON_PARAMETERS": "-v"
      }
    }
  }
}

[!NOTE] ์ด ๋„๊ตฌ๋Š” CI๋ฅผ ํ†ตํ•ด ์—”๋“œํˆฌ์—”๋“œ ํ…Œ์ŠคํŠธ๋ฉ๋‹ˆ๋‹ค. Claude๊ฐ€ VNC๋ฅผ ํ†ตํ•ด ์ž‘์—…์„ ์‹คํ–‰ํ•˜๋Š” ๋™์•ˆ ๋…๋ฆฝ์ ์ธ ๋น„์ „ ๋ชจ๋ธ์ด ๊ฒฐ๊ณผ๋ฅผ ๊ด€์ฐฐํ•˜๊ณ  ๊ฒ€์ฆํ•ฉ๋‹ˆ๋‹ค. ์‹ค์‹œ๊ฐ„ ์›Œํฌํ”Œ๋กœ์šฐ ์‹คํ–‰, ์‹œ์Šคํ…œ ํ”„๋กฌํ”„ํŠธ ๋ฐ ๋ฐ๋ชจ ๋…นํ™”๋ณธ์€ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ฐธ์กฐํ•˜์„ธ์š”.

๊ตฌ์„ฑ

MCP ํ”„๋ก์‹œ (ENV)

๋งค๊ฐœ๋ณ€์ˆ˜๊ธฐ๋ณธ๊ฐ’์„ค๋ช…
VNC_HOST127.0.0.1VNC ์„œ๋ฒ„ ์ฃผ์†Œ
VNC_PORT5900VNC ํฌํŠธ ๋ฒˆํ˜ธ
VNC_USERNAME์‚ฌ์šฉ์ž ์ด๋ฆ„ (ARD์— ํ•„์š”)
VNC_PASSWORD๋น„๋ฐ€๋ฒˆํ˜ธ
CLAUDE_KVM_DAEMON_PATHclaude-kvm-daemon๋ฐ๋ชฌ ๋ฐ”์ด๋„ˆ๋ฆฌ ๊ฒฝ๋กœ (PATH์— ์ด๋ฏธ ์žˆ์œผ๋ฉด ๋ถˆํ•„์š”)
CLAUDE_KVM_DAEMON_PARAMETERS๋ฐ๋ชฌ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ CLI ์ธ์ˆ˜

๋ฐ๋ชฌ ๋งค๊ฐœ๋ณ€์ˆ˜ (CLI)

CLAUDE_KVM_DAEMON_PARAMETERS์„ ํ†ตํ•ด ๋ฐ๋ชฌ์— ์ „๋‹ฌ๋˜๋Š” ์ถ”๊ฐ€ ์ธ์ˆ˜:

"CLAUDE_KVM_DAEMON_PARAMETERS": "--max-dimension 800 -v"
๋งค๊ฐœ๋ณ€์ˆ˜๊ธฐ๋ณธ๊ฐ’์„ค๋ช…
--max-dimension1280์ตœ๋Œ€ ๋””์Šคํ”Œ๋ ˆ์ด ์Šค์ผ€์ผ๋ง ํฌ๊ธฐ (px)
--connect-timeoutVNC ์—ฐ๊ฒฐ ํƒ€์ž„์•„์›ƒ (์ดˆ)
--bits-per-sampleํ”ฝ์…€๋‹น ๋น„ํŠธ ์ƒ˜ํ”Œ
--no-reconnect์ž๋™ ์žฌ์—ฐ๊ฒฐ ๋น„ํ™œ์„ฑํ™”
-v, --verbose์ƒ์„ธ ๋กœ๊น… (stderr)

๋Ÿฐํƒ€์ž„ ๊ตฌ์„ฑ (PC)

๋ชจ๋“  ํƒ€์ด๋ฐ ๋ฐ ๋””์Šคํ”Œ๋ ˆ์ด ๋งค๊ฐœ๋ณ€์ˆ˜๋Š” configure ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ๋Ÿฐํƒ€์ž„์— ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๊ฐ’์„ ๊ฒ€์‚ฌํ•˜๋ ค๋ฉด get_timing์„ ์‚ฌ์šฉํ•˜์„ธ์š”.

ํƒ€์ด๋ฐ ์„ค์ •:

{"method":"configure","params":{"click_hold_ms":80,"key_hold_ms":50}}
{"result":{"detail":"OK โ€” changed: click_hold_ms, key_hold_ms"}}

๋””์Šคํ”Œ๋ ˆ์ด ์Šค์ผ€์ผ๋ง ๋ณ€๊ฒฝ:

{"method":"configure","params":{"max_dimension":960}}
{"result":{"detail":"OK โ€” changed: max_dimension","scaledWidth":960,"scaledHeight":584}}

๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์žฌ์„ค์ •:

{"method":"configure","params":{"reset":true}}
{"result":{"detail":"OK โ€” reset to defaults","timing":{"click_hold_ms":50,"combo_mod_ms":10,"cursor_crop_radius":150,"double_click_gap_ms":50,"drag_min_steps":10,"drag_pixels_per_step":20,"drag_position_ms":30,"drag_press_ms":50,"drag_settle_ms":30,"drag_step_ms":5,"hover_settle_ms":400,"key_hold_ms":30,"max_dimension":1280,"paste_settle_ms":30,"scroll_press_ms":10,"scroll_tick_ms":20,"type_inter_key_ms":20,"type_key_ms":20,"type_shift_ms":10},"scaledWidth":1280,"scaledHeight":779}}

ํ˜„์žฌ ๊ฐ’ ๊ฐ€์ ธ์˜ค๊ธฐ:

{"method":"get_timing"}
{"result":{"timing":{"click_hold_ms":80,"combo_mod_ms":10,"cursor_crop_radius":150,"double_click_gap_ms":50,"drag_min_steps":10,"drag_pixels_per_step":20,"drag_position_ms":30,"drag_press_ms":50,"drag_settle_ms":30,"drag_step_ms":5,"hover_settle_ms":400,"key_hold_ms":50,"max_dimension":1280,"paste_settle_ms":30,"scroll_press_ms":10,"scroll_tick_ms":20,"type_inter_key_ms":20,"type_key_ms":20,"type_shift_ms":10},"scaledWidth":1280,"scaledHeight":779}}
๋งค๊ฐœ๋ณ€์ˆ˜๊ธฐ๋ณธ๊ฐ’์„ค๋ช…
max_dimension1280์ตœ๋Œ€ ์Šคํฌ๋ฆฐ์ƒท ํฌ๊ธฐ
cursor_crop_radius150์ปค์„œ ์ž๋ฅด๊ธฐ ๋ฐ˜๊ฒฝ (px)
click_hold_ms50ํด๋ฆญ ์œ ์ง€ ์‹œ๊ฐ„
double_click_gap_ms50๋”๋ธ” ํด๋ฆญ ๊ฐ„๊ฒฉ ์ง€์—ฐ
hover_settle_ms400ํ˜ธ๋ฒ„ ์ •์ฐฉ ๋Œ€๊ธฐ
drag_position_ms30๋“œ๋ž˜๊ทธ ์ „ ์œ„์น˜ ๋Œ€๊ธฐ
drag_press_ms50๋“œ๋ž˜๊ทธ ๋ˆ„๋ฆ„ ์œ ์ง€ ์ž„๊ณ„๊ฐ’
drag_step_ms5๋ณด๊ฐ„ ์ง€์  ์‚ฌ์ด
drag_settle_ms30ํ•ด์ œ ์ „ ์ •์ฐฉ
drag_pixels_per_step20ํ”ฝ์…€๋‹น ์ง€์  ๋ฐ€๋„
drag_min_steps10์ตœ์†Œ ๋ณด๊ฐ„ ๋‹จ๊ณ„
scroll_press_ms10์Šคํฌ๋กค ๋ˆ„๋ฆ„-ํ•ด์ œ ๊ฐ„๊ฒฉ
scroll_tick_ms20ํ‹ฑ ๊ฐ„ ์ง€์—ฐ
key_hold_ms30ํ‚ค ์œ ์ง€ ์‹œ๊ฐ„
combo_mod_ms10์ˆ˜์ •์ž ์ •์ฐฉ ์ง€์—ฐ
type_key_ms20ํƒ€์ดํ•‘ ์ค‘ ํ‚ค ์œ ์ง€
type_inter_key_ms20๋ฌธ์ž ๊ฐ„ ์ง€์—ฐ
type_shift_ms10Shift ํ‚ค ์ •์ฐฉ
paste_settle_ms30ํด๋ฆฝ๋ณด๋“œ ์“ฐ๊ธฐ ํ›„ ๋Œ€๊ธฐ

๋„๊ตฌ

๋ชจ๋“  ์ž‘์—…์€ ๋‹จ์ผ vnc_command ๋„๊ตฌ๋ฅผ ํ†ตํ•ด ์ˆ˜ํ–‰๋ฉ๋‹ˆ๋‹ค:

ํ™”๋ฉด

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
screenshot์ „์ฒด ํ™”๋ฉด PNG ์บก์ฒ˜
cursor_crop์‹ญ์ž์„  ์˜ค๋ฒ„๋ ˆ์ด์™€ ํ•จ๊ป˜ ์ปค์„œ ์ฃผ๋ณ€ ์ž๋ฅด๊ธฐ
diff_check๊ธฐ์ค€์„  ๋Œ€๋น„ ํ™”๋ฉด ๋ณ€๊ฒฝ ๊ฐ์ง€
set_baselineํ˜„์žฌ ํ™”๋ฉด์„ diff ์ฐธ์กฐ๋กœ ์ €์žฅ

๋งˆ์šฐ์Šค

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
mouse_clickx, y, button?ํด๋ฆญ (์™ผ์ชฝ|์˜ค๋ฅธ์ชฝ|๊ฐ€์šด๋ฐ)
mouse_double_clickx, y๋”๋ธ” ํด๋ฆญ
mouse_movex, y์ปค์„œ ์ด๋™
hoverx, y์ด๋™ + ์ •์ฐฉ ๋Œ€๊ธฐ
nudgedx, dy์ƒ๋Œ€์  ์ปค์„œ ์ด๋™
mouse_dragx, y, toX, toY์‹œ์ž‘์ ์—์„œ ๋์ ์œผ๋กœ ๋“œ๋ž˜๊ทธ
scrollx, y, direction, amount?์Šคํฌ๋กค (์œ„|์•„๋ž˜|์™ผ์ชฝ|์˜ค๋ฅธ์ชฝ)

ํ‚ค๋ณด๋“œ

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
key_tapkey๋‹จ์ผ ํ‚ค ๋ˆ„๋ฅด๊ธฐ (enter|escape|tab|space|...)
key_combokey ๋˜๋Š” keys์ˆ˜์ •์ž ์กฐํ•ฉ ("cmd+c" ๋˜๋Š” ["cmd","shift","3"])
key_typetext๋ฌธ์ž๋ณ„๋กœ ํ…์ŠคํŠธ ์ž…๋ ฅ
pastetextํด๋ฆฝ๋ณด๋“œ๋ฅผ ํ†ตํ•ด ํ…์ŠคํŠธ ๋ถ™์—ฌ๋„ฃ๊ธฐ

๊ฐ์ง€

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
detect_elements๊ฒฝ๊ณ„ ์ƒ์ž์™€ ํ•จ๊ป˜ OCR ํ…์ŠคํŠธ ๊ฐ์ง€ (Apple Vision)

์Šค์ผ€์ผ๋ง๋œ ๊ณต๊ฐ„์—์„œ ๊ฒฝ๊ณ„ ์ƒ์ž ์ขŒํ‘œ์™€ ํ•จ๊ป˜ ํ…์ŠคํŠธ ์š”์†Œ๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค:

{"method":"detect_elements"}
{"result":{"detail":"13 elements","elements":[{"confidence":1,"h":9,"text":"Finder","w":32,"x":37,"y":6},{"confidence":1,"h":9,"text":"File","w":15,"x":84,"y":6},{"confidence":1,"h":9,"text":"Edit","w":19,"x":112,"y":6},{"confidence":1,"h":9,"text":"View","w":22,"x":143,"y":6},{"confidence":1,"h":11,"text":"Go","w":15,"x":179,"y":6},{"confidence":1,"h":9,"text":"Window","w":35,"x":207,"y":6},{"confidence":1,"h":11,"text":"Help","w":22,"x":255,"y":6},{"confidence":1,"h":11,"text":"8โ€ข","w":26,"x":1161,"y":6},{"confidence":1,"h":9,"text":"Fri Feb 20 22:19","w":80,"x":1189,"y":6},{"confidence":1,"h":9,"text":"Assets","w":32,"x":1202,"y":97},{"confidence":1,"h":9,"text":"Passwords.kdbx","w":74,"x":1181,"y":168},{"confidence":1,"h":93,"text":"PHANTOM","w":633,"x":322,"y":477},{"confidence":1,"h":32,"text":"YOUR SERVER, YOUR NETWORK, YOUR PRIVACY","w":629,"x":325,"y":568}],"scaledHeight":717,"scaledWidth":1280}}

๊ตฌ์„ฑ

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
configure{<params>}๋Ÿฐํƒ€์ž„์— ํƒ€์ด๋ฐ/๋””์Šคํ”Œ๋ ˆ์ด ๋งค๊ฐœ๋ณ€์ˆ˜ ์„ค์ •
configure{reset: true}๋ชจ๋“  ๋งค๊ฐœ๋ณ€์ˆ˜๋ฅผ ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ ์žฌ์„ค์ •
get_timingํ˜„์žฌ ํƒ€์ด๋ฐ + ๋””์Šคํ”Œ๋ ˆ์ด ๋งค๊ฐœ๋ณ€์ˆ˜ ๊ฐ€์ ธ์˜ค๊ธฐ

์ œ์–ด

๋™์ž‘๋งค๊ฐœ๋ณ€์ˆ˜์„ค๋ช…
waitms?๋Œ€๊ธฐ (๊ธฐ๋ณธ๊ฐ’ 500ms)
health์—ฐ๊ฒฐ ์ƒํƒœ + ๋””์Šคํ”Œ๋ ˆ์ด ์ •๋ณด
shutdown์ •์ƒ์ ์ธ ๋ฐ๋ชฌ ์ข…๋ฃŒ

์ธ์ฆ

์ง€์›๋˜๋Š” VNC ์ธ์ฆ ๋ฐฉ๋ฒ•:

  • VNC Auth โ€” ๋น„๋ฐ€๋ฒˆํ˜ธ ๊ธฐ๋ฐ˜ ์ฑŒ๋ฆฐ์ง€-์‘๋‹ต (DES)
  • ARD โ€” Apple Remote Desktop (Diffie-Hellman + AES-128-ECB)

macOS๋Š” ARD ์ธ์ฆ ์œ ํ˜• 30 ์ž๊ฒฉ ์ฆ๋ช… ์š”์ฒญ์„ ํ†ตํ•ด ์ž๋™ ๊ฐ์ง€๋ฉ๋‹ˆ๋‹ค. ๊ฐ์ง€๋˜๋ฉด Meta ํ‚ค๊ฐ€ Super๋กœ ๋‹ค์‹œ ๋งคํ•‘๋ฉ๋‹ˆ๋‹ค(Command ํ‚ค ํ˜ธํ™˜์„ฑ).


MCP Badge

[!NOTE] ๋ฒ ์–ด๋ฉ”ํƒˆ Mac์—์„œ ์‹คํ–‰ ์ค‘์ด์‹ ๊ฐ€์š”? VNC ๊ฐ•ํ™”, SSH ํ„ฐ๋„๋ง, ์„ธ์…˜ ์•ˆ์ •์„ฑ ํŒ์€ Mac M1 ์ค€๋น„ ์š”๋ น์„ ์ฐธ์กฐํ•˜์„ธ์š”.


"Claude"๋Š” Anthropic, PBC์˜ ์ƒํ‘œ์ž…๋‹ˆ๋‹ค. ์ด ํ”„๋กœ์ ํŠธ๋Š” Anthropic๊ณผ ์ œํœดํ•˜๊ฑฐ๋‚˜ ์Šน์ธ๋ฐ›์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.

Copyright (c) 2026 Riza Emre ARAS โ€” MIT License