Inspiration
Spotlight already had the hard problem solved on paper: a "Must Watch" graph in Postgres that knows the correct order to watch a franchise in, and a private per-user watch history behind real auth. But that data was only reachable by clicking through the UI yourself. Ask any AI assistant "what order should I watch John Wick in?" and it answers from memory - no idea what you've actually seen, no way to act on the answer. WebMCP looked like the first real answer to that gap: instead of an agent scraping a rendered page or a separate backend replicating the app's auth, the tools just live inside the page's own already-authenticated session.
What it does
Spotlight registers 9 tools via document.modelContext.registerTool() on top of an app that already tracks streaming and theatrical releases, watchlists, and watch order for movies and shows. The flagship, plan_watch_order, reads the real "Must Watch" graph, cross-references what you've actually watched, and writes only the remaining titles into your real watchlist in the correct order - run it again after finishing a title and it correctly says there's nothing left to add. Two of the tools, mark_watched and reorder_watchlist, don't exist until they'd do something real: they register and unregister themselves live via toolchange as your watchlist's own shape changes. To prove the tool surface is genuinely agent-legible and not just spec-compliant, we also built an in-page chat panel (bring-your-own API key, Groq by default) where a real LLM reads the tool schemas with getTools() and drives them with executeTool() from plain English.
How we built it
React + TypeScript on the frontend, Postgres (Neon) for the release calendar, watchlists, and the watch-order graph, Vercel serverless functions for the API, and a GitHub Actions pipeline that refreshes release data from TMDB on a schedule. The WebMCP layer lives entirely in src/webmcp/: every tool wraps the exact same client-side functions the UI's own buttons already call, so there's no parallel "agent" backend and no duplicated logic.
Challenges we ran into
Chrome's experimental WebMCP flag expects executeTool()'s arguments as a JSON string, not the plain object the spec's own examples show - a real divergence we only found by testing. We also discovered no shipping agent (ChatGPT's desktop app, its Computer-Use mode, Codex) actually routes through document.modelContext yet; all of them fall back to generic DOM automation, which is exactly why we built the in-page chat panel instead of just asking an existing assistant to try it. On the infrastructure side: Vercel's Hobby plan caps you at 12 serverless functions, so guest sign-in had to extend an existing endpoint rather than ship as a new file, and none of OpenAI's, Azure's, or Groq's APIs set CORS headers for browser calls, which meant building a stateless same-origin relay just to let the chat panel talk to an LLM at all.
Accomplishments that we're proud of
Getting a real language model to call get_watch_order and then plan_watch_order on its own, unscripted, and watching four films land in a real account's watchlist in the correct order - live, not mocked. And handling the "no agent uses this yet" problem honestly instead of hiding it: we verified the gap directly, documented it, and built the one thing that actually demonstrates the tools are ready for when an agent does.
What we learned
How much of "making an app agent-ready" is really about discipline in the app's own code, not the WebMCP API itself - every tool only stayed simple because it called the same functions the UI already trusted. We also learned firsthand how far ahead the spec is of the ecosystem actually consuming it right now.
What's next for Spotlight
Once a shipping assistant actually calls document.modelContext on its own, Spotlight's tools are already sitting there waiting - no work required on our end. Beyond that: correct_watch_order already lets a user tell their agent "that link is wrong," which is the seed of letting an agent help curate the underlying graph itself, not just consume it.
Built With
- github-actions
- groq
- neon
- node.js
- postgresql
- react
- react-query
- tmdb-api
- typescript
- vercel
- vite
- webmcp
Log in or sign up for Devpost to join the conversation.