Skip to content

MCP Server (VN)

ardennguyen edited this page Jun 30, 2026 · 3 revisions

MCP Server (Tích hợp AI Agent)

Kết nối Claude Code (hoặc bất kỳ MCP client nào) với hội thoại Zalo. MCP server cung cấp 7 tools cho AI agent đọc, phân tích, và trả lời tin nhắn Zalo theo thời gian thực.

Từ v1.0.0 · Local cache từ v1.1.0 · Yêu cầu Node.js 20+


User Stories

🤖 "Tôi muốn Claude Code đọc tin nhắn Zalo"

Bạn đang code trong terminal và muốn Claude kiểm tra xem có ai nhắn Zalo không — không cần chuyển app.

# 1. Khởi động MCP server
zalo-agent mcp start

# 2. Claude Code tự phát hiện tools và gọi:
#    zalo_get_messages → đọc tin nhắn trong buffer
#    zalo_list_threads → xem các hội thoại đang hoạt động
#    zalo_get_history  → đọc lịch sử từ cache (offline, instant)

Cấu hình (thêm vào .claude/settings.json):

{
  "mcpServers": {
    "zalo": {
      "command": "zalo-agent",
      "args": ["mcp", "start"]
    }
  }
}

💬 "Tôi muốn Claude trả lời tin nhắn giúp"

Bạn đang code, đồng nghiệp hỏi nhanh trên Zalo. Bảo Claude: "trả lời thread đó là tí nữa check" và nó gọi zalo_send_message.

Bạn: "Trả lời thread X nói là tí nữa mình check"
Claude: [gọi zalo_send_message với threadId, text, threadType]
→ Đã gửi ✓

📡 "Tôi muốn chạy MCP trên VPS"

Server chạy 24/7, AI agent kết nối qua HTTP thay vì stdio.

zalo-agent mcp start --http 3847 --auth my-secret-token

MCP client kết nối: POST http://your-vps:3847/mcp với Authorization: Bearer my-secret-token.

🔔 "Tôi muốn nhận thông báo khi agent offline"

Khi không có AI agent nào kết nối, gửi tóm tắt tin nhắn mới vào nhóm Zalo để không bỏ lỡ.

Sửa ~/.zalo-agent-cli/mcp-config.json:

{
  "notify": {
    "enabled": true,
    "thread": "GROUP_ID_CỦA_BẠN",
    "on": ["dm"],
    "cooldown": "5m"
  }
}

🧹 "Tôi chỉ quan tâm một số hội thoại"

Lọc nhiễu — chỉ theo dõi DM, hoặc chỉ nhóm cụ thể:

{
  "watchThreads": ["dm:*"],
  "triggerKeywords": ["@bot", "gấp"]
}

Danh sách Tools (7 tools)

Tool Mô tả Tham số chính
zalo_get_messages Lấy tin nhắn từ buffer (polling theo cursor) threadId?, since, limit
zalo_send_message Gửi tin nhắn text đến thread threadId, text, threadType (0=DM, 1=Nhóm)
zalo_list_threads Liệt kê threads đang hoạt động + số tin chưa đọc type (dm/group/all)
zalo_search_threads Tìm kiếm thread theo tên (fuzzy, accent-insensitive) query, type, limit
zalo_mark_read Xóa tin nhắn cũ đến cursor cursor
zalo_get_history Lịch sử tin nhắn — cache-first (v1.1.0) threadId, limit, threadType, no_cache
zalo_view_media Mở file media bằng viewer hệ thống messageId, threadId?, open?

Cơ chế Cursor

Lần 1:  zalo_get_messages()           → { messages: [...], cursor: 5, hasMore: false }
Lần 2:  zalo_get_messages(since: 5)   → chỉ tin nhắn mới sau cursor 5
Dọn:    zalo_mark_read(cursor: 5)     → xóa tin nhắn cũ khỏi buffer

zalo_get_history — Cache-First (v1.1.0)

Mặc định, zalo_get_history đọc từ local cache (không cần mạng).

// Cache-first (mặc định) — đọc từ zalo.db, trả về source: "cache"
{ "threadId": "uid123", "limit": 50 }

// Bắt buộc fetch live từ Zalo + backfill cache — trả về source: "live"
{ "threadId": "uid123", "limit": 50, "no_cache": true }

Ghi chú về tên tham số: MCP tool dùng JSON key (no_cache với gạch dưới). Lệnh CLI dùng POSIX flag (--no-cache với gạch ngang kép). Cả hai đều là cú pháp đúng chuẩn.


Local Cache (v1.1.0)

mcp start ghi tất cả tin nhắn nhận được vào zalo.db — ngoài in-memory buffer.

zalo-agent mcp start
  → [mcp] Local cache active — events will be persisted to zalo.db

Cache path: ~/.zalo-agent-cli/accounts/<ownId>/zalo.db

Điều này có nghĩa là:

  • zalo_get_history đọc từ cache ngay lập tức (không gọi Zalo API)
  • msg search trên CLI tìm được cả tin nhắn nhận qua MCP
  • msg history trên CLI đọc từ cache thay vì gọi Zalo API

Kiến trúc

Zalo Cloud ──WebSocket──→ zalo-agent mcp start
                               │
                   ┌───────────┼──────────────┐
                   │           │              │
             SQLite zalo.db  Thread       Notifier
             (TẤT CẢ tin)   Filter      (nhóm Zalo)
             ghi thụ động   glob        gộp thông báo
              v1.1.0         lọc nhiễu   cooldown
                   │           │
                Ring Buffer (chỉ tin khớp filter)
                cursor-based, tự dọn dẹp
                   │
              MCP Server (stdio hoặc HTTP)
                   │
             Claude Code / MCP Client

SQLite (v1.1.0): Mọi tin nhắn được ghi vào zalo.db theo tài khoản để tìm kiếm offline và đọc cache-first.

Ring Buffer: Lưu tin nhắn đã lọc theo từng thread. Tự xóa theo thời gian (mặc định 2h) và kích thước (mặc định 500).

Thread Filter: Dùng glob pattern (dm:*, group:support_123) để chọn thread theo dõi. Bộ lọc nhiễu tự bỏ sticker, tin nhắn hệ thống, và emoji ngắn.

Notifier: Khi không có agent kết nối, gộp tin nhắn DM chưa đọc và gửi tóm tắt vào nhóm Zalo đã cấu hình.


Cấu hình

File: ~/.zalo-agent-cli/mcp-config.json

Trường Mặc định Mô tả
watchThreads ["dm:*", "group:*"] Glob pattern cho threads cần theo dõi
mode "manual" Chế độ polling
triggerKeywords ["@bot"] Từ khóa kích hoạt chú ý
notify.enabled false Bật thông báo nhóm
notify.thread null ID nhóm nhận thông báo
notify.on ["dm"] Loại sự kiện cần thông báo
notify.cooldown "5m" Thời gian gộp trước khi gửi
limits.maxMessagesPerPoll 20 Tối đa tin nhắn mỗi lần gọi
limits.bufferMaxAge "2h" Tự xóa tin nhắn cũ hơn
limits.bufferMaxSize 500 Tối đa tin nhắn mỗi thread

Lệnh

# Local (stdio — cho Claude Code)
zalo-agent mcp start

# HTTP (cho VPS / remote agent)
zalo-agent mcp start --http 3847

# HTTP với xác thực
zalo-agent mcp start --http 3847 --auth your-secret-token

# Config riêng
zalo-agent mcp start --config /path/to/mcp-config.json

Health Check (chế độ HTTP)

curl http://localhost:3847/health
# → {"status":"ok","uptime":123,"threads":5}

Bảo mật

  • stdio: Không cần auth (process local, cùng user)
  • HTTP: Bearer token cho tất cả endpoint trừ /health
  • Reconnect: Tự đăng nhập lại khi WebSocket đóng (trừ duplicate session = thoát)
  • Credentials: Dùng lại session zalo-agent đã có (không cần đăng nhập thêm)

Clone this wiki locally