zulip
zulipmcp
Führe KI-Agenten in Zulip als @erwähnbare Bots aus – oder binde sie in einen beliebigen MCP-Client ein. Funktioniert auch als Python-Bibliothek.
Schnellstart
Installiere das Paket:
uv add zulipmcp --git https://github.com/windborne/zulipmcp.gitFüge eine
.zuliprc-Datei mit deinen Zulip-Bot-Anmeldedaten zum Stammverzeichnis deines Projekts hinzu. Siehe Einen Bot oder eine Integration hinzufügen für Anweisungen zur Erstellung eines Bots. Der Bot-Typ muss „generic“ sein.Füge den MCP-Server zu deiner
.mcp.jsonhinzu:{ "mcpServers": { "zulip": { "command": "uv", "args": ["run", "python", "-m", "zulipmcp.mcp"] } } }Starte deinen MCP-Client neu. Die Zulip-Tools sollten nun verfügbar sein.
Anforderungen
Python >=3.10, verwaltet mit uv
Eine
.zuliprc-Datei für die Zulip-API-Authentifizierung (siehe Schnellstart)
Einstiegspunkte
Einstiegspunkt | Beschreibung |
| MCP-Server für Claude Code / MCP-Clients |
| MCP-Server über SSE (für Remote-/Web-Clients) |
| Listener: überwacht @Erwähnungen, startet Claude Code-Sitzungen |
Verwendung als Bibliothek
zulipmcp kann auch direkt als Python-Bibliothek importiert werden:
import zulipmcp
# Fetch and format recent messages
messages = zulipmcp.get_messages(hours_back=24, channels=["engineering"])
print(zulipmcp.format_messages(messages))
# Send a message
zulipmcp.send_message("engineering", "general", "Hello from Python!")
# Configure MCP hooks before starting the server
zulipmcp.configure(
message_prefix=lambda: "[bot] ",
on_session_end=lambda session: print(f"Session ended in #{session.stream}"),
)Listener
Das optionale Modul zulipmcp.listener überwacht Zulip auf @Erwähnungen und startet eine Headless-Claude-Code-Sitzung pro (Stream, Thema). Es ist das Bindeglied zwischen Zulip-Ereignissen und Claude Code – der MCP-Server kümmert sich um alle Zulip-Tools, der Listener verwaltet lediglich den Lebenszyklus.
# Minimal -- uses ./.zuliprc, ./.mcp.json (if present), and the bundled default prompt
uv run python -m zulipmcp.listener
# Full -- override MCP config and system prompt
uv run python -m zulipmcp.listener \
--mcp-config .mcp.json \
--system-prompt agent.md \
--log-dir ./logs
# Pass flags through to Claude Code (everything after --)
uv run python -m zulipmcp.listener -- --strict-mcp-config --model opusFlags:
Flag | Standard | Beschreibung |
|
| Pfad zur |
|
| Pfad zur |
|
| Datei für den angehängten System-Prompt (Standardpfad wird relativ zu |
|
| Arbeitsverzeichnis für gestartete Sitzungen |
|
| Name oder Pfad der Claude CLI-Binärdatei |
|
| Verzeichnis für Sitzungsprotokolldateien |
| (keine) | Alles nach |
Jede Sitzung erhält automatisch TRIGGER_MESSAGE_ID und SESSION_USER_EMAIL, sodass set_context() an der @Erwähnung verankert wird und Hooks den Anfragenden identifizieren können.
Der Listener ist bewusst minimal gehalten (~230 Zeilen). Er verzichtet auf Nebenläufigkeitsbegrenzungen, Arbeitsbereichsisolierung, Watchdogs für veraltete Sitzungen und Dashboards – füge diese hinzu, wenn du sie benötigst.
Wichtige Designdetails
Auf Nachrichten warten
Das listen-Tool verwendet die Echtzeit-Ereignis-API von Zulip (Long-Polling) anstelle von wiederholten GET /messages-Aufrufen. Beim Start holt es alle Nachrichten seit der last_seen_message_id nach, abonniert bei Bedarf den Stream für den Bot, registriert eine eingeschränkte Ereigniswarteschlange für den Stream/das Thema und führt dann Long-Polling über GET /events durch. Der Server blockiert, bis eine Nachricht eintrifft oder ca. 90 Sekunden vergangen sind (Heartbeat), was dies ca. 30-mal effizienter macht als ein Polling alle 2 Sekunden. Wenn die Warteschlange abläuft (BAD_EVENT_QUEUE_ID), erfolgt eine automatische Neuregistrierung. Die Warteschlange wird beim Beenden in einem finally-Block gelöscht.
Ein :robot_ear:-Emoji wird während des Wartens als visuelle Anzeige an die letzte Nachricht angehängt und entfernt, wenn das Warten aufhört. MCP-Keepalive-Pings werden nach jedem Long-Polling-Zyklus über ctx.info() gesendet.
Keine verpassten Nachrichten bei Antworten
Wenn reply aufgerufen wird, prüft es vor dem Senden auf neue Nachrichten. Falls jemand gepostet hat, während das LLM nachdachte, werden diese Nachrichten abgerufen und zusammen mit der Bestätigung „Nachricht gesendet“ zurückgegeben. Auf diese Weise sieht das LLM immer, was es verpasst hat, und kann entsprechend reagieren. Die last_seen_message_id wird auf den neuesten Stand gebracht – entweder die verpassten Nachrichten oder die gesendete Nachricht –, damit nichts verloren geht.
Beenden von Sitzungen
Benutzer können eine Bot-Sitzung beenden, indem sie mit einem konfigurierbaren Emoji (Standard: :stop_sign:) auf eine beliebige Bot-Nachricht reagieren. Die Prüfung auf Beendigung erfolgt sowohl während listen() (über Reaktionsereignisse) als auch vor reply() (über REST-API-Polling), was die Race Condition abdeckt, bei der ein Benutzer reagiert, während der Bot beschäftigt ist. Anpassbar mit configure(dismiss_emoji={"stop_sign", "wave"}).
Filterung der Bot-Sichtbarkeit
Themen, die /nobots oder /nb enthalten, sind für den Bot vollständig ausgeblendet. Nachrichten, die mit /nobots oder /nb beginnen, werden ebenfalls herausgefiltert. Dies ermöglicht es Menschen, private Unterhaltungen zu führen, die der Bot nicht sieht.
Umgebungsvariablen
Variable | Beschreibung |
| Absoluter Pfad zur |
| Nachrichten-ID, die die Sitzung ausgelöst hat (z. B. die @Erwähnung). Legt den Anker für das Warten fest, damit der Agent keine Nachrichten nach dem Auslöser verpasst. |
| E-Mail des Menschen, der die Sitzung ausgelöst hat. Wird für Hooks in |
| Stream-Name für die automatische Initialisierung einer Sitzung beim Serverstart (nur für direkte |
| Thema für die automatische Initialisierung. Erfordert |
| Zulassungsliste für das Lesen/Senden in privaten Streams. Nicht gesetzt = kein Zugriff auf private Streams. Akzeptiert |
| Zulassungsliste für das Senden in Streams. Nicht gesetzt = Schreiben überall erlaubt (abwärtskompatibel). Gleiche Formate wie oben. |
| Überschreibt das Festplatten-Cache-Verzeichnis (Standard ist das temporäre Systemverzeichnis). |
| Überschreibt das Protokollverzeichnis (Standard ist |
Lizenz
Latest Blog Posts
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/windborne/zulipmcp'
If you have feedback or need assistance with the MCP directory API, please join our Discord server