Crafting experience...
6/12/2026
Built At
Progress x GitNation
Hosted By
GitNation
Talks & workshops by core teams and top engineers.
Conference attendees at multi-track events like JSNation and React Summit are constantly context-switching β checking schedules, figuring out what's happening now, deciding between parallel talks. The information exists in static web pages that don't meet you where you are. If you're already talking to an AI assistant, you shouldn't have to leave that conversation to look up what's next.
ConfPilot is an MCP server that brings live conference schedules directly into AI chat. Ask "what's next?" or "find talks about performance" and get an interactive, themed widget β not just text. It uses the MCP Apps extension (structured content + embedded UI) so the AI's response IS the conference app: filterable by track, with countdown timers and calendar links.
he architecture has three layers:
- Data layer: JSON files per conference (JSNation, React Summit) loaded at startup, merged and sorted chronologically
- MCP server Express + Streamable HTTP): exposes whats_next and search_schedule tools. Each tool returns both plain text (for the LLM) and structuredContent (for the widget)
- Widget React + KendoReact, bundled as a single HTML file via vite-plugin-singlefile): served as an MCP Apps resource. It connects to the host via the @modelcontextprotocol/ext-apps bridge, receives the structured payload, and renders themed session cards with live countdowns
- MCP Apps is brand new β documentation is minimal and the ext-apps SDK had undocumented behaviors (e.g. ontoolresult payload shape, openLink capability detection). Lots of trial and error reading the SDK source
directly.
- Theming across mixed results β when a search returns sessions from both conferences, each card needs its own theme (yellow for JSNation, green for React Summit) while the overall panel stays coherent. Solved by attaching conference metadata to each session and theming at the card level.
- Iframe sandbox constraints β external links (target="_blank") don't work inside sandboxed iframes. Had to implement the openLink host capability with window.open fallback.
- Single-file bundling β the widget must be a self-contained HTML file (no external assets) since it's served as an MCP resource. vite-plugin-singlefile handles this, but KendoReact's CSS is large (~270KB gzipped)
- Built a working MCP Apps implementation from scratch β one of the first projects using the new structured content + embedded UI pattern (SEP-1865)
- The widget feels native to the chat experience: dark themed, responsive, with live countdowns and Google Calendar integration
- Learned the full MCP stack end-to-end: server SDK, Streamable HTTP transport, resource serving, and the Apps extension bridge
- Populated realistic schedules for two real conferences (120+ sessions) with proper timezone handling
- Deploy publicly so the MCP server is accessible without a local tunnel
- Live data sync β pull schedules from the conference API instead of static JSON, enabling real-time updates (room changes, cancellations)
- Personal schedule β let users mark favorites and get proactive "your next talk starts in 10 minutes" notifications via MCP sampling
- Multi-conference support β generalize to any GitNation event or conference with a public API
- Speaker photos β fetch and display avatars in the widget instead of initial badges