English | Tiếng Việt
zalo-bot-mcp
Talk to your AI agent from a Zalo group.
An MCP channel server for the Zalo Bot API. Messages sent to your Zalo bot arrive in an MCP client session; the session replies through a tool call.
Early. The server runs and has been exercised against a real bot, but it is not on PyPI yet and the MCP channel it targets is an experimental Claude Code capability.
How it works
Zalo group ──mention──▶ getUpdates ──▶ gate ──▶ MCP session
│ │
(not allowed) reply tool
│ │
dropped ◀───────┘
sendMessage
The server polls Zalo with getUpdates, so it needs no public URL, no webhook endpoint,
and no tunnel. It runs on a laptop behind NAT.
Every inbound message passes the gate before anything else sees it. The gate is the only door.
Access control
Direct messages follow one of three policies:
| Policy | Unknown sender gets |
|---|---|
pairing |
A short-lived code you approve out of band |
allowlist |
Nothing. The message is dropped silently |
disabled |
Nothing. All DMs are dropped |
Groups must be configured by ID. Adding the bot to a group does not enable it. You can also restrict which members are allowed to trigger it.
Two rules the code enforces:
- No Zalo message can change the access config. A message asking to be added to the allowlist is exactly what an injection attack looks like, so approvals happen outside the channel.
- The server refuses to start if the allowlist contains a wildcard. It is easy to widen an allowlist during testing and forget to narrow it again.
Being on the allowlist means you can talk to the bot. It does not grant authority to act on anything.
Zalo platform constraints
These come from the Zalo Bot API itself, and they shape what any Zalo bot can do. Zalo owns these rules and changes them without notice, so treat https://bot.zapps.me/ as the source of truth and this section as a summary that may be out of date:
- Groups are mention-gated. A bot receives a group message only when it is mentioned or when someone replies to one of its messages. It cannot watch a conversation passively.
- Messages cap at 2000 characters. Longer replies get split across several messages.
- No offset cursor.
getUpdatestakes onlytimeout, so deduplication happens bymessage_idrather than by advancing a cursor. - No message editing. Replies cannot be updated in place, so progress on a long task arrives as new messages.
- No reactions. The API has no reaction endpoint, so a bot cannot acknowledge a message
with an emoji. It can send a typing indicator (
sendChatAction) and stickers. - Free-plan quotas. Zalo's Basic (free) plan allows 3 bots per account, 50 users per bot, 3 group chats (marked beta), and 3,000 outbound messages per month. A paid Pro plan exists. Current plans and quotas: https://bot.zapps.me/.
Install
Two ways in, both need uv: as a Claude Code
plugin (/plugin marketplace add trongnguyenbinh/zalo-bot-mcp, then
/plugin install zalo@zalo-bot-mcp), or as a Python package registered in
your .mcp.json. Either way, Claude Code must then be started with the
channel flag or messages never reach the session.
The full walkthrough, from creating the bot on Zalo to the first replied
message, plus all /zalo:* skills and the zalo-bot-mcp-admin CLI, lives in
docs/getting-started.md
(bản tiếng Việt: docs/getting-started.vi.md).
Development
git clone https://github.com/trongnguyenbinh/zalo-bot-mcp.git
cd zalo-bot-mcp
python3 -m venv .venv && source .venv/bin/activate
pip install -e ".[dev]"
pytest
Runtime dependencies are httpx and mcp. Nothing else. The Zalo endpoints are called
directly, so the whole API surface stays readable in one file.
Not affiliated with Zalo
This is a personal, unofficial project. It is not built, endorsed, reviewed, or supported by Zalo, VNG Corporation, or any of their affiliates. "Zalo" is their trademark, used here only to say which service this talks to.
It calls the public Zalo Bot API the same way any third-party bot does. Your bot, your token, your account, your responsibility: read Zalo's own terms before pointing this at anything that matters, and expect the API to change without warning.
It is published under the MIT license, which means it comes with no warranty and no liability. If something breaks in your setup, you own the breakage.
License
MIT
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file zalo_bot_mcp-0.1.0.tar.gz.
File metadata
- Download URL: zalo_bot_mcp-0.1.0.tar.gz
- Upload date:
- Size: 108.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0e312decc9bca56308956cf10bf711dce13481810c613572aded38959c994adc
|
|
| MD5 |
c4713fbe01ac803e0291dfaa7c5755fd
|
|
| BLAKE2b-256 |
6e6f9e28a7d3418e68000be8ff36c9bee13ce3fd07842c842042bdf5ef2d1fba
|
Provenance
The following attestation bundles were made for zalo_bot_mcp-0.1.0.tar.gz:
Publisher:
release.yml on trongnguyenbinh/zalo-bot-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zalo_bot_mcp-0.1.0.tar.gz -
Subject digest:
0e312decc9bca56308956cf10bf711dce13481810c613572aded38959c994adc - Sigstore transparency entry: 2385208861
- Sigstore integration time:
-
Permalink:
trongnguyenbinh/zalo-bot-mcp@7d07271b460e3bd5f7f0b0d76ac5ea90cb8673cd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/trongnguyenbinh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d07271b460e3bd5f7f0b0d76ac5ea90cb8673cd -
Trigger Event:
push
-
Statement type:
File details
Details for the file zalo_bot_mcp-0.1.0-py3-none-any.whl.
File metadata
- Download URL: zalo_bot_mcp-0.1.0-py3-none-any.whl
- Upload date:
- Size: 27.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
3b2b3f4b60da9839114a21e03565d8b4060fee8d237f2cf1069bd880be22a5a9
|
|
| MD5 |
739ce52edd7ce5145200fcc1989ea196
|
|
| BLAKE2b-256 |
f29e0672991c5702e8b45dd55caf70276fb9ca4393b03767f9ca7cbcd0f123fd
|
Provenance
The following attestation bundles were made for zalo_bot_mcp-0.1.0-py3-none-any.whl:
Publisher:
release.yml on trongnguyenbinh/zalo-bot-mcp
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
zalo_bot_mcp-0.1.0-py3-none-any.whl -
Subject digest:
3b2b3f4b60da9839114a21e03565d8b4060fee8d237f2cf1069bd880be22a5a9 - Sigstore transparency entry: 2385208869
- Sigstore integration time:
-
Permalink:
trongnguyenbinh/zalo-bot-mcp@7d07271b460e3bd5f7f0b0d76ac5ea90cb8673cd -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/trongnguyenbinh
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@7d07271b460e3bd5f7f0b0d76ac5ea90cb8673cd -
Trigger Event:
push
-
Statement type: