AI Engineer Europe 2026
Building Interactive UIs in VS Code with MCP Apps — Marlene Mhangami & Liam Hampton, GitHub
Read the talk
Building interactive MCP Apps inside VS Code
Follow a text-only diagram request toward an interactive chat UI, then trace a Go profiling app through its MCP tool, HTML resource, React frontend, and sandboxed host.
From a talk by Marlene Mhangami and Liam Hampton
Before you start: Basic familiarity with chat assistants, server tools, and frontend development will help; the article introduces MCP’s core roles.
What would it take to put an interface inside chat?
How can a chat response become an interface you can actually use? Marlene Mhangami and Liam Hampton approach that question through MCP Apps, moving from the protocol’s basic roles to a working profiler inside VS Code. Mhangami introduces herself as a senior developer advocate at Microsoft and GitHub; Hampton works on developer tools advocacy for VS Code and GitHub Copilot.
Model Context Protocol (MCP) is an open protocol, created by Anthropic, that standardizes how applications provide context to language models. Its capabilities include tools, prompts, and resources. The architecture separates the application the user works in from the connections and programs that supply those capabilities.
| Role | Responsibility | Session example |
|---|---|---|
| Host | Application that wants access to server capabilities | VS Code |
| Client | Maintains a one-to-one connection with a server | GitHub Copilot, in the presenters’ explanation |
| Server | Lightweight program exposing capabilities through MCP | A custom or existing MCP server |
You can build a server yourself or use an existing one. In VS Code’s Extensions view, searching for @mcp brings up available servers. Mhangami recommends starting with the VS Code or GitHub listings because an arbitrary server downloaded from the internet can contain malicious code. A server is executable software, so choosing one is also a trust decision.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
From diagram text to an editable diagram
Consider a request to draw a diagram explaining MCP. In the early experiences Mhangami describes, the response was often text: ASCII art, diagram source, or a README decorated with emojis. The limitation here is the interaction experience, not a historical rule that MCP could carry only text: the 2024-11-05 tools specification already supported images and embedded resources. A textual representation still leaves the user without a directly manipulable diagram.
MCP Apps let server tools provide rich interactive components that render directly in chat. Mhangami repeats the diagram request using the Excalidraw MCP App server. Instead of just reading the response, the user can work with the diagram. Her slide is a screenshot, but she describes the live app’s ability to move diagram elements and edit their text without leaving the conversation.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
The host turns a resource into an interface
Mhangami traces the interaction with a simple analytics request:
- The user asks, “Show me analytics.”
- The agent chooses an appropriate tool exposed by an MCP server.
- The server supplies results associated with a UI resource reference pointing to HTML.
- The host—VS Code in this example—fetches the HTML and renders it inside a sandboxed iframe.
- The user interacts with the app, which can request more server data and update its display.
The host renders the interface; the model selects the tool. That distinction explains why the HTML is fetched by VS Code rather than by the Copilot client in her account.
The presentation describes the UI reference as arriving with the result. In the current MCP Apps architecture, the tool definition declares _meta.ui.resourceUri, so the host can discover—and potentially preload—the UI before the tool finishes. Subsequent app-to-tool communication also passes through the host. The essential separation remains: the tool produces data, a resource supplies the interface, and the host connects them.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Where clicking beats another prompt
For data exploration, an initial question might reveal a trend in a bar chart. The next action is often narrower: inspect particular values or switch to another chart. Repeatedly describing those actions in text makes the user translate a visual intention back into language. Buttons and other controls let the user take the next step directly.
Commerce offers a related example, aimed more at general chat products than at VS Code. A shopping assistant can return a link and send the buyer to a browser, but Mhangami’s proposed experience keeps product selection and checkout inside chat. The UI carries the transaction forward instead of making the conversation merely a directory of destinations.
The examples span several kinds of interface:
- Shopify: Mhangami describes preserving a merchant’s website branding in the rendered components, with a full checkout experience inside chat. This is the experience she highlights, rather than a walkthrough of a particular checkout API.
- Excalidraw: Architecture diagrams become interactive visualizations. She also mentions an example she calls Quip Code.
- Figma: She describes generating components on the fly, although she does not show a rendered Figma app example.
The common design goal is to keep the task’s useful interaction surface alongside the conversation.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Build a tool, a resource, and the link between them
Hampton starts his implementation with a skill from the Model Context Protocol MCP Apps repository. He modifies it and runs it through GitHub Copilot CLI to generate several apps. His demo repository includes the FlameGraph example he will demonstrate, alongside a Markdown viewer, flight-status app, and color picker. The purpose is to keep the interaction within one working context: VS Code.
The implementation has three essential pieces:
| Piece | What it supplies |
|---|---|
| Tool | A server operation the model can select |
| Resource | The bundled HTML interface |
| Link | The association between the tool and its UI resource |
A tool is distinct from the LLM that chooses it. Likewise, the resource is distinct from the tool’s data response: the host needs the association between them to know which interface should display that data. The frontend can be built with React, Vue, vanilla JavaScript, or Svelte.
The skill provides setup and run instructions, code examples, handlers, and tool-visibility guidance for the coding assistant. Visibility determines who can invoke a tool:
- Model only: The model can select it during the conversation.
- Model and app: Both the model and the embedded interface can invoke it.
- App only: The interface can invoke it without exposing it as a model-selectable operation.
That choice belongs in the app’s design because an interactive control and an agent need not have the same set of operations.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Turn a Go workload into profiling data
The Flamegraph Profiler app profiles a Go program containing bubble sort and a Fibonacci workload. These give the profiler recognizable functions whose execution costs can be inspected. A compact version of those two workload functions looks like this:
go
package workload
func BubbleSort(values []int) {
for end := len(values) - 1; end > 0; end-- {
for i := 0; i < end; i++ {
if values[i] > values[i+1] {
values[i], values[i+1] = values[i+1], values[i]
}
}
}
}
func Fibonacci(n uint) uint64 {
if n < 2 {
return uint64(n)
}
return Fibonacci(n-1) + Fibonacci(n-2)
}
Bubble sort repeatedly compares neighboring values and swaps them when necessary. The recursive Fibonacci function repeatedly evaluates smaller Fibonacci inputs. Together they illustrate the kinds of application work the demo is set up to inspect.
Hampton configures a five-second profiling window using Go’s pprof. The MCP server runs on localhost, with a local entry point invoking the TypeScript server implementation. The important server operation prepares the Go program, runs it, profiles it, and returns the resulting data. Five seconds is the collection window, not a reported speedup.
The linked frontend is a React app Hampton calls Flame App. It uses hooks to receive tool input and results, then presents the profile as a flame graph and information about where the program spends its time. This is the practical value of the tool/resource split: profiling remains server work, while the frontend makes the resulting data easier to inspect.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Inspect the result inside Copilot chat
With the MCP server installed and running, Hampton opens GitHub Copilot. The server exposes one tool, which he describes as “Profile the App.” He asks Copilot to profile the application; Copilot recognizes the installed Flame Graph Profiler, selects the tool, and begins loading the MCP App. The resulting interface appears inside an iframe in the chat window.
The interface exposes top functions and a profiling summary. Its size and presentation can be adjusted to fit the chat window; the onstage version is fairly large. Instead of repeatedly asking the model whether the profile is good or bad, or where time is being spent, the user can inspect the function information directly. Hampton’s claim is about reducing that conversational back-and-forth: the relevant data is already visible in the app.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Keep the interface useful and contained
The completed demo follows the same path as the earlier analytics example. A request to profile the application reaches the model, the model selects the tool, and the MCP server returns JSON data. The host recognizes the associated UI resource and renders the interface in chat. The model does not have to turn every part of the profile into prose before the user can explore it.
Hampton explains the iframe with a hamster analogy: leave a hamster loose in a room and it may chew things up; give it an enclosure and its activity stays contained. The corresponding goal is to keep an embedded app from having unrestricted access to VS Code settings or external systems. An iframe is part of that boundary, not a blanket ban on all external access: host permissions and content security policy govern permitted resources, and tool calls are mediated by the host. The interface can remain interactive without receiving the editor’s full authority.
The session closes with invitations to meet the GitHub team at its booth and continue learning through Microsoft Build’s code-focused sessions and workshops. The technical demonstration ends at the local server and embedded profiling UI: a useful application can live inside the conversation while the host retains responsibility for rendering and containment.
Suggest correction
This note stays in this page until you copy or download it. Nothing is submitted; reloading clears the draft.
Resources
From the talk
Example MCP Apps with local setup instructions, VS Code configuration and a companion app-building skill.
Go profiling example with an interactive flamegraph, top functions and an intentionally inefficient sample application.
The MCP Apps specification, SDK, framework examples and skills for generating interactive apps.
An MCP App server for streamed Excalidraw diagrams and interactive editing in supported chat hosts.
Further reading
Figma’s announcement explains how conversations in Claude become editable FigJam diagrams.
Updates since the talk
- MCP Apps architecture and securityDocumentation
Current documentation for UI resource declarations, host communication, iframe isolation, permissions and external resource policies.
Current VS Code instructions for adding, configuring and managing MCP servers and displaying MCP Apps in chat.
Read the complete timestamped transcript
- 0:00
[upbeat music] Hi, everyone.
- 0:15
Uh, we'll introduce ourselves. My name's Marlene, and I'm a senior developer advocate at Microsoft and GitHub.
- 0:22
And likewise, I'm Liam Hampton, and I also am working at Microsoft and GitHub on the developer tools advocacy team for Visual Studio Code and GitHub Copilot.
- 0:31
Yes. I do similar things, but probably Liam is more on the VS Code side as well. Um, so just to get started, a bit of an agenda of what we're gonna cover today in this session.
- 0:42
We're gonna talk about what MCP is, and then we're gonna talk about why we need MCP apps and what they are. And then Liam is gonna do some live demos of how to use MCP apps, how to build them and use them in VS Code.
- 0:58
So just to get started, maybe I can ask, uh, the question of how many of us know what MCP is. Okay, that's a good, that's a good amount of the room.
- 1:08
Okay, good. That means that we are up to date. I will do a quick then summary, uh, to talk about what it is. But MCP, of course, is an open protocol that standardizes how applications provide context to LLM.
- 1:23
So it was created by Anthropic. Uh, it is open, uh, it's an open protocol, so hope- thankfully the community can use it. And it allows us to access context, or LLMs to access context like tools or prompts or resources, um, in different ways.
- 1:42
So just so you get, uh, a bit of an overview of which parts of MCP we will be looking at with MCP tools, the first thing is that we have MCP hosts.
- 1:55
And hosts are pro- uh, are programs like VS Code that want to access data from your MCP servers. So you can have different types of hosts, um, and, uh, they will come with different clients as well.
- 2:09
So the second thing is that we have clients, and these are sometimes going to be the same as the host, but not all of the time, and these will maintain the one-to-one connection with the servers.
- 2:23
So in our case, in VS Code, we usually encourage people to use the client, uh, GitHub Copilot, and that's what we'll be looking at today. And then the final thing would be the servers.
- 2:33
And with servers, these are going to actually lightweight programs that expose specific capabilities through MCP to provide that context. And you can build your own servers, or you can use any of the many servers that are available out there.
- 2:50
So in VS Code, if you actually go to the extensions tab and you type in @MCP, you'll get a list of different servers that are available. We definitely encourage you to use the server list that is in VS Code just because sometimes you can have some security issues if you just go on the internet and pick a
- 3:10
random server. It can have malicious stuff in it. So we recommend using, um, what's there in, in VS Code or, or GitHub. So when MCP was first released, one of the downsides was that you would pretty much only have it return text.
- 3:28
So if someone was going to ask a question, like in this case, I would ask a question asking it to draw an image, a diagram explaining what MCP is.
- 3:39
And so a lot of the times in the early days of MCP or in general of LLMs, you can go to a GitHub repository and most of the readmes have ASCII art or they have a lot of emojis.
- 3:52
I feel like we were overcompensating with emojis because we actually couldn't generate diagrams or interesting rich texts with MCPs or the tools that we had available to us.
- 4:05
So a good question to ask is: How can we create rich UI experiences in chat? So this is exactly where MCP apps comes into play. So MCP apps let server tools return rich interactive components that render directly in the chat, so you're able to have the server actually return these nice UI elements
- 4:30
so that you can be able to interact with them directly in the chat, and also just improves the general visual element of things as well. So I showed earlier that ASCII art example where it was text return.
- 4:45
I asked the same question using the Excalidraw MCP server, which now uses an MCP app to generate a diagram that explains MCP, and you can see that it generates...
- 4:57
This is, uh, just a screenshot of, of what it looks like. But there, another really cool thing is that you can actually interact with that diagram. You can go ahead and move it around, um, even update the text and so on, because this is a live element that's actually available in the chat.
- 5:15
So how do, how do MCP apps actually work? A good example is that maybe we have a user. We start by the user asking a question. So they'll send a prompt.
- 5:26
Maybe they'll say, "Show me analytics," and the agent or the LLM is going to decide which tools to call using the MCP server. It'll connect and then decide on a tool.
- 5:36
And the server is going to return the tool results with a UI, a resource reference. So MCP has MCP resources, and this reference will point to an HTML element that is stored that the, uh, server has generated.
- 5:54
Then the host, so not the client, it wouldn't be GitHub Copilot, but the host, which is VS Code- Is going to fetch the HTML from that UI reference that was referenced from the server, and then the host is going to render the app inside a sandboxed iFrame.
- 6:12
So the user at that point is able to interact with the iFrame in the host, and there's really a nice separation there between the two, and then the app can call back to the server, back and forth, so that you have this live interaction experience.
- 6:27
And then the us- the server can return fresh data, and the app will, uh, update as well.
- 6:34
Some different use cases for MCP Apps. One, for example, is data exploration. You can think of if you are... Imagine if we were just typing into a chat all the time, and we wanted to understand more about a data set.
- 6:49
It would be difficult, or interact with a database. It'd be difficult to always type in and ask new questions. Oh, you know, maybe you found out information about a trend in, uh, um, with the bar chart, and then you wanted to find more information about, um, maybe some specific numbers in another chart.
- 7:09
And actually typing in that information is going to be tiring for the user when they can just click different buttons in the UI in that way. Another thing is e-commerce.
- 7:19
I think this is a really great example, where a user maybe in one case would want to be able to actually buy something in the chat UI. So maybe not as much in VS Code, but in other chat UIs, like in OpenAI or something like that.
- 7:34
The user should be able to, in the chat, actually go ahead and buy and go through the entire checkout experiences in the chat instead of just typing out. In the past, what would happen is maybe you type, uh, uh...
- 7:48
You can ask your, uh, client, "Can I buy something online?" And then it would just return links to you, and then you'd have to navigate over to the browser.
- 7:58
What we want is to keep the user inside the chat, and then have them interact and have that experience there.
- 8:06
Who is currently building MCP Apps? I think this is a good question to ask. Spotify is, uh, not Spotify. Shopify. [laughs] Shopify is an example of a company that's currently building with MCP Apps, and I listened to a really good talk about how they're also focusing on keeping the brand experience of a company the same
- 8:32
as if you were on the company's website. If the user is in the chat, the elements that are rendered should be the same, and it should give the same brand feel.
- 8:40
So they're really working on the UI elements that are returned so that the user can literally go through the full checkout experience, like I was mentioning, um, to be able to actually buy in the chat.
- 8:51
Another group that are using MCP Apps, like I mentioned before, is Excalidraw. That is really popular right now for maybe generating architecture diagrams or having interactive diagrams. If you go, go to Quip Code, for example, they have really nice MCP Apps that use Excalidraw to just generate, um, an image visualizing things.
- 9:14
Figma is another, uh, company that's using MCP Apps. I couldn't find a picture of [laughs] a nice Figma MCP App rendered, but generally speaking, they have, uh, components that you can generate on the fly with MCP Apps.
- 9:29
So I think that's all I'm going to cover, and now Liam is going to go ahead and do our live demo.
- 9:35
Yeah, nice one. Thank you. So everybody put their hand up when Marlene asked who's using MCP or who knows what MCP is. Who's using MCP Apps already?
- 9:46
Okay, there's like... All right, perfect. Uh, shout out at the back you can't see this. Um, but essentially an MCP App is gonna allow us to really interact or stay within one context, such as VS Code.
- 9:57
So the way that I do this is I actually borrowed, "borrowed" a skill which is on the Model Context Protocol repository online, so it's from Anthropic. I edited it a little bit, and I ran it through GitHub Copilot CLI.
- 10:09
That allows me to spit out a number of different MCP Apps. So in this repository here, I've got a FlameGraph one. That's the one we're gonna be showing today.
- 10:17
Uh, but I've got a Markdown viewer, flight status, um, color picker, et cetera. Just the gen- generic ones that you just go through when you're starting to build these projects.
- 10:25
So starting with this, uh, readme, you can see that there is three main parts to an MCP App. You've got the tool, which is the LLM itself, and the host, i.e.
- 10:34
at the moment, VS Code. You've got the resource, which is then the bundled HTML, HTML UI, which we're gonna be putting together. That could be in React, that could be in View, whatever, however you wanna render your UI.
- 10:45
Uh, and then you've got the link between the two. So the host and the MCP itself or the server are going to recognize there's a link between having the actual data response and a UI being available to render.
- 10:58
So there's a good ways you can do this. Like I said, you've got React, you've got Vanilla JS, you've got View, Svelte, et cetera. So you can just go through this whole skill.
- 11:04
This is gonna basically tell Copilot CLI or Claude or whatever AI tool that you're using how to run this or what to do when it comes to running this skill.
- 11:12
Uh, it's gonna set it up in a certain way, uh, and it's going to tell you exactly how to run it as well and how it should be run with code examples, such as handlers, tool visibility.
- 11:22
Um, so whether it's just the model that can call the application, whether it's the model and the app, or whether it's just the app. So that's who invokes the tool at any given point.
- 11:31
So for this example, I'm gonna be using a Go file. I'm a Go engineer. I write a lot of Go code. But all that I really care about in here is a bubble sort algorithm, so just comparing an array of values together.
- 11:41
Pretty standard in any coding interview. Uh, and then we've got the Fibonacci sequence as well, so N plus one. This is like big O, so essentially just adding to the next one before it.
- 11:51
What I'm doing there is I'm gonna use an MCP server to profile the application code over five seconds to see where's the time being spent most in this application.
- 12:00
As any profiling would do, this is using, uh, Go pprof, so the underlying profiler that you get in Go. But essentially, the MCP server is running a local host.
- 12:09
This is the entry point in here. It's just a server that I'm running locally. That then calls out to the server TypeScript. This is all written in TypeScript, uh, as per the skill that was, uh, enabled.
- 12:21
Of this entire file, this is the one that really matters the most, where the MCP is going to bundle up my Go program, run it, profile it, and spit out some data.
- 12:30
And it's at that point that the UI is then linked to the MCP server itself to render the front end. I... Over here, we have the React app, Flame App, which is using hooks in React, and in here we can see that we are going to look at the receiving the tool input.
- 12:47
We've got the results. We've got the, um, uh, where it's spending basically most of its time and the flame graph itself. So who here, who here has used flame graphs or touched them or kind of know?
- 12:58
Basically, it's a very nasty bit of data you get out at the end, and it's all jumbled up. Um, this is a really nice way to profile and see how it's working.
- 13:06
So I'm gonna open up GitHub Copilot and my, make sure my MCP server is running. I have it installed here, and there is one tool for it, so Profile the App.
- 13:15
Hopefully, if I go and ask GitHub Copilot, and it should still be working, it should recognize that it needs to call the tool itself. So we just give this just a moment to run.
- 13:25
There we go. It's noticed I've got the Flame, uh, Flame Graph Profiler installed. Should be using this. Loading the MCP app.
- 13:35
Give it just one second to load. There we go. We can close this. Here, this is what an MCP app is really looking like inside the chat window. So it's rendered out a UI in an iframe.
- 13:46
We can look at the top functions and the summary of how this is running. This can be edited and then run down and sort of massaged as you want to make it fit your chat window.
- 13:55
I know it's pretty big. Uh, but this gives a ge- a general overview of exactly what they're looking like and how you can measure them. Typically, what I would be doing with this data is asking my AI models, uh, is this good?
- 14:06
Is this bad? Where am I spending my time? There's a lot of back and forth. With a UI app that we have inside an iframe, you are just eliminating that.
- 14:13
You're absolutely getting rid of it. You just have it all available to you in here, so you can see where it's spending most of its time in the functions, et cetera, et cetera.
- 14:21
So that's a really good way to use it. Now, I wrote a very rudimentary drawing, which was a little bit better, um, on Marlene's slide here. But essentially what I've done is I said, profile my application.
- 14:32
That has been sent to the LLM model, which has then said, "Oh, I need to call this tool." The MCP server's run, gives me back some JSON data, passed it to the host.
- 14:41
The host has recognized that there's a resource to link, and therefore it has been rendered in an iframe in the chat window. The reason we're doing this in an iframe or why the iframe is the same reason that you put a hamster in a cage, right?
- 14:54
It, you don't let it loose in a room. It's just gonna chew things up. You don't want this application to interact with your VS Code settings, any APIs, anything external, all of that kind of stuff, so you want to keep it all contained inside the chat window.
- 15:06
That's the reason why it's in an iframe. And I believe that is actually at time now. So I guess, Marlene, anything else?
- 15:15
Uh, nope. Uh, we are, Microsoft is here. GitHub has a booth on the fourth floor, on the third floor. So, oh, [laughs]
- 15:25
Adebek, you need to be in the camera. But, uh, GitHub has a booth, uh, available. We also have Microsoft Build this year that's really gonna be focusing on, uh, code, and we'll have a bunch of workshops.
- 15:36
It's gonna be on the 3rd to the 6th, I think, of June. Um, and so we'd invite you to come by either our booth at GitHub or to check out Microsoft Build as well online.
- 15:46
But yeah, thanks for joining us.
- 15:48
Thanks a lot. Thank you. [audience applauds] [upbeat electronic music]