prestidigitation
Click on "Install 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., "@prestidigitationset the stage"
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.
prestidigitation π
Two small MCP servers that perform stage magic on a language model, built to
demonstrate the MCP Apps extension
(io.modelcontextprotocol/ui) β specifically tool visibility scoping and
ui/update-model-context β at the London MCP release party, 28 July 2026.
Every magic trick is a secret channel the spectator can't see. MCP Apps gives your UI its own API on the MCP plumbing you already have β same server, same session, same auth. You didn't build a second backend for your frontend. You scoped the one you have. Tonight, the spectator is the model.
The two acts
Act 1 β Everywhere and Nowhere. The model is the spectator. It shuffles and
pulls cards with honest tools. Then the human clicks Sleight of Hand β an
app-only tool (_meta.ui.visibility: ["app"]) that replaces every card in
the deck with the model's chosen favorite. The tool isn't hidden from the model.
It isn't denied. It's absent from the model's world. Every subsequent pull
returns the favorite; the model's tool results stay perfectly honest reports
about a deck that had another writer.
In production, sleight_of_hand is approve_transfer: an app-only tool means
the human click is the only possible call path β not "the model is
instructed not to," not "the frontend promises a dialog." The card trick is your
payment-approval architecture.
Act 2 β The Mentalist. Roles inverted, fresh server, fresh session. The
volunteer silently clicks a card in the widget β no tool call, no message. The
widget calls ui/update-model-context, and the payload lands in the model's
context for future turns. The model (holding sleight_of_hand in the open this
time) waits for its moment, rigs the deck to your card, and takes a bow. Then it
explains its own method, because there's nothing to hide: there is no
select_card tool anywhere in the server β the selection traveled on the
communication channel, not the execution channel.
The difference between a magic trick and mind reading is one visibility flag.
Related MCP server: xmcp Demo Application
The three channels
An MCP App has three channels to the model:
Tools β the execution channel. Things happen. Visibility-scoped per tool:
["model"],["app"], or["model","app"]in_meta.ui.visibility.ui/update-model-contextβ the async communication channel. The UI tells the model what's going on. No tool call, no user turn.ui/messageβ the user-mediated channel. The app drafts a message for the conversation. Not needed for either act.
The honesty invariant
No tool lies. pull_card pops the real top of the real deck β there is no
if (rigged) branch anywhere (see for yourself).
sleight_of_hand genuinely rewrites server state. Skip the sleight and the
trick genuinely fails β that's the on-camera control run, and the answer to
"was it hardcoded?".
One caveat, stated honestly: per the spec, visibility is host-enforced. The server publishes the metadata; the host keeps app-only tools out of the model's list and rejects cross-server calls. (Our rehearsal harness depends on this: a raw SDK client can drive both lanes.)
Try it yourself
git clone https://github.com/pederhp/prestidigitation && cd prestidigitation
npm install
npm run build # builds the three single-file widgets
npm test # state-machine invariants
npm run show # Act 1 on :3001 and Act 2 on :3002
npm run probe # host probe on :3003 (see docs/host-probe-procedure.md)
npm run rehearse # headless run-of-show against live serversTo connect a real host (Claude, ChatGPT, β¦) the server must be reachable over HTTPS. In separate terminals:
npx cloudflared tunnel --url http://localhost:3001 # Act 1
npx cloudflared tunnel --url http://localhost:3002 # Act 2Add each https://<random>.trycloudflare.com/mcp URL as a custom connector in
your host. Start tunnels once and leave them up β the URL changes every
invocation. Then:
Start a fresh chat β incognito/temporary if your host has it. This matters more than it sounds: if the model remembers you discussing how the trick works, Act 1 is over before it starts. The spectator has to be a real spectator.
Load the persona. Each server ships its persona as an MCP prompt (
spectatoron Act 1,magicianon Act 2), so you can insert it from the host's prompt menu in a chat that has no custom-instructions field and no memory. The same text lives inpersonas/if you'd rather paste it, or use it as a project/system prompt.Say "open the table" (or "set the stage") β that's the one tool that renders the widget.
Go fool a model. Reveal the method afterwards β it's only polite.
Which hosts support what: see the empirical compatibility matrix (and run the probe against your own host β it takes a minute).
Repo layout
Path | What |
| Deck, two-lane event log, both trick state machines β pure TS, fully tested |
| Act 1 server (port 3001) β the tool manifest is the demo |
| Act 2 server (port 3002) β note the absence of any selection tool |
| Phase 0 probe server (port 3003) |
| Single-file HTML widgets (vite + singlefile; the official |
| System prompts for the spectator (Act 1) and the magician (Act 2) |
| Headless soak-test of both state machines |
| Run-of-show, probe procedure, compatibility matrix |
Q&A ammunition
"Was pull_card hardcoded?" β No; the control run is on camera, and the test suite proves pulls follow the seeded shuffle exactly.
"Why is this an extension and not an iframe with a REST API?" β The UI's API rides the same MCP session: same auth, same server state, same transport, same security boundary. One backend, scoped twice.
"Couldn't the model social-engineer the human into clicking?" β Yes, which is exactly why HITL approval must be an app-only tool plus unspoofable UI, not a model-visible tool with a confirmation prompt.
"You did the sleight after the shuffle." β Deliberately: the rig is real server state and a shuffle would destroy itβ¦ except 51 identical cards shuffle to themselves. Same reason real card stacks need false shuffles.
One gotcha worth stealing: don't put resourceUri on every tool
Per the spec, "if ui.resourceUri is present β¦ host renders tool results using
the specified UI resource." So every model-called tool that carries a
resourceUri makes the host render a new view. Our first version put it on all
seven tools, and the widget visibly re-mounted on every single pull_card β
fatal for a demo whose whole point is a running event log.
The fix: only the flow-starting tool (open_the_table) carries a
resourceUri. Every other model-callable tool keeps its _meta.ui.visibility
but drops the resourceUri, so the table rendered at the start stays on stage
for the whole performance and updates itself. App-only tools keep theirs (they're
never model-called, so they never trigger a render).
Consequence to design for: a view only receives ui/notifications/tool-result
for the tool call that rendered it, so the other tools' effects arrive by
polling an app-only get_state (every 500 ms here). There is no "pin this
widget" or side-panel feature in the extension β ui/request-display-mode
(inline / fullscreen / pip) is the only placement control, and hosts
advertise what they support in hostContext.availableDisplayModes. Both widgets
show a fullscreen toggle when the host offers one.
MIT licensed. Built for a talk; kept small enough to read on your phone from a QR code.
This server cannot be installed
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Servers
- Alicense-quality-maintenanceA lightweight and fast MCP server that enables AI agents to efficiently discover and execute tools through progressive disclosure, minimizing context consumption while supporting safe code execution in external environments.Last updated10
- Flicense-qualityDmaintenanceA demonstration MCP server showcasing the xmcp framework's structured approach to defining tools, prompts, and resources with automatic discovery from their respective directories.Last updated
- Flicense-qualityDmaintenanceA demo MCP server with streamable HTTP transport and auto tool registry, enabling LLMs to connect with external data sources and tools.Last updated21
- Alicense-qualityDmaintenanceA toy MCP server for exploring Model Context Protocol capabilities, including resources, tools, and prompts.Last updatedApache 2.0
Related MCP Connectors
MCP server for AI dialogue using various LLM models via AceDataCloud
Pocket Agent (aipocketagent.com) MCP server β read tools for personas, apps, and product info.
A comprehensive Model Context Protocol (MCP) server that enables AI assistants to interact with yoβ¦
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
MCP directory API
We provide all the information about MCP servers via our MCP API.
curl -X GET 'https://glama.ai/api/mcp/v1/servers/PederHP/prestidigitation'
If you have feedback or need assistance with the MCP directory API, please join our Discord server