-
Notifications
You must be signed in to change notification settings - Fork 64
MCP Server
Connect Claude Code (or any MCP client) to your Zalo conversations. The MCP server exposes 4 tools that let AI agents read, reason about, and reply to Zalo messages in real-time.
Added in v1.2.0 · Requires Node.js 18+
You're working in the terminal and want Claude to check if anyone messaged you on Zalo — without switching apps.
# 1. Start MCP server (background process)
zalo-agent mcp start
# 2. Claude Code auto-discovers the tools and can call:
# zalo_get_messages → read buffered messages
# zalo_list_threads → see active conversationsConfig (add to .claude/settings.json):
{
"mcpServers": {
"zalo": {
"command": "zalo-agent",
"args": ["mcp", "start"]
}
}
}You're in a coding session and a colleague asks a quick question on Zalo. Tell Claude: "reply to that message with ..." and it calls zalo_send_message.
You: "Reply to thread X saying I'll check it after lunch"
Claude: [calls zalo_send_message with threadId, text, threadType]
→ Message sent ✓
Your server monitors Zalo 24/7. AI agents connect over HTTP instead of stdio.
zalo-agent mcp start --http 3847 --auth my-secret-tokenMCP clients connect via POST http://your-vps:3847/mcp with Authorization: Bearer my-secret-token.
When no AI agent is connected, forward message summaries to a Zalo group so you don't miss anything.
Edit ~/.zalo-agent-cli/mcp-config.json:
{
"notify": {
"enabled": true,
"thread": "GROUP_ID_HERE",
"on": ["dm"],
"cooldown": "5m"
}
}Filter noise — watch only DMs, or only specific groups:
{
"watchThreads": ["dm:*"],
"triggerKeywords": ["@bot", "urgent"]
}| Tool | Description | Key Params |
|---|---|---|
zalo_get_messages |
Get buffered messages (cursor-based polling) |
threadId?, since, limit
|
zalo_send_message |
Send text to a thread |
threadId, text, threadType (0=DM, 1=Group) |
zalo_list_threads |
List active threads with unread counts |
type (dm/group/all) |
zalo_mark_read |
Discard messages up to cursor | cursor |
1st call: zalo_get_messages() → { messages: [...], cursor: 5, hasMore: false }
2nd call: zalo_get_messages(since: 5) → only new messages after cursor 5
Cleanup: zalo_mark_read(cursor: 5) → discard old messages from buffer
Zalo Cloud ──WebSocket──→ zalo-agent mcp ──stdio/HTTP──→ Claude Code
│
┌─────────┼─────────┐
│ │ │
Ring Buffer Thread Notifier
(per-thread) Filter (Zalo group)
cursor-based glob batched alerts
auto-evict noise cooldown window
Ring Buffer: Stores messages per thread. Auto-evicts by age (default 2h) and size (default 500). Cursor-based reads for incremental polling.
Thread Filter: Glob patterns (dm:*, group:support_123) control which threads are watched. Noise filter drops stickers, system messages, and short emoji-only messages.
Notifier: When no agent is connected, batches unread DM notifications and sends a summary to a configured Zalo group.
Config file: ~/.zalo-agent-cli/mcp-config.json
| Field | Default | Description |
|---|---|---|
watchThreads |
["dm:*", "group:*"] |
Glob patterns for threads to monitor |
mode |
"manual" |
Polling mode |
triggerKeywords |
["@bot"] |
Keywords that trigger attention |
notify.enabled |
false |
Enable group notifications |
notify.thread |
null |
Group ID to send notifications to |
notify.on |
["dm"] |
Event types to notify on |
notify.cooldown |
"5m" |
Batch window before sending |
limits.maxMessagesPerPoll |
20 |
Max messages per get_messages call |
limits.bufferMaxAge |
"2h" |
Auto-evict messages older than this |
limits.bufferMaxSize |
500 |
Max messages per thread |
# Local (stdio — for Claude Code)
zalo-agent mcp start
# HTTP (for VPS / remote agents)
zalo-agent mcp start --http 3847
# HTTP with auth
zalo-agent mcp start --http 3847 --auth your-secret-token
# Custom config
zalo-agent mcp start --config /path/to/mcp-config.jsoncurl http://localhost:3847/health
# → {"status":"ok","uptime":123,"threads":5}- stdio: No auth needed (local process, same user)
-
HTTP: Bearer token auth on all endpoints except
/health - Reconnect: Auto re-login on WebSocket close (except duplicate session = fatal)
-
Credentials: Reuses existing
zalo-agentsession (no extra login)