zulip
zulipmcp
Запускайте ИИ-агентов в Zulip в качестве ботов, которым можно писать через @mention, или подключайте их к любому MCP клиенту. Также работает как библиотека Python.
Быстрый старт
Установите пакет:
uv add zulipmcp --git https://github.com/windborne/zulipmcp.gitДобавьте файл
.zuliprcв корневую директорию вашего проекта с учетными данными вашего бота Zulip. Инструкции по созданию бота см. в разделе Add a bot or integration. Тип бота должен быть "generic".Добавьте MCP-сервер в ваш
.mcp.json:{ "mcpServers": { "zulip": { "command": "uv", "args": ["run", "python", "-m", "zulipmcp.mcp"] } } }Перезапустите ваш MCP-клиент. Инструменты Zulip должны стать доступны.
Требования
Python >=3.10, управляется с помощью uv
Файл
.zuliprcдля аутентификации в API Zulip (см. Быстрый старт)
Точки входа
Точка входа | Описание |
| MCP-сервер для Claude Code / MCP-клиентов |
| MCP-сервер через SSE (для удаленных/веб-клиентов) |
| Прослушиватель: отслеживает @mentions, запускает сессии Claude Code |
Использование библиотеки
zulipmcp также можно импортировать напрямую как библиотеку Python:
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)
Опциональный модуль zulipmcp.listener отслеживает @mentions в Zulip и запускает по одной headless-сессии Claude Code на каждую пару (поток, тема). Это связующее звено между событиями Zulip и Claude Code — MCP-сервер обрабатывает все инструменты Zulip, а прослушиватель управляет только жизненным циклом.
# 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 opusФлаги:
Флаг | По умолчанию | Описание |
|
| Путь к |
|
| Путь к |
|
| Файл системного промпта (путь по умолчанию разрешается относительно |
|
| Рабочая директория для запущенных сессий |
|
| Имя или путь к бинарному файлу Claude CLI |
|
| Директория для файлов логов сессий |
| (нет) | Все, что идет после |
Для каждой сессии автоматически устанавливаются TRIGGER_MESSAGE_ID и SESSION_USER_EMAIL, чтобы set_context() привязывался к @mention, а хуки могли идентифицировать запрашивающего.
Прослушиватель намеренно сделан минималистичным (~230 строк). В нем отсутствуют ограничения параллелизма, изоляция рабочих пространств, сторожевые таймеры для зависших процессов и дашборды — добавьте их, когда они вам понадобятся.
Ключевые детали проектирования
Прослушивание сообщений
Инструмент listen использует API событий в реальном времени Zulip (long-polling) вместо повторяющихся вызовов GET /messages. При запуске он догоняет все сообщения, появившиеся после last_seen_message_id, при необходимости подписывает бота на поток, регистрирует суженную очередь событий для потока/темы, а затем выполняет long-polling через GET /events. Сервер блокируется до тех пор, пока не придет сообщение или не истечет ~90 секунд (heartbeat), что примерно в 30 раз эффективнее опроса каждые 2 секунды. Если очередь истекает (BAD_EVENT_QUEUE_ID), она автоматически перерегистрируется. Очередь удаляется в блоке finally при выходе.
Эмодзи robot_ear добавляется к последнему сообщению как визуальный индикатор во время прослушивания и удаляется, когда прослушивание останавливается. Пинги поддержания активности MCP отправляются через ctx.info() после каждого цикла long-polling.
Отсутствие пропущенных сообщений при ответе
Когда вызывается reply, он проверяет наличие новых сообщений перед отправкой. Если кто-то написал что-то, пока LLM «думала», эти сообщения извлекаются и возвращаются вместе с подтверждением «сообщение отправлено». Таким образом, LLM всегда видит то, что пропустила, и может соответствующим образом отреагировать. last_seen_message_id обновляется до самого нового значения — либо пропущенные сообщения, либо отправленное сообщение — чтобы ничего не потерялось.
Завершение сессии
Пользователи могут завершить сессию бота, отреагировав на любое сообщение бота настраиваемым эмодзи (по умолчанию: :stop_sign:). Проверка завершения выполняется как во время listen() (через события реакции), так и перед reply() (через опрос REST API), что покрывает состояние гонки, когда пользователь реагирует, пока бот занят работой. Настройте с помощью configure(dismiss_emoji={"stop_sign", "wave"}).
Фильтрация видимости бота
Темы, содержащие /nobots или /nb, полностью скрыты от бота. Сообщения, начинающиеся с /nobots или /nb, также отфильтровываются. Это позволяет людям вести приватные разговоры, которые бот не увидит.
Переменные окружения
Переменная | Описание |
| Абсолютный путь к |
| ID сообщения, которое инициировало сессию (например, @mention). Устанавливает якорь прослушивания, чтобы агент не пропустил сообщения после триггера. |
| Email человека, инициировавшего сессию. Сохраняется в |
| Имя потока для автоматической инициализации сессии при запуске сервера (только для прямых вызовов |
| Тема для автоинициализации. Требует |
| Список разрешенных для чтения/отправки приватных потоков. Если не задано = нет доступа к приватным потокам. Принимает |
| Список разрешенных для отправки потоков. Если не задано = запись разрешена везде (обратная совместимость). Те же форматы, что и выше. |
| Переопределение директории кэша на диске (по умолчанию системная временная директория). |
| Переопределение директории логов (по умолчанию |
Лицензия
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