About three.ws Herald
Herald is an MCP server that lets an agent announce finished or stalled tasks through a 3D companion that speaks in the user's open browser tab. It targets users who need timely alerts rather than log entries, and it keeps interruptions rare through importance thresholds and delivery rules.
Key features
- 013D companion speaks announcements in the browser tab
- 02announce tool sets importance, tone and optional link
- 03announce_result picks urgency from the task outcome
- 04check_rail verifies the key and channel without interrupting
- 05Delivery limited to the key owner's own live sessions
Use cases
- 01Alerting a user when a long task finishes
- 02Raising urgent notices when a job fails or a service breaks
- 03Asking the user for a decision that needs their attention
MCP support
Herald runs as an MCP server and exposes the announce, announce_result and check_rail tools to MCP clients.
Configuration
Local server config is the same for every client. Copy it into your client’s MCP config file.
npx -y @three-ws/herald-mcpTHREE_WS_API_KEYSecretA three.ws API key (sk_live_… / sk_test_…) with the herald:announce scope, or an OAuth access token for the same account, carried as Authorization: Bearer. Required: an announcement is always delivered to the key owner's own sessions. Aliases: THREE_WS_TOKEN, THREE_WS_BEARER. Treat like a password.THREE_WS_BASEBase URL of the three.ws API. Override only when self-hosting or targeting a preview deployment.THREE_WS_TIMEOUT_MSPer-request timeout in milliseconds for the announce call.Local servers need a runtime on your machine (e.g. Node.js 18+). Config file locations differ by client; see your client’s docs.
Tools
3Saved tool list · updated 2w ago
| Parameter | Type | Required | Description |
|---|---|---|---|
| key | string | No | Dedupe key. Two announcements sharing a key are said once, so a retrying job can call this every attempt without repeating itself. |
| url | string | No | Where clicking through goes: an absolute https URL or a three.ws path. |
| from | string | No | Who it is from, spoken as attribution ("your build", "Stripe", the agent's name). |
| text | string | Yes | The line to say out loud. One sentence. Write it as speech, not as a log line. |
| tone | enum | No | Colours the bubble and picks a default gesture. Default alert.neutral | alert | celebrate | error |
| emote | enum | No | Gesture the avatar arrives with. Rigs without it fall back to a wave.wave | dance | punch | backflip |
| importance | integer | No | 0-100, default 70. The client drops anything under its floor (50 by default) and only lets 90+ through quiet hours. Use 90+ for something broken or blocking, 60-80 for a finished task, under 50 for something that can wait for the inbox. |
Details
From the project README@three-ws/herald-mcp
Let your agent tell you something in person.
An MCP server with one idea behind it: when an agent finishes something that mattered, or gets stuck, it should not add a line to a log you will never scroll back to. It should walk up to you and say so.
Wire this in, and it does. Your own 3D companion appears in the corner of whatever browser tab you have open, gestures, and says the line out loud, with a link to click through.
you: run the migration, then the backfill, and tell me when it's done
agent: [runs for 22 minutes]
[calls announce_result: task "the backfill", outcome succeeded, 1320s]
your browser: your avatar walks on: "the backfill finished in 22m"
Tools
| Tool | What it does |
|---|---|
announce | Say one line, with importance (0-100), tone, a gesture, and an optional link. |
announce_result | Report a finished task. The urgency is chosen from the outcome, so a failure cuts through quiet hours and a success does not. |
check_rail | Prove the key and the rail work, without interrupting anybody (queues at importance 0, which every client drops). |
Install
npx -y @three-ws/herald-mcp
Claude Code:
claude mcp add herald -e THREE_WS_API_KEY=sk_live_... -- npx -y @three-ws/herald-mcp
Claude Desktop / Cursor (mcp.json):
{
"mcpServers": {
"herald": {
"command": "npx",
"args": ["-y", "@three-ws/herald-mcp"],
"env": { "THREE_WS_API_KEY": "sk_live_..." }
}
}
}
The key
Create one at three.ws/dashboard/developers
with the herald:announce scope, and put it in THREE_WS_API_KEY.
An announcement is always delivered to the key owner's own live sessions. There is no recipient parameter: this server cannot be pointed at anybody else, so the worst a leaked key can do is annoy the person who leaked it. Revoke it in the same place.
| Variable | Required | Default | Notes |
|---|---|---|---|
THREE_WS_API_KEY | yes | API key with herald:announce, or an OAuth access token. Aliases: THREE_WS_TOKEN, THREE_WS_BEARER. | |
THREE_WS_BASE | no | https://three.ws | Override for self-hosting or a preview deployment. |
THREE_WS_TIMEOUT_MS | no | 20000 | Per-request timeout. |
When to use it (and when not to)
Announcements are scarce on purpose. The receiving client applies an importance floor, a rate limit, dedupe, quiet hours, and a freshness window, so anything that does not clear the bar is dropped rather than queued. That is the feature: an interruption only works while it is rare.
Good: a long job finished, a job failed, a decision is needed, something broke, money moved.
Bad: progress updates, "starting step 3 of 7", anything the person can read later. Those belong in the notification inbox (@three-ws/notifications-mcp).
If nothing is open to hear it, the line expires in about five minutes. The rail is a live channel, not an archive.
Example calls
// something broke, and it should wake somebody up
{ "name": "announce", "arguments": {
"text": "The payments worker has been failing for 10 minutes",
"from": "watchdog", "importance": 95, "tone": "error",
"url": "https://three.ws/dashboard", "key": "payments-worker-down" } }
// a long task finished, and it should not
{ "name": "announce_result", "arguments": {
"task": "the nightly backfill", "outcome": "succeeded", "seconds": 1320 } }
// wiring check
{ "name": "check_rail", "arguments": { "note": "claude-code" } }
How it reaches a browser
POST /api/herald/announce queues the line on the account's rail; the page
listens over SSE and hands it to @three-ws/herald,
which decides whether it clears the person's own rules and then delivers it
through the 3D companion (or an accessible card when there is no GPU).
Try the whole loop, including the rules engine, at three.ws/herald.
License
Apache-2.0.
Comments
New to MCP?
From what the protocol is to installing your first server, these answers cover most first questions.
An open protocol that defines how AI applications connect to external tools and data in a uniform way. Clients talk to the model; MCP servers provide tools, resources and prompt templates. They exchange standard messages, so one server can be reused by many clients.