Inspiration

Interactive fiction is most exciting when players can try anything, but its most memorable mysteries still depend on deliberate reveals and consequences. Players should not have to choose between a rigid action menu and an AI story that can improvise past the clues that make discovery matter.

We wanted each discovery in the story to become a new capability for the agent. WebMCP made that relationship explicit and inspectable.

What it does

Once Upon is a living manuscript played through natural-language actions. Each player action becomes the next chapter on the page, while authored discoveries open new ways to interact with the story.

The first release centers on one complete authored mystery, The Last Manuscript. It begins in a correction room with a handleless door. Finding a pencil, following a memory, and reading a hidden manuscript do more than change the prose: each discovery gives the agent a new WebMCP action through the page. There are no character sheets, dice, fixed choices, or turn limits.

Why it matters

Most websites present a fixed interface and leave agents to guess how to operate it. Purely generated stories have the opposite problem: they can respond to anything, but they struggle to protect a carefully timed mystery. Once Upon uses WebMCP to connect free-form play with authored causality.

The human supplies intent and makes every meaningful choice. The agent turns those choices into a responsive narrative. The page protects secrets, commits consequences, and reveals new structured verbs when the story earns them. None of the three participants can create the complete experience alone.

This turns agent capability into a visible narrative mechanic rather than a hidden automation layer. The result is an agent-native experience that would be difficult to build reliably through UI guessing, DOM scraping, or an unconstrained model prompt.

How it works

The running product does not call a hosted model or require a specific provider. It works with whichever WebMCP-capable agent is already accompanying the player, so there is no app-owned model API key or provider lock-in.

Before every turn, the agent reads the page's structured story state. It then uses a currently allowed action and commits one to three short paragraphs back to the manuscript. The page types the chapter at reading speed, and the agent leaves the prose on the page instead of repeating it in chat.

Three stable core tools coordinate the story. Story-object tools are registered only after authored prerequisites are satisfied, remain registered until used, and retire after their one-shot interaction. Using an object changes the page before the next chapter is written; that commit must reference the same effect and every fact it revealed.

The page — not the model — owns session state, revision checks, authored discoveries, sealed facts, interaction rules, and completion order. Every mutation checks the active session and revision, while operation IDs make same-page retries idempotent. The agent remains free to improvise characters and consequences without inventing executable tools or revealing protected facts early.

Gameplay state remains in the current page and is not uploaded during play. After finishing the story, the player may explicitly create an anonymous, unlisted, read-only manuscript link. Only that completed reader copy is stored as story content, and it expires after 30 days.

How we built it

Codex was the primary coding agent throughout the project. It helped inspect and refactor the repository, shape the WebMCP protocol, implement the narrative state machine and interface, turn runtime edge cases into validation rules, add regression tests, and prepare the deployment. Claude Code was also used as a supporting coding tool during development.

Architecture

Once Upon is a TypeScript application built with React 19 and Vinext, deployed on ChatGPT Sites through a Cloudflare Workers-compatible runtime. The in-memory story engine owns narrative state and validation; the WebMCP bridge derives the live tool surface from that state; and Cloudflare D1 stores only completed manuscripts that a player explicitly chooses to share.

Testing

No account, API key, or credentials are required. Playing requires ChatGPT's in-app browser with an agent attached, or Google Chrome with WebMCP enabled.

  1. Open the public demo in a supported browser with an agent attached.
  2. Ask: “Play The Last Manuscript with me through this page. I look around the room before answering the speaker.”
  3. Verify that the player's move appears on the sheet and that the committed chapter is typed at reading speed instead of repeated in chat.
  4. Continue choosing actions. When a story object becomes available, explicitly ask the agent to use it and verify that the page changes before the next chapter is written.
  5. Enable Settings → Tool inspector to inspect the active tools and the prerequisites, registration, invocation, and retirement lifecycle.
  6. Choose Start over or reload to confirm that a fresh manuscript begins at the prologue.
  7. Follow the Pencil → Memory → Last Manuscript progression. After completion, choose Create a link to open the anonymous, read-only manuscript reader; the link expires after 30 days.

The repository passes strict TypeScript checks, linting, the Drizzle schema check, 90 unit tests, a production build, and 22 Playwright end-to-end tests.

Challenges and accomplishments

The hardest part was keeping free-form narration and authored causality in sync. The player can attempt anything, but an agent still has to recover cleanly from an interrupted turn, avoid revealing a secret early, and finish the exact page change caused by a story object.

We turned stale sessions, duplicate operations, interrupted turns, premature discoveries, and early completion into explicit validation rules and regression tests. The finished experience keeps the player's action, the agent's prose, and the page's evolving capabilities synchronized and inspectable from the prologue through the final passage.

What's next

More stories can be added through the same declarative experience definitions. Next, we want manuscripts to persist across visits. We also plan to expand agent compatibility testing from the evaluation scenarios already documented in the repository.

Built With

  • chatgpt-sites
  • claude-code
  • cloudflare-d1
  • cloudflare-workers
  • codex
  • drizzle-orm
  • playwright
  • react
  • typescript
  • vinext
  • vitest
  • webmcp
Share this project:

Updates

Submission history