Skip to main content
Glama

zulip-mcp

A small MCP server that lets coding agents share a work log in one Zulip stream. It has 7 tools, no database and no background process. Each agent runs its own copy with its own bot, so Zulip's sender column shows which agent posted.

If you need scheduled messages, file uploads, approvals or DMs, use zulipchat-mcp, which has up to 60 tools.

Tools

Tool

Result

zulip_status

One line: message count, last sender and age, recent mentions of this bot

zulip_read

Last 5 messages at 300 chars; full=true gives 15, untruncated. The newest post with all 4 labels is shown whole and stays visible, if it is among the last 50

zulip_send

Posts to a topic; an identical repeat within 120 s is not posted again

zulip_search

Full-text search across the stream, 10 hits at 200 chars

zulip_mentions

The 10 most recent messages that mention this bot

zulip_topics

Most recently active topics

zulip_react

Adds an emoji reaction to a message id

Related MCP server: coordination_bus/mcp_server.py

Topics

Topics default to <repo> / <branch>, the format Zulip's git integrations use, so agent posts and push events share a topic. The repo name comes from the origin URL, so every worktree of a repo shares one topic.

zulip_send needs topic, or path set to the repository being worked on. MCP clients choose the server's working directory, and it may be a different repo from the one being worked on. Read tools may fall back to that directory.

path gives the local branch. A push from feature to remote main needs an explicit topic.

Install

uv tool install git+https://github.com/teddybuild/zulip-mcp

Create a generic bot in Zulip and subscribe it to your stream.

Configuration

All configuration comes from environment variables. Bad values stop startup with exit code 2.

Variable

Required

Meaning

ZULIP_SITE

yes

Server URL, such as https://chat.example.com

ZULIP_EMAIL

yes

The bot's email

ZULIP_API_KEY

yes

The bot's API key

ZULIP_STREAM

yes

The one stream this server uses

ZULIP_INSECURE_TLS

no

1 skips certificate checks, for self-signed servers. Default 0

ZULIP_POST_RULES

no

1 applies the post rules below to handoff posts. Default 0

Prefer a launch script that pulls the key from your secret store and then runs zulip-mcp, so the key stays out of client config files. The examples below use a script called zulip-mcp-launch.

Client setup

Claude Code:

claude mcp add --scope user zulip -- zulip-mcp-launch

Codex:

codex mcp add zulip -- zulip-mcp-launch

Antigravity, in ~/.gemini/config/mcp_config.json:

{ "mcpServers": { "zulip": { "command": "zulip-mcp-launch", "args": [] } } }

OpenCode 2.x, in ~/.config/opencode/opencode.json:

{ "mcp": { "servers": { "zulip": { "type": "local", "command": ["zulip-mcp-launch"] } } } }

Post rules

Ordinary posts are free-form, so agents can post often. With ZULIP_POST_RULES=1, zulip_send with handoff=true rejects a message unless:

  • It has lines starting Did:, Gate:, Next: and Blocked:.

  • It is at most 600 characters.

  • It has no relative paths, because a reader in another repo cannot resolve them.

zulip-post-validate runs the same check on stdin (exit 0 or 2), so shell scripts share one copy of the rules.

Errors

Tool error text carries a code: config, validation, topic, auth_failed, rate_limited, unreachable, timeout, ambiguous_write or api_error. Reads retry up to 3 times. Writes never retry. ambiguous_write means Zulip may have saved the message, so read the topic before resending.

Development

uv sync
scripts/check.sh

License

MIT. See LICENSE and NOTICE.

Available Tools

7 tools
zulip_mentionsA
Read-only

The 10 most recent messages in the stream that mention this bot, at 300 chars each.

NameRequiredDescriptionDefault

No parameters

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered. The description adds genuinely useful behavior beyond that: a hard cap of 10 results and 300-character truncation per message, which tells the agent to expect short, lossy content and no pagination.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler; the result cap and truncation length are the two facts that matter and both appear immediately.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a zero-parameter read tool with annotations and no output schema, the description covers what is returned in broad terms (count, truncation, mention filter). It stops short of saying which stream or how results are ordered, which leaves a small gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

The tool takes zero parameters, so there is nothing for the description to disambiguate at the schema level; baseline 4 applies. The fixed limits are stated in the description rather than exposed as inputs, which is consistent.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific resource and scope: the 10 most recent messages that mention this bot, truncated to 300 chars. That distinguishes it from zulip_read and zulip_search by content type (mentions of the bot). The phrase 'in the stream' is slightly ambiguous without a stream parameter, keeping it short of a 5.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to prefer this over zulip_read or zulip_search, and no note that it cannot be filtered or paginated. The agent must infer that this is the lightweight 'did anyone ping me' call rather than a general message retriever.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zulip_reactA

Add an emoji reaction, by name such as "thumbs_up", to a message id.

NameRequiredDescriptionDefault
emojiYes
message_idYes

TDQS

A3.6/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=false, destructiveHint=false, idempotentHint=false, and openWorldHint=true, so the safety profile is covered. The description adds nothing about the non-idempotent behavior that matters here (what happens when the same emoji is added twice, whether it errors or duplicates) nor about required permissions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single front-loaded sentence with no filler. Minor deduction because the nested quoting around "thumbs_up" is slightly awkward and the emoji-name hint would read more cleanly as a separate clause.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a two-parameter, non-destructive tool with no output schema, the description is serviceable but thin: it omits duplicate-reaction behavior, permission requirements, and the message_id format. An agent can probably invoke it correctly, but edge cases are undocumented.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0%, so the description must carry parameter meaning and only partially does. The 'by name such as "thumbs_up"' clause genuinely helps, telling the agent to pass a Zulip emoji name rather than a unicode character, but message_id is left entirely unexplained and the exact naming convention (aliases, punctuation) remains ambiguous.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb ('Add') and resource ('emoji reaction') against a named target ('a message id'). This is clearly distinct from every sibling (zulip_send, zulip_read, zulip_search), so an agent can select it without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Usage is implied by the action itself: react to an existing message rather than post a new one. However, there is no explicit statement of when to prefer this over zulip_send (e.g., acknowledging a message without a reply) and no exclusions or prerequisites.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zulip_readC
Read-only

Last 5 messages of a topic at 300 chars each. full=True gives 15, untruncated. Posts with Did:, Gate:, Next: and Blocked: lines are never truncated. The newest one among the last 50 comes first when it is older than the messages shown.

NameRequiredDescriptionDefault
fullNo
pathNo
topicNo

TDQS

C2.8/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint and openWorldHint, so the safety profile is covered, and the description adds genuinely useful behavior: default 5-message/300-char truncation, the full=True expansion to 15 untruncated, and the exemption for posts containing Did:/Gate:/Next:/Blocked: lines. The ordering sentence ('newest one among the last 50 comes first when it is older than the messages shown') is real behavioral detail but is phrased ambiguously enough that an agent may misread the sort order.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

It is compact and front-loads the return-shape information, with no filler sentences. However, the telegraphic fragments ('at 300 chars each', 'full=True gives 15') and the convoluted final sentence about the newest of the last 50 hurt readability more than the length does.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema, the description does well to explain truncation and ordering, but for a read tool whose whole purpose is scoped retrieval it leaves the scoping parameters (path, topic) undefined. An agent cannot reliably decide what to pass to fetch a specific topic versus a default. The result-shape coverage does not compensate for the missing input semantics.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters2/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0% across three parameters, so the description must carry the load, and it only covers 'full' (15 messages, untruncated). 'path' and 'topic' are entirely unexplained — the agent cannot tell whether topic is required, how path relates to topic, or what happens when both are null. One of three parameters documented at zero schema coverage is a significant gap.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description conveys that it returns the last 5 messages of a topic, truncated to 300 chars, which implies a read of topic messages. But it is written as a fragment with no verb or resource framing, and it never distinguishes itself from siblings like zulip_search, zulip_topics, or zulip_mentions. An agent can guess the purpose but must infer it from output behavior rather than a stated scope.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The only conditional guidance is internal to the tool ('full=True gives 15, untruncated'), which explains a parameter rather than when to choose this tool. There is no statement of when to prefer it over zulip_search or zulip_topics, nor any prerequisite or exclusion. The agent gets no routing help among six siblings.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zulip_sendA

Post a message. Pass topic, or path set to the repository being worked on, whose repo and branch name the topic. An identical repeat within 120 s is not posted again. handoff=True marks an end-of-work post, which must meet the server's post rules if on.

NameRequiredDescriptionDefault
pathNo
topicNo
contentYes
handoffNo

TDQS

A3.5/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Goes well beyond the annotations by disclosing the 120-second duplicate-suppression window and the handoff/server post-rule constraint — both non-obvious behaviors for an agent. This partially softens the idempotentHint=false annotation (a repeat is effectively a no-op inside the window), but does not contradict it outright; the description still omits error/rate-limit behavior and any auth requirements for an openWorld tool.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness3/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Short and front-loaded with the core action, but the middle sentence is a compressed run-on ('...whose repo and branch name the topic') that takes a re-read to parse. Nothing is redundant, yet the grammar costs clarity.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For an openWorld, non-idempotent write with zero schema descriptions and no output schema, the description covers the important quirks (dedup window, handoff rules) but is silent on the topic/path precedence, what a successful call returns, and failure modes. Adequate to call it, not quite enough to call it confidently.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the description must carry the load, and it does explain topic, path (repo/branch-derived topic naming), and handoff. It adds real meaning but leaves 'content' entirely undefined and does not say what happens when both topic and path are supplied or when neither is.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

Opens with a specific verb+resource ('Post a message'), which cleanly separates it from the read-oriented siblings (zulip_read, zulip_search, zulip_mentions, zulip_topics) and from zulip_react. It does not name a sibling explicitly, but the post-vs-read split is unambiguous.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Gives field-level guidance ('Pass topic, or path set to the repository being worked on') and a mode cue ('handoff=True marks an end-of-work post'), which implies when to use it. However, it never states when to prefer zulip_react or a different channel/topic, and gives no prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zulip_statusB
Read-only

One line: a topic's message count, last sender and age, plus recent mentions of this bot. Topic defaults to path's repo and branch, then the server's folder.

NameRequiredDescriptionDefault
pathNo
topicNo

TDQS

B3.1/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety and network access are covered. The description adds the default-resolution chain for topic selection and the shape of the returned line, but says nothing about authentication requirements, failure modes, or how recent the "recent mentions" window is, which matter for an open-world read.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two compact sentences with no filler, and the output content is front-loaded before the defaulting rule. The opening phrase "One line:" is slightly cryptic but functions as a useful format hint.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

With no output schema and no annotations beyond read-only and open-world, the description must convey returns and defaults, which it does at a summary level. It still leaves gaps on the meaning of the "age" and "recent mentions" windows and on prerequisites for reaching the server, so an agent could call it but not fully predict the result.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 0% and both parameters are nullable with no descriptions, so the description carries the burden; it does so by explaining that topic falls back to the path's repo and branch and then to the server's folder. That fallback chain is exactly the meaning an agent needs to decide whether to pass path or topic, though path's own semantics are only implicit.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description states the tool returns a one-line topic summary: message count, last sender, age, and recent bot mentions. That is a specific resource and content set, but there is no clear verb ("status" is not clarified as a read/report action), and nothing explicitly separates it from zulip_mentions or zulip_topics, which overlap with the mention and topic elements.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no explicit when-to-use or when-not-to-use guidance, and no sibling is named as an alternative. The defaulting chain for topic selection is useful context but is a parameter behavior, not usage guidance.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

zulip_topicsC
Read-only

The stream's most recently active topics, newest first. limit is capped at 100.

NameRequiredDescriptionDefault
limitNo

TDQS

C2.8/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations already declare readOnlyHint=true and openWorldHint=true, so safety is covered. The description adds real behavioral value by disclosing result ordering (newest first) and the hard cap of 100 on limit, but it does not say whether an over-limit value is clamped or rejected, nor whether results are paginated or truncated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two short sentences, front-loaded with the resource and ordering before the constraint. Nothing is redundant, though the extreme terseness leaves the ambiguities noted elsewhere unaddressed rather than merely avoided.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool is simple (one optional parameter, no output schema), yet the description refers to 'the stream's' topics while the schema exposes no stream parameter, leaving the scope undefined. For a read tool with no output schema, the description should at least say which stream is used and roughly what each returned topic contains.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 0%, so the bare 'limit' integer with default 20 carries no meaning on its own; the description partially compensates by stating the maximum of 100. It still omits what limit counts (topics) and what happens at the boundary, so the single parameter is only half-explained.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose3/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description identifies the resource (a stream's most recently active topics) and the ordering (newest first), which loosely distinguishes it from message-oriented siblings like zulip_read and zulip_search. However, it is a noun phrase with no explicit verb (list/retrieve), and it never names the siblings or clarifies the relationship to them.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

There is no when-to-use guidance at all: nothing says to call this to discover which topics exist before reading messages, and no alternative (zulip_read, zulip_search) is mentioned as a substitute or complement. The agent must infer the tool's role from the name alone.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Tool Schema Changelog

Recent tool additions, removals, and schema changes observed during successful MCP inspections.

  1. 7 tool updatesv0.1.0
    • First observedzulip_mentions
    • First observedzulip_react
    • First observedzulip_read
    • First observedzulip_search
    • First observedzulip_send
    • First observedzulip_status
    • First observedzulip_topics

TDQS

A3.5/5.0

Scored across 7 tools

Disambiguation4/5

Most tools have distinct roles: read, send, search, topics, mentions, react, and status. There is some overlap because zulip_status includes recent mentions and topic recency, while zulip_read and zulip_search both retrieve message content, but the descriptions make the intended boundaries reasonably clear.

Naming Consistency4/5

All tools use a consistent zulip_ snake_case prefix, which makes them easy to recognize as a set. The main minor deviation is that some suffixes are verbs (read, send, search, react) while others are nouns (status, mentions, topics).

Tool Count5/5

Seven tools is well scoped for a Zulip integration focused on topic messaging and bot workflow. Each tool corresponds to a useful operation, and there are no obviously redundant or filler tools.

Completeness4/5

The surface covers the core lifecycle for this focused workflow: status, reading messages, sending, searching, listing topics, mentions, and reactions. Minor gaps remain, such as editing/deleting messages or removing reactions, but the main agent workflows are supported.

Maintenance

ActivityMaintained
ResponsivenessNo recent community issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    B
    maintenance
    Enables teams of coding agents to share one live plan synced through their existing git remote, so each agent receives teammates' contract, decision, and task changes at its next tool call. Provides tools for publishing contracts, logging decisions, adding and claiming tasks, and reviewing the plan for contradictions.
    456 npm
    4
    MIT
  • A
    license
    Not graded
    quality
    B
    maintenance
    Gives a hackathon team's AI coding agents and their humans a shared task board and inbox, so agents can atomically claim tasks, move them between todo/doing/blocked/done, post messages to teammates or the whole team, and read new messages plus board events since they last checked. It also exposes member and agent activity, letting multiple agents working in the same repo coordinate without duplicating work.
    MIT