Skip to main content
Glama
Dr-Agentic
by Dr-Agentic
README.md
# RCS X MCP Server

An [MCP (Model Context Protocol)](https://modelcontextprotocol.io) server that lets any AI assistant — ChatGPT, Claude, Cursor, Cline, Continue, Cody — compose, preview, validate, and send RCS Business Messages from inside the chat.

## Tools

| Tool | What it does |
|---|---|
| `create_message` | Draft an RCS rich card. Required: `recipient` (E.164), `body`. Optional: `title`, `description`, `mediaUrl`, `suggestedReplies` (max 4). Returns a `message_id` + structured payload. |
| `preview_render` | Render the message as an interactive iPhone widget inside the chat. The widget lets the user edit and push to a real iPhone. |
| `validate_carrier` | Check the recipient against an 80+ MNO database (AT&T, T-Mobile, Verizon, Dish, US Cellular, O2 UK, Vodafone, EE, Deutsche Telekom, Jio, Airtel, Singtel, Orange, SFR, Bouygues, Movistar, …). Returns PASS/WARN with carrier-specific warnings + recommendations. |
| `send_to_emulator` | Push the message to the RCS X iOS app via APNs for final visual proof before live send. **Destructive** (pushes to a real device). |
| `send_test` | Send a live test RCS via the MNO RBM API. Returns a delivery receipt with MNO name + per-message cost. **Destructive** + **open-world** (touches carrier billing). |

## Endpoints

| Path | Purpose |
|---|---|
| `POST /mcp` | MCP JSON-RPC 2.0 endpoint. Stateless — every request is independent. |
| `GET /.well-known/apps-sdk.json` | Apps SDK discovery manifest (name, icon, categories, tools). |
| `GET /.well-known/openai-apps-challenge` | OpenAI Apps submission challenge token. |
| `GET /ui/rcsx/widget.html` | The iPhone preview widget (CSP-protected, served from same origin). |

## Run locally

```bash
npm install
npx wrangler dev        # local dev server at http://localhost:8787
npm test                # 15 integration tests, all green
```

## Deploy

```bash
npx wrangler deploy     # publishes to rcsx-mcp-server.<acct>.workers.dev/mcp
```

## Use it from ChatGPT

1. Open ChatGPT → **Settings → Connectors → Developer mode** (toggle on; requires org-admin).
2. **Add connector** → URL: `https://rcsx-mcp-server.<acct>.workers.dev/mcp` → Label: `RCS X`.
3. In any chat: *"Draft an RCS to +14155551234 promoting a 40% off Black Friday deal."*

## Use it from Claude Desktop

Edit `~/Library/Application Support/Claude/claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "rcsx": {
      "command": "npx",
      "args": ["-y", "mcp-remote@latest", "https://rcsx-mcp-server.<acct>.workers.dev/mcp"]
    }
  }
}
```

## Use it from Cursor

`Settings → Features → Model Context Protocol → Add new global MCP server`:

```json
{
  "mcpServers": {
    "rcsx": {
      "url": "https://rcsx-mcp-server.<acct>.workers.dev/mcp"
    }
  }
}
```

## Architecture

- **Cloudflare Workers** — single-isolate, edge-deployed, sub-100ms cold start.
- **Stateless MCP transport** — every request is independent; fresh `McpServer` + fresh `WebStandardStreamableHTTPServerTransport` per incoming POST (per the SDK's `_hasHandledRequest` contract).
- **`@modelcontextprotocol/sdk` 1.29+** with full `inputSchema` + `outputSchema` on every tool (Apps SDK requirement) and proper `destructiveHint` / `openWorldHint` annotations.
- **Zod 4** for schema validation. Tool implementations are pure functions that return MCP-shaped `{ content, structuredContent, _meta }`.

## Why stateless

In stateless mode, the MCP SDK requires a fresh `Server` + `Transport` per request — both because the transport can only handle one request (`_hasHandledRequest` flag) AND because a server can only be connected to one transport at a time. Tool registration is cheap (Zod schemas + JSON), so the trade-off favors correctness.

## License

Apache-2.0 — see [LICENSE](./LICENSE).