Local-first MCP server for your own LINE and Telegram chats. Data stays on your machine.
Copy the AI prompt to install this server into Claude Code, Cursor, or another agent β or use 1-click editor setup below.
π‘ Paste the JSON block into your client's configuration file under mcpServers, then restart the application.
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.
chatmux is the core. Platforms plug in below it, consumers sit above it, and both sides of that boundary live in their own repos:
| Repo | Role |
|---|---|
| chatmux (this one) | Core daemon: storage, safety rail, MCP server, LINE adapter |
| chatmux-adapter-telegram | Second platform adapter (Telegram, MTProto user session) |
| chat.nvim | Reference consumer: read and reply to chats inside Neovim |
Adapters speak the adapter protocol; consumers speak MCP. Either side can be replaced without touching the other.
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.
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.
| Tool | Description |
|---|---|
list_chats | List chats with last message preview, search, pagination |
read_messages | Read messages from a chat, paginated by timestamp |
read_events | Tail the event log from an opaque cursor β resumable, survives backfill reordering, and re-delivers a message when it is edited or retracted |
search_messages | Full-text search (CJK supported via FTS5 trigram + LIKE fallback) |
send_message | Send message through SafetyRail (rate-limited, error-tracked) |
get_media | Local file path for a message's image or sticker; downloads and caches on first call |
probe_latest | Diagnostic, read-only: ask the adapter for a chat's newest N messages without landing them |
get_status | System status: adapter connection + storage stats |
| URI | Description |
|---|---|
chat://chats | All chat list |
chat://chats/{id}/messages | Recent messages for a chat |
chat://chats/{id}/info | Chat details with members |
chat://status | System status |
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.
Edit WorkingDirectory to point at your clone before copying it.
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.
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.
See docs/ for detailed architecture and protocol documentation.
Known and accepted, with what would make each worth revisiting.
No reviews yet β be the first to share how this listing worked for you.
Showcase your server listing on GitHub or your project documentation. Embed this dynamic SVG badge to highlight official listing status and live engagement.
[](https://allmcps.com/mcp/chatmux)<a href="https://allmcps.com/mcp/chatmux"><img src="https://allmcps.com/api/badge/chatmux?style=directory" alt="Chatmux on AllMCPs" /></a>