zulip
zulipmcp
ZulipでAIエージェントを@メンション可能なボットとして実行、または任意のMCPクライアントに接続します。Pythonライブラリとしても動作します。
クイックスタート
パッケージをインストールします:
uv add zulipmcp --git https://github.com/windborne/zulipmcp.gitプロジェクトのルートディレクトリに、Zulipボットの認証情報を含む
.zuliprcファイルを追加します。ボットの作成方法については、ボットまたはインテグレーションの追加を参照してください。ボットの種類は「generic」である必要があります。.mcp.jsonにMCPサーバーを追加します:{ "mcpServers": { "zulip": { "command": "uv", "args": ["run", "python", "-m", "zulipmcp.mcp"] } } }MCPクライアントを再起動します。これでZulipツールが利用可能になります。
要件
エントリーポイント
エントリーポイント | 説明 |
| Claude Code / MCPクライアント用MCPサーバー |
| SSE経由のMCPサーバー (リモート/Webクライアント用) |
| リスナー: @メンションを監視し、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}"),
)リスナー
オプションの zulipmcp.listener モジュールは、Zulipの@メンションを監視し、(ストリーム, トピック) ごとに1つのヘッドレス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 Codeセッション用の |
|
| 追加のシステムプロンプトファイル (デフォルトパスは現在の作業ディレクトリではなく |
|
| 生成されたセッションの作業ディレクトリ |
|
| Claude CLIバイナリ名またはパス |
|
| セッションログファイル用ディレクトリ |
| (なし) |
|
各セッションには TRIGGER_MESSAGE_ID と SESSION_USER_EMAIL が自動的に設定されるため、set_context() は@メンションにアンカーされ、フックはリクエスト元を識別できます。
このリスナーは意図的に最小限(約230行)に抑えられています。同時実行数の制限、ワークスペースの分離、スタック監視、ダッシュボードなどは含まれていません。必要に応じて追加してください。
設計の詳細
メッセージのリスニング
listen ツールは、繰り返し GET /messages を呼び出す代わりに、ZulipのリアルタイムイベントAPI(ロングポーリング)を使用します。開始時に last_seen_message_id 以降のメッセージをキャッチアップし、必要に応じてボットをストリームにサブスクライブし、ストリーム/トピック用に絞り込まれたイベントキューを登録してから GET /events を介してロングポーリングを行います。サーバーはメッセージが到着するか、約90秒経過(ハートビート)するまでブロックするため、2秒ごとのポーリングよりも約30倍効率的です。キューの有効期限が切れた場合 (BAD_EVENT_QUEUE_ID)、自動的に再登録されます。キューは終了時の finally ブロックで削除されます。
リスニング中は視覚的なインジケーターとして最後のメッセージに :robot_ear: 絵文字が追加され、リスニング停止時に削除されます。MCPのキープアライブpingは、各ロングポーリングサイクルの後に ctx.info() を介して送信されます。
返信時のメッセージ取りこぼし防止
reply が呼び出されると、送信 前 に新しいメッセージがないか確認します。LLMが思考している間に誰かが投稿した場合、それらのメッセージが取得され、「メッセージ送信」の確認とともに返されます。これにより、LLMは取りこぼした内容を常に把握し、それに応じて反応できます。last_seen_message_id は、取りこぼしたメッセージと送信されたメッセージのうち、最も新しいものに更新されるため、何も見落とすことはありません。
セッションの終了
ユーザーは、ボットのメッセージに対して設定可能な絵文字(デフォルト: :stop_sign:)でリアクションすることで、ボットセッションを終了できます。終了チェックは listen() 中(リアクションイベント経由)と reply() 前(REST APIポーリング経由)の両方で実行され、ボットが作業中にユーザーがリアクションする競合状態をカバーします。configure(dismiss_emoji={"stop_sign", "wave"}) でカスタマイズ可能です。
ボットの可視性フィルタリング
/nobots または /nb を含むトピックは、ボットから完全に隠されます。/nobots または /nb で始まるメッセージもフィルタリングされます。これにより、人間はボットに見られないプライベートな会話を行うことができます。
環境変数
変数 | 説明 |
|
|
| セッションをトリガーしたメッセージID(例: @メンション)。エージェントがトリガー後のメッセージを見逃さないようにリスニングアンカーを設定します。 |
| セッションをトリガーした人間のメールアドレス。フック用に |
| サーバー起動時にセッションを自動初期化するためのストリーム名( |
| 自動初期化用のトピック。 |
| プライベートストリームの読み取り/送信許可リスト。未設定の場合はプライベートストリームへのアクセス不可。 |
| ストリーム送信許可リスト。未設定の場合はどこでも書き込み可能(後方互換性)。上記と同じ形式。 |
| ディスクキャッシュディレクトリの上書き(デフォルトはシステム一時ディレクトリ)。 |
| ログディレクトリの上書き(デフォルトは |
ライセンス
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