Tutor & MCP Apps prototype - #74649
Draft
breville wants to merge 6 commits into
Draft
Conversation
AI chat on the left teaches averages; the model drives three widgets on the right (bar chart, multiple choice, JS editor) over real MCP: each widget is an in-page MCP server advertising tools plus a ui:// HTML template per the MCP Apps extension, rendered in a sandboxed iframe speaking the spec's postMessage JSON-RPC. The host discovers everything from tools/list. Completions go through the AI gateway; tool calls are encoded via structured output since the gateway has no native tool API. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Found in browser testing: the shared widget CSP (script-src 'unsafe-inline') blocked new Function, so student code never ran. Only the code widget gets 'unsafe-eval'; the network stays blocked for all widgets. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Chart, then multiple choice, then the code editor, one interaction each; the mean-line chart replay moves to the wrap-up. The prompt now tells the model to advance after a single interaction per widget. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Live-model run produced starterCode with newlines flattened to spaces, which both wraps badly and breaks the code (a // comment swallows the rest of the line). The editor now scrolls horizontally instead of wrapping, and the tool description plus the interaction contract tell the model to encode line breaks as \n in argumentsJson. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
breville
marked this pull request as draft
August 14, 2026 17:17
user-select: none on the svg, and preventDefault when a drag grabs a bar so the browser never starts a selection that could extend into surrounding text. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The post-tool-call loop iteration existed so the model could retry a failed call, but it also let an eager model chain chart, question, and editor with no student input between them. Now a call that renders a widget breaks the loop; only failed calls (nothing on screen) get another model call within the cap. The interaction contract tells the model the turn ends there. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[written by Claude]
This adds a demo page at
/ai_tutorial_demo(signed-in users) exploring a new shape of guided lesson: an AI tutor chats with the student on the left, and brings up interactive activities on the right — a bar chart, a multiple-choice question, and a small code editor — deciding what to show and when based on what the student does. The lesson it teaches is how to calculate an average.The point of the demo is the architecture as much as the page. Each widget is a self-contained MCP server following the MCP Apps spec (the standard Anthropic and OpenAI ship for embedding interactive UI in AI hosts). The AI learns what widgets exist entirely from metadata the servers advertise, and the widgets report student actions back through the same protocol. The servers run in-page for the demo, but nothing about the page knows that — any of them could move behind a remote URL, which is the path to third parties building labs that plug into our tutor.
Example
Open the page signed in. The tutor greets you and puts up an editable bar chart, and asks you to eyeball the average. Drag a bar — the tutor sees the change and moves to a multiple-choice check. Answer it and the tutor opens a code editor with a starter
averagefunction. Press Run and the tutor reads your console output and responds. An "MCP activity" log at the bottom right shows the actual protocol traffic (tool discovery, template fetches, tool calls) for anyone curious about the plumbing.How it works
ui://HTML template. The page's host runtime discovers tools withtools/list, prefetches templates, and renders them in sandboxed iframes that speak the MCP Apps postMessage protocol. Student actions flow back asui/update-model-contextevents.sandbox="allow-scripts"and a no-network content-security policy. Student code in the editor widget executes inside that sandbox.Testing
test/unit/aiTutorialDemo/).🤖 Generated with Claude Code