@mulmobridge/xmpp
v1.0.1
Published
XMPP / Jabber bridge for MulmoBridge — connect any XMPP server (ejabberd, Prosody, etc.) to MulmoClaude
Downloads
478
Readme
@mulmobridge/xmpp
Experimental — please test and report issues.
XMPP / Jabber bridge for MulmoClaude. Connects to any XMPP server (ejabberd, Prosody, Tigase, dino-im.org, snikket.org, …) with a JID + password and bridges type="chat" message stanzas to MulmoClaude. Outbound TLS — no public URL needed.
Setup
1. Create a JID
Register the bot on any XMPP server. A few public servers that accept registrations:
- xmpp.jp (JP)
- jabber.de (DE)
- disroot.org (NL)
- yax.im (DE)
Or run your own Prosody / ejabberd.
2. Find the service URI
Most servers support both ports; pick one:
- Implicit TLS (direct TLS, recommended):
xmpps://<host>:5223 - STARTTLS:
xmpp://<host>:5222
If you don't know which your server supports, xmpps://<domain>:5223 is the common default.
3. Run the bridge
# Testing with mock server
npx @mulmobridge/mock-server &
[email protected] \
XMPP_PASSWORD=... \
XMPP_SERVICE=xmpps://example.com:5223 \
MULMOCLAUDE_AUTH_TOKEN=mock-test-token \
npx @mulmobridge/xmpp
# With real MulmoClaude
[email protected] \
XMPP_PASSWORD=... \
XMPP_SERVICE=xmpps://example.com:5223 \
npx @mulmobridge/xmppAdd the bot as a contact (or send an unsolicited message from an allowlisted JID) and start chatting.
Environment variables
| Variable | Required | Default | Description |
| ------------------------ | -------- | ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| XMPP_JID | yes | — | Full JID, e.g. [email protected] |
| XMPP_PASSWORD | yes | — | Account password |
| XMPP_SERVICE | yes | — | Connection URI, e.g. xmpps://example.com:5223 (implicit TLS) or xmpp://example.com:5222 (STARTTLS) |
| XMPP_ALLOWED_JIDS | no | (all) | CSV of bare JIDs allowed to converse, e.g. [email protected],[email protected]. Empty = everyone |
| XMPP_RESOURCE | no | mulmobridge | XMPP resource identifier (shows up alongside the JID in some clients) |
| XMPP_REPLY_MODE | no | bare | bare (default) sends replies to user@domain and lets the server route to whichever resource is active — works for multi-device users. full echoes back to the sender's full JID (user@domain/resource), useful when the server's roster/carbons config doesn't forward bare-addressed messages to every resource |
| MULMOCLAUDE_AUTH_TOKEN | no | auto | MulmoClaude bearer token override |
| MULMOCLAUDE_API_URL | no | http://localhost:3001 | MulmoClaude server URL |
Auth token persistence across server restarts
The MulmoClaude server regenerates a fresh bearer token on every startup and writes it to ~/mulmoclaude/.session-token. The bridge reads that file once at launch and keeps the token in memory — so if the server restarts while the bridge is running, the bridge keeps using the old token and every API call returns 401, silently.
Fix: set MULMOCLAUDE_AUTH_TOKEN to the same long random value on both the server and the bridge. The server uses it verbatim instead of regenerating, so the token survives restarts and the bridge stays authenticated.
# Server (one-time setup — same value across restarts)
MULMOCLAUDE_AUTH_TOKEN=long-random-string yarn dev
# Bridge (separate process / machine — same value)
MULMOCLAUDE_AUTH_TOKEN=long-random-string \
<bridge-specific-envs> \
npx <this-package>@latestRecommended: at least 32 characters of random data (the server logs a warning at startup for shorter values).
How it works
- The bridge connects to
XMPP_SERVICEand authenticates withXMPP_JID+XMPP_PASSWORDusing@xmpp/client. - On
onlineit broadcasts<presence/>so contacts see the bot as available, then listens forstanzaevents. - For each incoming
<message type="chat">(ortype="normal") with a<body>, the bridge strips the resource from the sender's JID, checks the allowlist, and forwards the plain text to MulmoClaude keyed by the sender's bare JID. - MulmoClaude's reply is sent back as another
<message type="chat">stanza, chunked at 10 000 chars. Theto=attribute is the sender's bare JID by default — seeXMPP_REPLY_MODEin the env table above for when to flip to full-JID.
Bare vs full JID reply
RFC 6121 requires servers to route bare-addressed chat messages to the most-active or all resources, which is normally what you want for a user jumping between phone and laptop. A handful of servers (or custom carbons configurations) deliver bare-addressed messages only to the primary resource, or silently drop them when no resource is "available". If replies reach the sender from one device but not another, set XMPP_REPLY_MODE=full so each reply goes straight back to the exact resource the message came from.
Troubleshooting
| Symptom | Cause | Fix |
| -------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------ |
| error: ECONNREFUSED | Wrong host/port or server not reachable | Verify the service URI; try the other port |
| error: authentication failed | Wrong password or JID domain mismatch | Double-check credentials; some servers require a specific SASL mechanism |
| Bridge sends nothing on receive | Stanza is not type="chat" (likely groupchat or headline) | Group-chat support is not implemented yet — send via a direct 1:1 chat |
| Contacts don't see bot as online | XMPP_ALLOWED_JIDS excluded your JID and <presence/> not broadcast to them | Ensure bot is added as a contact and approved |
Security notes
- Credentials travel to the XMPP server — always use
xmpps://(implicit TLS) orxmpp://+ STARTTLS-required on the server side. - Public servers may log message metadata. For sensitive agents, run your own Prosody / ejabberd.
- Without
XMPP_ALLOWED_JIDS, anyone who learns the bot's JID can converse with MulmoClaude. Setting an allowlist is strongly recommended. - Group-chat (MUC) support is intentionally deferred to v0.2 to avoid accidentally leaking MulmoClaude responses to a whole room; open an issue if you need it.
Ecosystem
Part of the @mulmobridge/* package family.
Shared libraries:
@mulmobridge/client— socket.io client library used by every bridge below@mulmobridge/protocol— wire types and constants@mulmobridge/chat-service— server-side relay + session store@mulmobridge/relay— Cloudflare Workers webhook proxy@mulmobridge/mock-server— mock server for local bridge development
Bridges (one npm package per platform):
@mulmobridge/bluesky— Bluesky DMs over atproto@mulmobridge/chatwork— Chatwork (Japanese business chat)@mulmobridge/cli— interactive terminal bridge@mulmobridge/discord— Discord bot via Gateway@mulmobridge/email— IMAP poll + SMTP reply, threading preserved@mulmobridge/google-chat— Google Chat via MulmoBridge relay@mulmobridge/irc— IRC (Libera, Freenode, custom)@mulmobridge/line— LINE Messaging API via MulmoBridge relay@mulmobridge/line-works— LINE Works (enterprise LINE)@mulmobridge/mastodon— Mastodon DMs + mentions@mulmobridge/matrix— Matrix / Element@mulmobridge/mattermost— Mattermost@mulmobridge/messenger— Facebook Messenger via MulmoBridge relay@mulmobridge/nostr— Nostr NIP-04 encrypted DMs@mulmobridge/rocketchat— Rocket.Chat@mulmobridge/signal— Signal via signal-cli-rest-api@mulmobridge/slack— Slack Socket Mode@mulmobridge/teams— Microsoft Teams via Bot Framework@mulmobridge/telegram— Telegram bot@mulmobridge/twilio-sms— SMS via Twilio Programmable Messaging@mulmobridge/viber— Viber Public Account bots@mulmobridge/webhook— generic HTTP webhook bridge@mulmobridge/whatsapp— WhatsApp Cloud API via MulmoBridge relay@mulmobridge/xmpp— XMPP / Jabber ← this package@mulmobridge/zulip— Zulip
Related projects
Published from the MulmoClaude monorepo by Receptron.
- MulmoClaude — an open-source AI assistant platform that runs on your own computer. Claude Code as the engine, a personal wiki for long-term memory, schema-driven collections for your data, and chat that summons the right GUI (markdown, charts, forms, spreadsheets, wikis) for each task.
- MulmoTerminal — a terminal-first cockpit for running many AI coding agents in parallel. One roster showing every session's summary and PR status, tmux-backed session persistence, git-worktree isolation, one-click PRs, and mobile push with remote reply.
- MulmoTerminal manual — setup, workflows, feature reference, configuration, mobile notifications, and alternative / local model providers. Available in English and Japanese.
