Metadata-Version: 2.4
Name: revia-mcp
Version: 0.1.3
Summary: Python client for the Revia MCP bridge — connect your coding agent to WhatsApp, Telegram, Slack, and Gmail
Author-email: Moussa Mokhtari <me@moussamokhtari.com>
License: MIT
Keywords: coding-agent,gmail,mcp,revia,telegram,whatsapp
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Requires-Python: >=3.10
Requires-Dist: httpx>=0.27.0
Requires-Dist: mcp>=1.0.0
Requires-Dist: websockets>=12.0
Provides-Extra: dev
Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Description-Content-Type: text/markdown

# Revia MCP Client

Python client for the [Revia](https://revia.devshub.ai) MCP bridge. Connect your Python code to WhatsApp, Telegram, Slack, and Gmail through a single async client. Also supports bidirectional chat with coding agents connected to your Revia instance.

## Contents

- [Install](#install)
- [Quickstart](#quickstart)
- [Real-time events via WebSocket](#real-time-events-via-websocket)
- [Chat with connected coding agents](#chat-with-connected-coding-agents)
- [WebSocket client (agent-side)](#websocket-client-agent-side)
- [API Reference](#api-reference)
- [Token](#token)
- [License](#license)

## Install

```bash
pip install revia-mcp
```

## Quickstart

```python
import asyncio
from revia_mcp import ReviaMCPClient

async def main():
    async with ReviaMCPClient(
        "https://revia.devshub.ai/api/v1/mcp",
        token="rvagent_YOUR_TOKEN_HERE",
    ) as revia:

        # Health check
        pong = await revia.ping()
        print(pong)  # {"status": "pong", "user_id": "...", ...}

        # List channels
        channels = await revia.channels_list()
        for ch in channels["channels"]:
            print(f"{ch['platform']}: {'connected' if ch['reachable'] else 'offline'}")

        # Send a WhatsApp message
        await revia.messages_send(
            "whatsapp:974XXXXXXXX@s.whatsapp.net",
            "Hello from Python!",
        )

        # Read recent messages
        msgs = await revia.messages_read("whatsapp:974XXXXXXXX@s.whatsapp.net", limit=10)
        for m in msgs["messages"]:
            print(f"[{m['timestamp']}] {m.get('sender')}: {m.get('content')}")

        # Send an email
        await revia.email_send(
            to="client@example.com",
            subject="Meeting follow-up",
            body="Thanks for your time today!",
        )

asyncio.run(main())
```

## Real-time events via WebSocket

```python
async def stream_events():
    async with ReviaMCPClient(
        "https://revia.devshub.ai/api/v1/mcp",
        token="rvagent_YOUR_TOKEN_HERE",
    ) as revia:

        async for event in revia.events_ws():
            print(f"[{event['platform']}] {event['from']}: {event['content']}")
```

The WebSocket reconnects automatically on disconnect with exponential backoff. Pass `name="MyBot"` to register with a human-readable name so Revia can discover and chat with your agent.

## Chat with connected coding agents

Revia can discover and chat with coding agents that are connected via WebSocket. Use `agents_list` to see who's online, then `agent_chat` to send a natural language message and get a response:

```python
async def chat_with_agents():
    async with ReviaMCPClient(
        "https://revia.devshub.ai/api/v1/mcp",
        token="rvagent_YOUR_TOKEN_HERE",
    ) as revia:

        # See who's connected
        agents = await revia.agents_list()
        for a in agents["agents"]:
            print(f"  {a['name']} ({a['agent_id']})")

        # Send a natural language message and get a response
        reply = await revia.agent_chat(
            agent_id="agent_abc123",
            message="What's the status of the deployment?",
        )
        print(reply["response"])
```

The call blocks for up to 60 seconds waiting for the agent's response. Pass `timeout_s` to adjust.

## WebSocket client (agent-side)

If you're building a coding agent that Revia should be able to chat with, use `ReviaWebSocket` directly. It handles auth, registration, event streaming, and chat responses:

```python
import asyncio
from revia_mcp.ws import ReviaWebSocket

async def handle_chat(chat_id: str, message: str) -> str:
    """Revia sent us a message — respond in natural language."""
    if "deployment" in message.lower():
        return "Deployment is green — all pods healthy, last deploy 5 minutes ago."
    if "errors" in message.lower():
        return "No errors in the last hour. Error rate is 0.02%."
    return f"I received: {message}"

async def main():
    ws = ReviaWebSocket(
        "wss://revia.devshub.ai/api/v1/mcp/ws",
        token="rvagent_YOUR_TOKEN_HERE",
        name="My CodeSync Agent",
        on_chat=handle_chat,
    )

    async for event in ws:
        print(f"[{event.get('platform', 'system')}] {event.get('type')}: {event.get('content', '')}")

asyncio.run(main())
```

If you prefer manual control over chat responses, omit `on_chat` and handle `chat` events yourself:

```python
async for event in ws:
    if event.get("type") == "chat":
        chat_id = event["chat_id"]
        message = event["message"]
        # ... think about it ...
        await ws.send_chat_response(chat_id, "Here's my response.")
    else:
        print(f"Event: {event}")
```

**`ReviaWebSocket` constructor:**

| Param | Type | Default | Description |
|-------|------|---------|-------------|
| `ws_url` | `str` | required | WebSocket URL, e.g. `wss://revia.devshub.ai/api/v1/mcp/ws` |
| `token` | `str` | required | Agent token (`rvagent_...`) |
| `name` | `str` | `"Python Agent"` | Human-readable name shown in Revia's `agents_list` |
| `on_chat` | `Callable` | `None` | Async callback `(chat_id, message) -> str` for auto-responding to Revia |
| `reconnect` | `bool` | `True` | Automatically reconnect on disconnect with exponential backoff |

**Properties and methods:**

| Member | Type | Description |
|--------|------|-------------|
| `agent_id` | `str \| None` | The agent ID assigned by the server after registration |
| `send_chat_response(chat_id, message)` | `async` | Manually send a response to a chat message from Revia |

## API Reference

### Health

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `ping()` | `ping` | Health check — returns user scope and server time |

### Channels & Contacts

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `channels_list()` | `channels_list` | List channels and connectivity |
| `contacts_list(platform?, query?, limit?)` | `contacts_list` | List contacts |
| `conversations_list(platform?, limit?)` | `conversations_list` | List conversations |
| `conversation_get(target)` | `conversation_get` | Get one conversation |

### Messages

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `messages_read(target, limit?, before?, after?)` | `messages_read` | Read message history |
| `messages_send(target, message, reply_to?)` | `messages_send` | Send a message |
| `attachments_fetch(target, message_id?, limit?)` | `attachments_fetch` | Fetch attachment metadata |

### Email

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `email_list(query?, max_results?)` | `email_list` | List Gmail messages |
| `email_search(query, max_results?)` | `email_search` | Search Gmail |
| `email_read(email_id)` | `email_read` | Read full email |
| `email_send(to, subject, body, cc?, draft?)` | `email_send` | Send or draft email |

### Revia AI

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `revia_ask(prompt, contact?, use_context?)` | `revia_ask` | Ask Revia (read-only) |
| `conversation_claim(target, ttl_s?)` | `conversation_claim` | Mute auto-responder |

### Events

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `events_poll(after_cursor?, limit?)` | `events_poll` | Poll for events |
| `events_wait(after_cursor?, timeout_ms?, limit?)` | `events_wait` | Long-poll for events |
| `events_subscribe(callback_url, events?, secret?)` | `events_subscribe` | Register webhook |
| `events_unsubscribe(subscription_id)` | `events_unsubscribe` | Remove webhook |
| `events_ws(name?, on_chat?)` | — | WebSocket event stream (recommended) |

### Agents

| Method | MCP Tool | Description |
|--------|----------|-------------|
| `agents_list()` | `agents_list` | List connected coding agents |
| `agent_chat(agent_id, message, timeout_s?)` | `agent_chat` | Chat with a connected agent |

## Token

Generate an agent token in the Revia dashboard: **Settings → Coding Agent (MCP) → Generate Token**. Tokens use the `rvagent_` prefix and are shown only once.

## License

MIT
