Sealed Case for Alexa+
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Sealed Case for Alexa+Let's play Sealed Case and search behind the counter."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Sealed Case for Alexa+
A voice-only, one-player murder mystery served as a self-hosted MCP server. The AI game master runs the whole night, and it structurally cannot know who did it.
Built for the Amazon Developer Hackathon "Build, Ship, Shape", Alexa+ track.
Streamable HTTP · MCP protocol 2025-11-25 · Node (tested on 24) · MIT
The problem
We publish murder mystery scenarios. The biggest thing standing between a customer and a game they have already bought isn't price or quality. They have to get three to seven people free on the same evening, plus one more person who agrees to run the table and never gets to play.
The obvious fix is to let an AI be the game master. That doesn't work, and the reason is structural, not a matter of prompting:
If the script is in the model's context, the model knows who did it. Then it plays every suspect, judges every deduction and narrates every scene while knowing.
Anyone who has tried it has seen the model soften a guilty suspect's denial, steer the player toward the answer, or answer a question no character in the room could answer. You can't instruct that away, because the answer is already in the model's context.
Why MCP fixes it structurally
MCP lets the knowledge live somewhere the model cannot read. This server holds the case; the assistant holds the conversation. They meet at a tool boundary that the server controls.
The solution lives in one closure inside
engine.js, in the server process. No tool, resource, prompt or error message returns it.The tools expose only what a player standing in the room could learn: search a place, examine an object, question a suspect, review notes, accuse.
The verdict exists only after an accusation is committed.
accuseworks in two steps. The first call reads the accusation back to the player. Only a second call with the same three choices andconfirmed: true, made after the player says yes, is graded. There is no tool that grades without that.
So Alexa+ (or any MCP client) can call every tool in any order, as many times as it likes, and it ends up where the player is: holding evidence and reasoning it out. It is not following an instruction to keep a secret; the secret is simply not in anything it receives.
The tests check this mechanically instead of just saying it here (see Tests).
Built for voice
| Every tool result has a |
Verbatim material is separate | A suspect's reply ( |
Natural phrasing | Arguments take what the player said: |
Tool descriptions for speech | Each description lists the phrases it answers ("search the counter", "ask the owner where he was", "I accuse…") so a voice assistant picks the right tool. |
Forgiving misheard input | If the topic of a question can't be understood, it doesn't use up one of the eight questions. |
One game per session | State is keyed by |
Tools
Tool | What the player says | Notes |
| "Let's play Sealed Case." | Opening briefing; opens the investigation |
| "Who was there?" | |
| "Search behind the counter." | Counter, door, stairwell, coat rack, kitchen |
| "Look at the bottle." |
|
| "Ask the owner where he was." | 8 questions in total; reply in |
| "What do we know?" | |
| "How am I doing?" | |
| "How do I accuse?" | Culprit, method, motive choices |
| "It was the owner…" then "Yes." | Two-step; graded only when |
| "No, wait." | |
| "Tell me what happened." | Refuses until the case is solved |
| "Let me try again." | After a wrong accusation; notes are kept |
| "Start over." |
Also available: resource sealed-case://lantern-room/briefing (the public case file) and prompt play_sealed_case (game master instructions). Neither contains the solution.
Run it
git clone <this repository>
cd sealed-case-mcp
npm install
npm test # 13 tests, including the leak proofs
npm start # http://127.0.0.1:3000/mcpVariable | Default | |
|
| |
|
| On localhost, the SDK's DNS rebinding protection is on |
| (none) | Comma-separated Host header allowlist; set it when you bind to |
|
| Idle games are closed after this long |
|
|
Connect an MCP client
The endpoint is POST/GET/DELETE /mcp, using Streamable HTTP with sessions.
Scripted client (included):
npm run demoplays a short game againstMCP_URL(defaulthttp://127.0.0.1:3000/mcp) using the official SDK client and prints what the assistant would say.MCP Inspector:
npx @modelcontextprotocol/inspector, choose Streamable HTTP, URLhttp://127.0.0.1:3000/mcp. (We haven't tried this client ourselves.)Alexa+: Alexa+ needs to reach the server over HTTPS, so expose
/mcpat a public URL (a reverse proxy or tunnel in front ofnpm start, withHOST=0.0.0.0andALLOWED_HOSTS=<your hostname>), then register that URL as an MCP server following the Alexa+ track's connection instructions. We haven't yet tested it end to end against Alexa+ itself; the tests use the MCP SDK client.Any other MCP client that speaks Streamable HTTP works the same way. The server (MCP TypeScript SDK 1.30.1) answers with the protocol version the client requests if the SDK supports it, and otherwise with its latest,
2025-11-25. The SDK client requests2025-11-25.
Tests
npm test (which runs node --test) runs everything through the real server. The client side uses the SDK's own Client and StreamableHTTPClientTransport.
File | What it proves |
| Nothing reachable carries the solution before an accusation is committed. It is checked two ways. (1) Marker grep: every tool result, |
| Negotiated protocol is |
| Every result from every branch, scripted and randomised, has a |
Why the differential test and not just a grep for the culprit's name? The culprit is one of the three suspects, so the culprit's name correctly appears in the suspect list, the ledger and other people's testimony. Grepping for it proves nothing. We checked that the test catches real leaks by planting two. First, the engine was changed to list the culprit first among the accusation options, a leak that uses no solution text at all. The marker grep passed it, and the differential tests failed it. Second, hear_ending was allowed to answer before a verdict. All three seal tests failed.
What was built during the hackathon window (after 2026-08-31)
This project reuses the case and game engine from our earlier project Sealed Case (MIT, © 2026 Ai-Q Labs), a browser game built on WebMCP in August 2026. We're saying exactly what was reused so judges don't have to guess.
Reused
case/lantern-room.js: the scenario (provenance header added; the fictional publisher was renamed to Akeboshi so its name cannot be confused with a real company).engine.js: the game rules and the solution closure. One change:createEngine()now takes the case as a parameter, so each MCP session gets its own engine and the tests can swap in a different solution.The tool vocabulary is modeled on Sealed Case's WebMCP tools.
New for this hackathon
server.js: a self-hosted Streamable HTTP MCP server using the official SDK, with per-session games keyed byMcp-Session-Id, idle-session expiry and a session cap, and DNS rebinding protection on localhost. Sealed Case had no server at all; it ran entirely in a browser tab.mcp.js: an MCP tool surface redesigned for voice. The tools are organized around what a player says, the descriptions are written for tool selection from speech, and there are tool annotations, a resource and a prompt.game.js: the voice layer. It adds thespeechfield on every result, splits verbatim testimony and descriptions into separate fields, resolves natural phrasing to ids, groups objects into searchable places, and keeps misheard questions from costing anything.Committed accusations over MCP. In Sealed Case, the verdict came from a click in the web page. With voice there's no page, so the commit step became a read-back plus a spoken "yes" (
accusewithconfirmed: true), and the tests show one call can never both stage and grade an accusation.The solution now stays in a server process, where the browser version kept it in page memory. A client, an assistant, or a person with devtools gets only tool results.
All 13 tests, including the differential leak proof and the concurrency tests.
demo-client.js, this README, and the demo script below.
Demo script (under 3 minutes)
Record the terminal on its own, with no editor, file tree or browser chrome in the frame. First set a short prompt so no local path is ever on screen:
function prompt { "PS> " }Time | On screen | Say |
0:00–0:20 | Title card | "Murder mysteries need five people and a game master who never gets to play. An AI game master that reads the script knows the answer. Sealed Case fixes that with MCP." |
0:20–0:40 |
| "Thirteen tests. The key one replays every call against a copy of the case with a different culprit. Before you accuse, every response is byte-identical, so nothing the assistant hears depends on who did it." |
0:40–0:50 |
| "This is a self-hosted MCP server over Streamable HTTP, protocol 2025-11-25." |
0:50–2:20 |
| Read the PLAYER lines aloud as the player. Point out: the |
2:20–2:45 | Scroll to the | "The assistant can gather evidence and repeat my accusation back to me. Only my yes commits it. It never knew the answer, so it couldn't have steered me toward it." |
2:45–2:55 | Closing card | "Sealed Case for Alexa+. One player, by voice, with a game master who doesn't know the ending." |
Files
File | |
| Entry point. Express + |
| Tools, resource and prompt. |
| Voice layer: |
| Game rules; the solution closure. (Reused, see above.) |
| The scenario. The only place the solution exists. (Reused.) |
| Scripted player using the SDK client. |
|
|
The scenario is original and entirely fictional. Every person, publisher, magazine and establishment in it is invented.
License
MIT, © 2026 Ai-Q Labs. See LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Generate game-ready 3D models, textures, and audio from natural language, over MCP.
AI voice generation: text-to-speech and voice cloning from any MCP client.
Hosted MCP server connecting claude.ai, ChatGPT and other AI apps to your own computer
Official remote MCP server for Archivist AI TTRPG campaign memory: characters, sessions, and more.