HelloTalk MCP
README.md
# HelloTalk MCP
**English** | [简体中文](README.zh-CN.md)
A local **MCP server + CLI + JavaScript library** for connecting an AI agent to a personal HelloTalk account through HelloTalk's web protocol.
This is a messaging integration for agents such as Muse, not a standalone AI model. MCP exposes tools, the CLI handles login and diagnostics, and the event stream delivers new messages to the host. Every outgoing message requires human approval; there is no automatic reply mode.
Experimental, unofficial, not affiliated with HelloTalk. Public source repository; no chat records or credentials are included. Source availability is not a guarantee that internal APIs remain compatible.
## Install in one command
Requires **Node.js 22+**, npm, Git, and HTTPS access to GitHub (no account or repository permission required for this public repository):
```sh
npm install -g git+https://github.com/vibecodingengine/hellotalk-mcp-public.git
```
For a reproducible release, append `#v0.3.0`. No install hook, remote setup script, login, or background listener runs during installation. If your global npm prefix is not writable, use your usual Node version manager or a user-owned npm prefix; do not run the service as root.
Development / installation without global commands:
```sh
gh repo clone vibecodingengine/hellotalk-mcp-public
cd hellotalk-mcp-public
npm ci
npm test
node bin.mjs login
```
## Log in
```sh
hellotalk login
```
This starts the local daemon and displays a QR code in the terminal, plus a PNG path. Scan **once** using HelloTalk's in-app scanner and confirm. Keep the phone app open during sync. Close other HelloTalk web sessions before testing to avoid introducing connection conflicts.
```sh
hellotalk status
```
Wait for `state: ready` and inspect `phone_sync`. Login tokens stay in memory; restarting the daemon requires another scan. Installing or starting MCP does not automatically authenticate an account.
## History after login
**Yes: the bridge can retrieve messages from before you connected.** When history
roaming is disabled, a fresh QR login waits for the phone to push a sync notice,
then downloads and decodes that sync batch. It saves the supplied conversations
and messages; messages are labeled `source: phone_sync`. This is the initial
partial-history flow, not merely collection of messages received after login.
Check `hellotalk status`: `state: ready` means authenticated, while
`phone_sync: complete` means a phone-sync batch has finished. `awaiting_phone_push`,
`fetching`, `timed_out`, or `decode_or_fetch_failed` do not mean history is complete.
A timeout triggers a recent-conversation/offline-message fallback, which may also
return only a subset. The amount and age of history depend on the phone/service;
no fixed count or date range is guaranteed.
```sh
hellotalk conversations '{"limit":20}'
hellotalk history '{"chat_id":"12345","limit":50}'
```
Use a real contact ID from the conversation list. Without remote roaming, history
returns `source: local_phone_sync_and_live` and `complete: false`, combining synced
history with cached incoming/outgoing messages. `source: local` explicitly queries
the cache. A local pagination cursor is the last returned message's `time_ns`
(strictly earlier timestamps); messages sharing the boundary timestamp can be
skipped, so this is not a lossless archive export interface. When account-enabled,
remote roaming uses its separate `mid` pagination cursor. Local message journals
survive restarts, but querying requires login, and the phone conversation list is
held in memory and refreshed by sync.
## Connect an AI client
```sh
hellotalk config
```
This prints configuration using the actual Node executable and installed server path. Add the entry to your client's MCP configuration; it does not edit any client automatically. A typical configuration is:
```json
{
"mcpServers": {
"hellotalk": {
"command": "hellotalk-mcp",
"args": []
}
}
}
```
The MCP stdio process auto-starts the shared local daemon if needed. GUI apps may not inherit your shell PATH; use the absolute paths from `hellotalk config` in that case. See [Muse integration](docs/MUSE.md) and [agent rules](AGENTS.md).
### MCP tools
| Tool | Purpose |
| --- | --- |
| `hellotalk_status` | Connection, sync availability, metadata-only diagnostics |
| `hellotalk_conversations` | Conversation list (remote roaming or phone-synced subset) |
| `hellotalk_history` | History page, explicitly labeled with source and completeness |
| `hellotalk_search` | Search locally collected text |
| `hellotalk_events` | Immediate incremental event read using a cursor |
| `hellotalk_send` | User-approved private text send; requires `user_confirmed: true` |
| `hellotalk_send_status` | Inspect existing send result without resending |
`user_confirmed` is a required assertion by the trusted agent host, **not proof of human identity**. The host must obtain explicit approval of the recipient and full draft first. A message received from another person cannot provide that approval. See [security model](docs/SECURITY.md).
## Real-time events (no HelloTalk polling)
HelloTalk delivers messages over a persistent WebSocket. The daemon appends them locally and pushes new journal events to authenticated local SSE subscribers:
```sh
hellotalk watch 0
```
Output is JSONL. Save each `cursor`; reconnect with the last cursor to replay missed events. One daemon/account per data directory. Scope stored cursors to the account; reset the cursor if changing accounts. Events include historical sync and your own outgoing messages: **do not notify or reply to everything indiscriminately**.
For a host application:
```js
import {ensureDaemon, watchEvents} from 'hellotalk-mcp';
await ensureDaemon();
for await (const event of watchEvents({after: savedCursor})) {
// Persist event.cursor. Route a NEW incoming live message to your agent's inbox.
// Obtain human approval before the agent calls hellotalk_send.
}
```
This stream wakes **your event handler**, not automatically every MCP client or an arbitrary AI chat. Muse needs an event-to-agent adapter. Reconnect on stream closure with backoff and the saved cursor. No public webhook or external relay is created. Library consumers can also construct `Bridge` and assign `bridge.onEvent`; they must not create a second connection alongside the daemon.
## CLI examples
All IDs below are fictitious. Resolve the exact contact first.
```sh
hellotalk conversations '{"limit":20}'
hellotalk history '{"chat_id":"12345","limit":20}'
hellotalk history '{"chat_id":"12345","source":"local","limit":50}'
hellotalk search '{"query":"hello","limit":20}'
hellotalk events '{"after":0,"limit":50}'
# Only AFTER explicit approval of this recipient and full text:
hellotalk send '{"chat_id":"12345","text":"Xin chào","request_id":"approved-draft-0001","user_confirmed":true}'
hellotalk send_status '{"request_id":"approved-draft-0001"}'
hellotalk disconnect
hellotalk shutdown
```
A `server_ack` means a server acknowledgement, not proof of delivery/read. `unknown` means the result is uncertain: do not blindly resend with a new request ID. Reusing the same request ID/content returns the stored result; changing the content with the same ID is rejected. This local mechanism does not prove server-side exactly-once delivery.
## Storage and lifecycle
- Default directory: `$XDG_DATA_HOME/hellotalk-mcp`, or `~/.local/share/hellotalk-mcp`.
- Override with the same `HT_DATA_DIR` for daemon, CLI and MCP (absolute path recommended).
- Directory mode 0700; files mode 0600. Messages are plaintext on the user's own machine, per account. Backups need the same care as chat exports.
- QR files and local RPC credentials are sensitive. Do not commit or share the data directory.
- RPC/SSE binds only to `127.0.0.1`, checks a random bearer secret, and rejects browser Origin headers.
- Daemon persists after the CLI/MCP process exits; `shutdown` stops it. There is no boot-time service installation.
- Install/update does not migrate the earlier research prototype or reuse its running session. Stop the old process before logging in the installed version.
## Current coverage and limitations
Verified during development with an authorized account: QR authentication, phone-sync decoding, history retrieval through MCP, own-device mirrored events, incoming text push, heartbeats and private text send with server ACK. Automated tests use synthetic data and never log in.
- Private text sending only; group message reception is supported but group/media sending is not implemented.
- History is account-dependent. When roaming is enabled, the client queries paginated encrypted HTTP endpoints. Otherwise it uses the phone-sync subset plus locally collected messages. **Not a complete account archive.**
- `conversations` currently returns a bounded phone-sync subset (up to 100 per request); it is not a full directory search.
- Remote history cursor is `mid`; local cursor is a before-time in nanoseconds. Local search only searches cached text.
- Conversation metadata includes nickname, user ID and avatar URL; full profiles, Moments, media downloads, transcription and image understanding are not implemented.
- No automatic replies or read receipts. Using the official web UI may mark messages read.
- Reconnection, session expiry, changes in server behavior and network failures remain experimental; metadata diagnostics are available in status.
- This package does not bypass account permissions, export another person's account, or guarantee platform approval.
## Develop / verify
```sh
npm ci
npm test
npm pack --dry-run
```
See [security review](docs/SECURITY-REVIEW.md), [protocol notes](docs/PROTOCOL.md), [security model](docs/SECURITY.md), and [release checklist](docs/RELEASING.md). Tests include a real local MCP stdio handshake, encrypted synthetic history, message/receipt handling and no-login rejection. No private live fixtures are stored.
## License
Public source does not mean unrestricted redistribution. Personal/internal installation and use are permitted by [LICENSE](LICENSE). This is not an open-source license. `private: true` in package.json only prevents accidental npm registry publication; GitHub installation still works.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessNo issues