AI代理平台

Peacock是一个基于Python的模型上下文协议(MCP)服务器,为兼容MCP的AI代理提供文件系统操作、浏览器自动化、虚拟机控制和任务调度等41种工具。

  • by richknowles
  • Python
  • 本地部署
  • 更新于
在 GitHub 查看 richknowles/peacock

使用说明

🦚 Peacock MCP Server

The AI agent platform that makes Playwright look slow.


Chapter 1 — What Peacock Is

Overview

Peacock is a Model Context Protocol (MCP) server written in pure Python. It gives any MCP-compatible AI agent — Claude Desktop, custom agents, LLM pipelines — a complete toolkit for operating a real computer:

  • Filesystem — read, write, search, execute commands
  • Browser automation — Chrome (via CDP), Firefox, Safari, Edge across macOS, Linux, and Windows
  • VM control — Proxmox VE: start/stop VMs, run commands inside guests, take VNC screenshots, open browsers in guest OS
  • Remote browser — control Chrome on a Mac or Windows VM from a headless LXC over SSH
  • Scheduling — native cron (Linux/macOS) and Windows Task Scheduler

41 MCP tools. Zero Node.js. No bundled browsers. No Playwright.


Security Hardening

For admins and security teams: Peacock was subjected to a full pre-release vulnerability audit. Every finding was remediated before v1.1.0 shipped. The table below is the complete record.

# Finding Severity Remediation
1 Path traversal via startswith() string comparison HIGH Replaced with Path.relative_to() — raises ValueError on any escape attempt
2 Symlink escape via unresolved BASE_DIR HIGH BASE_DIR resolved with .resolve() at startup, eliminating symlink chains
3 Command injection via shell=True CRITICAL Switched to shlex.split() + shell=False; shell metacharacters never interpreted
4 TOCTOU race in write_file mkdir MEDIUM Path re-verified with _safe_path() after mkdir to catch symlink swaps
5 Unbounded glob patterns (DoS vector) MEDIUM Allowlist regex on pattern characters; ** depth capped at 2
6 No rate limiting MEDIUM Token bucket: 30 calls / 10 s per tool, enforced server-side
7 Unvalidated mode parameter in write_file LOW–MED Strict allowlist — only "w" or "a" accepted
8 Error messages leak home path LOW All exception strings scrubbed; home path replaced with ~ before returning

Baseline security posture (always enforced):

  • All filesystem operations restricted to the user's home directory via _safe_path()
  • BASE_DIR is configurable — set it to a dedicated sandbox directory for tighter containment
  • Command execution timeout: 30 seconds maximum
  • Server runs as the invoking user — never root, never elevated

Tool Reference (41 tools)

Filesystem

Tool Description
read_file(path) Read a file; returns content with byte count
write_file(path, content, mode) Write (w) or append (a) to a file; creates parent dirs
list_directory(path, show_hidden) List directory contents with sizes
execute_command(command, cwd) Run a shell command; 30 s timeout, no shell injection
search_files(pattern, directory, max_results) Recursive glob search with pattern allowlist
get_file_info(path) Size, permissions, mtime, extension

Browser — Chrome (CDP)

Chrome attaches to a running instance via the Chrome DevTools Protocol — zero launch latency, access to your real cookies, extensions, and saved passwords. No WebDriver, no browser download.

Tool Description
browser_open(url, browser, cdp_host, cdp_port) Open/attach browser; cdp_host accepts a remote IP for cross-machine control
browser_navigate(url) Navigate current tab
browser_new_tab(url) Open new tab
browser_close_tab() Close current tab
browser_click(selector) Click element by CSS selector
browser_type(selector, text) Clear and type into an input
browser_get_content() Page title, URL, HTML preview
browser_get_text(selector) Visible text of page or element
browser_scroll(direction, pixels) Scroll up / down / left / right
browser_screenshot(save_path) PNG screenshot
browser_execute_js(script) Execute JavaScript, return result
browser_wait_for(selector, timeout) Poll until element appears
browser_list_tabs() All open tabs with title + URL
browser_list_sessions() All active Peacock browser sessions
browser_close() Close session, free resources

Browser — Bookmarks & Tab Groups

Tool Description
browser_bookmark_add(url, title, folder, browser) Add one bookmark; writes Chrome JSON directly, triggers Safari Reading List, opens Firefox dialog
browser_bookmark_group(urls_and_titles, folder, browser) Bookmark a JSON list of {url, title} objects in one call
browser_open_tab_group(urls_and_titles, group_name, cdp_host) Open all URLs as tabs, attempt Chrome 102+ tab group, bookmark as folder

Browser — Remote & SSH

Tool Description
browser_setup_ssh_tunnel(remote_host, remote_user, cdp_port, ssh_key) SSH tunnel from this machine to a remote Chrome CDP port; enables cross-machine control
browser_close_ssh_tunnel() Close the active SSH tunnel

Mac-Specific (SSH + AppleScript)

Control Safari or Chrome on a Mac from any remote machine — including a headless LXC.

Tool Description
mac_safari_open_and_bookmark(urls_and_titles, folder, mac_host, mac_user) Open Safari tabs, create bookmark folder, attempt Tab Group (Safari 15+)
mac_chrome_open_and_bookmark(urls_and_titles, folder, mac_host, mac_user) Open Chrome tabs and write bookmarks via remote python3

VM / Proxmox

Tool Description
vm_connect(host, username, password) Connect to Proxmox VE REST API
vm_list() All VMs across all nodes with status
vm_status(vm_id) CPU%, RAM, uptime for one VM
vm_start(vm_id) Start a VM
vm_stop(vm_id, force) Graceful shutdown or force-stop
vm_screenshot(vm_id, save_path) VNC screenshot via vncdotool
vm_execute(vm_id, command) Run command in guest via QEMU Guest Agent
vm_browser_open(vm_id, url, browser) Launch browser in guest OS
vm_list_connections() Active Proxmox connections
vm_disconnect() Close Proxmox connection

Scheduling

Tool Description
schedule_task(name, cron_expr, command) Add/update a named cron job (Linux/macOS) or Windows Task Scheduler entry
list_scheduled_tasks() All Peacock-managed scheduled tasks
remove_scheduled_task(name) Remove by name

Chapter 2 — Human Installation & Operation

Prerequisites

Platform Requirement
macOS Python 3.10+, Claude Desktop
Linux Python 3.10+, python3-venv, Claude Desktop
Windows Python 3.10+ (from python.org, "Add to PATH" checked), Claude Desktop

Install

macOS

git clone https://github.com/richknowles/peacock
cd peacock
./install_mac.sh

Linux

git clone https://github.com/richknowles/peacock
cd peacock
./install.sh

Windows — open PowerShell as Administrator:

git clone https://github.com/richknowles/peacock
cd peacock
.\install_windows.ps1

The installer creates a .venv, installs all dependencies, and prints the exact JSON block to paste into your Claude Desktop config.


Configure Claude Desktop

Paste the output from the installer into your Claude Desktop config file and restart.

Platform Config file location
macOS ~/Library/Application Support/Claude/claude_desktop_config.json
Linux ~/.config/Claude/claude_desktop_config.json
Windows %APPDATA%\Claude\claude_desktop_config.json

It looks like this (paths filled in by the installer):

{
  "mcpServers": {
    "peacock": {
      "command": "/path/to/peacock/.venv/bin/python3",
      "args": ["/path/to/peacock/peacock_server.py"]
    }
  }
}

Verify the Install

.venv/bin/python3 peacock_server.py

Expected output:

🦚 PEACOCK MCP SERVER — v1.1.2 🦚
Built by Rich Knowles
🖥️  Platform: Darwin
📁 Base directory: /Users/yourname
🌐 Browser tools: ✅ ready
🖥️  VM tools:      ✅ ready
🚀 Starting server...

Browser Setup (Human)

Chrome — no setup needed

Peacock attaches to Chrome you already have open. Nothing to install or configure.

Firefox

.venv/bin/pip install webdriver-manager   # downloads GeckoDriver automatically on first use

Safari (macOS only — one-time)

sudo safaridriver --enable

Edge

Built into Windows. No setup needed.

Proxmox VM Control (optional)

.venv/bin/pip install proxmoxer
.venv/bin/pip install vncdotool   # only needed for vm_screenshot

Inside each guest VM, install and start qemu-guest-agent for vm_execute to work.


Troubleshooting

ModuleNotFoundError: No module named 'mcp' — Re-run the installer. The .venv may not have been activated.

Permission denied on the server script — chmod +x peacock_server.py

Claude Desktop doesn't see Peacock — Check the JSON syntax is valid, restart Claude Desktop fully, and check logs at ~/.config/Claude/logs/ (Linux) or ~/Library/Logs/Claude/ (macOS).

Browser tools unavailable — Run .venv/bin/pip install selenium webdriver-manager websocket-client requests inside the Peacock directory.

browser_bookmark_add for Chrome — bookmarks don't appear — Chrome must be restarted to pick up direct file changes to the Bookmarks JSON.


Chapter 3 — Agent Installation & Operation

What Agents Can Do

Any MCP-compatible AI agent can load Peacock and gain all 41 tools immediately. This includes agents running on:

  • Claude Desktop (local)
  • Headless LXC containers (Ubuntu 22.04 recommended)
  • Remote servers and VMs
  • Any platform with Python 3.10+ and an MCP client

Agent Install (Headless Linux / LXC)

sudo apt update && sudo apt install -y python3 python3-pip python3-venv openssh-client git
git clone https://github.com/richknowles/peacock
cd peacock
./install.sh

Configure the agent's MCP client to point to:

command: /path/to/peacock/.venv/bin/python3
args:    [/path/to/peacock/peacock_server.py]

Controlling a Remote Browser from a Headless Agent

Path A — Mac Chrome via SSH tunnel (recommended)

On the Mac (one-time):

# Enable Remote Login
# System Settings → General → Sharing → Remote Login → ON

# Authorize the agent's SSH key
ssh-copy-id agent_user@agent_host   # run from Mac, pointing at the LXC

# Start Chrome with remote debugging
open -a "Google Chrome" --args --remote-debugging-port=9222

Agent calls:

browser_setup_ssh_tunnel("192.168.1.x", "rich", cdp_port=9222)
browser_open_tab_group('[{"url":"...","title":"..."}]', group_name="Watch List")

Path B — Mac Safari / Chrome via AppleScript (no CDP needed)

On the Mac (one-time):

# Enable Remote Login (same as above)
ssh-copy-id agent_user@agent_host

Agent calls:

mac_safari_open_and_bookmark(
  '[{"url":"https://example.com","title":"Item"}]',
  folder="Product Watch",
  mac_host="192.168.1.x",
  mac_user="rich"
)

Safari tabs open on the Mac, a bookmark folder is created, and a Tab Group is attempted (Safari 15+ / macOS Monterey+). No CDP, no display, no extensions.

Path C — Windows VM via Proxmox Guest Agent

vm_connect("proxmox-host", "root@pam", "password")
vm_execute(101, 'cmd /c start chrome --remote-debugging-port=9222 --remote-debugging-host=0.0.0.0')
browser_open_tab_group('[{"url":"...","title":"..."}]', cdp_host="windows-vm-ip")

Agent Workflow: Product Watch Cron Job

A complete example — Hermes-Agent on an LXC sets up a recurring product watch that opens tabs on the user's Mac:

1. mac_safari_open_and_bookmark(
     '[{"url":"https://amazon.com/dp/X","title":"Widget"},
       {"url":"https://ebay.com/itm/123","title":"Widget (eBay)"}]',
     folder="Widget Watch",
     mac_host="192.168.1.50",
     mac_user="rich"
   )

2. schedule_task(
     name="widget-watch",
     cron_expr="0 8 * * *",
     command="python3 /home/hermes/check_widget_price.py"
   )

Result: every morning at 08:00 the price check script runs; any time the user wants to browse manually, the tabs and bookmarks are ready in Safari.


Remote Browser Capability Matrix

Scenario Tool Requires
Agent on LXC → Mac Chrome (fast, full control) browser_setup_ssh_tunnel + browser_open Remote Login on Mac, SSH key
Agent on LXC → Mac Safari (tabs + bookmarks) mac_safari_open_and_bookmark Remote Login on Mac, SSH key
Agent on LXC → Mac Chrome (tabs + bookmarks, no CDP) mac_chrome_open_and_bookmark Remote Login on Mac, SSH key
Agent on LXC → Windows VM browser vm_execute + browser_open(cdp_host=...) Proxmox Guest Agent in VM
Agent on LXC → Windows VM browser (simple) vm_browser_open Proxmox Guest Agent in VM

Chapter 4 — Human Tips & Tricks

Change the security boundary. BASE_DIR in peacock_server.py defaults to your home directory. Point it at a dedicated workspace folder to tighten the sandbox, or expand it to / only if you fully understand the implications.

Keep Chrome open for instant response. Peacock attaches to a running Chrome tab in milliseconds. If Chrome is closed, it launches a fresh profile — which is slower and doesn't have your cookies. Leave Chrome open.

Regenerate the animated logo.

.venv/bin/pip install Pillow numpy
.venv/bin/python3 make_logo_anim.py

Run a quick sanity check before connecting Claude Desktop.

.venv/bin/python3 -c "import peacock_browser, peacock_vm; print('All modules OK')"

Tab groups aren't appearing after browser_open_tab_group. Chrome's tab group API (chrome.tabGroups) is an extension-only API. Peacock tries the CDP method (Chrome 102+) but it's experimental. The tabs are still open — select them all, right-click, and choose Add tabs to new group in 2 seconds.

Bookmark changes don't appear in Chrome. Chrome reads the Bookmarks file at startup. Close and reopen Chrome after browser_bookmark_add or browser_bookmark_group to see new entries.

Use execute_command for anything not covered by a dedicated tool. It runs any shell command. On macOS you can call osascript, open, say, or any CLI tool. On Linux, curl, jq, ffmpeg — whatever is installed.


Chapter 5 — Agent Tips & Tricks

Always check browser_list_sessions() before opening a new browser. Reusing an existing session is instant. Opening a new one takes 1–3 s for Selenium, ~100 ms for CDP.

Use cdp_host for cross-machine control without a tunnel. If the Chrome machine is on a trusted private network and firewall rules allow port 9222, pass cdp_host="192.168.1.x" directly to browser_open. No SSH tunnel required.

Chain vm_execute + browser_open for Windows VM browsing.

vm_execute(101, 'cmd /c start chrome --remote-debugging-port=9222 --remote-debugging-host=0.0.0.0')
# wait ~3s for Chrome to start
browser_open("https://example.com", cdp_host="192.168.1.101", cdp_port=9222)

After that, all 15+ browser control tools work against the Windows VM's Chrome.

Use browser_execute_js to extract structured data.

browser_execute_js("Array.from(document.querySelectorAll('.price')).map(e => e.innerText)")

Returns a JSON array. Faster and more reliable than scraping HTML.

browser_wait_for before browser_click. Always wait for the target element to exist before clicking. Pages with dynamic content will silently fail otherwise.

Prefer browser_get_text over browser_get_content for data extraction. get_content returns the full HTML source (can be large). get_text returns only visible text, which is smaller and easier to parse.

SSH key path matters on LXC. When calling mac_safari_open_and_bookmark or browser_setup_ssh_tunnel, pass ssh_key="/home/hermes/.ssh/id_ed25519" explicitly if the agent's home directory is non-standard.

schedule_task creates idempotent entries. Calling schedule_task with the same name replaces the existing entry rather than adding a duplicate. Safe to call repeatedly.

Check VM status before vm_execute. Always call vm_status(vm_id) first. If the VM is stopped, vm_execute will silently fail because the QEMU Guest Agent isn't running.

Screenshot → read the result path → open it. browser_screenshot saves to ~/peacock_screenshot_<timestamp>.png by default. Pass a specific save_path if you need a predictable location for follow-up read_file calls.


About

Built by: Rich Knowles

Why "Peacock"? Because the AI wants to show off. 🦚

License: MIT