EchoHoard
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@EchoHoardwhat was the URL I copied an hour ago?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Echo's Hoard
Everything you copy, kept on your own PC, searchable, with the things you copy often pinned. The app watches your clipboard in the background; an assistant reaches the same history through MCP, so it can answer "what was that URL I copied an hour ago", paste back the last thing you copied, or put new text on your clipboard for you.
Everything stays on the machine: SQLite for the clip history, PNG files for images, no accounts, no network.
Part of the Hoard family (see faustus-plugin.json).
What it does
Clips = whatever you copy: text, or an image stored as a PNG. With optional local OCR, image text becomes searchable and available to Faustus as clearly marked derived text; without OCR, the clip keeps a placeholder like "[imagen 1254×1254]". Each clip tracks kind, a one-line preview, the source app/window when known, first/last seen, how many times the same content was copied, pinned, label, tags.
Dedupe: copying the same content again bumps
last_seen_at/timeson the existing clip instead of creating a new one.Kind detection: url, email, path, code, number, image, or plain text — from the content alone (see
echo/detect.py).Sensitive content (privacy first): a clip that looks like a password, an API key/token, a credit card number (Luhn-checked) or an IBAN is flagged
sensitiveand its real content is replaced by a placeholder like[oculto: contraseña]before it ever reaches the database — not hidden in the UI, never stored. The assistant never receives it, not even partially. A per-app exclusion list (ECHO_EXCLUDE_APPS, defaultKeePass,1Password,Bitwarden,keepassxc) skips capture entirely for password managers. A pause switch stops capture (UI + tool).Retention: everything is kept for
ECHO_RETENTION_DAYS(default 30) unless pinned; capped atECHO_MAX_CLIPS(default 5000), oldest unpinned dropped first; images capped atECHO_MAX_IMAGE_MB(default 200) total. A soft delete keeps a 24h undo window before the janitor purges it for good. Housekeeping runs at startup and every 10 minutes.Search: FTS5 over text/label/tags/source window title, diacritics-insensitive, prefix match, filterable by kind/pinned/time/app.
Capture backend (
echo/backends/): a small interface (read(),write(),foreground()) with three implementations — Windows (ctypesagainst user32/kernel32, no pywin32, pollsGetClipboardSequenceNumbercheaply and only reads on change; retries a locked clipboard a few times, then skips that change rather than crashing), generic/cross-platform (pyperclip, polling text by comparing sha256; no images, no source app), and a fake backend used by tests. Selected byECHO_BACKEND(auto/windows/generic/fake).
Related MCP server: mcp-clipboardify
Requirements
Windows 10/11 (also runs on Linux/macOS with the generic backend, without images or source-app detection), Python 3.11+ (3.13 fine), Node 22 only to build the client.
Python's
sqlite3must have FTS5 (the official Windows builds do). The app fails loudly at startup otherwise.
Install and run (Windows)
git clone <this repo> echo-hoard
cd echo-hoard
python -m venv venv
venv\Scripts\pip install -r requirements.txt
npm install
npm run build
venv\Scripts\python -m echoOpen http://127.0.0.1:5188, go to Historial to see and search what you've copied, Fijados for your pinned clips, and Estado to pause/resume watching and purge old clips.
python scripts/launch.pystarts the app on a free port and opens the browser.python scripts/dev.pyruns uvicorn--reload+ the Vite dev server (proxying/api).
Configuration (environment)
Variable | Default | Meaning |
|
| Preferred port; |
|
| Database ( |
|
|
|
|
|
|
|
| Unpinned clips older than this are purged; |
|
| Cap on unpinned clips; oldest dropped first. |
|
| Cap on total image storage; oldest images dropped first. |
|
| Set to |
|
| Language(s) as Tesseract spells them, for example |
|
| Comma-separated process names never captured. |
| Extra host names accepted behind a tunnel (see below). |
Access from your phone (behind a tunnel)
The server binds 127.0.0.1 and only answers requests whose Host is localhost, 127.0.0.1 or [::1]. To reach it from your phone through a tunnel that fronts the app, list the extra host names in ECHO_ALLOWED_HOSTS, comma-separated, exact names or *.suffix: ECHO_ALLOWED_HOSTS=my-pc.example,*.ts.net. Port and letter case are ignored, and the Origin of API calls must resolve to one of those hosts too (any scheme or port). Cross-site fetches are still refused; opening the app from another page (a link, a bookmarklet, the share sheet) is a normal navigation and works.
Once opened through the tunnel, the browser offers to install it (PWA).
API
All JSON; errors are { "error": "..." } (plus a machine-readable code, and issues for bad input). Agent-tool answers are capped at about 20 KB (truncated says what was cut). The request guard, the error envelope, the PWA files, the single-page-app server (index.html is never cached), the MCP bridge, the agent routes, the database class and the search-query builder are the shared Hoard Link commons (echo/hoard_link/), not code of this app. A second python -m echo reports the running instance and exits without touching the token or the database; the token in data/mcp-token is created once and stays.
GET /api/health→{ service: "echo-hoard", version, dataDirConfigured, hoard_link }(the sharedhoard_link.service.health_router);GET /api/statusPOST /api/pause,POST /api/resumeGET /api/clips?kind&pinned&since&until&app&limit&offset,POST /api/clips{text}(sets the clipboard AND stores it),GET/PATCH/DELETE /api/clips/{id},POST /api/clips/{id}/restore,POST /api/clips/{id}/copy(put it back on the clipboard),GET /api/clips/{id}/imageDELETE /api/clips?before=<iso>(bulk purge, irreversible; UI confirms)GET /api/search?q&kind&pinned&since&until&app&limitGET /api/agent/tools(catalog + instructions),POST /api/agent/call(Bearer token fromdata/mcp-token)
Faustus assistant
Once the shared Hoard Link launcher is installed, the app shows the family's Faustus panel (a floating button). The conversation, the model and the tools live in Faustus; this app only tells the panel what is open.
Context per view. The view reports the page (
history,pinned,status), the active filters (kind, search text) and the ids of the clips on screen (up to 20). A clip whose label is being edited is sent as kindclipwith its real id, clip kind, source app, last seen, times, pinned, label, tags, size and a preview of at most 200 characters. The full clip text is never sent, and sensitive or deleted clips are left out entirely, also from the visible ids. Nothing is sent as an object where no clip is being edited.Unsaved fields. The panel asks for them with the
echo:context-requestwindow event. The open label editor (clip-label) answers with the label typed so far and adirtyflag.Refresh. When the assistant finishes a turn the open view reloads in place (
hoard:copilot-turn-end/window.hoardCopilot.onTurnEnd, merged into one reload). A label you are typing keeps your text; an untouched one follows the new value.Saving. The label editor sends only the changed field in
PATCH /api/clips/{id}, which merges just the fields it carries (nulland unknown fields are ignored, an empty label clears it).Tests.
node --test client/copilot-context.test.mjsandvenv\Scripts\python -m pytest -q tests/test_api.py.
MCP tools
mcp_server.py is a stdio bridge: it fetches the tool list from the running app and proxies every call to POST /api/agent/call with the token from <DATA_DIR>/mcp-token. It never opens the database. Env: ECHO_URL, ECHO_TOKEN_FILE (or ECHO_TOKEN).
Tool | What it does |
| The most recently copied clips. Sensitive ones come back as |
| Full-text search over the clipboard history. |
| The full text of one clip (paginated); refuses sensitive clips outright. |
| Read up to 20 selected clips together, in order, with source and date for a comparison or summary in Faustus. |
| Put text on the clipboard and store it as a clip (write, idempotent by content). |
| Put an existing clip back on the clipboard (write; refuses sensitive unless |
| Pin/unpin and set label/tags (write). |
| Soft-delete a clip (write, destructive; 24h undo window). |
| Whether Echo is watching, counts, retention config. |
| Pause/resume watching (write). |
The shipped instructions tell the assistant: this is the user's own data, quote it only when asked; a sensitive clip is never returned, not even partially, and never ask the user to unhide one; clip_set changes what the user will paste next, so say what was put there; prefer clip_search with a time window over listing everything; never read the data folder or database directly.
Tests
venv\Scripts\python -m pytest -qCovers kind detection (URL/email/path/code/number/text table), sensitive detection (passwords by window title and by length, API key prefixes, JWT-like strings, Luhn-checked card numbers, IBAN checksum, and the negatives: a normal sentence, a plain 16-char word, a URL), dedupe bumping times, retention/cap/janitor with an injected clock, FTS with accents, pin/label/tags, soft delete + restore + purge, the fake backend driving the watcher end to end (push three contents, one a duplicate, → two clips, one with times: 2), pause/resume, the HTTP API, agent tools through /api/agent/call with the token (including the sensitive refusals), the request guard, the PWA endpoints, and a subprocess end-to-end test through the MCP stdio client. No test touches the real clipboard.
License
MIT — Luissalet.
This server cannot be deployed
Maintenance
Related MCP Connectors
Give Claude, Cursor, or another AI assistant direct access to your QuickSnip library.
Gives your AI assistant persistent memory and intelligence about your work patterns.
Encrypted long-term memory shared across your AI assistants (Claude, ChatGPT, Perplexity).
Cross-device AI memory with encrypted activity capture and context handoff between AI tools
Related MCP Servers
- AlicenseNot gradedqualityAmaintenanceGives AI assistants direct access to macOS clipboard - letting Claude copy generated code, text, or files straight to your clipboard for pasting anywhere on Mac.251MIT
- AlicenseNot gradedqualityDmaintenanceProvides clipboard access tools (get and set) for AI assistants via the Model Context Protocol, enabling seamless clipboard operations across platforms.1MIT
- AlicenseNot gradedqualityCmaintenanceEnables Claude to browse, search, and restore clipboard history with type classification, secret detection, and Touch ID-gated decryption.19MIT
- AlicenseNot gradedqualityAmaintenanceEnables AI agents to read and write the system clipboard in native app formats such as Slack, Mural, Figma, and Outlook without API keys. It decodes clipboard content into structured data and generates app-ready clipboard payloads.MIT