RCS X · GPT App Strategy Hub · v0.1 · Strategy & Quick Wins

One product. Three surfaces.

RCS X is simultaneously the iOS app, the MCP server, and the ChatGPT app. ChatGPT becomes the conversational UI; the iOS app becomes the real-device renderer; the MCP server is the spine that keeps both in sync. This hub is the source of truth — strategy, design, impl, plan, and progress all live here.

Author Morsy Cheikhrouhou Hub rcsx-gpt-app.pages.dev Stack Cloudflare Workers · MCP · OpenAI Apps SDK Reference openai/openai-apps-sdk-examples Last update 2026-06-27
Hub Documents · Vision Architecture Anatomy Quick Wins Roadmap MCP Server Widget Distribution Risks Asks ● live

00 Documents linked from this hub

The hub is the index. Each card below is a real document we add over time. Today: Strategy & Quick Wins (this page). Future: implementation plan, design specs, progress dashboard, and any artifact that needs a public URL.

Live

Strategy & Quick Wins

Vision, architecture, RCS message anatomy, M0–M4 plan, the 5 QWs, risks, open asks.

This page · index.html
Soon

Implementation Plan

Sprint-by-sprint engineering plan: server, widget, auth, deploy, observability, cost model.

impl.html · target W2 of M0
Soon

Design Specs

Component library, iPhone-frame widget specs, theme tokens, UX principles for the ChatGPT surface.

design.html · target W1 of M0
Soon

Progress Dashboard

Live KPI panel: QWs shipped, MCP tools live, ChatGPT installs, paid-tier conversions, ARR.

progress.html · target M1 launch
Soon

Use Cases

Persona-driven scenarios: agency marketer, brand operator, dev integrating RCS, regulator reviewing.

usecases.html · target M1
Soon

Carrier Validation Reference

Validated against MNO RBM APIs. Country matrix. The moat: we are the only ChatGPT app that knows.

carriers.html · target M2
Soon

Brand & Marketing

RCS X app store listing, ChatGPT app store submission copy, landing page, social assets.

brand.html · target M1
Soon

API Reference

Auto-generated from the MCP server: every tool, every input schema, every output contract.

api.html · target M0 end

01 Vision

RCS is the carrier-grade successor to SMS. It's supported by every major MNO, runs natively on Android, and works on iPhone via the standard Messages app. But it has a discoverability problem: brand operators have to imagine what their message will look like before pressing send — and what gets rendered on iPhone vs Android vs carrier fallback can be wildly different.

RCS X solves this by making the entire message pipeline conversational. You tell ChatGPT what you want to send. ChatGPT calls our MCP server. Our MCP server returns a tool result that includes both the validation verdict and an interactive widget showing exactly how the message renders on an iPhone. You click "Send to device" and it pushes to the RCS X iOS app, which renders on a real device for one last proof. Then it ships.

Why now

OpenAI shipped the Apps SDK in 2025, standardized on MCP. Every ChatGPT install is now a potential install for our app. Distribution is solved for us.

The moat

Carrier-grade validation. RBM APIs vary by MNO. We are the only ChatGPT app that knows that +1-415 from AT&T resolves differently than the same number on T-Mobile.

Why a widget

A text-only ChatGPT tool result forces the model to describe the rendering. A widget shows it. Same information, 10× trust, 10× conversion to "Send."

Why three surfaces? ChatGPT owns discovery + authoring. iOS app owns real-device proof. MCP server owns the wire contract + validation logic. Each surface does one thing well. None of them owns the message — the MCP server does.

02 Architecture — the 3-surface view

The MCP server is the spine. ChatGPT and the iOS app are both clients. Both consume the same tools, see the same data, and render the same widget bundle. The server is the single source of truth for what an RCS message is and whether it will render correctly.

BACKEND · MCP SERVER RCS X MCP Server Cloudflare Worker · Streamable HTTP create_message drafts RCS payload preview_render returns widget HTML validate_carrier checks MNO rules send_to_emulator pushes to iOS app FRONTEND · CLIENT 1 ChatGPT Apps SDK · sandboxed iframe Model calls our MCP tools. Widget renders inline. Reads window.openai toolInput / toolOutput / theme FRONTEND · CLIENT 2 iOS App Syed's existing renderer Real-device iMessage proof. APNs push for low latency. Same widget bundle, native chrome. EXTERNAL · MNO RBM APIs Carrier Network AT&T · T-Mobile · Verizon O2 · Vodafone · Orange · Reliance Jio · 80+ MNOs PERSISTENCE D1 (SQLite at the edge) Messages · audit log · carrier rule cache · tenant KV: widget bundle cache WIDGET BUNDLE ui://rcsx/widget.html Served as embedded resource. Vite build · single HTML file with web component. MCP / Streamable HTTP _meta.ui.resourceUri MCP / WebSocket APNs push RBM / RCS Business Messaging embedded resource ChatGPT client iOS client MCP server External carrier Widget bundle

What the server is responsible for

03 Anatomy of an RCS message — the live widget preview

Below is a live render of what the ChatGPT widget will display when the model calls preview_render. The user sees this inside ChatGPT before sending, can edit the message, and clicks "Push to iPhone" to fire it into the iOS app for real-device proof.

9:41••• RCS
Today 9:41 AM
Hi! Acme Bank here. Did you get a chance to look at the rewards offer we sent?
card
View Offer
Save for Later
Tap a button above ⤴

What you see

  • Header bar — verified sender (Acme Bank), 9:41 timestamp, RCS badge indicating rich-message session.
  • Inbound bubble — the previous turn (gray, iMessage-style).
  • Outbound card — our message rendered: title, body, image, expiration, and 2 suggested reply buttons (View Offer / Save for Later).
  • Typing indicator — animates while the next message loads; this is the live "is the user going to tap a button?" wait state.

What the model sees

A structured tool result containing the RCS payload (recipient, type, media URL, suggested replies), the carrier verdict (PASS / WARN with reason), and the widget HTML returned inline. The widget is the visual proof; the JSON is the contract.

{
  "recipient": "+14155551234",
  "type": "rich_card",
  "body": "25x points on travel. Expires Sep 30.",
  "media": "https://cdn.rcsx.app/cards/travel.png",
  "suggested_replies": [
    { "label": "View Offer",     "postback": "VIEW_OFFER" },
    { "label": "Save for Later", "postback": "SAVE_LATER" }
  ],
  "validation": { "verdict": "PASS", "carrier": "T-Mobile US" }
}

04 Quick wins — 7 days from zero to ChatGPT-installable

The first week is just proving the wire works. We don't need to invent anything new — we need to copy the OpenAI reference patterns and stand up the minimum viable version of our specific use case.

QW1 · Days 1-2
QW2 · Days 3-5
QW3 · Day 6
QW4 · Day 7
QW5 · Week 2

QW1 · Fork & rename the reference M0

Clone pizzaz_server_node from openai/openai-apps-sdk-examples. Rename to rcsx_server_node. Replace the pizza tools with our 5 RCS tools (create_message, preview_render, validate_carrier, send_to_emulator, send_test). Working MCP server by Friday.

QW2 · Build the iMessage widget M0

Single HTML file with one web component. Left panel: input fields (recipient, body, media, replies). Right panel: an iPhone frame that renders the message live, exactly as you see in §03. ~300 lines of HTML + CSS + JS.

QW3 · Wire widget to MCP M0

Use window.openai.toolInput and toolOutput to pipe the form values into the tool call. The widget triggers callTool("create_message", {...}). Result lands in toolOutput, which the widget re-renders. End-to-end loop closes.

QW4 · ngrok + Loom demo Ship

Expose localhost:8000 via ngrok. Add the connector in ChatGPT developer mode. Record a 60-second Loom: "Ask ChatGPT to send an RCS, see the iPhone preview, click 'Push to iPhone,' watch the iOS app receive it." That's our launch video.

QW5 · Submit to ChatGPT Apps store Revenue

App submission flow: store listing, screenshots, description, privacy policy, App Submission Guidelines compliance. Once approved, every ChatGPT install is a potential install for us. Distribution is solved.

Out of scope (intentionally) Later

Carrier-validation moat (M2), paid tier (M3), iOS-app parity (M4). All real revenue work, all gated on M1 install base. Don't gold-plate QW1-QW4.

05 Roadmap — M0 to M4

Each milestone is independently shippable and verifiable. M0 is end-to-end. M1 is distribution. M2 is the moat. M3 is revenue. M4 closes the loop with the iOS app.

M0
Local end-to-end
Week 1

It works on localhost

M1
Public listing
Weeks 2-3

ChatGPT Apps store

M2
Carrier moat
Weeks 4-6

validate_carrier ships

M3
Paid tier
Weeks 7-10

Agency pricing live

M4
iOS parity
Weeks 11-14

One backend, two clients

M0 · Local end-to-end

QW1-QW4 done. Working app in ChatGPT developer mode. Loom published. Validation here: install + invoke + see widget + call tool successfully.

Gate: ngrok + ChatGPT dev mode + successful tool call + widget renders

M1 · Public listing

Submit to Apps SDK. Get listed in ChatGPT apps store + Codex plugin. First 100 installs. Marketing site & landing live.

Gate: OpenAI approves + 100 installs within 30 days

M2 · Carrier-validation moat

Add validate_carrier backed by real RBM API data. Country matrix. This is the only ChatGPT app that knows MNO rules.

Gate: 80+ carriers indexed + verdict accuracy > 95%

M3 · Paid tier for agencies

Per the Apps SDK monetization guide. Seat-based pricing for marketing teams. Pro tier unlocks carrier validation + bulk send.

Gate: $10k MRR within 90 days of paid tier GA

M4 · iOS app parity

Syed's app points at the same MCP server, not a parallel backend. One source of truth. iOS app becomes the mobile companion, not a separate product.

Gate: iOS app calls MCP tools directly + shared audit log

After M4

Internationalization (locale-aware rendering), B2B2C partnerships (carrier co-marketing), enterprise SSO + SOC 2, a developer tier for non-RCS messaging (WhatsApp Business, Viber).

TBD · revised post-M3

06 MCP server — the spine

The server is a single Cloudflare Worker that exposes MCP over Streamable HTTP. The Tools SDK handles protocol details; we focus on the RCS domain logic. Reference: openai/openai-apps-sdk-examples, pizzaz_server_node.

Tool surface (v1)

ToolInputOutputSide effects
create_messagerecipient, body, media URL, suggested repliesmessage_id, draft payload, validation hintswrites to D1
preview_rendermessage_idstructured payload + widget HTMLnone (read-only)
validate_carrierrecipient, messageverdict, carrier, warnings, suggestionscached in D1
send_to_emulatormessage_idemulator status, push tokenAPNs push to iOS app
send_testmessage_iddelivery receipt, MNO responsecalls RBM API (paid tier)

Why Cloudflare Workers

Server instructions (the model-facing prompt)

You are RCS X, an agent that helps users compose, preview, validate, and send
RCS Business Messaging. Always: (1) collect the recipient number, (2) draft
the message, (3) preview it in the widget before sending, (4) validate carrier
compatibility, (5) confirm with the user before send_to_emulator or send_test.
Never send a message without an explicit "yes" from the human. If carrier
validation returns WARN, surface the reason and propose an alternative.
Auth is the only non-trivial backend work. The Apps SDK supports OAuth. The iOS app uses APNs tokens. The model uses ChatGPT's connector auth. We need a single tenant model on day one, multi-tenant after M2.

07 The ChatGPT widget — what gets rendered inline

The widget is a single HTML file containing a web component. It lives at ui://rcsx/widget.html, served as an embedded resource by the MCP server with the right _meta["ui.resourceUri"] metadata. Inside ChatGPT, it renders in a sandboxed iframe and talks to the host via the window.openai bridge.

Anatomy of a widget call (what the model emits)

// tool call from the model
{
  "name": "preview_render",
  "arguments": { "message_id": "msg_8x2kq" }
}

// tool result from our server
{
  "content": [
    { "type": "text", "text": "Preview generated for T-Mobile US." }
  ],
  "_meta": {
    "ui": {
      "resourceUri": "ui://rcsx/widget.html",
      "title": "RCS preview · 25x points on travel"
    }
  }
}

// ChatGPT fetches ui://rcsx/widget.html, renders it in an iframe,
// wires window.openai = { toolInput, toolOutput, theme, displayMode, ... }
// The widget can then call callTool("send_to_emulator", {...}) to act.

What the widget reads & writes

Reads

  • window.openai.toolInput — model-passed args
  • window.openai.toolOutput — server response
  • window.openai.displayMode — inline / pip / fullscreen
  • window.openai.theme — light / dark, follow ChatGPT
  • window.openai.widgetState — persisted state

Writes

  • setWidgetState({...}) — persists across turns
  • callTool(name, args) — call another MCP tool
  • requestDisplayMode("fullscreen") — expand
  • openExternal(url) — open a link in new tab
  • sendFollowUpMessage(text) — nudge the model

UI components (v1 widget set)

ComponentPurposeWhere it appears
rcs-phone-frameiPhone mockup with status bar, notch, scrollable threadright panel of the widget
rcs-message-bubblein / out bubble, supports text + media + suggested repliesinside the phone frame
rcs-recipient-inputvalidated phone input with country codeleft panel of the widget
rcs-carrier-badgeshows the detected carrier + validation verdicttop of the widget
rcs-suggested-reply-editoradd/remove suggested reply buttonsleft panel, below body

08 Distribution — how it reaches users

Three channels, in order of leverage.

1. ChatGPT Apps store Primary

OpenAI's official discovery surface. Every ChatGPT install is a potential install for us. Submission is approval-gated, not self-serve, today. Once approved, we're listed next to the Apps SDK reference examples.

Approval: 2-6 weeks (per App submission guidelines)

2. Codex plugin Bonus

Every published Apps SDK app automatically becomes a Codex plugin. Developer audience: same ChatGPT account, IDE/CLI surface. Free distribution to a different persona.

Auto-generated on Apps store approval

3. MCP endpoint Devs

Our /mcp URL is publicly accessible. Any MCP-compatible client (Claude Desktop, Cursor, custom agents) can connect. We're the RCS transport for the agent internet, not just ChatGPT.

Self-serve · no approval

Why this is a 10× improvement over the X-token path

The X token revocation problem is now off the critical path. Distribution no longer depends on a working @rcsxPlatform auth token. ChatGPT is the discovery layer; we ship through them. The X account, if it ever works again, becomes a marketing surface for ChatGPT install CTAs — not a distribution bottleneck.

09 Risks & mitigations

RiskLikelihoodImpactMitigation
Apps SDK approval is slow / denied Medium High ChatGPT developer mode lets us ship and demo without approval. Iterate on UX, then submit. If denied, ship as a pure MCP server (path 3 above).
ChatGPT model doesn't call our tools reliably Medium Medium Server instructions encode the call order. Tool descriptions are explicit. Iterate tool descriptions based on real call logs.
iOS app contract not aligned with MCP Medium Medium QW1 is the proof: fork the reference, ship working in 2 days. If Syed's app needs a different transport, we adapt the server, not the widget.
Carrier validation data is incomplete or wrong Medium High Start with the 5 largest US MNOs (AT&T, T-Mobile, Verizon, Dish, US Cellular). Expand to top 25 international before claiming M2.
Widget iframe limitations (no localStorage, no third-party cookies, etc.) Low Medium Apps SDK runtime gives us widgetState and callTool for persistence. No need for localStorage in v1.
Cloudflare Workers pricing surprises (D1, KV, DO bandwidth) Low Low Workers free tier covers M0-M1. Set billing alerts at $20, $100, $500. Track per-tenant cost in D1.
OpenAI changes the Apps SDK protocol Low High Pin the SDK version, follow the changelog (/changelog). The Apps SDK is open MCP — even if OpenAI pivots, the server works with any MCP host.

10 Open asks — what we need to move

Three answers unblock QW1. Send them as a reply, we'll start the same day.

#AskWhyDefault if no answer
1 Repo location Where do I put rcsx_server_node? New GitHub repo under your personal org, or under RCS X's existing org? I'll create a new rcsx-platform/rcsx-server repo. You can move it later.
2 Deploy target Cloudflare Workers (my default, free, fast) — or do you have an existing RCS X backend I should hook into? Cloudflare Workers. We can bridge to Render or anywhere else via outbound HTTP if needed.
3 iPhone frame asset Do you have the iOS frame SVG/PNG from Syed's app, or should I use an open-source iPhone frame as placeholder? I'll use the open-source devices.css iPhone 15 frame until Syed ships one.
Bonus ask (not blocking): one 15-minute call with Syed in the next 2 weeks to confirm the iOS app's transport contract. We can ship the widget without it, but M4 parity will be faster if we align early.

11 Sources & references