
chatmux
io.github.echoedinvoker由 GitHub 帳號 echoedinvoker 發布v0.1.0更新於 Oct 24, 2026
Local-first MCP server for your own LINE and Telegram chats. Data stays on your machine.
概覽
本地優先的常駐程式,把你自己的 LINE 與 Telegram 聊天記錄存在本機,並以 MCP 工具提供給 AI 用戶端,用來列出、讀取、搜尋和傳送訊息。
- 可以做什麼
- 列出聊天,含最後一則訊息預覽、搜尋與分頁
- 依時間戳分頁讀取聊天訊息,並進行全文搜尋(支援中日韓文字)
- 從可續傳的事件日誌讀取,訊息被編輯或收回時會重新投遞
- 透過具備限流的安全護欄傳送訊息
- 取得訊息中圖片或貼圖的本地檔案路徑,首次呼叫時下載並快取
- 查看轉接器連線與儲存狀態,並以 MCP 資源讀取聊天清單、訊息、聊天詳情和狀態
- 適用情境
- 適合希望助理在自己電腦上處理個人聊天記錄的人,例如摘要、搜尋或回覆對話,而不把聊天資料上傳給第三方。
- 執行需求
- 以 Bun 在本機啟動常駐程式(bun install、bun run start);LINE 轉接器以 Node 與 tsx 執行。需要 adapters.json 設定,LINE 需掃 QR 碼登入,Telegram 轉接器另有自己的憑證與登入流程。MCP 用戶端預設透過 127.0.0.1 的 7717 埠以 streamable HTTP 連線(可用 CHATMUX_MCP_PORT 或 mcp.port 調整),同機消費者也可用 unix socket。
安裝
在 SourceWeft 中
- 開啟 儀表板中的 chatmux,將其新增到工作區。
- 為需要使用其工具的對話啟用該服務。
Desktop only,透過 STDIO。 STDIO 服務會啟動本機處理程序,因此需要 SourceWeft 桌面主機。
其他 MCP 客戶端
參照 儲存庫 中的啟動說明。
README
chatmux
Local-first personal chat data layer daemon. Connects IM platforms (v0.1: LINE) via child-process adapters, stores messages to JSONL + SQLite/FTS5, exposes MCP tools for AI clients.
The three repos
chatmux is the core. Platforms plug in below it, consumers sit above it, and both sides of that boundary live in their own repos:
Adapters speak the adapter protocol; consumers speak MCP. Either side can be replaced without touching the other.
Quickstart
1. Install
2. Decide whether to connect an account yet
With no adapters.json, bun run start launches the LINE adapter, which means step 3 puts
your LINE account on the line — read Account Risk Warning before you
run it. If you would rather look around first, start with no adapter at all:
The daemon comes up with storage and the full MCP interface — you can initialize, list tools,
and read resources. There is simply no chat data behind them until an adapter is connected. Set
CHATMUX_DATA_DIR to keep this trial run out of your real data directory:
Each entry in adapters takes platform, a command string, and an args array
(plus optional cwd and env):
For Telegram, follow the setup in chatmux-adapter-telegram — it has its own credentials and login flow, and does not involve LINE.
3. First login (QR code)
4. Connect Claude Code
Register the daemon's MCP endpoint with Claude Code:
The daemon listens on two transports at once: a TCP port on 127.0.0.1 (default 7717) for
standard MCP clients like Claude Code, and a unix socket for same-host sidecar consumers like
chat.nvim. Use the TCP url for Claude Code — the MCP
spec only defines stdio and streamable HTTP transports, so no MCP client accepts a unix socket path.
Port is configurable via CHATMUX_MCP_PORT, or mcp.port in adapters.json; set it to 0 to
disable the TCP listener. See docs/mcp-interface.md.
Architecture
- Core daemon (Bun): central process managing storage, safety, and MCP server
- LINE adapter (Node+tsx): child process connecting to LINE via IOSIPAD slot
- Storage: JSONL append-only truth source + SQLite/FTS5 queryable view
- MCP server: Streamable HTTP over TCP (standard MCP clients; loopback by default, settable for containers) + unix socket (same-host sidecars), 8 tools + 4 resources
MCP Tools
MCP Resources
Writing a consumer
Core exposes primitives, not policy. Anything that decides what matters — which chats are worth surfacing, where a notification goes, when to stay quiet — belongs in a consumer, on the far side of the MCP boundary.
examples/notifier/ is a working reference: it tails the event
log with a persisted cursor and hands each message to a hook you fill in. Its
mcp-client.ts uses raw fetch rather than the TypeScript SDK, so it doubles as a
wire-protocol reference for consumers in any language.
systemd Service
Edit WorkingDirectory to point at your clone before copying it.
How it comes back
The unit ships Restart=always, not on-failure. A chat backend is supposed to be there
all day, and there are three ways it can stop being there — it crashes, something sends it
a signal, or it exits cleanly — of which on-failure only recovers from the first.
systemctl --user stop still stops it: a stop you asked for is not a failure, under either
setting.
⚠️ If you are on an older unit with
Restart=on-failure,kill -TERMwill not bring it back — and that is not a missing restart policy. systemd counts SIGTERM, SIGHUP, SIGINT and SIGPIPE as an intended stop, soon-failureleaves the service sitting ininactiveafter any of them. Onlykill -9(SIGKILL) counts as a failure there.With the
Restart=alwaysthis unit now ships, TERM comes back too — measured 2026-08-02:kill -TERM $MainPIDmovedNRestarts1 → 2 and produced a newMainPIDwithin the 10sRestartSec. That makes TERM the useful test:kill -9restarts under either setting, so it cannot tell you which one is in effect. If you want to confirmalwaysis live, send TERM and watchsystemctl --user show chatmux -p MainPID,NRestartschange.
StartLimitIntervalSec=300 / StartLimitBurst=5 cap a crash loop: five starts inside five
minutes and systemd stops trying, leaving the unit failed for you to look at rather than
restarting into the same wall forever. Clear it with systemctl --user reset-failed chatmux.
Containers
A systemd user service is the intended way to run chatmux. If you want it in a
container instead, deploy/container/ is a reference that builds
and answers — not an official image, and it runs zero adapters, because adapters
hold logged-in sessions and a container you rebuild is the wrong home for those.
The one thing you cannot skip is CHATMUX_MCP_HOST. The daemon binds 127.0.0.1 by
default, which inside a container is the container's own loopback — a published port
then maps to a socket nobody is listening on, and every connection is refused while the
logs look perfectly healthy. Read deploy/container/README.md before assuming your
port mapping is broken.
Development
See docs/ for detailed architecture and protocol documentation.
Limitations
Known and accepted, with what would make each worth revisiting.
- The chat list caps at 1000, silently.
chat://chatsis hard-coded to that limit. Consumers can detect an overflow by comparing thetotalfield against what arrived, so it will not bite you without saying so. Worth raising once a vault approaches ~500 chats, or the first time that completeness check fires. - The JSONL log holds duplicate history. Backfill re-ingested some messages many times over, leaving the event log several times larger than the messages in it. This has stopped: recent growth is almost entirely new distinct messages, and the worst-case duplicate count has been frozen across repeated measurements. It is not a correctness problem — ingestion is idempotent and the SQLite projection is unaffected — so the fix, if ever needed, is a one-off compaction rather than a code change. Worth doing if the log passes ~500 MB, if the duplicate count starts climbing again, or if cold start slows noticeably.
- Retractions in Telegram one-to-one chats are missed. Group retractions land; direct ones do not, because the adapter cannot recover the chat id for those events from its entity cache, and core will not match a message on id alone — that ambiguity is exactly what the storage key was widened to remove. So a message you retracted on your phone can stay visible here. Worth fixing once the adapter can resolve the chat id itself, or as soon as retraction accuracy matters to a consumer.
- Reactions are not stored at all. The platforms send them; no layer reads them. Nothing in core, the schema, or the MCP surface represents a reaction, so a consumer cannot show what a phone shows. Worth building when reactions carry meaning you would otherwise miss — it is new storage, not a display tweak.
read_receiptis declared but never emitted. The LINE adapter advertises the capability and core is ready to ingest it; nothing constructs the event. Whether read state should reach a UI at all is an open product question, not a pending bug — but the declaration is wrong today, so do not branch onsupported_eventsfor this one. Worth fixing as soon as any consumer does branch on it, or once that product question gets an answer.
⚠️ Account Risk Warning
This project uses @evex/linejs, an unofficial LINE client library. Using unofficial APIs may violate LINE's Terms of Service. Your LINE account may be restricted, suspended, or permanently banned. Use at your own risk.
The IOSIPAD device slot is used to avoid interfering with your phone's LINE app, but LINE may change their multi-device policy at any time.
⚠️ Legal Disclaimer
This software is provided "as is", without warranty of any kind. The author is not responsible for any consequences of using this software, including but not limited to account restrictions, data loss, or violations of third-party terms of service.
This is a personal tool for personal use. Do not use it for spam, harassment, unauthorized access to others' messages, or any illegal activity.
🔒 Privacy Disclosure
chatmux stores decrypted message content in plaintext on your local machine:
~/.local/share/chatmux/events.jsonl— all events (append-only)~/.local/share/chatmux/chatmux.db— SQLite database with messages, contacts, chats~/.local/share/chatmux/adapters/line/auth.json— LINE auth token~/.local/share/chatmux/adapters/line/storage.json— E2EE key storage
These files are protected by filesystem permissions (owner-only). Do not share these files. The auth token grants full access to your LINE account. The E2EE keys can decrypt your messages.
v0.1 does not encrypt the database. SQLCipher encryption is planned for v0.2.
License
MIT
來源:README.md,提交 7f8d5a5
工具
0版本歷史
1- v0.1.0最新Sep 16, 2026
評分
已滿足適用檢查項的 50%
該評分衡量此收錄條目的完整程度,依據註冊中心條目、端點與公開來源計算得出。它不是對伺服器本身的評價,也不表示伺服器安全或目前可用:可連通性是帶日期的檢查結果,評分也不包含安裝量或使用者評價。
- 近 30 天內可連通25 分
請保持端點能夠回應 MCP 握手;SourceWeft 每 30 天探測一次。
- 已宣告認證方式10 分
請在註冊中心條目中宣告憑證請求標頭,或保持端點能夠回應探測,以便判定其認證方式。
- 已列出工具15 分
請讓伺服器在無憑證時回應 tools/list,或發布可在沙箱中無憑證啟動的軟體包。
- 描述必需15 分
- 圖示10 分
- 文件15 分
- 授權條款10 分