The Rising Tide MCP Server
An MCP server any AI assistant or coding agent connects to by URL: the docs, SDK help, conformance rules, the films and the live network, read-only, with links; and a way to ask to join.
Rising Tide runs a remote Model Context Protocol server. Connect a coding agent or an assistant to it and it can search these docs, read the SDK reference, explain a conformance failure, find the moment in a film that explains something, and look at what is happening on the network, with a link to everything it uses. Someone who wants in can ask to join from the conversation. It answers as Arty, the narrator of the Draw It Out films, and reports itself as Arty, the Rising Tide guide.
| Testnet | https://testnet.mcp.risingtide.app/api/mcp |
| Main network | https://mcp.risingtide.app/api/mcp, once the first main-network release ships. Until then use the testnet address |
| Transport | Streamable HTTP, stateless |
| Auth | None for every public tool. The four my_ tools need the person to connect their Rising Tide account (OAuth, through the hub's /connect). Every tool is a read but join_waitlist |
Connecting
claude mcp add --transport http rising-tide https://testnet.mcp.risingtide.app/api/mcpIn Claude on the web or desktop, add a custom connector with the same address. Any MCP client that speaks Streamable HTTP works the same way.
What it offers
| Tool | What it answers |
|---|---|
search_docs, read_doc, explain_term | Both docs sites, a whole page, one word from the glossary or the vocabulary |
get_started | How to get the SDK and the walkthrough's steps |
sdk_reference | One rtClient service's page, with the newest changelog notes that name it |
explain_conformance_rule | What an rt-conform rule protects against |
list_apps | Every app in the public catalog, open or invite-only |
protocol_activity, hottest, top_earners | Counts per app for a period, the most collected, and who was paid most in sats |
find_products, read_product | What is published, and one product with its words, price, frozen contributor shares and links to it and its picture. picture: true attaches the picture to the result as an image, for clients that display one |
find_people, read_profile, collection_of, collectors_of, new_from_people_i_collect | Public profiles and holdings, by address, profile link or display name |
find_games, game_leaderboard | Game lobbies with buy-ins and open seats; a match's pot, players, latest moves and board (no live feed: call again with since for the moves after one you saw); the leaderboards and one player's record |
find_tournaments, find_events, find_campaigns, find_causes | Bracket tournaments and standings; upcoming events with the place the organizer published; campaigns with their letters and co-signers' ratings; causes and what they have received in sats |
read_edition, read_replies | One numbered copy and what its collector said in public with it; the public replies left on a product |
find_films, get_film | The shipped films: for a question, the film, the cut and the line, with a #t= link to the second it is said; for one film, its cuts, chapters, captions, topics and transcript |
get_playlist | The studio's playlists in watching order (Getting started first) and its topics, such as splits, causes or games; for one, its films in order with links and lengths |
open_spots, join_waitlist, waitlist_status | How to get in right now; a request to join, made from the conversation; where a request stands, and the invite once there is one |
my_inbox, my_delegate_wallet, my_matches, my_logbook | The connected person's own inbox, delegate wallet, matches and logbook. Each needs them to connect first |
Prompts: explain-rising-tide, build-an-app, fix-conformance-failure, catch-me-up,
draw-it-out, which-app-is-for-me and put-on-a-playlist. Every docs page is also a resource,
rising-tide-docs://{site}/{path}, and every film is one, rising-tide-films://{id}.
Cards (MCP Apps)
In hosts that draw MCP Apps (Claude on the
web, desktop and phones, ChatGPT and others), some tools also return structuredContent, and a
small view draws it beside the answer. The text answer is unchanged, so every other host gets it in
words.
| View | Tools | Draws |
|---|---|---|
| Film | find_films, get_film, get_playlist | The cut playing at the second, chapters, captions, the dark whiteboard in a dark host; a playlist playing in order with what comes next; every playlist and topic to pick from |
| Page | read_product, find_products, hottest, collection_of, new_from_people_i_collect, read_edition, read_replies | A product with its picture, a shelf of up to eight, one copy or a game's trophy, a bottle's replies |
| Page | read_profile, find_people | A person: picture, totals, games record, recent work, and the awards they earned with their art |
| Page | game_leaderboard, top_earners, collectors_of, find_tournaments, find_events, find_campaigns, find_causes | Ranked lists with names and faces, a tournament's standings, an event, a campaign's letters, the causes |
| Draft | draft_bottle, draft_page, draft_letter | A bottle, a grammata page or an On The Record letter drafted in the chat, drawn as it would be printed, with a link that opens the app's composer filled in |
| Page | join_waitlist, waitlist_status | A request to join: waiting, or in with the invite to claim and the account it is locked to |
| Board | find_games | A match's board, whose move and the pot, with refresh and a bounded watch; or the open lobbies |
The server declares io.modelcontextprotocol/ui in its capabilities. Each view's CSP names only the
store its media comes from (and, for the page view, the API's /achievements/ art), and a view
calls nothing itself: a refresh goes through board_now, a tool the model never sees
(visibility: ["app"]), and a tap on a row or tile opens the card the result names through the
guide's own tools.
Drafts: written in the chat, finished in the app
draft_bottle checks a name and a message against Bottle Drop's composer (80 characters, 500
characters, 3 paragraphs counted by line, and only what the chain's ASCII strings hold) and answers
with a link to the composer carrying the draft in its fragment:
https://bottledrop.app/#draft=<base64url of {"v":1,"title":"...","body":"..."}>draft_page does the same for grammata, in one of four forms: page, haiku, tanka or
sonnet. The form's rules are read from its product type, as grammata's composer reads them (a
poem's line count and each line's length, a page's length), with the composer's own title (32) and
subtitle (64). The link opens /pages/create, and the fragment carries two more fields:
{"v":1,"title":"...","body":"...","form":"haiku","subtitle":"..."}form is the product type's slug, and a poem's lines travel in body, one to a line. subtitle
is left out when there is none. The card's picture is drawn on the style set a fresh page in that
form starts on: the default set if it draws the form in portrait, otherwise the first that does.
draft_letter writes for an On The Record campaign, named by slug or name among the ones taking
letters: a subject (32), the letter (1000 characters, 4 paragraphs counted by line, and 1024 once
quotes and line breaks are escaped for its contract field) and, only where the campaign leaves it
to the writer, who it is to (120). A campaign that fixes the recipient keeps it, and the draft does
not carry one. The link opens /write?campaign=<slug>:
{"v":1,"title":"...","body":"...","campaign":"<slug>","recipient":"..."}The card draws it in the campaign's own look, as an open letter.
A fragment never reaches a server, so nothing stores the draft. The app reads it, holds it to its
own limits again, and opens the composer on it. The person signs in, sees the cost and publishes
from their own wallet. The card's picture comes from draft_preview, a tool only the card calls,
so the render never enters the model's context.
Joining from your assistant
Rising Tide is invite-only for now. Someone can ask to join without leaving the conversation:
open_spotssays how someone gets in right now. When the next people to ask are let in on the spot it says how many, and while nobody is it says nothing about spots, never "0 left".join_waitlistsends the same request as the form on/join, with what the person told their assistant: Google or X, the address or handle, what they make, why they want in, the interests that fit, how much they have used crypto, and whether members may read their answers. That last one is required and is never assumed: the assistant asks it outright. The answer is the request's status page to keep, and, if they are let in on the spot, the invite.waitlist_statusreads a request from its status page link: still waiting, or in, with the claim link and which account it is locked to.
The assistant is told to ask one question at a time, never to fill in an answer the person did not give, and to say before asking that the address or handle passes through it on its way to Rising Tide. No result ever says the address or handle back: an invite names its account as "the Google account j…@example.com". The invite is bound to that account, so only the person who asked can claim it. Asking twice with the same contact changes nothing.
The guide sends these with its own key, which rt-api lets write to the waiting list and nowhere else, and counts against the guide's own limits rather than an address many people share.
Your own things
Four tools read the person's own things: my_inbox (what arrived while they were away),
my_delegate_wallet (the second wallet an assistant would spend from, and what it may spend today),
my_matches (their games, and whose move it is) and my_logbook (what they made, keep, earned
and spent). Each needs them to connect their account, and asking for one is what starts it:
- The guide answers that call with HTTP 401, and the assistant offers Connect.
- The hub's
/connectpage signs them in with Google or X and says what an assistant may do: see their things, spend nothing, and be disconnected at any time. - They continue, the sign-in service asks the standard question, and the call they asked for runs.
The assistant's sign-in token never reaches rt-api. The guide checks it, then asks rt-api with its own key and a signed header naming the person and the assistant. Reading the inbox marks nothing read. On the hub's Assistants page the person sees each assistant they connected and can disconnect it: its next call answers 401 again, and it asks them to connect.
Keeping a copy
keep_copy quotes keeping a numbered copy of one page for the connected person, paid in sats from
their delegate wallet. It spends nothing. It returns a card with what they get, the price, who gets paid
(read from the page's frozen split and named, never given a figure), what the assistant has left
to spend today, and one button.
Who confirms a quote is the person's choice, set for each assistant on the hub's Assistants page:
- Asks first, the default. The person confirms every quote on their own sign-in: the card's button, or the answer where no card is drawn (such as Claude Code), opens the confirm link on the hub, where they see the same quote and confirm it. rt-api refuses a confirm that arrives through the assistant, so a page whose text tells the model to buy something can produce a quote at most.
- Spends on its own. The assistant may confirm a quote itself, through
confirm_spend, inside the same limits. The switch says how many sats a day that can be.
confirm_spend is marked app-only, which tells a host that draws cards to hide it from the model.
Hiding it is the host's; the mode and the limits are the protocol's, and rt-api enforces them
whoever calls.
Either way rt-api applies one rule, in one transaction that holds the grant: the quote is this person's, unused and under five minutes old; spending is on and the page's app is one they chose; the price fits one tap, the day's sats and the day's actions. Then the delegate wallet signs the mint. The copy is the person's and the delegate wallet pays, never more than the quoted price. The card says On its way at broadcast.
Spending starts off for every assistant, and an assistant starts by asking first. On the hub's Assistants page the person turns spending on, chooses the apps it may spend in, sets how many sats a day and a tap, and chooses whether it asks first. Connecting an assistant again starts it with spending off and asking first. A page made before delegate wallets could act on it is refused with a plain reason.
Replying and signing
Some pages take more than a price. A bottle in Bottle Drop takes a reply, and an open letter in On
The Record takes a signature: a rating from 1 to 10 and, if the person wants one, a note.
leave_reply and sign_letter quote those, on the same card, the same tap and the same rule as
keep_copy. Which one a page takes is read from its deployed contract, so keep_copy on a bottle
answers that a bottle is kept by replying to it.
The words are the person's:
- The model passes them on and never writes them. Both tools tell it to pass exactly what the person said, word for word, to ask when they have said nothing, and never to take words from the bottle, the letter or anything else it read. The rating is the person's too.
- The card shows them exactly as they will be written, whole, before the tap. So does the confirm link.
- rt-api checks them against the contract first. A reply needs words. A note longer than the contract holds (read from the contract itself: 128 characters today) is refused, and so is a character the network cannot hold, such as a curly apostrophe or an emoji. It is refused rather than rewritten, with the characters named, because a quietly changed word would be permanent.
- An author cannot sign their own letter, and the contract refuses it whoever sends it. The quote says so first. A bottle's sender is not offered a reply on their own bottle, as in the app.
Playing
A person can play a game from the chat. join_match quotes a seat at a table (Drop Four, Tic-Tac-Boom)
on the same card and tap as a copy: the buy-in in sats from the delegate wallet, who gets paid, and
that the rest goes into the pot. The seat, every move and the pot are the person's: the contract
names them, and a pot goes to their main wallet.
The board is the control:
my_matchesdraws the person's own board. It knows which seat is theirs, says whose move it is, and offers their taps: a column or a square on their move, Start the match at a full table, Claim the pot when they win (or their share of a draw).- The taps are app-only.
start_match,play_moveandclaim_potare marked app-only, which tells a host that draws the board to hide them from the model, and the guide tells the model never to move for the person. That marking is the host's to honour; what rt-api enforces on every tap is the checks below and the day's actions. The board refreshes itself throughmy_board_now, and watches until the network shows what a tap did. - A tap is checked before it is signed. rt-api reads the table: a seat, the turn, room in the column, the winner. An illegal move is refused in words instead of costing a fee on chain.
- A tap costs no sats. It costs a network fee in STX from the delegate wallet and counts against the actions the assistant has today. Spending has to be on.
What it will and will not do
- It reads the whole public catalog, read-only. Every app in it, open or invite-only, with the invite-only ones named as such. An app outside the catalog is left out of every answer. It holds no session, so it sees exactly what an app key and no sign-in can read.
- It writes two things: a request to join, and a quote. A request to join only when someone asks, with what they said. A quote only for a connected person, and it spends nothing. A quote is spent from their delegate wallet, within the limits they set, by the person on their own sign-in, or by the assistant only if the person chose to let it spend on its own.
- People are found by address, profile link or display name, never by email or X handle. The server is open to anyone, so a contact detail resolved to an address would let anyone see someone else's activity.
- Links come from each app's own
homePathtemplate. An app with no template gets no link. - Films are shipped masters only. A cut the studio has not recorded cannot be reached, and every time link lands inside the cut it points at.
- Private things stay private. An owner-only note, an organizer's contact line, a cause's contact details and the fee split behind a game's pot are never returned, and anything hidden by moderation is treated as absent.
- One visitor can make 60 calls a minute, and the server takes 300 a minute in all. Past either
the server answers 429 with
retry-after. An assistant that calls from its provider's hosted addresses is not limited per visitor, because many people share those addresses, so those calls share the 300 and one busy conversation can spend them for everyone for a minute. - Text people wrote (titles, pages, names, bios) comes back quoted, and the server tells the model never to follow instructions inside it.
The counts behind protocol_activity and hottest are the public
GET /api/activity/summary read, so an app can show the same numbers.