---
title: "Zulip MCP server for AI agents - actionlake"
description: "Give Claude 156 Zulip actions through one MCP server: users, channels, server and organizations, messages. 100,000 calls a month free, no card."
canonical: https://actionlake.com/connectors/zulip
updated: 2026-10-23
---

Connectors · Email & messaging

# Zulip MCP server for AI agents.

actionlake is an MCP gateway: one remote MCP server that connects Claude and other MCP clients to Zulip and the rest of your systems. It gives your agent 156 Zulip actions (48 reads, 73 writes and 35 that wait for a confirmation) and holds the Zulip credential itself, so the agent never does. It paces Zulip's limits and records every call.

[Connect Zulip free](https://actionlake.com/console?start=sandbox) [See pricing](https://actionlake.com/pricing)

100,000 free calls a month. No card, no email, no password: press Start a free sandbox on the next screen and keep the key it shows you.

`claude mcp add --transport http actionlake https://connect.actionlake.com/mcp`

the first call

```
do {
  action: "zulip.users.get_users",
  intent: "check which Zulip account is connected"
}
# Get users · read · 1 upstream call
```

- 156 actions in one signed file
- 48 read look, never change
- 73 write create and update
- 35 wait for a yes destructive, confirmed first

Set up

## Connect Zulip in three steps.

1. 01
   ### Add actionlake to Claude.
   Run the command once in Claude Code; its consent page can create a free sandbox: 100,000 calls a month, no card. In the Claude app, add a custom connector with the URL below and paste your key on the consent page. Creating a new sandbox from the Claude app is not yet tested by us.
   `https://connect.actionlake.com/mcp`
2. 02
   ### Connect Zulip.
   Username and secret. No consent screen: your agent can connect it for you, but the key then passes through your chat. To keep it out of the model's context, paste it in the console instead. actionlake stores what you paste write-only, sealed under your tenant's key.
   - `email` The Zulip API email of the user or bot (for bots, the bot's email such as mybot-bot@acme.zulipchat.com)
   - `api_key` The API key of that user or bot (Personal settings > Account & privacy > API key, or the bot's key under Personal…
   - `host` Where your Zulip lives: your host
   ```
   account { op: "connections.requirements", service: "zulip" }
   # free: exactly what to paste, and what is found for you
   ```
3. 03
   ### Make the first call. Check before a write.
   Ask in plain words; Claude picks the action. Before anything changes, `check` validates the call and prices it, for free.
   ```
   do    { action: "zulip.users.get_users" }
   # get users · read · 1 upstream call
   check { action: "zulip.users.create_user", input: { … } }
   # free: inputs, permissions, cost and confirmations, nothing sent
   ```

Zulip at a glance

**Sign-in**

Username and secret. No consent screen: your agent can connect it for you, but the key then passes through your chat. To keep it out of the model's context, paste it in the console instead.

**You provide**

`email` `api_key`

**Setup fields**

`host`

**Limits we pace to**

200 calls a minute, per connection

**API covered**

Zulip REST API v1 (OpenAPI 3.0.1, 1.0.0), at your Zulip instance's API base URL, which you enter when connecting (path /api/v1)

**Built from**

Zulip's documentation, read 23 October 2026[OpenAPI spec (GitHub)](https://raw.githubusercontent.com/zulip/zulip/main/zerver/openapi/zulip.yaml) [zulip.com](https://zulip.com/api/rest)

**Service file**

Version 1.0.0, signed (Ed25519)

**Cached reads**

40 of 48 reads, for up to 5 minutes; a write clears what it affects

**Shared entities**

4, so ask can line Zulip up with your other systems

**Data**

Processed and stored in Sydney, Australia. No US region yet

Capabilities

## What an AI agent can do in Zulip.

156 actions in 12 areas. Every one carries its effect, so a key can allow the reads and hold the rest.

- **48** read look, never change
- **73** write create and update
- **35** destructive wait for a confirmation

1. ### Users
   44
   13 read · 19 write · 12 destructive
   Get users · Get user groups · Create a user · Create a user group
2. ### Channels
   29
   11 read · 14 write · 4 destructive
   Get all channels · Create a channel · Get a channel by ID · Update a channel
3. ### Server and organizations
   27
   8 read · 12 write · 7 destructive
   Add a code playground · Add a linkifier · Add an allowed domain · Create a custom profile field
4. ### Messages
   19
   8 read · 9 write · 2 destructive
   Get messages · Send a message · Fetch a single message · Edit a message
5. ### Drafts
   8
   2 read · 4 write · 2 destructive
   Create drafts · Create a saved snippet · Get all saved snippets · Edit a draft
6. ### Invites
   6
   1 read · 3 write · 2 destructive
   Create a reusable invitation link · Get all invitations · Resend an email invitation · Send invitations
7. ### Mobile
   6
   0 read · 5 write · 1 destructive
   Send an E2EE test notification to mobile device(s) · Register a logged-in device · Register E2EE push device · Register E2EE push device to bouncer
8. ### Navigation views
   4
   1 read · 2 write · 1 destructive
   Add a navigation view · Get all navigation views · Update the navigation view · Remove a navigation view

**4 more areas · 13 actions**

- Scheduled messages **4**
- Bots **3**
- Real time events **3**
- Reminders **3**

Top actions

## The Zulip API, shaped for agents.

The ids your agent types, what each does, and the one name it shares with other systems. 22 of Zulip's 22 action names are shared with at least one other connector, so an agent learns them once.

| Action | What it does | Effect | Same name in |
| --- | --- | --- | --- |
| `zulip.users.get_users` Get users | Get users. | read | `identity.user.list` 474 connectors |
| `zulip.users.get_user_groups` Get user groups | Get user groups. | read | `identity.group.list` 262 connectors |
| `zulip.messages.get_messages` Get messages | Get messages. | read | `comm.message.list` 42 connectors |
| `zulip.channels.get_streams` Get all channels | Get all channels. | read | `comm.channel.list` 27 connectors |
| `zulip.users.create_user` Create a user | Create a user. | write | `identity.user.create` 262 connectors |
| `zulip.users.create_user_group` Create a user group | Create a user group. | write | `identity.group.create` 205 connectors |
| `zulip.messages.send_message` Send a message | Send a message. | write | `comm.message.send` 25 connectors |
| `zulip.channels.create_channel` Create a channel | Create a channel. | write | `comm.channel.create` 16 connectors |
| `zulip.messages.delete_message` Delete a message | Delete a message. | destructive | `comm.message.delete` 27 connectors |
| `zulip.users.get_own_user` Get own user | Get own user. | read | `identity.current_user.get` 307 connectors |
| `zulip.users.get_user_group_members` Get user group members | Get user group members. | read | `identity.group_member.list` 103 connectors |
| `zulip.users.update_user_group_members` Update user group members | Update user group members. | write | `identity.group_member.update` 34 connectors |

Try it

## Prompts to paste into Claude.

Each one names the Zulip actions it will call, so you know what it reads and what it changes before you send it.

1. Read read
   Who has access in Zulip? List every user and their role.
   calls `zulip.users.get_users`
2. Write write
   Create a user in Zulip. Show me exactly what you will send before you save it.
   calls `zulip.users.create_user`

Governance for Zulip

## Destructive actions wait for a yes.

35 Zulip actions are destructive. The first 10:

- Delete a message `zulip.messages.delete_message`
- Remove an emoji reaction `zulip.messages.remove_reaction`
- Unmute a user `zulip.users.unmute_user`
- Delete a draft `zulip.drafts.delete_draft`
- Delete your profile picture `zulip.users.delete_avatar`
- Unsubscribe from a channel `zulip.channels.unsubscribe`
- Delete a topic `zulip.channels.delete_topic`
- Deactivate a user `zulip.users.deactivate_user`
- Remove an FCM registration token `zulip.users.remove_fcm_token`
- Remove a bot's stored data `zulip.bots.remove_bot_storage`

A destructive action runs only with `confirm: true`. Under the `human` policy the agent cannot confirm for itself: the run stops until a named person approves, in the console or from a signed link in an email. The cap on a key is refused before the call is sent, never after.

do zulip.messages.delete_message confirm_policy: **human**

Delete a message?

**intent:** the user asked me to delete a message

run suspended · waiting for a named person · key _zulip-agent_ cannot confirm itself

In the console, or from an emailed signed link.

a key for this connector

```
account {
  op: "keys.create", name: "zulip-agent",
  allowed_actions: ["zulip.*"], cap_calls: 2000,
  confirm_policy: "human_for_writes",
  approval_rules: [
    { match: "zulip.messages.delete_message", approver: "lead@example.com" },
    { match: "zulip.messages.remove_reaction", approver: "lead@example.com" },
    { match: "zulip.users.unmute_user", approver: "lead@example.com" }
  ]
}
```

Illustrative. Scoped to Zulip only, capped at 2,000 upstream calls, every write confirmed, and the destructive ones approved by a named person.

Cost

## What Zulip costs on actionlake.

Every Zulip action is one upstream call, the only thing actionlake bills. Searching, `check`, `cost`, `account` and any call Zulip refused with 401, 403, 429 or a 5xx are free. Paid plans start at US$49 a month for 250,000 calls, with overage from US$0.30 down to US$0.18 per 1,000.

- 1 upstream call per action all 156 Zulip actions
- 156 actions page each page of a long list is one call
- 40 reads can be cached a cache hit costs nothing
- 100,000 calls a month, free paid plans from US$49 a month for 250,000

[See pricing](https://actionlake.com/pricing)

Action index

## Every Zulip action.

156 actions by area: the id your agent calls, what it does, and its effect.

**Users 44**

- `zulip.users.add_alert_words` Add alert words write
- `zulip.users.add_apns_token` Add an APNs device token write
- `zulip.users.add_fcm_token` Add an FCM registration token write
- `zulip.users.create_user` Create a user write
- `zulip.users.create_user_group` Create a user group write
- `zulip.users.deactivate_own_user` Deactivate own user destructive
- `zulip.users.deactivate_user` Deactivate a user destructive
- `zulip.users.deactivate_user_group` Deactivate a user group destructive
- `zulip.users.delete_avatar` Delete your profile picture destructive
- `zulip.users.get_alert_words` Get all alert words read
- `zulip.users.get_attachments` Get attachments read
- `zulip.users.get_bot_api_key` Get a bot's API key read
- `zulip.users.get_is_user_group_member` Get user group membership status read
- `zulip.users.get_own_user` Get own user read
- `zulip.users.get_user` Get a user read
- `zulip.users.get_user_by_email` Get a user by email read
- `zulip.users.get_user_group_members` Get user group members read
- `zulip.users.get_user_group_subgroups` Get subgroups of a user group read
- `zulip.users.get_user_groups` Get user groups read
- `zulip.users.get_user_presence` Get a user's presence read
- `zulip.users.get_user_status` Get a user's status read
- `zulip.users.get_users` Get users read
- `zulip.users.mute_user` Mute a user write
- `zulip.users.reactivate_user` Reactivate a user write
- `zulip.users.regenerate_api_key` Regenerate your API key destructive
- `zulip.users.regenerate_bot_api_key` Regenerate a bot's API key destructive
- `zulip.users.remove_alert_words` Remove alert words destructive
- `zulip.users.remove_apns_token` Remove an APNs device token destructive
- `zulip.users.remove_attachment` Delete an attachment destructive
- `zulip.users.remove_fcm_token` Remove an FCM registration token destructive
- `zulip.users.remove_profile_data` Remove your profile data destructive
- `zulip.users.set_typing_status` Set "typing" status write
- `zulip.users.set_typing_status_for_message_edit` Set "typing" status for message editing write
- `zulip.users.unmute_user` Unmute a user destructive
- `zulip.users.update_presence` Update your presence write
- `zulip.users.update_profile_data` Update your profile data write
- `zulip.users.update_settings` Update settings write
- `zulip.users.update_status` Update your status write
- `zulip.users.update_status_for_user` Update user status write
- `zulip.users.update_user` Update a user write
- `zulip.users.update_user_by_email` Update a user by email write
- `zulip.users.update_user_group` Update a user group write
- `zulip.users.update_user_group_members` Update user group members write
- `zulip.users.update_user_group_subgroups` Update subgroups of a user group write

**Channels 29**

- `zulip.channels.add_default_stream` Add a default channel write
- `zulip.channels.archive_stream` Archive a channel destructive
- `zulip.channels.create_big_blue_button_video_call` Create BigBlueButton video call read
- `zulip.channels.create_channel` Create a channel write
- `zulip.channels.create_channel_folder` Create a channel folder write
- `zulip.channels.create_constructor_groups_video_call` Create Constructor Groups video call write
- `zulip.channels.create_nextcloud_talk_video_call` Create Nextcloud Talk video call write
- `zulip.channels.create_webex_video_call` Create Webex video call write
- `zulip.channels.delete_topic` Delete a topic destructive
- `zulip.channels.get_channel_folders` Get channel folders read
- `zulip.channels.get_stream_by_id` Get a channel by ID read
- `zulip.channels.get_stream_email_address` Get channel's email address read
- `zulip.channels.get_stream_id` Get channel ID read
- `zulip.channels.get_stream_topics` Get topics in a channel read
- `zulip.channels.get_streams` Get all channels read
- `zulip.channels.get_subscribers` Get channel subscribers read
- `zulip.channels.get_subscription_status` Get subscription status read
- `zulip.channels.get_subscriptions` Get subscribed channels read
- `zulip.channels.get_user_channels` Get a user's subscribed channels read
- `zulip.channels.mute_topic` Topic muting write
- `zulip.channels.patch_channel_folders` Reorder channel folders write
- `zulip.channels.remove_default_stream` Remove a default channel destructive
- `zulip.channels.subscribe` Subscribe to a channel write
- `zulip.channels.unsubscribe` Unsubscribe from a channel destructive
- `zulip.channels.update_channel_folder` Update a channel folder write
- `zulip.channels.update_stream` Update a channel write
- `zulip.channels.update_subscription_property` Update a subscription setting write
- `zulip.channels.update_subscription_settings` Bulk update subscription settings write
- `zulip.channels.update_user_topic` Update personal preferences for a topic write

**Server and organizations 27**

- `zulip.server_and_organizations.add_code_playground` Add a code playground write
- `zulip.server_and_organizations.add_linkifier` Add a linkifier write
- `zulip.server_and_organizations.add_realm_domain` Add an allowed domain write
- `zulip.server_and_organizations.create_custom_profile_field` Create a custom profile field write
- `zulip.server_and_organizations.deactivate_custom_emoji` Deactivate custom emoji destructive
- `zulip.server_and_organizations.deactivate_realm` Deactivate an organization destructive
- `zulip.server_and_organizations.delete_custom_profile_field` Delete a custom profile field destructive
- `zulip.server_and_organizations.delete_realm_domain` Remove an allowed domain destructive
- `zulip.server_and_organizations.delete_realm_export` Delete a data export destructive
- `zulip.server_and_organizations.export_realm` Create a data export write
- `zulip.server_and_organizations.get_custom_emoji` Get all custom emoji read
- `zulip.server_and_organizations.get_custom_profile_fields` Get all custom profile fields read
- `zulip.server_and_organizations.get_linkifiers` Get linkifiers read
- `zulip.server_and_organizations.get_presence` Get presence of all users read
- `zulip.server_and_organizations.get_realm_domains` Get allowed domains read
- `zulip.server_and_organizations.get_realm_export_consents` Get data export consent state read
- `zulip.server_and_organizations.get_realm_exports` Get all data exports read
- `zulip.server_and_organizations.get_server_settings` Get server settings read
- `zulip.server_and_organizations.patch_realm_domain` Update an allowed domain write
- `zulip.server_and_organizations.remove_code_playground` Remove a code playground destructive
- `zulip.server_and_organizations.remove_linkifier` Remove a linkifier destructive
- `zulip.server_and_organizations.reorder_custom_profile_fields` Reorder custom profile fields write
- `zulip.server_and_organizations.reorder_linkifiers` Reorder linkifiers write
- `zulip.server_and_organizations.test_welcome_bot_custom_message` Test welcome bot custom message write
- `zulip.server_and_organizations.update_custom_profile_field` Update a custom profile field write
- `zulip.server_and_organizations.update_linkifier` Update a linkifier write
- `zulip.server_and_organizations.update_realm_user_settings_defaults` Update realm-level defaults of user settings write

**Messages 19**

- `zulip.messages.add_reaction` Add an emoji reaction write
- `zulip.messages.check_messages_match_narrow` Check if messages match a narrow read
- `zulip.messages.check_thumbnail_status` Check thumbnail status read
- `zulip.messages.delete_message` Delete a message destructive
- `zulip.messages.get_file_temporary_url` Get public temporary URL for an uploaded file read
- `zulip.messages.get_message` Fetch a single message read
- `zulip.messages.get_message_history` Get a message's edit history read
- `zulip.messages.get_messages` Get messages read
- `zulip.messages.get_read_receipts` Get a message's read receipts read
- `zulip.messages.mark_all_as_read` Mark all messages as read write
- `zulip.messages.mark_stream_as_read` Mark messages in a channel as read write
- `zulip.messages.mark_topic_as_read` Mark messages in a topic as read write
- `zulip.messages.remove_reaction` Remove an emoji reaction destructive
- `zulip.messages.render_message` Render a message read
- `zulip.messages.report_message` Report a message write
- `zulip.messages.send_message` Send a message write
- `zulip.messages.update_message` Edit a message write
- `zulip.messages.update_message_flags` Update personal message flags write
- `zulip.messages.update_message_flags_for_narrow` Update personal message flags for narrow write

**Drafts 8**

- `zulip.drafts.create_drafts` Create drafts write
- `zulip.drafts.create_saved_snippet` Create a saved snippet write
- `zulip.drafts.delete_draft` Delete a draft destructive
- `zulip.drafts.delete_saved_snippet` Delete a saved snippet destructive
- `zulip.drafts.edit_draft` Edit a draft write
- `zulip.drafts.edit_saved_snippet` Edit a saved snippet write
- `zulip.drafts.get_drafts` Get drafts read
- `zulip.drafts.get_saved_snippets` Get all saved snippets read

**Invites 6**

- `zulip.invites.create_invite_link` Create a reusable invitation link write
- `zulip.invites.get_invites` Get all invitations read
- `zulip.invites.resend_email_invite` Resend an email invitation write
- `zulip.invites.revoke_email_invite` Revoke an email invitation destructive
- `zulip.invites.revoke_invite_link` Revoke a reusable invitation link destructive
- `zulip.invites.send_invites` Send invitations write

**Mobile 6**

- `zulip.mobile.e2ee_test_notify` Send an E2EE test notification to mobile device(s) write
- `zulip.mobile.register_client_device` Register a logged-in device write
- `zulip.mobile.register_push_device` Register E2EE push device write
- `zulip.mobile.register_remote_push_device` Register E2EE push device to bouncer write
- `zulip.mobile.remove_client_device` Remove a registered device destructive
- `zulip.mobile.test_notify` Send a test notification to mobile device(s) write

**Navigation views 4**

- `zulip.navigation_views.add_navigation_view` Add a navigation view write
- `zulip.navigation_views.edit_navigation_view` Update the navigation view write
- `zulip.navigation_views.get_navigation_views` Get all navigation views read
- `zulip.navigation_views.remove_navigation_view` Remove a navigation view destructive

**Scheduled messages 4**

- `zulip.scheduled_messages.create_scheduled_message` Create a scheduled message write
- `zulip.scheduled_messages.delete_scheduled_message` Delete a scheduled message destructive
- `zulip.scheduled_messages.get_scheduled_messages` Get scheduled messages read
- `zulip.scheduled_messages.update_scheduled_message` Edit a scheduled message write

**Bots 3**

- `zulip.bots.get_bot_storage` Get a bot's stored data read
- `zulip.bots.remove_bot_storage` Remove a bot's stored data destructive
- `zulip.bots.update_bot_storage` Update a bot's stored data write

**Real time events 3**

- `zulip.real_time_events.delete_queue` Delete an event queue destructive
- `zulip.real_time_events.get_events` Get events from an event queue read
- `zulip.real_time_events.register_queue` Register an event queue write

**Reminders 3**

- `zulip.reminders.create_message_reminder` Create a message reminder write
- `zulip.reminders.delete_reminder` Delete a reminder destructive
- `zulip.reminders.get_reminders` Get reminders read

Questions

## The Zulip MCP server, answered.

**Is there a Zulip MCP server for Claude?**

Yes. actionlake is an MCP gateway: a remote MCP server that gives Claude, or another MCP client, 156 Zulip actions across users, channels, server and organizations and messages, through the same eight tools it uses for every other connector. actionlake is independent; it is not made or endorsed by Zulip.

**What do I need to connect Zulip?**

The Zulip API email of the user or bot (for bots, the bot's email such as mybot-bot@acme.zulipchat.com) and The API key of that user or bot (Personal settings > Account & privacy > API key, or the bot's key under Personal…. Plus your host. The free call account { op: "connections.requirements", service: "zulip" } lists exactly what to paste.

**Can an AI agent delete or change things in Zulip?**

Only if its key allows it, and only with an explicit confirmation. 35 Zulip actions are destructive, including delete a message, remove an emoji reaction and unmute a user. Each runs only with confirm: true. Under the human confirm policy, or an approval rule on the key, the run waits until a named person approves it.

**Will an AI agent use up my Zulip API limit?**

actionlake paces every call to the limits in the Zulip service file: 200 calls a minute per connection. Repeated reads are answered from cache (40 Zulip actions can be), which never reaches Zulip.

**What does a Zulip action cost?**

One upstream call, the only unit actionlake bills. A list that pages bills one call per page (156 Zulip actions page). Cache hits, searches, dry runs and calls Zulip refused with 401, 403, 429 or a 5xx are free. The Free plan includes 100,000 calls a month with no card. Paid plans start at US$49 a month for 250,000 calls, with overage from US$0.30 down to US$0.18 per 1,000.

**Which Zulip API does it cover?**

The Zulip REST API v1 (OpenAPI 3.0.1, 1.0.0) at your Zulip instance's API base URL, which you enter when connecting (path /api/v1). It is built from Zulip's documentation as read on 23 October 2026. 156 actions in 12 areas, each one in the signed service file (version 1.0.0).

**Does actionlake keep my Zulip data, and where?**

actionlake processes and stores data in Sydney, Australia; there is no US region yet. Reads may be cached for up to 5 minutes, and a write clears the reads it affects. Each run's request and response is kept, sealed, for your plan's trace window: 1 day on Free, 3 days on Starter, 7 days on Pro, 14 days on Team, 30 days on Business and 30 days on Enterprise. Your Zulip credential is sealed under your tenant's key, never logged and never returned. Your traffic is not used to train models.

**Which AI clients can use it?**

Claude Code, tested by us end to end, and the Claude app as a custom connector, tested by us with an existing key. Other MCP clients that support remote servers over Streamable HTTP (MCP revisions 2025-06-18 and 2025-11-25) and OAuth dynamic client registration, or a bearer header, should connect the same way; we have not tested them. Or plain REST, under the same action names.

## More connectors like Zulip

Shares the most action names with

- [Cisco Webex 16](https://actionlake.com/connectors/cisco-webex)
- [Rocket.Chat 13](https://actionlake.com/connectors/rocket-chat)
- [Discord 11](https://actionlake.com/connectors/discord)
- [Matrix / Element (Client-Server + Synapse Admin) 10](https://actionlake.com/connectors/matrix-element-client-server-synapse-admin)
- [Google Chat 9](https://actionlake.com/connectors/google-chat)
- [Avaya Experience Platform 7](https://actionlake.com/connectors/avaya-experience-platform)

Joins with, on shared entities

- [Lark Suite 3](https://actionlake.com/connectors/lark-suite)
- [Zoom 3](https://actionlake.com/connectors/zoom)
- [Discourse 3](https://actionlake.com/connectors/discourse)
- [Fireflies.ai 3](https://actionlake.com/connectors/fireflies-ai)
- [Freshworks Freshchat 3](https://actionlake.com/connectors/freshworks-freshchat)
- [HaloPSA 2](https://actionlake.com/connectors/halopsa)

Browse

- [All Email & messaging connectors](https://actionlake.com/connectors/category/email-and-messaging)
- [All connectors](https://actionlake.com/connectors)
- [How actionlake compares](https://actionlake.com/compare)

actionlake is independent. It is not made or endorsed by Zulip; the name is the vendor's own. Counts are from the Zulip service file, version 1.0.0.

## Give your agent Zulip today.

[Connect Zulip free](https://actionlake.com/console?start=sandbox) [See pricing](https://actionlake.com/pricing)

Start free - 100,000 calls/month, no card. No signup. Hard caps on every key. Cached answers are free.

---

Source: https://actionlake.com/connectors/zulip
More: https://actionlake.com/llms.txt
