Metadata-Version: 2.5
Name: zulipchat-mcp
Version: 0.7.6
Summary: Model Context Protocol (MCP) server that connects AI assistants to Zulip Chat with a 20-tool core mode and 60-tool extended mode
Project-URL: Homepage, https://github.com/akougkas/zulipchat-mcp
Project-URL: Documentation, https://github.com/akougkas/zulipchat-mcp#readme
Project-URL: Repository, https://github.com/akougkas/zulipchat-mcp.git
Project-URL: Issues, https://github.com/akougkas/zulipchat-mcp/issues
Project-URL: Changelog, https://github.com/akougkas/zulipchat-mcp/releases
Author-email: Anthony Kougkas <a.kougkas@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: agent-plugins,agent-skills,ai-assistant,automation,chatops,claude-code,clio-coder,codex,copilot,cursor,gemini-cli,mcp,model-context-protocol,opencode,windsurf,zulip
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Communications :: Conferencing
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Requires-Dist: anthropic>=0.78.0
Requires-Dist: cryptography>=50.0.0
Requires-Dist: duckdb>=1.3.0
Requires-Dist: fastmcp[tasks]<5,>=4.0.4
Requires-Dist: httpx2>=2.12.0
Requires-Dist: httpx>=0.28.0
Requires-Dist: mcp-types<3,>=2.2.0
Requires-Dist: prometheus-client>=0.22.0
Requires-Dist: pydantic>=2.11.0
Requires-Dist: pyjwt>=2.13.0
Requires-Dist: python-dotenv>=1.2.2
Requires-Dist: pyyaml>=6.0.3
Requires-Dist: requests>=2.33.0
Requires-Dist: structlog>=25.4.0
Requires-Dist: tomli-w>=1.2.0
Requires-Dist: tomli>=2.5.0; python_version < '3.11'
Requires-Dist: urllib3>=2.7.0
Requires-Dist: zulip>=0.9.0
Description-Content-Type: text/markdown

# ZulipChat MCP Server

<div align="center">

  <h3>Model Context Protocol server for Zulip Chat. Connect Claude Code, Codex, Clio Coder, OpenCode, Copilot, Antigravity CLI, Gemini CLI, and other MCP clients to Zulip.</h3>

  [![PyPI](https://img.shields.io/pypi/v/zulipchat-mcp)](https://pypi.org/project/zulipchat-mcp/)
  [![CI](https://github.com/akougkas/zulipchat-mcp/actions/workflows/ci.yml/badge.svg)](https://github.com/akougkas/zulipchat-mcp/actions/workflows/ci.yml)
  [![Publish](https://github.com/akougkas/zulipchat-mcp/actions/workflows/publish.yml/badge.svg)](https://github.com/akougkas/zulipchat-mcp/actions/workflows/publish.yml)
  [![Coverage Gate](https://img.shields.io/badge/coverage%20gate-60%25-blue)](https://github.com/akougkas/zulipchat-mcp/actions/workflows/ci.yml)
  [![Downloads](https://img.shields.io/pypi/dm/zulipchat-mcp)](https://pypi.org/project/zulipchat-mcp/)
  [![GitHub stars](https://img.shields.io/github/stars/akougkas/zulipchat-mcp)](https://github.com/akougkas/zulipchat-mcp/stargazers)
  [![Python](https://img.shields.io/pypi/pyversions/zulipchat-mcp)](https://pypi.org/project/zulipchat-mcp/)
  [![License](https://img.shields.io/github/license/akougkas/zulipchat-mcp)](LICENSE)
  [![MCP](https://img.shields.io/badge/MCP-Compatible-blue)](https://modelcontextprotocol.io)

  [Quick Start](#quick-start) · [Setup Wizard](docs/user-guide/setup-wizard.md) · [Integrations](docs/integrations/README.md) · [Two-Tier Tools](#two-tier-tool-architecture) · [Contributing](CONTRIBUTING.md)
</div>

---

## Quick Start

```bash
uvx zulipchat-mcp --zulip-config-file ~/.zuliprc
```

Configure this command in your MCP client to let the assistant read and write
Zulip messages with the configured account.

Need a zuliprc? **Zulip Settings > Personal > Account & privacy > API key** — download the file, save it as `~/.zuliprc`.

Interactive onboarding:

```bash
uvx --from zulipchat-mcp zulipchat-mcp-setup
```

## What This Does

ZulipChat MCP bridges any MCP-compatible AI assistant (Claude Code, Gemini CLI, Cursor, Windsurf, etc.) to your Zulip workspace. The assistant can:

- **Send and read messages** — stream messages, DMs, replies, reactions
- **Search conversation history** — full-text search with filters for sender, stream, time range
- **Resolve people by name** — verify a unique recipient before sending; ambiguous names need clarification
- **Switch identities** — post as yourself or as a bot, in the same session
- **Monitor activity** — search recent messages, get stream info, check who's online
- **Bind sessions to Zulip topics** — give long-running agent sessions a stable control topic
- **Receive ordinary bot mentions** — an event-fed local inbox that your own host adapter polls to wake an agent and reply in the source topic, without `/reply` for conversation. The server is the transport; it does not launch or supervise coding agents
- **Reuse dated snapshots** — short-lived message caches and rate-aware request admission reduce repeated API reads
- **Request approvals in-topic** — owner replies with `/approve REQUEST_ID` or `/deny REQUEST_ID` in the session topic; each decision names the request it answers
- **Load Agent Skills** — four packaged instructions for messaging, session control, notifications, and bounded work loops, available as local files and MCP Resources
- **Export agent packages** — native host configuration and skills, Claude's hook/plugin assets, or an Agent Plugins 1.0.0 package

### Agent setup

```bash
# Substitute another supported client as needed.
uvx --from zulipchat-mcp zulipchat-mcp-integrate export --client clio-coder \
  --output-dir /absolute/path/to/project \
  --zulip-config-file /absolute/path/to/.zuliprc --extended-tools
```

Exports support `claude-code`, `codex`, `opencode`, `copilot`, `vscode`,
`antigravity-cli`, `clio-coder`, and `generic`. Add `--mode plugin` for a package.
For several Zulip organizations, export once per organization with
`--server-id zulipchat-<org>`; exports merge into one host configuration.
Account state lives under `~/.local/state/zulipchat-mcp/`. Host trust remains explicit;
Clio configures MCP execution separately from plugin content. See the
[capability matrix](docs/integrations/agent-skills.md),
[Clio guide](docs/integrations/clio-coder.md), and
[complete workflow](docs/integrations/agent-workflow.md).

For read-only access, add `--tool-profile read-only`: discovery and execution
both expose nine core reads or 23 extended reads. The default full profile
retains 20/60 tools. See [API coverage and efficiency](docs/developer-guide/zulip-api-proxy.md)
for cache freshness, rate limits and the boundary between message transport and
host execution. The [live Luna experiment](docs/testing/clio-bot-mentions.md)
records normal mention-to-bot replies from a real Clio TUI driven by a private,
unshipped host adapter. Other hosts were tested through exported configuration
and fake-credential checks, not live sessions.

## Two-Tier Tool Architecture

v0.6.0 introduced a deliberate split: **20 core tools** by default, **60 tools** when you need more.

### Core Mode (default)

The 20 tools that cover most daily use:

| Category | Tools |
|----------|-------|
| **Messaging** | `send_message`, `edit_message`, `get_message`, `add_reaction` |
| **Search** | `search_messages`, `get_streams`, `get_stream_info`, `get_stream_topics` |
| **Users** | `resolve_user`, `get_users`, `get_own_user` |
| **Agent Comms** | `teleport_chat`, `register_agent`, `ensure_agent_session`, `agent_message`, `request_user_input`, `wait_for_response` |
| **System** | `switch_identity`, `server_info`, `manage_message_flags` |

Why 20 instead of 60? Fewer tools means faster tool selection, lower token overhead, and less confusion for the AI. Most tasks — sending messages, searching, reacting, and binding an agent session to Zulip — only need the core set.

### Extended Mode

Need scheduled messages, event queues, file uploads, analytics, or advanced search?

```bash
uvx zulipchat-mcp --zulip-config-file ~/.zuliprc --extended-tools
```

Or via environment variable:
```bash
ZULIPCHAT_EXTENDED_TOOLS=1 uvx zulipchat-mcp --zulip-config-file ~/.zuliprc
```

Extended mode adds: `toggle_reaction`, `cross_post_message`, `advanced_search`, `construct_narrow`, `get_scheduled_messages`, `manage_scheduled_message`, `get_drafts`, `create_draft`, `edit_draft`, `delete_draft`, `register_events`, `get_events`, `listen_events`, `upload_file`, `manage_files`, `get_daily_summary`, `manage_user_mute`, `get_user`, `get_presence`, `get_user_groups`, and more.

## Installation

Full per-client setup guide: [docs/integrations/README.md](docs/integrations/README.md)

### Claude Code

```bash
claude mcp add zulipchat -- uvx zulipchat-mcp --zulip-config-file ~/.zuliprc
```

With dual identity (you + a bot):
```bash
claude mcp add zulipchat -- uvx zulipchat-mcp \
  --zulip-config-file ~/.zuliprc \
  --zulip-bot-config-file ~/.zuliprc-bot
```

Optional Claude hook bridge for lifecycle and approval routing:
```bash
uvx --from zulipchat-mcp zulipchat-mcp-hook \
  --zulip-config-file ~/.zuliprc \
  --zulip-bot-config-file ~/.zuliprc-bot
```

Optional Claude package export for project-local hooks, skills, and subagents:
```bash
uvx --from zulipchat-mcp zulipchat-mcp-integrate export \
  --client claude-code \
  --mode standalone \
  --output-dir . \
  --zulip-config-file ~/.zuliprc \
  --zulip-bot-config-file ~/.zuliprc-bot
```

### Gemini CLI

Add to `~/.gemini/settings.json` under `mcpServers`:

```json
{
  "zulipchat": {
    "command": "uvx",
    "args": ["zulipchat-mcp", "--zulip-config-file", "/path/to/.zuliprc"]
  }
}
```

### Claude Desktop / Cursor / Any MCP Client

Add to your MCP configuration:

```json
{
  "mcpServers": {
    "zulipchat": {
      "command": "uvx",
      "args": ["zulipchat-mcp", "--zulip-config-file", "/path/to/.zuliprc"]
    }
  }
}
```

### Configuration Options

| Option | Description |
|--------|-------------|
| `--zulip-config-file PATH` | Path to your zuliprc file |
| `--zulip-bot-config-file PATH` | Bot zuliprc for dual identity |
| `--extended-tools` | Register all 60 tools instead of the 20-tool core set |
| `--tool-profile {full,read-only}` | Filter discovery and enforce read-only Zulip calls; default: `full` |
| `--transport {stdio,http}` | Transport to serve on (default: `stdio`) |
| `--host HOST` | Bind host for HTTP transport (default: `127.0.0.1`) |
| `--port PORT` | Bind port for HTTP transport (default: `8000`) |
| `--auth-token TOKEN` | Bearer auth token for HTTP transport (or `ZULIPCHAT_HTTP_AUTH_TOKEN`) |
| `--allowed-host HOST` | Additional trusted HTTP hostname; repeat for multiple names |
| `--allowed-origin URL` | Additional trusted browser origin; repeat for multiple origins |
| `--unsafe` | Enable administrative tools (use with caution) |
| `--debug` | Enable debug logging |
| `--associate-existing-db` | Deliberately associate an unbound legacy database with the verified current account |

### Remote HTTP Transport

ZulipChat MCP supports stateless HTTP deployments under the MCP 2026-07-28 protocol:

```bash
# Run server over HTTP with bearer authentication
ZULIPCHAT_HTTP_AUTH_TOKEN=your-secret-token \
  uvx zulipchat-mcp --zulip-config-file ~/.zuliprc --transport http --host 0.0.0.0 --port 8000 --allowed-host mcp.internal
```

Generate client integration snippets for remote HTTP connections:

```bash
uvx --from zulipchat-mcp zulipchat-mcp-integrate print --client claude-code --remote-url http://mcp.internal:8000/mcp --remote-token your-secret-token
```

HTTP startup requires a bearer token for non-loopback binds and validates Host and Origin headers. Configure `--allowed-host` for the hostname used by clients or a reverse proxy; terminate TLS at the proxy for remote connections. A token grants access to the configured Zulip account: deploy a separate instance per trusted account, rather than sharing it across unrelated users.

HTTP tools reject server-local file paths, outbound event callbacks, and `switch_identity`. Upload text with `file_content` or binary bytes with `file_content_base64`; download without `download_path` to obtain a URL. Use stdio for local file operations and runtime identity switching. Attachment deletion requires `--unsafe`.

Persistent state defaults to an account-scoped directory. An explicitly selected
`ZULIPCHAT_DB_PATH` is associated with the normalized realm and user/bot
principals; a different account cannot reuse it. Legacy state is left intact and
requires deliberate association. See [database migration](docs/user-guide/configuration.md#persistent-state-and-account-migration).

Agent sessions, approvals, listener cursors, and default background-task storage remain local state. Use a single instance for these workflows. Separate DuckDB paths avoid writer conflicts but do not share session data; ordinary round-robin routing across such replicas is not supported. Legacy HTTP clients may also retain transport sessions.

### AI Analytics & LLM Provider

AI-powered analytics tools (`analyze_stream_with_llm`, `analyze_team_activity_with_llm`, `intelligent_report_generator`) execute using a server-side Anthropic LLM provider:

- Set `ANTHROPIC_API_KEY` on the server process for LLM generation.
- Optionally set `ANTHROPIC_MODEL` to override the default model (`claude-opus-5`).
- Without an API key, analytics tools return structured data summaries with `llm_unavailable: true` so your client assistant can analyze the data directly.

### More clients

Dedicated setup pages:

- [Gemini CLI](docs/integrations/gemini-cli.md)
- [Codex](docs/integrations/codex.md)
- [OpenCode](docs/integrations/opencode.md)
- [VS Code + GitHub Copilot](docs/integrations/vscode-copilot.md)
- [Cursor](docs/integrations/cursor.md)
- [Windsurf](docs/integrations/windsurf.md)
- [Antigravity](docs/integrations/antigravity.md)
- [Generic MCP](docs/integrations/generic.md)

## Dual Identity

Configure both a user and a bot zuliprc to let your assistant switch between identities mid-session:

```bash
uvx zulipchat-mcp \
  --zulip-config-file ~/.zuliprc \
  --zulip-bot-config-file ~/.zuliprc-bot
```

The assistant posts as **you** by default. Call `switch_identity` to post as the bot — useful for automated notifications, agent-to-agent communication, or keeping human vs. bot messages distinct.

## Real-World Examples

**"Catch me up on what happened in #engineering today"**
→ Assistant calls `search_messages` with stream + time filter, summarizes the thread.

**"Tell the team we're deploying at 3pm"**
→ Assistant calls `send_message` to #engineering with the announcement.

**"Who sent that message about the API migration?"**
→ Assistant calls `search_messages` with keywords, returns sender and context.

**"React with :thumbs_up: to Sarah's last message"**
→ Assistant calls `resolve_user` ("Sarah"), `search_messages` (sender), then `add_reaction`.

**"DM Jaime that the PR is ready"**
→ Assistant calls `teleport_chat` with fuzzy name resolution — no email needed.

## Development

```bash
git clone https://github.com/akougkas/zulipchat-mcp.git
cd zulipchat-mcp
uv sync
uv run zulipchat-mcp --zulip-config-file ~/.zuliprc
```

Run checks:
```bash
uv run pytest -q              # full test suite, 60% coverage gate
uv run ruff check .           # Linting
uv run mypy src               # Type checking
```

For packaging, dependency, FastMCP, or startup changes, run the release smoke:

```bash
uv build
scripts/pre_release_smoke.sh --version X.Y.Z --allow-dirty
```

See [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide, and [CLAUDE.md](CLAUDE.md) / [AGENTS.md](AGENTS.md) for AI agent instructions.

## Architecture

```
src/zulipchat_mcp/
├── core/           # Client wrapper, identity, caching, security
├── tools/          # MCP tool implementations (two-tier registration)
├── services/       # Background listener and session event routing
├── utils/          # Logging, DuckDB persistence, metrics
└── config.py       # config loading (zuliprc + environment fallback)
```

Built on [FastMCP](https://github.com/PrefectHQ/fastmcp) with async-first design, [DuckDB](https://duckdb.org) for agent state persistence, and smart user/stream caching for fast fuzzy resolution.

## Privacy

- **No data collection** — nothing leaves your machine except Zulip API calls
- **No telemetry** — zero analytics, tracking, or usage reporting
- **Local execution** — all processing happens on your hardware
- **Credentials stay local** — API keys are never logged or transmitted beyond your Zulip server

Full policy: [PRIVACY.md](PRIVACY.md)

## License

MIT — See [LICENSE](LICENSE)

## Links

- [Documentation Index](docs/README.md)
- [Support](SUPPORT.md)
- [Security Policy](SECURITY.md)
- [Zulip API Documentation](https://zulip.com/api/)
- [Model Context Protocol](https://modelcontextprotocol.io)
- [Report Issues](https://github.com/akougkas/zulipchat-mcp/issues)
- [Discussions](https://github.com/akougkas/zulipchat-mcp/discussions)

---

<div align="center">
  <sub>Built for the Zulip community</sub>
</div>

<!-- mcp-name: io.github.akougkas/zulipchat -->
